From 4f99f868f09bbffa2e15733b8b7c78eba07a199e Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 6 Dec 2020 21:23:48 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- Makefile.am.in | 1 - arts/kde/CMakeLists.txt | 10 +- arts/kde/Makefile.am | 18 +- arts/kde/kartsdispatcher.cc | 60 - arts/kde/kartsdispatcher.cpp | 60 + arts/kde/kaudioconverter.cc | 198 - arts/kde/kaudioconverter.cpp | 198 + arts/kde/kconverttest.cc | 96 - arts/kde/kconverttest.cpp | 96 + arts/kde/kiotest.cc | 54 - arts/kde/kiotest.cpp | 54 + arts/kde/kiotestslow.cc | 131 - arts/kde/kiotestslow.cpp | 131 + arts/kde/kplayobject.cc | 301 -- arts/kde/kplayobject.cpp | 301 ++ arts/kde/kplayobjectcreator.cc | 104 - arts/kde/kplayobjectcreator.cpp | 104 + arts/kde/kplayobjectfactory.cc | 256 -- arts/kde/kplayobjectfactory.cpp | 256 ++ arts/message/CMakeLists.txt | 2 +- arts/message/Makefile.am | 2 +- arts/message/artsmessage.cc | 93 - arts/message/artsmessage.cpp | 93 + dcop/dcopidl/CMakeLists.txt | 2 +- dcop/dcopidl/Makefile.am | 10 +- dcop/dcopidl/scanner.cc | 2747 ------------ dcop/dcopidl/scanner.cpp | 2747 ++++++++++++ dcop/dcopidl/scanner.ll | 2 +- dcop/dcopidl/yacc.cc | 3390 --------------- dcop/dcopidl/yacc.cc.h | 135 - dcop/dcopidl/yacc.cpp | 3390 +++++++++++++++ dcop/dcopidl/yacc.cpp.h | 135 + doc/common/Doxyfile.global | 8 +- interfaces/terminal/test/Makefile.am | 2 +- interfaces/terminal/test/main.cc | 63 - interfaces/terminal/test/main.cpp | 63 + kab/CMakeLists.txt | 2 +- kab/ChangeLog | 2 +- kab/Makefile.am | 6 +- kab/addressbook.cc | 2040 --------- kab/addressbook.cpp | 2040 +++++++++ kab/kabapi.cc | 220 - kab/kabapi.cpp | 220 + kab/qconfigDB.cc | 2547 ----------- kab/qconfigDB.cpp | 2547 +++++++++++ libtdemid/CMakeLists.txt | 8 +- libtdemid/Makefile.am | 8 +- libtdemid/alsaout.cc | 571 --- libtdemid/alsaout.cpp | 571 +++ libtdemid/alsaout.h | 2 +- libtdemid/dattypes.cc | 110 - libtdemid/dattypes.cpp | 110 + libtdemid/deviceman.cc | 828 ---- libtdemid/deviceman.cpp | 828 ++++ libtdemid/fmout.cc | 354 -- libtdemid/fmout.cpp | 354 ++ libtdemid/gusout.cc | 691 --- libtdemid/gusout.cpp | 691 +++ libtdemid/libtdemid.cc | 263 -- libtdemid/libtdemid.cpp | 263 ++ libtdemid/midfile.cc | 460 -- libtdemid/midfile.cpp | 460 ++ libtdemid/midimapper.cc | 456 -- libtdemid/midimapper.cpp | 456 ++ libtdemid/midiout.cc | 301 -- libtdemid/midiout.cpp | 301 ++ libtdemid/midistat.cc | 115 - libtdemid/midistat.cpp | 115 + libtdemid/mt32togm.cc | 18 - libtdemid/mt32togm.cpp | 18 + libtdemid/notearray.cc | 122 - libtdemid/notearray.cpp | 122 + libtdemid/player.cc | 959 ----- libtdemid/player.cpp | 959 +++++ libtdemid/synthout.cc | 211 - libtdemid/synthout.cpp | 211 + libtdemid/tests/Makefile.am | 4 +- libtdemid/tests/apitest.cc | 25 - libtdemid/tests/apitest.cpp | 25 + libtdemid/tests/notesoff.cc | 24 - libtdemid/tests/notesoff.cpp | 24 + libtdemid/track.cc | 566 --- libtdemid/track.cpp | 566 +++ libtdemid/voiceman.cc | 279 -- libtdemid/voiceman.cpp | 279 ++ tdecert/CMakeLists.txt | 2 +- tdecert/Makefile.am | 2 +- tdecert/tdecertpart.cc | 876 ---- tdecert/tdecertpart.cpp | 876 ++++ tdecore/tdeglobalsettings.h | 2 +- tdecore/tests/kurltest.cpp | 8 +- tdehtml/CMakeLists.txt | 4 +- tdehtml/ChangeLog | 6 +- tdehtml/Makefile.am | 4 +- tdehtml/tdehtml_iface.cc | 233 - tdehtml/tdehtml_iface.cpp | 233 + tdehtml/tdehtml_settings.cc | 1064 ----- tdehtml/tdehtml_settings.cpp | 1064 +++++ tdeio/Makefile.am | 2 +- tdeio/bookmarks/CMakeLists.txt | 10 +- tdeio/bookmarks/Makefile.am | 8 +- tdeio/bookmarks/kbookmark.cc | 538 --- tdeio/bookmarks/kbookmark.cpp | 538 +++ tdeio/bookmarks/kbookmarkbar.cc | 552 --- tdeio/bookmarks/kbookmarkbar.cpp | 552 +++ tdeio/bookmarks/kbookmarkdombuilder.cc | 81 - tdeio/bookmarks/kbookmarkdombuilder.cpp | 81 + tdeio/bookmarks/kbookmarkdrag.cc | 167 - tdeio/bookmarks/kbookmarkdrag.cpp | 167 + tdeio/bookmarks/kbookmarkexporter.cc | 30 - tdeio/bookmarks/kbookmarkexporter.cpp | 30 + tdeio/bookmarks/kbookmarkimporter.cc | 99 - tdeio/bookmarks/kbookmarkimporter.cpp | 99 + tdeio/bookmarks/kbookmarkimporter_crash.cc | 213 - tdeio/bookmarks/kbookmarkimporter_crash.cpp | 213 + tdeio/bookmarks/kbookmarkimporter_ie.cc | 183 - tdeio/bookmarks/kbookmarkimporter_ie.cpp | 183 + tdeio/bookmarks/kbookmarkimporter_kde1.cc | 154 - tdeio/bookmarks/kbookmarkimporter_kde1.cpp | 154 + tdeio/bookmarks/kbookmarkimporter_ns.cc | 241 -- tdeio/bookmarks/kbookmarkimporter_ns.cpp | 241 ++ tdeio/bookmarks/kbookmarkimporter_opera.cc | 168 - tdeio/bookmarks/kbookmarkimporter_opera.cpp | 168 + tdeio/bookmarks/kbookmarkmanager.cc | 731 ---- tdeio/bookmarks/kbookmarkmanager.cpp | 731 ++++ tdeio/bookmarks/kbookmarkmenu.cc | 1185 ------ tdeio/bookmarks/kbookmarkmenu.cpp | 1185 ++++++ tdeio/httpfilter/CMakeLists.txt | 2 +- tdeio/httpfilter/Makefile.am | 2 +- tdeio/httpfilter/httpfilter.cc | 372 -- tdeio/httpfilter/httpfilter.cpp | 372 ++ tdeio/kssl/CMakeLists.txt | 16 +- tdeio/kssl/Makefile.am | 46 +- tdeio/kssl/kopenssl.cc | 2123 ---------- tdeio/kssl/kopenssl.cpp | 2123 ++++++++++ tdeio/kssl/ksmimecrypto.cc | 417 -- tdeio/kssl/ksmimecrypto.cpp | 417 ++ tdeio/kssl/kssl.cc | 699 --- tdeio/kssl/kssl.cpp | 699 +++ tdeio/kssl/ksslcertchain.cc | 194 - tdeio/kssl/ksslcertchain.cpp | 194 + tdeio/kssl/ksslcertdlg.cc | 174 - tdeio/kssl/ksslcertdlg.cpp | 174 + tdeio/kssl/ksslcertificate.cc | 1236 ------ tdeio/kssl/ksslcertificate.cpp | 1236 ++++++ tdeio/kssl/ksslcertificatecache.cc | 399 -- tdeio/kssl/ksslcertificatecache.cpp | 399 ++ tdeio/kssl/ksslcertificatefactory.cc | 122 - tdeio/kssl/ksslcertificatefactory.cpp | 122 + tdeio/kssl/ksslcertificatehome.cc | 246 -- tdeio/kssl/ksslcertificatehome.cpp | 246 ++ tdeio/kssl/ksslconnectioninfo.cc | 66 - tdeio/kssl/ksslconnectioninfo.cpp | 66 + tdeio/kssl/ksslcsessioncache.cc | 120 - tdeio/kssl/ksslcsessioncache.cpp | 120 + tdeio/kssl/ksslinfodlg.cc | 475 --- tdeio/kssl/ksslinfodlg.cpp | 475 +++ tdeio/kssl/ksslkeygen.cc | 222 - tdeio/kssl/ksslkeygen.cpp | 222 + tdeio/kssl/ksslpeerinfo.cc | 171 - tdeio/kssl/ksslpeerinfo.cpp | 171 + tdeio/kssl/ksslpemcallback.cc | 58 - tdeio/kssl/ksslpemcallback.cpp | 58 + tdeio/kssl/ksslpkcs12.cc | 274 -- tdeio/kssl/ksslpkcs12.cpp | 274 ++ tdeio/kssl/ksslpkcs7.cc | 189 - tdeio/kssl/ksslpkcs7.cpp | 189 + tdeio/kssl/ksslsession.cc | 82 - tdeio/kssl/ksslsession.cpp | 82 + tdeio/kssl/ksslsettings.cc | 345 -- tdeio/kssl/ksslsettings.cpp | 345 ++ tdeio/kssl/ksslsigners.cc | 251 -- tdeio/kssl/ksslsigners.cpp | 251 ++ tdeio/kssl/ksslutils.cc | 103 - tdeio/kssl/ksslutils.cpp | 103 + tdeio/kssl/ksslx509map.cc | 103 - tdeio/kssl/ksslx509map.cpp | 103 + tdeio/kssl/ksslx509v3.cc | 143 - tdeio/kssl/ksslx509v3.cpp | 143 + tdeio/tdefile/tdefiledialog.h | 6 +- tdeio/tdeio/kmimetypechooser.cpp | 2 +- tdeio/tdeio/tdefileitem.cpp | 2 +- tdeio/tdeio/tdefileitem.h | 2 +- tdeio/tests/kurifiltertest.cpp | 2 +- tdeioslave/file/CMakeLists.txt | 2 +- tdeioslave/file/Makefile.am | 2 +- tdeioslave/file/file.cc | 1890 --------- tdeioslave/file/file.cpp | 1890 +++++++++ tdeioslave/ftp/CMakeLists.txt | 2 +- tdeioslave/ftp/Makefile.am | 2 +- tdeioslave/ftp/ftp.cc | 2674 ------------ tdeioslave/ftp/ftp.cpp | 2674 ++++++++++++ tdeioslave/http/CMakeLists.txt | 2 +- tdeioslave/http/Makefile.am | 2 +- tdeioslave/http/README.webdav | 2 +- tdeioslave/http/http.cc | 6131 --------------------------- tdeioslave/http/http.cpp | 6131 +++++++++++++++++++++++++++ tdeioslave/http/http_cache_cleaner.cpp | 4 +- tdeioslave/iso/Makefile.am | 2 +- tdeioslave/iso/iso.cpp | 2 +- tderandr/CMakeLists.txt | 2 +- tderandr/Makefile.am | 2 +- tderandr/libtderandr.cc | 1629 ------- tderandr/libtderandr.cpp | 1629 +++++++ tdeui/ksharedpixmap.h | 2 +- tdeui/tdetoolbarlabelaction.cpp | 2 +- tdewallet/backend/CMakeLists.txt | 6 +- tdewallet/backend/Makefile.am | 12 +- tdewallet/backend/blockcipher.cc | 37 - tdewallet/backend/blockcipher.cpp | 37 + tdewallet/backend/blowfish.cc | 259 -- tdewallet/backend/blowfish.cpp | 259 ++ tdewallet/backend/blowfishtables.h | 2 +- tdewallet/backend/cbc.cc | 149 - tdewallet/backend/cbc.cpp | 149 + tdewallet/backend/sha1.cc | 343 -- tdewallet/backend/sha1.cpp | 343 ++ tdewallet/backend/tdewalletbackend.cc | 838 ---- tdewallet/backend/tdewalletbackend.cpp | 838 ++++ tdewallet/backend/tdewalletentry.cc | 89 - tdewallet/backend/tdewalletentry.cpp | 89 + tdewallet/backend/tests/CMakeLists.txt | 4 +- tdewallet/client/CMakeLists.txt | 2 +- tdewallet/client/Makefile.am | 2 +- tdewallet/client/tdewallet.cc | 713 ---- tdewallet/client/tdewallet.cpp | 713 ++++ win/common.pro | 2 +- win/pro_files/dcop/dcopidl/dcopidl.pro | 4 +- win/pro_files/tdeio/tdeio.pro | 68 +- 229 files changed, 48810 insertions(+), 48817 deletions(-) delete mode 100644 arts/kde/kartsdispatcher.cc create mode 100644 arts/kde/kartsdispatcher.cpp delete mode 100644 arts/kde/kaudioconverter.cc create mode 100644 arts/kde/kaudioconverter.cpp delete mode 100644 arts/kde/kconverttest.cc create mode 100644 arts/kde/kconverttest.cpp delete mode 100644 arts/kde/kiotest.cc create mode 100644 arts/kde/kiotest.cpp delete mode 100644 arts/kde/kiotestslow.cc create mode 100644 arts/kde/kiotestslow.cpp delete mode 100644 arts/kde/kplayobject.cc create mode 100644 arts/kde/kplayobject.cpp delete mode 100644 arts/kde/kplayobjectcreator.cc create mode 100644 arts/kde/kplayobjectcreator.cpp delete mode 100644 arts/kde/kplayobjectfactory.cc create mode 100644 arts/kde/kplayobjectfactory.cpp delete mode 100644 arts/message/artsmessage.cc create mode 100644 arts/message/artsmessage.cpp delete mode 100644 dcop/dcopidl/scanner.cc create mode 100644 dcop/dcopidl/scanner.cpp delete mode 100644 dcop/dcopidl/yacc.cc delete mode 100644 dcop/dcopidl/yacc.cc.h create mode 100644 dcop/dcopidl/yacc.cpp create mode 100644 dcop/dcopidl/yacc.cpp.h delete mode 100644 interfaces/terminal/test/main.cc create mode 100644 interfaces/terminal/test/main.cpp delete mode 100644 kab/addressbook.cc create mode 100644 kab/addressbook.cpp delete mode 100644 kab/kabapi.cc create mode 100644 kab/kabapi.cpp delete mode 100644 kab/qconfigDB.cc create mode 100644 kab/qconfigDB.cpp delete mode 100644 libtdemid/alsaout.cc create mode 100644 libtdemid/alsaout.cpp delete mode 100644 libtdemid/dattypes.cc create mode 100644 libtdemid/dattypes.cpp delete mode 100644 libtdemid/deviceman.cc create mode 100644 libtdemid/deviceman.cpp delete mode 100644 libtdemid/fmout.cc create mode 100644 libtdemid/fmout.cpp delete mode 100644 libtdemid/gusout.cc create mode 100644 libtdemid/gusout.cpp delete mode 100644 libtdemid/libtdemid.cc create mode 100644 libtdemid/libtdemid.cpp delete mode 100644 libtdemid/midfile.cc create mode 100644 libtdemid/midfile.cpp delete mode 100644 libtdemid/midimapper.cc create mode 100644 libtdemid/midimapper.cpp delete mode 100644 libtdemid/midiout.cc create mode 100644 libtdemid/midiout.cpp delete mode 100644 libtdemid/midistat.cc create mode 100644 libtdemid/midistat.cpp delete mode 100644 libtdemid/mt32togm.cc create mode 100644 libtdemid/mt32togm.cpp delete mode 100644 libtdemid/notearray.cc create mode 100644 libtdemid/notearray.cpp delete mode 100644 libtdemid/player.cc create mode 100644 libtdemid/player.cpp delete mode 100644 libtdemid/synthout.cc create mode 100644 libtdemid/synthout.cpp delete mode 100644 libtdemid/tests/apitest.cc create mode 100644 libtdemid/tests/apitest.cpp delete mode 100644 libtdemid/tests/notesoff.cc create mode 100644 libtdemid/tests/notesoff.cpp delete mode 100644 libtdemid/track.cc create mode 100644 libtdemid/track.cpp delete mode 100644 libtdemid/voiceman.cc create mode 100644 libtdemid/voiceman.cpp delete mode 100644 tdecert/tdecertpart.cc create mode 100644 tdecert/tdecertpart.cpp delete mode 100644 tdehtml/tdehtml_iface.cc create mode 100644 tdehtml/tdehtml_iface.cpp delete mode 100644 tdehtml/tdehtml_settings.cc create mode 100644 tdehtml/tdehtml_settings.cpp delete mode 100644 tdeio/bookmarks/kbookmark.cc create mode 100644 tdeio/bookmarks/kbookmark.cpp delete mode 100644 tdeio/bookmarks/kbookmarkbar.cc create mode 100644 tdeio/bookmarks/kbookmarkbar.cpp delete mode 100644 tdeio/bookmarks/kbookmarkdombuilder.cc create mode 100644 tdeio/bookmarks/kbookmarkdombuilder.cpp delete mode 100644 tdeio/bookmarks/kbookmarkdrag.cc create mode 100644 tdeio/bookmarks/kbookmarkdrag.cpp delete mode 100644 tdeio/bookmarks/kbookmarkexporter.cc create mode 100644 tdeio/bookmarks/kbookmarkexporter.cpp delete mode 100644 tdeio/bookmarks/kbookmarkimporter.cc create mode 100644 tdeio/bookmarks/kbookmarkimporter.cpp delete mode 100644 tdeio/bookmarks/kbookmarkimporter_crash.cc create mode 100644 tdeio/bookmarks/kbookmarkimporter_crash.cpp delete mode 100644 tdeio/bookmarks/kbookmarkimporter_ie.cc create mode 100644 tdeio/bookmarks/kbookmarkimporter_ie.cpp delete mode 100644 tdeio/bookmarks/kbookmarkimporter_kde1.cc create mode 100644 tdeio/bookmarks/kbookmarkimporter_kde1.cpp delete mode 100644 tdeio/bookmarks/kbookmarkimporter_ns.cc create mode 100644 tdeio/bookmarks/kbookmarkimporter_ns.cpp delete mode 100644 tdeio/bookmarks/kbookmarkimporter_opera.cc create mode 100644 tdeio/bookmarks/kbookmarkimporter_opera.cpp delete mode 100644 tdeio/bookmarks/kbookmarkmanager.cc create mode 100644 tdeio/bookmarks/kbookmarkmanager.cpp delete mode 100644 tdeio/bookmarks/kbookmarkmenu.cc create mode 100644 tdeio/bookmarks/kbookmarkmenu.cpp delete mode 100644 tdeio/httpfilter/httpfilter.cc create mode 100644 tdeio/httpfilter/httpfilter.cpp delete mode 100644 tdeio/kssl/kopenssl.cc create mode 100644 tdeio/kssl/kopenssl.cpp delete mode 100644 tdeio/kssl/ksmimecrypto.cc create mode 100644 tdeio/kssl/ksmimecrypto.cpp delete mode 100644 tdeio/kssl/kssl.cc create mode 100644 tdeio/kssl/kssl.cpp delete mode 100644 tdeio/kssl/ksslcertchain.cc create mode 100644 tdeio/kssl/ksslcertchain.cpp delete mode 100644 tdeio/kssl/ksslcertdlg.cc create mode 100644 tdeio/kssl/ksslcertdlg.cpp delete mode 100644 tdeio/kssl/ksslcertificate.cc create mode 100644 tdeio/kssl/ksslcertificate.cpp delete mode 100644 tdeio/kssl/ksslcertificatecache.cc create mode 100644 tdeio/kssl/ksslcertificatecache.cpp delete mode 100644 tdeio/kssl/ksslcertificatefactory.cc create mode 100644 tdeio/kssl/ksslcertificatefactory.cpp delete mode 100644 tdeio/kssl/ksslcertificatehome.cc create mode 100644 tdeio/kssl/ksslcertificatehome.cpp delete mode 100644 tdeio/kssl/ksslconnectioninfo.cc create mode 100644 tdeio/kssl/ksslconnectioninfo.cpp delete mode 100644 tdeio/kssl/ksslcsessioncache.cc create mode 100644 tdeio/kssl/ksslcsessioncache.cpp delete mode 100644 tdeio/kssl/ksslinfodlg.cc create mode 100644 tdeio/kssl/ksslinfodlg.cpp delete mode 100644 tdeio/kssl/ksslkeygen.cc create mode 100644 tdeio/kssl/ksslkeygen.cpp delete mode 100644 tdeio/kssl/ksslpeerinfo.cc create mode 100644 tdeio/kssl/ksslpeerinfo.cpp delete mode 100644 tdeio/kssl/ksslpemcallback.cc create mode 100644 tdeio/kssl/ksslpemcallback.cpp delete mode 100644 tdeio/kssl/ksslpkcs12.cc create mode 100644 tdeio/kssl/ksslpkcs12.cpp delete mode 100644 tdeio/kssl/ksslpkcs7.cc create mode 100644 tdeio/kssl/ksslpkcs7.cpp delete mode 100644 tdeio/kssl/ksslsession.cc create mode 100644 tdeio/kssl/ksslsession.cpp delete mode 100644 tdeio/kssl/ksslsettings.cc create mode 100644 tdeio/kssl/ksslsettings.cpp delete mode 100644 tdeio/kssl/ksslsigners.cc create mode 100644 tdeio/kssl/ksslsigners.cpp delete mode 100644 tdeio/kssl/ksslutils.cc create mode 100644 tdeio/kssl/ksslutils.cpp delete mode 100644 tdeio/kssl/ksslx509map.cc create mode 100644 tdeio/kssl/ksslx509map.cpp delete mode 100644 tdeio/kssl/ksslx509v3.cc create mode 100644 tdeio/kssl/ksslx509v3.cpp delete mode 100644 tdeioslave/file/file.cc create mode 100644 tdeioslave/file/file.cpp delete mode 100644 tdeioslave/ftp/ftp.cc create mode 100644 tdeioslave/ftp/ftp.cpp delete mode 100644 tdeioslave/http/http.cc create mode 100644 tdeioslave/http/http.cpp delete mode 100644 tderandr/libtderandr.cc create mode 100644 tderandr/libtderandr.cpp delete mode 100644 tdewallet/backend/blockcipher.cc create mode 100644 tdewallet/backend/blockcipher.cpp delete mode 100644 tdewallet/backend/blowfish.cc create mode 100644 tdewallet/backend/blowfish.cpp delete mode 100644 tdewallet/backend/cbc.cc create mode 100644 tdewallet/backend/cbc.cpp delete mode 100644 tdewallet/backend/sha1.cc create mode 100644 tdewallet/backend/sha1.cpp delete mode 100644 tdewallet/backend/tdewalletbackend.cc create mode 100644 tdewallet/backend/tdewalletbackend.cpp delete mode 100644 tdewallet/backend/tdewalletentry.cc create mode 100644 tdewallet/backend/tdewalletentry.cpp delete mode 100644 tdewallet/client/tdewallet.cc create mode 100644 tdewallet/client/tdewallet.cpp diff --git a/Makefile.am.in b/Makefile.am.in index 94e20cf66..9dcc14524 100644 --- a/Makefile.am.in +++ b/Makefile.am.in @@ -51,7 +51,6 @@ messages: fgrep -v "/tests" dirs > dirs.new && mv dirs.new dirs ;\ dirs=`cat dirs` ;\ find $$dirs -maxdepth 1 -name "*.cpp" -print > files ;\ - find $$dirs -maxdepth 1 -name "*.cc" -print >> files ;\ find $$dirs -maxdepth 1 -name "*.h" -print >> files ;\ echo ./tdecore/tde-config.cpp.in >> files ;\ $(EXTRACTRC) `find $$dirs -maxdepth 1 \( -name "*.rc" -o -name "*.ui" \) ` ./dnssd/kcm_tdednssd.kcfg > rc.cpp; \ diff --git a/arts/kde/CMakeLists.txt b/arts/kde/CMakeLists.txt index 091be3526..211a76924 100644 --- a/arts/kde/CMakeLists.txt +++ b/arts/kde/CMakeLists.txt @@ -43,15 +43,15 @@ install( FILES set( target artskde ) set( ${target}_SRCS - artskde.cc kioinputstream_impl.cpp kplayobject.cc - kplayobjectfactory.cc kartsfloatwatch.cpp kartsdispatcher.cc + artskde.cpp kioinputstream_impl.cpp kplayobject.cpp + kplayobjectfactory.cpp kartsfloatwatch.cpp kartsdispatcher.cpp kaudiorecordstream.cpp kaudioplaystream.cpp kartsserver.cpp - kdatarequest_impl.cpp kaudioconverter.cc kvideowidget.cpp - kplayobjectcreator.cc kaudiomanagerplay.cpp + kdatarequest_impl.cpp kaudioconverter.cpp kvideowidget.cpp + kplayobjectcreator.cpp kaudiomanagerplay.cpp ) add_custom_command( - OUTPUT artskde.cc artskde.h + OUTPUT artskde.cpp artskde.h COMMAND ${ARTS_MCOPIDL_EXECUTABLE} -I${ARTS_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/artskde.idl DEPENDS artskde.idl diff --git a/arts/kde/Makefile.am b/arts/kde/Makefile.am index 37a86f2ad..394b0a32a 100644 --- a/arts/kde/Makefile.am +++ b/arts/kde/Makefile.am @@ -2,11 +2,11 @@ INCLUDES = -I$(top_builddir)/arts/kde \ -I$(top_srcdir) -I$(includedir)/arts $(all_includes) lib_LTLIBRARIES = libartskde.la -libartskde_la_SOURCES = artskde.cc kioinputstream_impl.cpp kplayobject.cc \ - kplayobjectfactory.cc kartsfloatwatch.cpp kartsdispatcher.cc \ +libartskde_la_SOURCES = artskde.cpp kioinputstream_impl.cpp kplayobject.cpp \ + kplayobjectfactory.cpp kartsfloatwatch.cpp kartsdispatcher.cpp \ kaudiorecordstream.cpp kaudioplaystream.cpp \ - kartsserver.cpp kdatarequest_impl.cpp kaudioconverter.cc \ - kvideowidget.cpp kplayobjectcreator.cc \ + kartsserver.cpp kdatarequest_impl.cpp kaudioconverter.cpp \ + kvideowidget.cpp kplayobjectcreator.cpp \ kaudiomanagerplay.cpp libartskde_la_LIBADD = $(LIB_TDEIO) -lqtmcop -lsoundserver_idl -lartsflow_idl -lmcop $(LIB_TQT) $(LIB_TDECORE) -lkmedia2_idl -lartsflow $(LIB_TDEUI) $(LIB_X11) libartskde_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 3:0:2 @@ -23,15 +23,15 @@ noinst_HEADERS = kplayobjectcreator.h kplayobjectfactory_p.h artskde.mcoptype: artskde.h artskde.mcopclass: artskde.h MCOPINC = -I$(srcdir) -artskde.cc artskde.h: $(top_srcdir)/arts/kde/artskde.idl $(MCOPIDL) +artskde.cpp artskde.h: $(top_srcdir)/arts/kde/artskde.idl $(MCOPIDL) $(MCOPIDL) -I$(includedir)/arts -t $(MCOPINC) $(top_srcdir)/arts/kde/artskde.idl -DISTCLEANFILES = artskde.cc artskde.h artskde.mcoptype artskde.mcopclass +DISTCLEANFILES = artskde.cpp artskde.h artskde.mcoptype artskde.mcopclass check_PROGRAMS = kiotest kiotestslow kconverttest -kiotest_SOURCES = kiotest.cc -kiotestslow_SOURCES = kiotestslow.cc -kconverttest_SOURCES = kconverttest.cc +kiotest_SOURCES = kiotest.cpp +kiotestslow_SOURCES = kiotestslow.cpp +kconverttest_SOURCES = kconverttest.cpp kiotest_LDADD = libartskde.la -lqtmcop -lkmedia2 -lsoundserver_idl kiotestslow_LDADD = $(kiotest_LDADD) diff --git a/arts/kde/kartsdispatcher.cc b/arts/kde/kartsdispatcher.cc deleted file mode 100644 index fa41502f8..000000000 --- a/arts/kde/kartsdispatcher.cc +++ /dev/null @@ -1,60 +0,0 @@ - /* - - Copyright (C) 2001 Nikolas Zimmermann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - */ - -#include -#include - -#include - -#include "kartsdispatcher.moc" - -int KArtsDispatcher::m_refCount = 0; -Arts::Dispatcher *KArtsDispatcher::artsDispatcher = 0; -Arts::QIOManager *KArtsDispatcher::artsQIOManager = 0; - -KArtsDispatcher::KArtsDispatcher(TQObject *parent, const char *name) - : TQObject(parent, name) -{ - m_refCount++; - if(artsDispatcher == 0) - { - if (!Arts::Dispatcher::the()) // only if no Arts::Dispatcher is created yet - { - artsQIOManager = new Arts::QIOManager(); - artsDispatcher = new Arts::Dispatcher(artsQIOManager); - } - else - kdWarning(400) << "An Arts::Dispatcher() instance exists already while trying to instantiate KArtsDispatcher!" << endl; - } -} - -KArtsDispatcher::~KArtsDispatcher() -{ - m_refCount--; - if(m_refCount == 0) - { - delete KArtsDispatcher::artsDispatcher; - artsDispatcher = 0; - - delete KArtsDispatcher::artsQIOManager; - artsQIOManager = 0; - } -} diff --git a/arts/kde/kartsdispatcher.cpp b/arts/kde/kartsdispatcher.cpp new file mode 100644 index 000000000..fa41502f8 --- /dev/null +++ b/arts/kde/kartsdispatcher.cpp @@ -0,0 +1,60 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include +#include + +#include + +#include "kartsdispatcher.moc" + +int KArtsDispatcher::m_refCount = 0; +Arts::Dispatcher *KArtsDispatcher::artsDispatcher = 0; +Arts::QIOManager *KArtsDispatcher::artsQIOManager = 0; + +KArtsDispatcher::KArtsDispatcher(TQObject *parent, const char *name) + : TQObject(parent, name) +{ + m_refCount++; + if(artsDispatcher == 0) + { + if (!Arts::Dispatcher::the()) // only if no Arts::Dispatcher is created yet + { + artsQIOManager = new Arts::QIOManager(); + artsDispatcher = new Arts::Dispatcher(artsQIOManager); + } + else + kdWarning(400) << "An Arts::Dispatcher() instance exists already while trying to instantiate KArtsDispatcher!" << endl; + } +} + +KArtsDispatcher::~KArtsDispatcher() +{ + m_refCount--; + if(m_refCount == 0) + { + delete KArtsDispatcher::artsDispatcher; + artsDispatcher = 0; + + delete KArtsDispatcher::artsQIOManager; + artsQIOManager = 0; + } +} diff --git a/arts/kde/kaudioconverter.cc b/arts/kde/kaudioconverter.cc deleted file mode 100644 index 1eb8c20e5..000000000 --- a/arts/kde/kaudioconverter.cc +++ /dev/null @@ -1,198 +0,0 @@ - /* - - Copyright (C) 2002 Nikolas Zimmermann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - */ - -#include "config.h" -#include "artskde.h" -#include "connect.h" -#include "flowsystem.h" -#include "audiosubsys.h" -#include "dynamicrequest.h" -#include "kdatarequest_impl.h" -#include "kioinputstream_impl.h" -#include "kaudioconverter.moc" - -#include - -#include -#include - -#include -#include -#include -#include - -using namespace std; - -KAudioConverter::KAudioConverter() -{ - m_incoming = 0; - m_started = false; -} - -KAudioConverter::~KAudioConverter() -{ - delete m_incoming; -} - -bool KAudioConverter::setup(int samplingRate) -{ - string backupAudioIO = Arts::AudioSubSystem::the()->audioIO(); - int backupSamplingRate = Arts::AudioSubSystem::the()->samplingRate(); - - Arts::AudioSubSystem::the()->audioIO("null"); - Arts::AudioSubSystem::the()->samplingRate(samplingRate); - - if(!Arts::AudioSubSystem::the()->open()) - { - Arts::AudioSubSystem::the()->audioIO(backupAudioIO); - Arts::AudioSubSystem::the()->samplingRate(backupSamplingRate); - - return false; - } - - return true; -} - -void KAudioConverter::slotMimeType(const TQString &mimeType) -{ - m_mimeType = mimeType; - kapp->exit_loop(); -} - -void KAudioConverter::requestPlayObject(const KURL &url) -{ - string queryInterface = "Arts::PlayObject"; - - Arts::TDEIOInputStream inputStream; - - if(!url.isLocalFile()) - { - Arts::TDEIOInputStream_impl *inputStreamImpl = new Arts::TDEIOInputStream_impl(); - inputStream = Arts::TDEIOInputStream::_from_base(inputStreamImpl); - - TQObject::connect(inputStreamImpl, TQT_SIGNAL(mimeTypeFound(const TQString &)), TQT_SLOT(slotMimeType(const TQString &))); - - inputStream.openURL(url.url().latin1()); - inputStream.streamStart(); - - // ugly hacks.. :/ - kapp->enter_loop(); - - queryInterface = "Arts::StreamPlayObject"; - } - else - { - KMimeType::Ptr mimetype = KMimeType::findByURL(url); - m_mimeType = mimetype->name(); - } - - Arts::TraderQuery query; - query.supports("Interface", queryInterface); - query.supports("MimeType", string(m_mimeType.latin1())); - - string objectType; - - vector *offers = query.query(); - if(!offers->empty()) - objectType = offers->front().interfaceName(); // first offer - - delete offers; - - if(objectType.empty()) - { - m_incoming = 0; - return; - } - - if(!url.isLocalFile()) - { - Arts::StreamPlayObject result = Arts::SubClass(objectType); - result.streamMedia(inputStream); - result._node()->start(); - - m_incoming = new KPlayObject(result, true); - } - else - { - Arts::PlayObject result = Arts::SubClass(objectType); - - if(result.loadMedia(string(TQFile::encodeName(url.path())))) - { - result._node()->start(); - m_incoming = new KPlayObject(result, false); - } - else - m_incoming = 0; - } -} - -void KAudioConverter::start() -{ - if(m_started || !m_incoming) - return; - - m_started = true; - - emit rawStreamStart(); - - m_incoming->play(); - - Arts::KDataRequest_impl *requestImpl = new Arts::KDataRequest_impl(); - m_request = Arts::KDataRequest::_from_base(requestImpl); - - Arts::connect(m_incoming->object(), "left", m_request, "left"); - Arts::connect(m_incoming->object(), "right", m_request, "right"); - - TQObject::connect(requestImpl, TQT_SIGNAL(newBlockSize(long)), TQT_SIGNAL(newBlockSize(long))); - TQObject::connect(requestImpl, TQT_SIGNAL(newBlockPointer(long)), TQT_SIGNAL(newBlockPointer(long))); - TQObject::connect(requestImpl, TQT_SIGNAL(newData()), TQT_SIGNAL(newData())); - - // Special mpeglib case - // TODO: needed at all?? - usleep(100000); - if(m_incoming->object()._base()->_isCompatibleWith("DecoderBaseObject")) - if(!Arts::DynamicRequest(m_incoming->object()).method("_set_blocking").param(true).invoke()) - cerr << "mpeglib, and blocking attribute can't be changed?" << endl; - - m_request.start(); - - // TODO: Maybe do this async, using TQTimer::singleShot - // But jowenn i think jowenn is right -> this would - // lead to problems in slotNewData() when accessing the data - // (could already be overwritten...) - while(m_incoming->state() != Arts::posIdle) - m_request.goOn(); - - stop(); -} - -void KAudioConverter::stop() -{ - if(!m_started || !m_incoming) - return; - - m_incoming->halt(); - m_request.streamEnd(); - - m_started = false; - - emit rawStreamFinished(); -} diff --git a/arts/kde/kaudioconverter.cpp b/arts/kde/kaudioconverter.cpp new file mode 100644 index 000000000..1eb8c20e5 --- /dev/null +++ b/arts/kde/kaudioconverter.cpp @@ -0,0 +1,198 @@ + /* + + Copyright (C) 2002 Nikolas Zimmermann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "config.h" +#include "artskde.h" +#include "connect.h" +#include "flowsystem.h" +#include "audiosubsys.h" +#include "dynamicrequest.h" +#include "kdatarequest_impl.h" +#include "kioinputstream_impl.h" +#include "kaudioconverter.moc" + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace std; + +KAudioConverter::KAudioConverter() +{ + m_incoming = 0; + m_started = false; +} + +KAudioConverter::~KAudioConverter() +{ + delete m_incoming; +} + +bool KAudioConverter::setup(int samplingRate) +{ + string backupAudioIO = Arts::AudioSubSystem::the()->audioIO(); + int backupSamplingRate = Arts::AudioSubSystem::the()->samplingRate(); + + Arts::AudioSubSystem::the()->audioIO("null"); + Arts::AudioSubSystem::the()->samplingRate(samplingRate); + + if(!Arts::AudioSubSystem::the()->open()) + { + Arts::AudioSubSystem::the()->audioIO(backupAudioIO); + Arts::AudioSubSystem::the()->samplingRate(backupSamplingRate); + + return false; + } + + return true; +} + +void KAudioConverter::slotMimeType(const TQString &mimeType) +{ + m_mimeType = mimeType; + kapp->exit_loop(); +} + +void KAudioConverter::requestPlayObject(const KURL &url) +{ + string queryInterface = "Arts::PlayObject"; + + Arts::TDEIOInputStream inputStream; + + if(!url.isLocalFile()) + { + Arts::TDEIOInputStream_impl *inputStreamImpl = new Arts::TDEIOInputStream_impl(); + inputStream = Arts::TDEIOInputStream::_from_base(inputStreamImpl); + + TQObject::connect(inputStreamImpl, TQT_SIGNAL(mimeTypeFound(const TQString &)), TQT_SLOT(slotMimeType(const TQString &))); + + inputStream.openURL(url.url().latin1()); + inputStream.streamStart(); + + // ugly hacks.. :/ + kapp->enter_loop(); + + queryInterface = "Arts::StreamPlayObject"; + } + else + { + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + m_mimeType = mimetype->name(); + } + + Arts::TraderQuery query; + query.supports("Interface", queryInterface); + query.supports("MimeType", string(m_mimeType.latin1())); + + string objectType; + + vector *offers = query.query(); + if(!offers->empty()) + objectType = offers->front().interfaceName(); // first offer + + delete offers; + + if(objectType.empty()) + { + m_incoming = 0; + return; + } + + if(!url.isLocalFile()) + { + Arts::StreamPlayObject result = Arts::SubClass(objectType); + result.streamMedia(inputStream); + result._node()->start(); + + m_incoming = new KPlayObject(result, true); + } + else + { + Arts::PlayObject result = Arts::SubClass(objectType); + + if(result.loadMedia(string(TQFile::encodeName(url.path())))) + { + result._node()->start(); + m_incoming = new KPlayObject(result, false); + } + else + m_incoming = 0; + } +} + +void KAudioConverter::start() +{ + if(m_started || !m_incoming) + return; + + m_started = true; + + emit rawStreamStart(); + + m_incoming->play(); + + Arts::KDataRequest_impl *requestImpl = new Arts::KDataRequest_impl(); + m_request = Arts::KDataRequest::_from_base(requestImpl); + + Arts::connect(m_incoming->object(), "left", m_request, "left"); + Arts::connect(m_incoming->object(), "right", m_request, "right"); + + TQObject::connect(requestImpl, TQT_SIGNAL(newBlockSize(long)), TQT_SIGNAL(newBlockSize(long))); + TQObject::connect(requestImpl, TQT_SIGNAL(newBlockPointer(long)), TQT_SIGNAL(newBlockPointer(long))); + TQObject::connect(requestImpl, TQT_SIGNAL(newData()), TQT_SIGNAL(newData())); + + // Special mpeglib case + // TODO: needed at all?? + usleep(100000); + if(m_incoming->object()._base()->_isCompatibleWith("DecoderBaseObject")) + if(!Arts::DynamicRequest(m_incoming->object()).method("_set_blocking").param(true).invoke()) + cerr << "mpeglib, and blocking attribute can't be changed?" << endl; + + m_request.start(); + + // TODO: Maybe do this async, using TQTimer::singleShot + // But jowenn i think jowenn is right -> this would + // lead to problems in slotNewData() when accessing the data + // (could already be overwritten...) + while(m_incoming->state() != Arts::posIdle) + m_request.goOn(); + + stop(); +} + +void KAudioConverter::stop() +{ + if(!m_started || !m_incoming) + return; + + m_incoming->halt(); + m_request.streamEnd(); + + m_started = false; + + emit rawStreamFinished(); +} diff --git a/arts/kde/kconverttest.cc b/arts/kde/kconverttest.cc deleted file mode 100644 index 647c2f320..000000000 --- a/arts/kde/kconverttest.cc +++ /dev/null @@ -1,96 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "kconverttest.moc" - -using namespace std; -using namespace Arts; - -static TDECmdLineOptions options[] = -{ - { "+[URL]", I18N_NOOP("URL to open"), 0 }, - TDECmdLineLastOption -}; - -KConvertTest::KConvertTest() -{ -} - -void KConvertTest::slotRawStreamStart() -{ -// cout << "[START]\n\n" << endl; -} - -void KConvertTest::slotNewBlockSize(long blockSize) -{ - m_blockSize = blockSize; -} - -void KConvertTest::slotNewBlockPointer(long blockPointer) -{ - m_blockPointer = blockPointer; -} - -void KConvertTest::slotNewData() -{ - fwrite((void *) m_blockPointer, 1, m_blockSize, stdout); -} - -void KConvertTest::slotRawStreamFinished() -{ -// cout << "\n\n[END]" << endl; -} - -int main(int argc, char **argv) -{ - TDEAboutData aboutData("kconverttest", I18N_NOOP("KConvertTest"), I18N_NOOP("0.1"), "", TDEAboutData::License_GPL, ""); - - TDECmdLineArgs::init(argc, argv, &aboutData); - TDECmdLineArgs::addCmdLineOptions(options); - TDEApplication app; - - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - - KURL url; - - if(args->count()) - url = args->arg(0); - else - exit(1); - - args->clear(); - - KConvertTest *get = new KConvertTest(); - - KArtsDispatcher dispatcher; - KAudioConverter converter; - - // FIXME: crashes - // converter.setup(44100); - converter.requestPlayObject(url); - - TQObject::connect(&converter, TQT_SIGNAL(rawStreamStart()), get, TQT_SLOT(slotRawStreamStart())); - - TQObject::connect(&converter, TQT_SIGNAL(newBlockSize(long)), get, TQT_SLOT(slotNewBlockSize(long))); - TQObject::connect(&converter, TQT_SIGNAL(newBlockPointer(long)), get, TQT_SLOT(slotNewBlockPointer(long))); - TQObject::connect(&converter, TQT_SIGNAL(newData()), get, TQT_SLOT(slotNewData())); - - TQObject::connect(&converter, TQT_SIGNAL(rawStreamFinished()), get, TQT_SLOT(slotRawStreamFinished())); - - converter.start(); - - app.exec(); -} - diff --git a/arts/kde/kconverttest.cpp b/arts/kde/kconverttest.cpp new file mode 100644 index 000000000..647c2f320 --- /dev/null +++ b/arts/kde/kconverttest.cpp @@ -0,0 +1,96 @@ +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "kconverttest.moc" + +using namespace std; +using namespace Arts; + +static TDECmdLineOptions options[] = +{ + { "+[URL]", I18N_NOOP("URL to open"), 0 }, + TDECmdLineLastOption +}; + +KConvertTest::KConvertTest() +{ +} + +void KConvertTest::slotRawStreamStart() +{ +// cout << "[START]\n\n" << endl; +} + +void KConvertTest::slotNewBlockSize(long blockSize) +{ + m_blockSize = blockSize; +} + +void KConvertTest::slotNewBlockPointer(long blockPointer) +{ + m_blockPointer = blockPointer; +} + +void KConvertTest::slotNewData() +{ + fwrite((void *) m_blockPointer, 1, m_blockSize, stdout); +} + +void KConvertTest::slotRawStreamFinished() +{ +// cout << "\n\n[END]" << endl; +} + +int main(int argc, char **argv) +{ + TDEAboutData aboutData("kconverttest", I18N_NOOP("KConvertTest"), I18N_NOOP("0.1"), "", TDEAboutData::License_GPL, ""); + + TDECmdLineArgs::init(argc, argv, &aboutData); + TDECmdLineArgs::addCmdLineOptions(options); + TDEApplication app; + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + KURL url; + + if(args->count()) + url = args->arg(0); + else + exit(1); + + args->clear(); + + KConvertTest *get = new KConvertTest(); + + KArtsDispatcher dispatcher; + KAudioConverter converter; + + // FIXME: crashes + // converter.setup(44100); + converter.requestPlayObject(url); + + TQObject::connect(&converter, TQT_SIGNAL(rawStreamStart()), get, TQT_SLOT(slotRawStreamStart())); + + TQObject::connect(&converter, TQT_SIGNAL(newBlockSize(long)), get, TQT_SLOT(slotNewBlockSize(long))); + TQObject::connect(&converter, TQT_SIGNAL(newBlockPointer(long)), get, TQT_SLOT(slotNewBlockPointer(long))); + TQObject::connect(&converter, TQT_SIGNAL(newData()), get, TQT_SLOT(slotNewData())); + + TQObject::connect(&converter, TQT_SIGNAL(rawStreamFinished()), get, TQT_SLOT(slotRawStreamFinished())); + + converter.start(); + + app.exec(); +} + diff --git a/arts/kde/kiotest.cc b/arts/kde/kiotest.cc deleted file mode 100644 index ed9a3fadf..000000000 --- a/arts/kde/kiotest.cc +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "qiomanager.h" -#include "artskde.h" - -using namespace std; -using namespace Arts; - - -static TDECmdLineOptions options[] = -{ - { "+[URL]", I18N_NOOP("URL to open"), 0 }, - TDECmdLineLastOption -}; - -int main(int argc, char **argv) -{ - TDEAboutData aboutData( "kiotest", I18N_NOOP("KIOTest"), I18N_NOOP("0.1"), "", TDEAboutData::License_GPL, ""); - - TDECmdLineArgs::init(argc,argv,&aboutData); - TDECmdLineArgs::addCmdLineOptions(options); - TDEApplication app; - QIOManager qiomanager; - Dispatcher dispatcher(&qiomanager); - TDEIOInputStream stream; - StdoutWriter writer; - - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - - if(args->count()) - { - if(!stream.openURL(args->arg(0))) - { - printf("can't open url"); - exit(1); - } - } - else - exit(1); - - args->clear(); - - connect(stream, writer); - - writer.start(); - stream.start(); - - app.exec(); -} diff --git a/arts/kde/kiotest.cpp b/arts/kde/kiotest.cpp new file mode 100644 index 000000000..ed9a3fadf --- /dev/null +++ b/arts/kde/kiotest.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include "qiomanager.h" +#include "artskde.h" + +using namespace std; +using namespace Arts; + + +static TDECmdLineOptions options[] = +{ + { "+[URL]", I18N_NOOP("URL to open"), 0 }, + TDECmdLineLastOption +}; + +int main(int argc, char **argv) +{ + TDEAboutData aboutData( "kiotest", I18N_NOOP("KIOTest"), I18N_NOOP("0.1"), "", TDEAboutData::License_GPL, ""); + + TDECmdLineArgs::init(argc,argv,&aboutData); + TDECmdLineArgs::addCmdLineOptions(options); + TDEApplication app; + QIOManager qiomanager; + Dispatcher dispatcher(&qiomanager); + TDEIOInputStream stream; + StdoutWriter writer; + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + if(args->count()) + { + if(!stream.openURL(args->arg(0))) + { + printf("can't open url"); + exit(1); + } + } + else + exit(1); + + args->clear(); + + connect(stream, writer); + + writer.start(); + stream.start(); + + app.exec(); +} diff --git a/arts/kde/kiotestslow.cc b/arts/kde/kiotestslow.cc deleted file mode 100644 index 93bfac388..000000000 --- a/arts/kde/kiotestslow.cc +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "qiomanager.h" -#include "artskde.h" - -using namespace std; -using namespace Arts; - -namespace Arts { -/* simulate slow receiver */ -class KIOTestSlow_impl : public KIOTestSlow_skel, - public TimeNotify, - public StdSynthModule -{ - int pos; - list< DataPacket* > q; - InputStream _inputStream; - -public: - InputStream inputStream() { return _inputStream; } - void inputStream(InputStream i) { _inputStream = i; } - - KIOTestSlow_impl() - { - Dispatcher::the()->ioManager()->addTimer(10, this); - pos = 0; - } - void notifyTime() - { - if(!_inputStream.isNull() && _inputStream.eof()) - { - printf("\n[*EOF*] remaining = %d packets\n"); - _inputStream = InputStream::null(); - return; - } - - int TODO = 100; - do { - if(q.empty()) - return; - - DataPacket *p = q.front(); - char ch = p->contents[pos++]; - if(p->size == pos) - { - p->processed(); - q.pop_front(); - pos = 0; - } - - if(ch == '\n') - { - long size = 0; - list*>::iterator i; - for(i = q.begin(); i != q.end(); i++) - size += (*i)->size; - printf("\n[queued %8ld] ",size-pos); - } - else - putchar(ch); - - } while(TODO-- > 0); - } - void process_data(DataPacket *p) - { - if(p->size == 0) - p->processed(); - else - q.push_back(p); - } -}; -REGISTER_IMPLEMENTATION(KIOTestSlow_impl); -}; - -static TDECmdLineOptions options[] = -{ - { "+[URL]", I18N_NOOP("URL to open"), 0 }, - TDECmdLineLastOption -}; - -#undef USE_FILEINPUTSTREAM - -int main(int argc, char **argv) -{ - TDEAboutData aboutData( "kiotestslow", I18N_NOOP("KIOTest"), I18N_NOOP("0.1"), "", TDEAboutData::License_GPL, ""); - - TDECmdLineArgs::init(argc,argv,&aboutData); - TDECmdLineArgs::addCmdLineOptions(options); - TDEApplication app; - QIOManager qiomanager; - Dispatcher dispatcher(&qiomanager); -#ifndef USE_FILEINPUTSTREAM - TDEIOInputStream stream; -#else - FileInputStream stream; -#endif - KIOTestSlow writer; - - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - - if(args->count()) - { -#ifdef USE_FILEINPUTSTREAM - if(!stream.open(args->arg(0))) -#else - if(!stream.openURL(args->arg(0))) -#endif - { - printf("can't open url"); - exit(1); - } - } - else - exit(1); - - args->clear(); - - writer.inputStream(stream); - connect(stream, writer); - - writer.start(); - stream.start(); - - app.exec(); -} diff --git a/arts/kde/kiotestslow.cpp b/arts/kde/kiotestslow.cpp new file mode 100644 index 000000000..93bfac388 --- /dev/null +++ b/arts/kde/kiotestslow.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "qiomanager.h" +#include "artskde.h" + +using namespace std; +using namespace Arts; + +namespace Arts { +/* simulate slow receiver */ +class KIOTestSlow_impl : public KIOTestSlow_skel, + public TimeNotify, + public StdSynthModule +{ + int pos; + list< DataPacket* > q; + InputStream _inputStream; + +public: + InputStream inputStream() { return _inputStream; } + void inputStream(InputStream i) { _inputStream = i; } + + KIOTestSlow_impl() + { + Dispatcher::the()->ioManager()->addTimer(10, this); + pos = 0; + } + void notifyTime() + { + if(!_inputStream.isNull() && _inputStream.eof()) + { + printf("\n[*EOF*] remaining = %d packets\n"); + _inputStream = InputStream::null(); + return; + } + + int TODO = 100; + do { + if(q.empty()) + return; + + DataPacket *p = q.front(); + char ch = p->contents[pos++]; + if(p->size == pos) + { + p->processed(); + q.pop_front(); + pos = 0; + } + + if(ch == '\n') + { + long size = 0; + list*>::iterator i; + for(i = q.begin(); i != q.end(); i++) + size += (*i)->size; + printf("\n[queued %8ld] ",size-pos); + } + else + putchar(ch); + + } while(TODO-- > 0); + } + void process_data(DataPacket *p) + { + if(p->size == 0) + p->processed(); + else + q.push_back(p); + } +}; +REGISTER_IMPLEMENTATION(KIOTestSlow_impl); +}; + +static TDECmdLineOptions options[] = +{ + { "+[URL]", I18N_NOOP("URL to open"), 0 }, + TDECmdLineLastOption +}; + +#undef USE_FILEINPUTSTREAM + +int main(int argc, char **argv) +{ + TDEAboutData aboutData( "kiotestslow", I18N_NOOP("KIOTest"), I18N_NOOP("0.1"), "", TDEAboutData::License_GPL, ""); + + TDECmdLineArgs::init(argc,argv,&aboutData); + TDECmdLineArgs::addCmdLineOptions(options); + TDEApplication app; + QIOManager qiomanager; + Dispatcher dispatcher(&qiomanager); +#ifndef USE_FILEINPUTSTREAM + TDEIOInputStream stream; +#else + FileInputStream stream; +#endif + KIOTestSlow writer; + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + if(args->count()) + { +#ifdef USE_FILEINPUTSTREAM + if(!stream.open(args->arg(0))) +#else + if(!stream.openURL(args->arg(0))) +#endif + { + printf("can't open url"); + exit(1); + } + } + else + exit(1); + + args->clear(); + + writer.inputStream(stream); + connect(stream, writer); + + writer.start(); + stream.start(); + + app.exec(); +} diff --git a/arts/kde/kplayobject.cc b/arts/kde/kplayobject.cc deleted file mode 100644 index f11c0eb8f..000000000 --- a/arts/kde/kplayobject.cc +++ /dev/null @@ -1,301 +0,0 @@ - /* - - Copyright (C) 2001 Nikolas Zimmermann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - */ - -#include "kplayobject.h" -#include "kplayobject.moc" -#include "kplayobjectcreator.h" -#include - -KPlayObject::KPlayObject() : TQObject() -{ - m_playObject = Arts::PlayObject::null(); - m_isStream = false; -} - -KPlayObject::KPlayObject(Arts::PlayObject playobject, bool isStream) : TQObject() -{ - m_playObject = playobject; - m_isStream = isStream; -} - -KPlayObject::~KPlayObject() -{ -} - -void KPlayObject::play() -{ - object().play(); -} - -void KPlayObject::seek(Arts::poTime newTime) -{ - if(!m_isStream) - object().seek(newTime); - else - kdDebug( 400 ) << "Seeking in a Stream? huh?" << endl; -} - -void KPlayObject::pause() -{ - object().pause(); -} - -void KPlayObject::halt() -{ - object().halt(); -} - -TQString KPlayObject::description() -{ - return TQString::fromLatin1(object().description().c_str()); -} - -Arts::poTime KPlayObject::currentTime() -{ - return object().currentTime(); -} - -Arts::poTime KPlayObject::overallTime() -{ - return object().overallTime(); -} - -Arts::poCapabilities KPlayObject::capabilities() -{ - return object().capabilities(); -} - -TQString KPlayObject::mediaName() -{ - return TQString::fromLatin1(object().mediaName().c_str()); -} - -Arts::poState KPlayObject::state() -{ - return object().state(); -} - -Arts::PlayObject KPlayObject::object() -{ - return m_playObject; -} - -bool KPlayObject::isNull() -{ - if( !this ) - return true; - return object().isNull(); -} - -void KPlayObject::setObject(Arts::PlayObject playObject) -{ - m_playObject = playObject; -} - -bool KPlayObject::stream() -{ - return m_isStream; -} - -struct KDE::PlayObject::PrivateData -{ - PrivateData() : creator( 0 ), - isProxy( false ), - internalState( Arts::posIdle ) {} - ~PrivateData() { - delete creator; - } - Arts::SoundServerV2 server; - KDE::PlayObjectCreator* creator; - bool createBUS; - bool isProxy; - Arts::poState internalState; - KURL url; -}; - -KDE::PlayObject::PlayObject() : TQObject() -{ - m_playObject = Arts::PlayObject::null(); - m_isStream = false; - d = new PrivateData; -} - -KDE::PlayObject::PlayObject(Arts::PlayObject playobject, bool isStream) : TQObject() -{ - m_playObject = playobject; - m_isStream = isStream; - d = new PrivateData; - - //very funny! you can't connect to signals before creating - //the object - so nobody will ever receive this signal (mkretz) - // - //emit playObjectCreated(); -} - -KDE::PlayObject::PlayObject( Arts::SoundServerV2 server, const KURL& url, bool isStream, bool createBUS ) : TQObject() -{ - kdDebug( 400 ) << "KDE::PlayObject: created as proxy for URL " << url.url()<< endl; - - m_playObject = Arts::PlayObject::null(); - m_isStream = isStream; - d = new PrivateData; - d->server = server; - d->url = url; - d->createBUS = createBUS; - d->isProxy = true; -} - -KDE::PlayObject::~PlayObject() -{ - kdDebug( 400 ) << "KDE::PlayObject: destroyed" << endl; - - delete d; -} - -void KDE::PlayObject::play() -{ - kdDebug( 400 ) << "KDE::PlayObject::play()" << endl; - - if ( object().isNull() ) { - if ( m_isStream ) { - if ( d->creator ) - delete d->creator; - d->creator = new KDE::PlayObjectCreator( d->server ); - d->creator->create( d->url, d->createBUS, this, TQT_SLOT( attachPlayObject( Arts::PlayObject ) ) ); - kdDebug( 400 ) << "KDE::PlayObject::play(): creator called" << endl; - d->internalState = Arts::posPlaying; - } - return; - } - object().play(); -} - -void KDE::PlayObject::attachPlayObject( Arts::PlayObject playObject ) -{ - kdDebug( 400 ) << "KDE::PlayObject::attachPlayObject()" << endl; - - m_playObject = playObject; - emit playObjectCreated(); - if ( object().isNull() ) - return; - switch ( d->internalState ) { - case Arts::posIdle: - object().halt(); - break; - case Arts::posPaused: - object().pause(); - break; - case Arts::posPlaying: - object().play (); - break; - } -} - -void KDE::PlayObject::seek(Arts::poTime newTime) -{ - if ( object().isNull() ) - return; - if(!m_isStream) - object().seek(newTime); - else - kdDebug( 400 ) << "Seeking in a Stream? huh?" << endl; -} - -void KDE::PlayObject::pause() -{ - if ( !object().isNull() ) - object().pause(); - d->internalState = Arts::posPaused; -} - -void KDE::PlayObject::halt() -{ - kdDebug( 400 ) << "KDE::PlayObject::halt()" << endl; - if ( !object().isNull() ) - object().halt(); - else if ( d->creator ) { - delete d->creator; - d->creator = 0; - kdDebug( 400 ) << "KDE::PlayObject::halt(): creator destroyed" << endl; - } - d->internalState = Arts::posIdle; -} - -TQString KDE::PlayObject::description() -{ - if ( object().isNull() ) - return TQString(); - return TQString::fromLatin1(object().description().c_str()); -} - -Arts::poTime KDE::PlayObject::currentTime() -{ - if ( object().isNull() ) - return Arts::poTime( 0, 0, -1, "" ); - return object().currentTime(); -} - -Arts::poTime KDE::PlayObject::overallTime() -{ - if ( object().isNull() ) - return Arts::poTime( 0, 0, -1, "" ); - return object().overallTime(); -} - -Arts::poCapabilities KDE::PlayObject::capabilities() -{ - if ( object().isNull() ) - return static_cast( 0 ); - return object().capabilities(); -} - -TQString KDE::PlayObject::mediaName() -{ - if ( object().isNull() ) - return TQString(); - return TQString::fromLatin1(object().mediaName().c_str()); -} - -Arts::poState KDE::PlayObject::state() -{ - if ( object().isNull() ) - return d->internalState; - return object().state(); -} - -Arts::PlayObject KDE::PlayObject::object() -{ - return m_playObject; -} - -bool KDE::PlayObject::isNull() -{ - if ( !this ) - return true; - if ( d->isProxy ) - return false; - return object().isNull(); -} - -bool KDE::PlayObject::stream() -{ - return m_isStream; -} diff --git a/arts/kde/kplayobject.cpp b/arts/kde/kplayobject.cpp new file mode 100644 index 000000000..f11c0eb8f --- /dev/null +++ b/arts/kde/kplayobject.cpp @@ -0,0 +1,301 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "kplayobject.h" +#include "kplayobject.moc" +#include "kplayobjectcreator.h" +#include + +KPlayObject::KPlayObject() : TQObject() +{ + m_playObject = Arts::PlayObject::null(); + m_isStream = false; +} + +KPlayObject::KPlayObject(Arts::PlayObject playobject, bool isStream) : TQObject() +{ + m_playObject = playobject; + m_isStream = isStream; +} + +KPlayObject::~KPlayObject() +{ +} + +void KPlayObject::play() +{ + object().play(); +} + +void KPlayObject::seek(Arts::poTime newTime) +{ + if(!m_isStream) + object().seek(newTime); + else + kdDebug( 400 ) << "Seeking in a Stream? huh?" << endl; +} + +void KPlayObject::pause() +{ + object().pause(); +} + +void KPlayObject::halt() +{ + object().halt(); +} + +TQString KPlayObject::description() +{ + return TQString::fromLatin1(object().description().c_str()); +} + +Arts::poTime KPlayObject::currentTime() +{ + return object().currentTime(); +} + +Arts::poTime KPlayObject::overallTime() +{ + return object().overallTime(); +} + +Arts::poCapabilities KPlayObject::capabilities() +{ + return object().capabilities(); +} + +TQString KPlayObject::mediaName() +{ + return TQString::fromLatin1(object().mediaName().c_str()); +} + +Arts::poState KPlayObject::state() +{ + return object().state(); +} + +Arts::PlayObject KPlayObject::object() +{ + return m_playObject; +} + +bool KPlayObject::isNull() +{ + if( !this ) + return true; + return object().isNull(); +} + +void KPlayObject::setObject(Arts::PlayObject playObject) +{ + m_playObject = playObject; +} + +bool KPlayObject::stream() +{ + return m_isStream; +} + +struct KDE::PlayObject::PrivateData +{ + PrivateData() : creator( 0 ), + isProxy( false ), + internalState( Arts::posIdle ) {} + ~PrivateData() { + delete creator; + } + Arts::SoundServerV2 server; + KDE::PlayObjectCreator* creator; + bool createBUS; + bool isProxy; + Arts::poState internalState; + KURL url; +}; + +KDE::PlayObject::PlayObject() : TQObject() +{ + m_playObject = Arts::PlayObject::null(); + m_isStream = false; + d = new PrivateData; +} + +KDE::PlayObject::PlayObject(Arts::PlayObject playobject, bool isStream) : TQObject() +{ + m_playObject = playobject; + m_isStream = isStream; + d = new PrivateData; + + //very funny! you can't connect to signals before creating + //the object - so nobody will ever receive this signal (mkretz) + // + //emit playObjectCreated(); +} + +KDE::PlayObject::PlayObject( Arts::SoundServerV2 server, const KURL& url, bool isStream, bool createBUS ) : TQObject() +{ + kdDebug( 400 ) << "KDE::PlayObject: created as proxy for URL " << url.url()<< endl; + + m_playObject = Arts::PlayObject::null(); + m_isStream = isStream; + d = new PrivateData; + d->server = server; + d->url = url; + d->createBUS = createBUS; + d->isProxy = true; +} + +KDE::PlayObject::~PlayObject() +{ + kdDebug( 400 ) << "KDE::PlayObject: destroyed" << endl; + + delete d; +} + +void KDE::PlayObject::play() +{ + kdDebug( 400 ) << "KDE::PlayObject::play()" << endl; + + if ( object().isNull() ) { + if ( m_isStream ) { + if ( d->creator ) + delete d->creator; + d->creator = new KDE::PlayObjectCreator( d->server ); + d->creator->create( d->url, d->createBUS, this, TQT_SLOT( attachPlayObject( Arts::PlayObject ) ) ); + kdDebug( 400 ) << "KDE::PlayObject::play(): creator called" << endl; + d->internalState = Arts::posPlaying; + } + return; + } + object().play(); +} + +void KDE::PlayObject::attachPlayObject( Arts::PlayObject playObject ) +{ + kdDebug( 400 ) << "KDE::PlayObject::attachPlayObject()" << endl; + + m_playObject = playObject; + emit playObjectCreated(); + if ( object().isNull() ) + return; + switch ( d->internalState ) { + case Arts::posIdle: + object().halt(); + break; + case Arts::posPaused: + object().pause(); + break; + case Arts::posPlaying: + object().play (); + break; + } +} + +void KDE::PlayObject::seek(Arts::poTime newTime) +{ + if ( object().isNull() ) + return; + if(!m_isStream) + object().seek(newTime); + else + kdDebug( 400 ) << "Seeking in a Stream? huh?" << endl; +} + +void KDE::PlayObject::pause() +{ + if ( !object().isNull() ) + object().pause(); + d->internalState = Arts::posPaused; +} + +void KDE::PlayObject::halt() +{ + kdDebug( 400 ) << "KDE::PlayObject::halt()" << endl; + if ( !object().isNull() ) + object().halt(); + else if ( d->creator ) { + delete d->creator; + d->creator = 0; + kdDebug( 400 ) << "KDE::PlayObject::halt(): creator destroyed" << endl; + } + d->internalState = Arts::posIdle; +} + +TQString KDE::PlayObject::description() +{ + if ( object().isNull() ) + return TQString(); + return TQString::fromLatin1(object().description().c_str()); +} + +Arts::poTime KDE::PlayObject::currentTime() +{ + if ( object().isNull() ) + return Arts::poTime( 0, 0, -1, "" ); + return object().currentTime(); +} + +Arts::poTime KDE::PlayObject::overallTime() +{ + if ( object().isNull() ) + return Arts::poTime( 0, 0, -1, "" ); + return object().overallTime(); +} + +Arts::poCapabilities KDE::PlayObject::capabilities() +{ + if ( object().isNull() ) + return static_cast( 0 ); + return object().capabilities(); +} + +TQString KDE::PlayObject::mediaName() +{ + if ( object().isNull() ) + return TQString(); + return TQString::fromLatin1(object().mediaName().c_str()); +} + +Arts::poState KDE::PlayObject::state() +{ + if ( object().isNull() ) + return d->internalState; + return object().state(); +} + +Arts::PlayObject KDE::PlayObject::object() +{ + return m_playObject; +} + +bool KDE::PlayObject::isNull() +{ + if ( !this ) + return true; + if ( d->isProxy ) + return false; + return object().isNull(); +} + +bool KDE::PlayObject::stream() +{ + return m_isStream; +} diff --git a/arts/kde/kplayobjectcreator.cc b/arts/kde/kplayobjectcreator.cc deleted file mode 100644 index 039c8a3bc..000000000 --- a/arts/kde/kplayobjectcreator.cc +++ /dev/null @@ -1,104 +0,0 @@ - /* - - Copyright (C) 2002 Matthias Welwarsky - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - */ - -#include -#include "artskde.h" -#include "kplayobjectcreator.h" -#include "kplayobjectcreator.moc" -#include "kioinputstream_impl.h" - -#include - -#include - -KDE::PlayObjectCreator::PlayObjectCreator(Arts::SoundServerV2 server) -{ - m_server = server; -} - -KDE::PlayObjectCreator::~PlayObjectCreator() -{ -} - -bool KDE::PlayObjectCreator::create(const KURL& url, bool createBUS, const TQObject* receiver, const char* slot) -{ - // no need to go any further, and I hate deep indentation - if (m_server.isNull() || url.isEmpty() ) - return false; - - connect( this, TQT_SIGNAL( playObjectCreated( Arts::PlayObject ) ), - receiver, slot ); - - // check if the URL is a local file - if (!url.isLocalFile()) - { - m_createBUS = createBUS; - - // This is the RightWay(tm) according to stw - Arts::TDEIOInputStream_impl* instream_impl = new Arts::TDEIOInputStream_impl(); - m_instream = Arts::TDEIOInputStream::_from_base(instream_impl); - - // signal will be called once the ioslave knows the mime-type of the stream - connect(instream_impl, TQT_SIGNAL(mimeTypeFound(const TQString &)), - this, TQT_SLOT(slotMimeType(const TQString &))); - - // GO! - m_instream.openURL(url.url().latin1()); - m_instream.streamStart(); - - return true; - } - kdDebug( 400 ) << "stream is local file: " << url.url() << endl; - - // usual stuff if we have a local file - KMimeType::Ptr mimetype = KMimeType::findByURL(url); - emit playObjectCreated ( - m_server.createPlayObjectForURL(std::string(TQFile::encodeName(url.path())), - std::string(mimetype->name().latin1()), - createBUS) - ); - return true; -} - -void KDE::PlayObjectCreator::slotMimeType(const TQString& mimetype) -{ - - kdDebug( 400 ) << "slotMimeType called: " << mimetype << endl; - - TQString mimetype_copy = mimetype; - - if ( mimetype_copy == "application/octet-stream" ) - mimetype_copy = TQString("audio/x-mp3"); - - if (mimetype_copy == "application/x-zerosize") - emit playObjectCreated(Arts::PlayObject::null()); - - playObject = m_server.createPlayObjectForStream( - m_instream, - std::string( mimetype_copy.latin1() ), - m_createBUS ); - if ( playObject.isNull() ) { - m_instream.streamEnd(); - emit playObjectCreated( Arts::PlayObject::null() ); - return; - } - emit playObjectCreated( playObject ); -} diff --git a/arts/kde/kplayobjectcreator.cpp b/arts/kde/kplayobjectcreator.cpp new file mode 100644 index 000000000..039c8a3bc --- /dev/null +++ b/arts/kde/kplayobjectcreator.cpp @@ -0,0 +1,104 @@ + /* + + Copyright (C) 2002 Matthias Welwarsky + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include +#include "artskde.h" +#include "kplayobjectcreator.h" +#include "kplayobjectcreator.moc" +#include "kioinputstream_impl.h" + +#include + +#include + +KDE::PlayObjectCreator::PlayObjectCreator(Arts::SoundServerV2 server) +{ + m_server = server; +} + +KDE::PlayObjectCreator::~PlayObjectCreator() +{ +} + +bool KDE::PlayObjectCreator::create(const KURL& url, bool createBUS, const TQObject* receiver, const char* slot) +{ + // no need to go any further, and I hate deep indentation + if (m_server.isNull() || url.isEmpty() ) + return false; + + connect( this, TQT_SIGNAL( playObjectCreated( Arts::PlayObject ) ), + receiver, slot ); + + // check if the URL is a local file + if (!url.isLocalFile()) + { + m_createBUS = createBUS; + + // This is the RightWay(tm) according to stw + Arts::TDEIOInputStream_impl* instream_impl = new Arts::TDEIOInputStream_impl(); + m_instream = Arts::TDEIOInputStream::_from_base(instream_impl); + + // signal will be called once the ioslave knows the mime-type of the stream + connect(instream_impl, TQT_SIGNAL(mimeTypeFound(const TQString &)), + this, TQT_SLOT(slotMimeType(const TQString &))); + + // GO! + m_instream.openURL(url.url().latin1()); + m_instream.streamStart(); + + return true; + } + kdDebug( 400 ) << "stream is local file: " << url.url() << endl; + + // usual stuff if we have a local file + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + emit playObjectCreated ( + m_server.createPlayObjectForURL(std::string(TQFile::encodeName(url.path())), + std::string(mimetype->name().latin1()), + createBUS) + ); + return true; +} + +void KDE::PlayObjectCreator::slotMimeType(const TQString& mimetype) +{ + + kdDebug( 400 ) << "slotMimeType called: " << mimetype << endl; + + TQString mimetype_copy = mimetype; + + if ( mimetype_copy == "application/octet-stream" ) + mimetype_copy = TQString("audio/x-mp3"); + + if (mimetype_copy == "application/x-zerosize") + emit playObjectCreated(Arts::PlayObject::null()); + + playObject = m_server.createPlayObjectForStream( + m_instream, + std::string( mimetype_copy.latin1() ), + m_createBUS ); + if ( playObject.isNull() ) { + m_instream.streamEnd(); + emit playObjectCreated( Arts::PlayObject::null() ); + return; + } + emit playObjectCreated( playObject ); +} diff --git a/arts/kde/kplayobjectfactory.cc b/arts/kde/kplayobjectfactory.cc deleted file mode 100644 index 708fe516e..000000000 --- a/arts/kde/kplayobjectfactory.cc +++ /dev/null @@ -1,256 +0,0 @@ - /* - - Copyright (C) 2001 Nikolas Zimmermann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - */ - -#include -#include "kplayobject.h" -#include "artskde.h" -#include "kplayobjectfactory.h" -#include "kplayobjectfactory_p.h" -#include "kplayobjectcreator.h" -#include "kioinputstream_impl.h" -#include "kartsdispatcher.h" -#include "kartsserver.h" - -#include -#include -#include "kaudiomanagerplay.h" -#include -#include - -using namespace std; - -KPlayObjectFactory::KPlayObjectFactory(Arts::SoundServerV2 server) -{ - m_server = server; - m_allowStreaming = true; - m_stream = false; -} - -KPlayObjectFactory::KPlayObjectFactory(KArtsServer* server) -{ - m_server = server->server(); - m_allowStreaming = true; - m_stream = false; -} - -KPlayObjectFactory::~KPlayObjectFactory() -{ -} - -KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& url, bool createBUS) -{ - KMimeType::Ptr mimetype = KMimeType::findByURL(url); - return createPlayObject(url, mimetype->name(), createBUS); -} - - -KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& _url, const TQString &mimetype, bool createBUS) -{ - // WHY DOES BROKEN TDEIO_MEDIA GIVE WRONG URLS? - // I hate it - // I hate it - // It sucks - // tdeio_media please die - KURL url = TDEIO::NetAccess::mostLocalURL(_url, 0); - - if(!m_server.isNull()) - { - if(mimetype == "application/octet-stream" && m_allowStreaming) - { - Arts::TDEIOInputStream instream; - instream.openURL(url.url().latin1()); - - m_stream = true; - - // TODO: what else than hardcoding audio/x-mp3 ? - return new KPlayObject(m_server.createPlayObjectForStream(instream, string("audio/x-mp3"), createBUS), true); - } - else - return new KPlayObject(m_server.createPlayObjectForURL(string(TQFile::encodeName(url.path())), string(mimetype.latin1()), createBUS), false); - } - else - return new KPlayObject(); -} - - - -// - -KDE::PlayObjectFactory::PlayObjectFactory(Arts::SoundServerV2 server) -{ - d = new PrivateData; - d->server = server; - d->amanPlay = 0; - d->helper = 0; - d->allowStreaming = true; - d->isStream = false; -} - -KDE::PlayObjectFactory::PlayObjectFactory(KArtsServer* server) -{ - d = new PrivateData; - d->server = server->server(); - d->amanPlay = 0; - d->helper = 0; - d->allowStreaming = true; - d->isStream = false; -} - -KDE::PlayObjectFactory::~PlayObjectFactory() -{ - delete d->helper; - delete d; -} - -void KDE::PlayObjectFactory::setAudioManagerPlay( KAudioManagerPlay * amanPlay ) -{ - d->amanPlay = amanPlay; - if( ! d->helper ) - d->helper = new POFHelper; -} - -KDE::PlayObject *KDE::PlayObjectFactory::createPlayObject(const KURL& url, bool createBUS) -{ - KMimeType::Ptr mimetype = KMimeType::findByURL(url); - return createPlayObject(url, mimetype->name(), createBUS); -} - -KDE::PlayObject *KDE::PlayObjectFactory::createPlayObject(const KURL& _url, const TQString &mimetype, bool createBUS) -{ - // WHY DOES BROKEN TDEIO_MEDIA GIVE WRONG URLS? - // I hate it - // I hate it - // It sucks - // tdeio_media please die - KURL url = TDEIO::NetAccess::mostLocalURL(_url, 0); - - // return a NULL playobject if the server is NULL - if ( d->server.isNull() || url.isEmpty() ) - return new KDE::PlayObject(); - - // if the program wants to use it's own Synth_AMAN_PLAY we don't need a - // bus - if( d->amanPlay && createBUS ) - { - kdWarning( 400 ) << "KDE::PlayObjectFactory was instructed to use a Synth_AMAN_PLAY for output but the program also asked for a Synth_BUS_UPLINK" << endl; - createBUS = false; - } - - // decide if it's a local file. mpeglib provides cdda reading and decoding, so we prefer that over tdeio_audiocd - if ( url.isLocalFile() || !d->allowStreaming || (url.protocol() == "audiocd" && mimetype == "application/x-cda" && mimeTypes().contains( "application/x-cda" ) ) ) - { - // we rely on the delivered mimetype if it's a local file - d->playObj = new KDE::PlayObject( d->server.createPlayObjectForURL( string( TQFile::encodeName( url.path() ) ), string( mimetype.latin1() ), createBUS ), false ); - } - else - { - // if non-local, let the KPlayObject figure out the mimetype itself - // this invokes asynchronous creation automatically - d->playObj = new KDE::PlayObject( d->server, url, true, createBUS ); - } - - if( d->playObj->isNull() ) - { - delete d->playObj; - d->playObj = 0; - return new KDE::PlayObject(); // return a NULL playobject - } - - if( d->amanPlay ) - { - d->helper->po = d->playObj; - d->helper->ap = d->amanPlay; - if( d->playObj->object().isNull() && d->amanPlay ) - TQObject::connect( d->playObj, TQT_SIGNAL( playObjectCreated() ), d->helper, TQT_SLOT( connectAmanPlay() ) ); - else - d->helper->connectAmanPlay(); - } - - return d->playObj; -} - -TQStringList KDE::PlayObjectFactory::mimeTypes(void) -{ - KArtsDispatcher dispatcher; // we need such a thing, otherwise we crash - Arts::TraderQuery query; - vector *offers = query.query(); - - TQStringList results; - for(vector::iterator offer = offers->begin(); - offer != offers->end(); ++offer) - { - vector *mimetypes = (*offer).getProperty("MimeType"); - - for(vector::iterator mimetype = mimetypes->begin(); - mimetype != mimetypes->end(); ++mimetype) - { - TQString name = TQString(TQString::fromLocal8Bit((*mimetype).c_str())).stripWhiteSpace(); - if(KMimeType::mimeType(name)) - results.append(name); - } - - delete mimetypes; - } - delete offers; - - // clean out duplicates - results.sort(); - for(TQStringList::iterator result = results.begin(); result != results.end(); ) - { - TQStringList::iterator previous = result; - ++result; - if(result != results.end() && *result == *previous) - { - results.remove(result); - result = previous; - } - } - - return results; -} - -/* ### KDE4 -void KDE::PlayObjectFactory::connectAmanPlay() -{ - kdDebug( 400 ) << k_funcinfo << endl; - if( d->playObj->object().isNull() ) - return; - - d->amanPlay->start(); - d->playObj->object()._node()->start(); - Arts::connect( d->playObj->object(), "left" , d->amanPlay->amanPlay(), "left" ); - Arts::connect( d->playObj->object(), "right", d->amanPlay->amanPlay(), "right" ); -} -*/ - -void KDE::POFHelper::connectAmanPlay() -{ - kdDebug( 400 ) << k_funcinfo << endl; - if( po->object().isNull() ) - return; - - ap->start(); - po->object()._node()->start(); - Arts::connect( po->object(), "left" , ap->amanPlay(), "left" ); - Arts::connect( po->object(), "right", ap->amanPlay(), "right" ); -} - -#include "kplayobjectfactory_p.moc" diff --git a/arts/kde/kplayobjectfactory.cpp b/arts/kde/kplayobjectfactory.cpp new file mode 100644 index 000000000..708fe516e --- /dev/null +++ b/arts/kde/kplayobjectfactory.cpp @@ -0,0 +1,256 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include +#include "kplayobject.h" +#include "artskde.h" +#include "kplayobjectfactory.h" +#include "kplayobjectfactory_p.h" +#include "kplayobjectcreator.h" +#include "kioinputstream_impl.h" +#include "kartsdispatcher.h" +#include "kartsserver.h" + +#include +#include +#include "kaudiomanagerplay.h" +#include +#include + +using namespace std; + +KPlayObjectFactory::KPlayObjectFactory(Arts::SoundServerV2 server) +{ + m_server = server; + m_allowStreaming = true; + m_stream = false; +} + +KPlayObjectFactory::KPlayObjectFactory(KArtsServer* server) +{ + m_server = server->server(); + m_allowStreaming = true; + m_stream = false; +} + +KPlayObjectFactory::~KPlayObjectFactory() +{ +} + +KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& url, bool createBUS) +{ + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + return createPlayObject(url, mimetype->name(), createBUS); +} + + +KPlayObject *KPlayObjectFactory::createPlayObject(const KURL& _url, const TQString &mimetype, bool createBUS) +{ + // WHY DOES BROKEN TDEIO_MEDIA GIVE WRONG URLS? + // I hate it + // I hate it + // It sucks + // tdeio_media please die + KURL url = TDEIO::NetAccess::mostLocalURL(_url, 0); + + if(!m_server.isNull()) + { + if(mimetype == "application/octet-stream" && m_allowStreaming) + { + Arts::TDEIOInputStream instream; + instream.openURL(url.url().latin1()); + + m_stream = true; + + // TODO: what else than hardcoding audio/x-mp3 ? + return new KPlayObject(m_server.createPlayObjectForStream(instream, string("audio/x-mp3"), createBUS), true); + } + else + return new KPlayObject(m_server.createPlayObjectForURL(string(TQFile::encodeName(url.path())), string(mimetype.latin1()), createBUS), false); + } + else + return new KPlayObject(); +} + + + +// + +KDE::PlayObjectFactory::PlayObjectFactory(Arts::SoundServerV2 server) +{ + d = new PrivateData; + d->server = server; + d->amanPlay = 0; + d->helper = 0; + d->allowStreaming = true; + d->isStream = false; +} + +KDE::PlayObjectFactory::PlayObjectFactory(KArtsServer* server) +{ + d = new PrivateData; + d->server = server->server(); + d->amanPlay = 0; + d->helper = 0; + d->allowStreaming = true; + d->isStream = false; +} + +KDE::PlayObjectFactory::~PlayObjectFactory() +{ + delete d->helper; + delete d; +} + +void KDE::PlayObjectFactory::setAudioManagerPlay( KAudioManagerPlay * amanPlay ) +{ + d->amanPlay = amanPlay; + if( ! d->helper ) + d->helper = new POFHelper; +} + +KDE::PlayObject *KDE::PlayObjectFactory::createPlayObject(const KURL& url, bool createBUS) +{ + KMimeType::Ptr mimetype = KMimeType::findByURL(url); + return createPlayObject(url, mimetype->name(), createBUS); +} + +KDE::PlayObject *KDE::PlayObjectFactory::createPlayObject(const KURL& _url, const TQString &mimetype, bool createBUS) +{ + // WHY DOES BROKEN TDEIO_MEDIA GIVE WRONG URLS? + // I hate it + // I hate it + // It sucks + // tdeio_media please die + KURL url = TDEIO::NetAccess::mostLocalURL(_url, 0); + + // return a NULL playobject if the server is NULL + if ( d->server.isNull() || url.isEmpty() ) + return new KDE::PlayObject(); + + // if the program wants to use it's own Synth_AMAN_PLAY we don't need a + // bus + if( d->amanPlay && createBUS ) + { + kdWarning( 400 ) << "KDE::PlayObjectFactory was instructed to use a Synth_AMAN_PLAY for output but the program also asked for a Synth_BUS_UPLINK" << endl; + createBUS = false; + } + + // decide if it's a local file. mpeglib provides cdda reading and decoding, so we prefer that over tdeio_audiocd + if ( url.isLocalFile() || !d->allowStreaming || (url.protocol() == "audiocd" && mimetype == "application/x-cda" && mimeTypes().contains( "application/x-cda" ) ) ) + { + // we rely on the delivered mimetype if it's a local file + d->playObj = new KDE::PlayObject( d->server.createPlayObjectForURL( string( TQFile::encodeName( url.path() ) ), string( mimetype.latin1() ), createBUS ), false ); + } + else + { + // if non-local, let the KPlayObject figure out the mimetype itself + // this invokes asynchronous creation automatically + d->playObj = new KDE::PlayObject( d->server, url, true, createBUS ); + } + + if( d->playObj->isNull() ) + { + delete d->playObj; + d->playObj = 0; + return new KDE::PlayObject(); // return a NULL playobject + } + + if( d->amanPlay ) + { + d->helper->po = d->playObj; + d->helper->ap = d->amanPlay; + if( d->playObj->object().isNull() && d->amanPlay ) + TQObject::connect( d->playObj, TQT_SIGNAL( playObjectCreated() ), d->helper, TQT_SLOT( connectAmanPlay() ) ); + else + d->helper->connectAmanPlay(); + } + + return d->playObj; +} + +TQStringList KDE::PlayObjectFactory::mimeTypes(void) +{ + KArtsDispatcher dispatcher; // we need such a thing, otherwise we crash + Arts::TraderQuery query; + vector *offers = query.query(); + + TQStringList results; + for(vector::iterator offer = offers->begin(); + offer != offers->end(); ++offer) + { + vector *mimetypes = (*offer).getProperty("MimeType"); + + for(vector::iterator mimetype = mimetypes->begin(); + mimetype != mimetypes->end(); ++mimetype) + { + TQString name = TQString(TQString::fromLocal8Bit((*mimetype).c_str())).stripWhiteSpace(); + if(KMimeType::mimeType(name)) + results.append(name); + } + + delete mimetypes; + } + delete offers; + + // clean out duplicates + results.sort(); + for(TQStringList::iterator result = results.begin(); result != results.end(); ) + { + TQStringList::iterator previous = result; + ++result; + if(result != results.end() && *result == *previous) + { + results.remove(result); + result = previous; + } + } + + return results; +} + +/* ### KDE4 +void KDE::PlayObjectFactory::connectAmanPlay() +{ + kdDebug( 400 ) << k_funcinfo << endl; + if( d->playObj->object().isNull() ) + return; + + d->amanPlay->start(); + d->playObj->object()._node()->start(); + Arts::connect( d->playObj->object(), "left" , d->amanPlay->amanPlay(), "left" ); + Arts::connect( d->playObj->object(), "right", d->amanPlay->amanPlay(), "right" ); +} +*/ + +void KDE::POFHelper::connectAmanPlay() +{ + kdDebug( 400 ) << k_funcinfo << endl; + if( po->object().isNull() ) + return; + + ap->start(); + po->object()._node()->start(); + Arts::connect( po->object(), "left" , ap->amanPlay(), "left" ); + Arts::connect( po->object(), "right", ap->amanPlay(), "right" ); +} + +#include "kplayobjectfactory_p.moc" diff --git a/arts/message/CMakeLists.txt b/arts/message/CMakeLists.txt index 12e91f65e..0a9be01cb 100644 --- a/arts/message/CMakeLists.txt +++ b/arts/message/CMakeLists.txt @@ -26,7 +26,7 @@ link_directories( set( target artsmessage ) set( ${target}_SRCS - artsmessage.cc + artsmessage.cpp ) tde_add_executable( ${target} diff --git a/arts/message/Makefile.am b/arts/message/Makefile.am index 24b7a6d18..363d561df 100644 --- a/arts/message/Makefile.am +++ b/arts/message/Makefile.am @@ -2,7 +2,7 @@ INCLUDES = $(all_includes) bin_PROGRAMS = artsmessage -artsmessage_SOURCES = artsmessage.cc +artsmessage_SOURCES = artsmessage.cpp artsmessage_LDADD = ../../tdeui/libtdeui.la artsmessage_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(KDE_MT_LDFLAGS) diff --git a/arts/message/artsmessage.cc b/arts/message/artsmessage.cc deleted file mode 100644 index eaa5c8e2c..000000000 --- a/arts/message/artsmessage.cc +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright (C) 2001 Jeff Tranter - tranter@kde.org - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - ------------------------------------------------------------------------- - -This application displays an error, warning, or informational message -in a dialog. It is normally used by artsd in conjunction with the -m -option. By abstracting this out of artsd, we keep it independent of -any particular graphics toolkit. - -This version uses KDE. Equivalent versions could be written using Qt, -Gnome, etc. and used instead. - -*/ - -#include - -#include -#include -#include -#include -#include -#include - -// command line options -static TDECmdLineOptions options[] = - { - { "e", 0,0 }, - { "error", I18N_NOOP("Display error message (default)"), 0 }, - { "w", 0, 0}, - { "warning", I18N_NOOP("Display warning message"), 0 }, - { "i", 0, 0 }, - { "info", I18N_NOOP("Display informational message"), 0 }, - { "+message", I18N_NOOP("Message string to be displayed"), 0 }, - TDECmdLineLastOption // End of options. - }; - -TDEAboutData aboutData("artsmessage", I18N_NOOP("artsmessage"), "0.1", - I18N_NOOP("Utility to display aRts error messages"), - TDEAboutData::License_GPL, "(c) 2001, Jeff Tranter", 0, 0, "tranter@kde.org"); - -int main(int argc, char **argv) { - aboutData.addAuthor("Jeff Tranter", 0, "tranter@kde.org"); - TDEGlobal::locale()->setMainCatalogue("tdelibs"); - TDECmdLineArgs::init(argc, argv, &aboutData); - TDECmdLineArgs::addCmdLineOptions(options); - TDEApplication app; - - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - TQString msg; - - // must be at least one argument - if (args->count() == 0) { - args->usage(); - } - - // build up message string from remaining arguments - for (int i = 0; i < args->count(); i++) { - if (i == 0) - msg = args->arg(i); - else - msg += TQString(" ") + args->arg(i); - } - - const int notifyOptions = 0; // never activate KNotify - if (args->isSet("w")) { - KMessageBox::sorry(0, msg, i18n("Warning"), notifyOptions); - } else if (args->isSet("i")) { - TQString id = msg; - id.replace(TQRegExp("[\\[\\]\\s=]"), "_"); - KMessageBox::information(0, msg, i18n("Informational"), id, notifyOptions); - } else { - KMessageBox::error(0, msg, i18n("Error"), notifyOptions); - } - - return 0; -} diff --git a/arts/message/artsmessage.cpp b/arts/message/artsmessage.cpp new file mode 100644 index 000000000..eaa5c8e2c --- /dev/null +++ b/arts/message/artsmessage.cpp @@ -0,0 +1,93 @@ +/* + Copyright (C) 2001 Jeff Tranter + tranter@kde.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +------------------------------------------------------------------------ + +This application displays an error, warning, or informational message +in a dialog. It is normally used by artsd in conjunction with the -m +option. By abstracting this out of artsd, we keep it independent of +any particular graphics toolkit. + +This version uses KDE. Equivalent versions could be written using Qt, +Gnome, etc. and used instead. + +*/ + +#include + +#include +#include +#include +#include +#include +#include + +// command line options +static TDECmdLineOptions options[] = + { + { "e", 0,0 }, + { "error", I18N_NOOP("Display error message (default)"), 0 }, + { "w", 0, 0}, + { "warning", I18N_NOOP("Display warning message"), 0 }, + { "i", 0, 0 }, + { "info", I18N_NOOP("Display informational message"), 0 }, + { "+message", I18N_NOOP("Message string to be displayed"), 0 }, + TDECmdLineLastOption // End of options. + }; + +TDEAboutData aboutData("artsmessage", I18N_NOOP("artsmessage"), "0.1", + I18N_NOOP("Utility to display aRts error messages"), + TDEAboutData::License_GPL, "(c) 2001, Jeff Tranter", 0, 0, "tranter@kde.org"); + +int main(int argc, char **argv) { + aboutData.addAuthor("Jeff Tranter", 0, "tranter@kde.org"); + TDEGlobal::locale()->setMainCatalogue("tdelibs"); + TDECmdLineArgs::init(argc, argv, &aboutData); + TDECmdLineArgs::addCmdLineOptions(options); + TDEApplication app; + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + TQString msg; + + // must be at least one argument + if (args->count() == 0) { + args->usage(); + } + + // build up message string from remaining arguments + for (int i = 0; i < args->count(); i++) { + if (i == 0) + msg = args->arg(i); + else + msg += TQString(" ") + args->arg(i); + } + + const int notifyOptions = 0; // never activate KNotify + if (args->isSet("w")) { + KMessageBox::sorry(0, msg, i18n("Warning"), notifyOptions); + } else if (args->isSet("i")) { + TQString id = msg; + id.replace(TQRegExp("[\\[\\]\\s=]"), "_"); + KMessageBox::information(0, msg, i18n("Informational"), id, notifyOptions); + } else { + KMessageBox::error(0, msg, i18n("Error"), notifyOptions); + } + + return 0; +} diff --git a/dcop/dcopidl/CMakeLists.txt b/dcop/dcopidl/CMakeLists.txt index f3a8c5049..989a959be 100644 --- a/dcop/dcopidl/CMakeLists.txt +++ b/dcop/dcopidl/CMakeLists.txt @@ -24,7 +24,7 @@ link_directories( set( target dcopidl ) set( ${target}_SRCS - main.cpp yacc.cc scanner.cc + main.cpp yacc.cpp scanner.cpp ) tde_add_executable( ${target} diff --git a/dcop/dcopidl/Makefile.am b/dcop/dcopidl/Makefile.am index d896a4a34..7b071dd6a 100644 --- a/dcop/dcopidl/Makefile.am +++ b/dcop/dcopidl/Makefile.am @@ -7,8 +7,8 @@ AM_CPPFLAGS = -DYYDEBUG bin_PROGRAMS = dcopidl -dcopidl_SOURCES = main.cpp yacc.cc scanner.cc -noinst_HEADERS = yacc.cc.h +dcopidl_SOURCES = main.cpp yacc.cpp scanner.cpp +noinst_HEADERS = yacc.cpp.h dcopidl_LDADD = $(LIB_TQT) dcopidl_LDFLAGS = $(KDE_RPATH) $(AM_LDFLAGS) @@ -16,12 +16,12 @@ dcopidl_LDFLAGS = $(KDE_RPATH) $(AM_LDFLAGS) ####### Build rules parser: - cd $(srcdir) && flex -B -8 -oscanner.cc scanner.ll ;\ - bison -t -d -v -o yacc.cc yacc.yy && mv yacc.hh yacc.cc.h + cd $(srcdir) && flex -B -8 -oscanner.cpp scanner.ll ;\ + bison -t -d -v -o yacc.cpp yacc.yy && mv yacc.hh yacc.cpp.h check-local: $(srcdir)/run_test.sh $(srcdir) EXTRA_DIST = dcopidl_test.h scanner.ll yacc.yy -MAINTAINERCLEANFILES = yacc.cc.output +MAINTAINERCLEANFILES = yacc.cpp.output diff --git a/dcop/dcopidl/scanner.cc b/dcop/dcopidl/scanner.cc deleted file mode 100644 index 55a20aba3..000000000 --- a/dcop/dcopidl/scanner.cc +++ /dev/null @@ -1,2747 +0,0 @@ -#line 2 "scanner.cc" - -#line 4 "scanner.cc" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart(yyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int yyleng; - -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart (FILE *input_file ); -void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); -void yy_delete_buffer (YY_BUFFER_STATE b ); -void yy_flush_buffer (YY_BUFFER_STATE b ); -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); -void yypop_buffer_state (void ); - -static void yyensure_buffer_stack (void ); -static void yy_load_buffer_state (void ); -static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); - -#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); - -void *yyalloc (yy_size_t ); -void *yyrealloc (void *,yy_size_t ); -void yyfree (void * ); - -#define yy_new_buffer yy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer(yyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer(yyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -#define yywrap(n) 1 -#define YY_SKIP_YYWRAP - -typedef unsigned char YY_CHAR; - -FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; - -typedef int yy_state_type; - -extern int yylineno; - -int yylineno = 1; - -extern char *yytext; -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - -#define YY_NUM_RULES 84 -#define YY_END_OF_BUFFER 85 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_acclist[672] = - { 0, - 6, 6, 85, 6, 83, 84, 1, 6, 83, 84, - 2, 84, 6, 83, 84, 6, 83, 84, 6, 83, - 84, 6, 23, 83, 84, 6, 83, 84, 6, 14, - 83, 84, 6, 15, 83, 84, 7, 21, 83, 84, - 6, 17, 83, 84, 6, 20, 83, 84, 6, 18, - 83, 84, 6, 28, 83, 84, 6, 83, 84, 6, - 69, 79, 83, 84, 6, 78, 83, 84, 6, 16, - 83, 84, 6, 22, 83, 84, 6, 24, 83, 84, - 6, 27, 83, 84, 6, 25, 83, 84, 6, 72, - 83, 84, 6, 72, 83, 84, 6, 72, 83, 84, - - 6, 72, 83, 84, 6, 72, 83, 84, 6, 30, - 83, 84, 6, 31, 83, 84, 6, 72, 83, 84, - 6, 72, 83, 84, 6, 72, 83, 84, 6, 72, - 83, 84, 6, 72, 83, 84, 6, 72, 83, 84, - 6, 72, 83, 84, 6, 72, 83, 84, 6, 72, - 83, 84, 6, 72, 83, 84, 6, 72, 83, 84, - 6, 72, 83, 84, 6, 72, 83, 84, 6, 72, - 83, 84, 6, 72, 83, 84, 6, 12, 83, 84, - 5, 13, 83, 84, 6, 19, 83, 84, 6, 6, - 34, 6, 6, 82, 6, 6, 11, 6, 9, 6, - - 6, 6, 4, 6, 32, 6, 6, 76, 3, 6, - 8, 6, 6, 79, 6, 6, 6, 69, 6, 80, - 6, 78, 6, 78, 6, 26, 6, 33, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 82, 6, 6, 6, 9, 9, 6, 6, 81, 81, - - 6, 81, 6, 6, 6, 29, 6, 6, 8, 8, - 6, 75, 6, 6, 74, 6, 80, 6, 72, 6, - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - 72, 6, 72, 6, 58, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 6, 6, 6, 6, 6, - 6, 77, 6, 6, 72, 6, 72, 6, 72, 6, - - 72, 6, 61, 72, 6, 59, 72, 6, 72, 6, - 72, 6, 36, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 72, 6, 50, 72, 6, 72, 6, - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - 72, 6, 57, 72, 6, 72, 6, 72, 6, 72, - 6, 72, 6, 6, 6, 6, 6, 6, 73, 6, - 62, 72, 6, 72, 6, 72, 6, 72, 6, 39, - 72, 6, 35, 72, 6, 72, 6, 60, 72, 6, - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - 49, 72, 6, 72, 6, 72, 6, 56, 72, 6, - 72, 6, 72, 6, 72, 6, 72, 6, 38, 72, - 6, 72, 6, 6, 66, 72, 6, 72, 6, 72, - 6, 72, 6, 51, 72, 6, 44, 72, 6, 63, - 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, - 72, 6, 43, 72, 6, 55, 72, 6, 72, 6, - 47, 72, 6, 45, 72, 6, 40, 72, 6, 72, - 6, 72, 6, 72, 6, 6, 72, 6, 72, 6, - 6, 72, 6, 46, 72, 6, 72, 6, 72, 6, - - 53, 72, 6, 72, 6, 54, 72, 6, 65, 72, - 6, 72, 6, 42, 72, 6, 6, 67, 72, 6, - 72, 6, 70, 6, 70, 6, 72, 6, 72, 6, - 41, 72, 6, 72, 6, 48, 72, 6, 6, 6, - 68, 72, 6, 6, 72, 6, 37, 72, 6, 52, - 72, 6, 11, 6, 6, 71, 6, 72, 10, 11, - 6, 6, 72, 10, 6, 72, 6, 72, 6, 64, - 72 - } ; - -static yyconst flex_int16_t yy_accept[320] = - { 0, - 1, 2, 3, 4, 7, 11, 13, 16, 19, 22, - 26, 29, 33, 37, 41, 45, 49, 53, 57, 60, - 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, - 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, - 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, - 185, 189, 190, 192, 193, 195, 195, 196, 197, 198, - 200, 200, 201, 202, 202, 203, 204, 206, 207, 209, - 210, 212, 213, 215, 216, 217, 219, 221, 223, 225, - 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, - 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, - - 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, - 287, 289, 291, 292, 292, 293, 294, 296, 297, 298, - 300, 301, 303, 304, 305, 307, 308, 310, 311, 313, - 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, - 334, 336, 338, 340, 342, 344, 347, 349, 351, 353, - 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, - 375, 377, 379, 381, 383, 385, 385, 385, 386, 387, - 388, 389, 390, 391, 393, 394, 396, 398, 400, 402, - 405, 408, 410, 412, 415, 417, 419, 421, 423, 425, - 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, - - 448, 450, 452, 455, 457, 459, 461, 463, 463, 463, - 464, 465, 466, 467, 468, 470, 473, 475, 477, 479, - 482, 485, 487, 490, 492, 494, 496, 498, 500, 502, - 504, 506, 508, 510, 513, 515, 517, 520, 522, 524, - 526, 528, 531, 533, 533, 533, 534, 537, 539, 541, - 543, 546, 549, 552, 554, 556, 558, 560, 562, 565, - 568, 570, 573, 576, 579, 581, 583, 585, 586, 588, - 590, 591, 593, 596, 598, 600, 603, 605, 608, 611, - 613, 616, 617, 620, 622, 624, 625, 626, 628, 630, - 633, 635, 638, 639, 640, 643, 644, 646, 649, 652, - - 653, 654, 655, 655, 657, 659, 659, 659, 661, 662, - 662, 664, 665, 665, 665, 667, 669, 672, 672 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 4, 5, 6, 7, 1, 1, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, - 19, 19, 19, 19, 19, 20, 20, 21, 22, 23, - 24, 25, 26, 1, 27, 28, 29, 30, 31, 32, - 33, 33, 33, 34, 35, 36, 33, 33, 37, 38, - 39, 40, 41, 42, 43, 33, 33, 44, 33, 33, - 45, 46, 47, 1, 48, 1, 49, 50, 51, 52, - - 53, 54, 55, 56, 57, 33, 58, 59, 60, 61, - 62, 63, 33, 64, 65, 66, 67, 68, 33, 69, - 70, 33, 71, 1, 72, 73, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst flex_int32_t yy_meta[74] = - { 0, - 1, 2, 3, 4, 1, 5, 1, 1, 5, 1, - 1, 6, 1, 1, 1, 1, 1, 7, 7, 8, - 1, 1, 1, 1, 1, 5, 8, 8, 8, 8, - 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 9, 1, 5, 1, 4, 7, 7, - 8, 8, 8, 7, 4, 4, 4, 4, 4, 4, - 9, 4, 4, 9, 4, 9, 4, 9, 9, 4, - 1, 10, 1 - } ; - -static yyconst flex_int16_t yy_base[337] = - { 0, - 0, 0, 923, 0, 0, 1107, 898, 72, 74, 0, - 73, 0, 0, 904, 0, 0, 894, 71, 64, 79, - 85, 894, 0, 69, 890, 82, 148, 221, 61, 69, - 73, 0, 0, 81, 53, 75, 67, 93, 98, 84, - 139, 115, 120, 148, 140, 141, 149, 150, 0, 1107, - 0, 0, 0, 206, 0, 174, 289, 178, 1107, 179, - 910, 197, 903, 902, 353, 1107, 0, 894, 243, 1107, - 114, 115, 257, 266, 286, 0, 405, 293, 0, 0, - 0, 882, 100, 162, 176, 156, 190, 175, 222, 226, - 188, 213, 230, 233, 264, 189, 232, 237, 212, 227, - - 275, 290, 254, 238, 287, 256, 299, 289, 298, 295, - 294, 300, 1107, 326, 372, 442, 370, 905, 377, 0, - 1107, 898, 357, 479, 0, 368, 322, 0, 432, 349, - 386, 0, 229, 320, 102, 304, 365, 301, 350, 366, - 325, 373, 374, 385, 383, 878, 402, 386, 371, 437, - 381, 400, 382, 384, 419, 403, 420, 438, 439, 448, - 449, 450, 455, 452, 451, 508, 0, 532, 603, 477, - 528, 667, 500, 503, 540, 456, 498, 514, 473, 877, - 876, 497, 513, 875, 512, 489, 516, 525, 518, 874, - 534, 529, 536, 538, 530, 539, 537, 540, 542, 543, - - 541, 546, 864, 547, 545, 548, 544, 601, 716, 612, - 634, 578, 881, 607, 619, 862, 555, 457, 583, 848, - 847, 601, 843, 561, 589, 585, 602, 614, 616, 617, - 637, 638, 632, 841, 633, 639, 840, 651, 624, 647, - 640, 839, 654, 662, 663, 660, 838, 644, 680, 700, - 837, 835, 678, 686, 688, 652, 696, 697, 834, 832, - 706, 830, 829, 823, 698, 701, 683, 726, 713, 724, - 798, 723, 814, 729, 714, 809, 704, 808, 800, 731, - 799, 770, 764, 733, 871, 701, 0, 732, 734, 643, - 750, 575, 826, 828, 565, 583, 737, 309, 158, 848, - - 173, 783, 791, 0, 757, 775, 351, 1107, 834, 782, - 790, 1107, 787, 793, 774, 798, 56, 1107, 944, 953, - 963, 973, 983, 992, 1002, 1012, 1022, 1028, 1037, 1047, - 1051, 1059, 1067, 1076, 1086, 1096 - } ; - -static yyconst flex_int16_t yy_def[337] = - { 0, - 318, 1, 318, 319, 319, 318, 319, 320, 321, 319, - 322, 319, 319, 318, 319, 319, 319, 319, 319, 319, - 319, 319, 319, 319, 319, 319, 323, 323, 28, 28, - 28, 319, 319, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 319, 318, - 319, 319, 319, 320, 319, 324, 319, 321, 318, 325, - 326, 321, 319, 318, 319, 318, 319, 319, 319, 318, - 327, 319, 319, 319, 319, 319, 319, 319, 319, 319, - 319, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 318, 328, 320, 319, 325, 329, 321, 319, - 318, 319, 319, 319, 319, 319, 327, 330, 319, 319, - 319, 77, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 324, 331, 320, 320, 321, - 319, 319, 319, 319, 319, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - - 28, 28, 28, 28, 28, 28, 28, 324, 324, 320, - 320, 321, 319, 319, 319, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 324, 324, 321, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 321, 28, 28, - 332, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 321, 28, 28, 332, 319, 333, 28, 28, 28, - 28, 28, 321, 334, 28, 319, 28, 28, 28, 334, - - 335, 321, 336, 319, 28, 335, 318, 318, 321, 326, - 28, 318, 318, 326, 28, 28, 28, 0, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318 - } ; - -static yyconst flex_int16_t yy_nxt[1181] = - { 0, - 4, 5, 6, 5, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, - 22, 23, 24, 25, 26, 4, 27, 27, 27, 27, - 27, 28, 27, 27, 29, 27, 27, 27, 30, 27, - 27, 31, 27, 27, 32, 4, 33, 27, 27, 27, - 34, 27, 35, 36, 27, 27, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 27, 27, - 49, 50, 51, 52, 52, 70, 59, 55, 60, 82, - 71, 52, 82, 56, 64, 61, 68, 82, 69, 69, - 69, 81, 53, 82, 72, 82, 73, 73, 74, 82, - - 72, 82, 78, 78, 78, 53, 81, 82, 84, 75, - 82, 86, 87, 91, 76, 75, 85, 57, 65, 82, - 79, 92, 77, 93, 82, 128, 82, 95, 82, 178, - 62, 75, 129, 129, 129, 133, 88, 75, 94, 89, - 96, 82, 90, 56, 64, 61, 82, 77, 52, 52, - 98, 52, 52, 52, 52, 52, 52, 52, 52, 97, - 52, 52, 52, 52, 52, 82, 82, 82, 52, 52, - 52, 52, 52, 52, 82, 82, 82, 100, 307, 113, - 59, 59, 82, 101, 82, 128, 102, 99, 82, 61, - 118, 134, 52, 52, 52, 104, 105, 307, 106, 59, - - 103, 82, 82, 136, 108, 107, 112, 52, 61, 110, - 109, 55, 135, 111, 82, 82, 82, 56, 52, 114, - 52, 52, 52, 138, 52, 52, 52, 52, 52, 52, - 52, 52, 137, 52, 52, 52, 52, 52, 82, 82, - 147, 52, 52, 52, 52, 52, 52, 83, 82, 61, - 118, 57, 82, 82, 141, 82, 82, 119, 82, 82, - 69, 69, 69, 82, 82, 52, 52, 52, 61, 176, - 139, 150, 72, 126, 73, 73, 74, 56, 142, 151, - 82, 72, 82, 74, 74, 74, 140, 75, 143, 144, - 82, 52, 148, 52, 54, 126, 75, 54, 130, 156, - - 130, 82, 149, 131, 131, 131, 115, 115, 72, 75, - 78, 78, 78, 82, 54, 82, 82, 158, 75, 155, - 82, 82, 145, 75, 82, 82, 82, 82, 79, 146, - 82, 152, 116, 128, 54, 82, 153, 54, 54, 154, - 179, 157, 54, 166, 166, 75, 82, 159, 177, 54, - 164, 82, 54, 312, 54, 161, 54, 116, 63, 163, - 162, 122, 160, 165, 181, 120, 131, 131, 131, 167, - 123, 123, 59, 52, 171, 171, 82, 55, 63, 59, - 173, 118, 173, 56, 184, 174, 174, 174, 61, 168, - 168, 82, 82, 128, 167, 180, 124, 82, 63, 82, - - 82, 63, 63, 131, 131, 131, 63, 82, 82, 82, - 82, 82, 82, 63, 182, 313, 63, 57, 63, 191, - 63, 124, 132, 132, 132, 185, 82, 170, 82, 82, - 183, 132, 132, 132, 132, 132, 132, 187, 186, 188, - 190, 118, 196, 56, 193, 82, 82, 195, 61, 129, - 129, 129, 189, 132, 132, 132, 132, 132, 132, 169, - 169, 169, 175, 82, 82, 82, 198, 194, 169, 169, - 169, 169, 169, 169, 82, 82, 82, 82, 82, 59, - 199, 82, 82, 82, 175, 197, 216, 248, 61, 192, - 169, 169, 169, 169, 169, 169, 172, 172, 172, 82, - - 219, 203, 204, 200, 201, 172, 172, 172, 172, 172, - 172, 205, 206, 113, 202, 82, 207, 174, 174, 174, - 174, 174, 174, 82, 82, 208, 208, 172, 172, 172, - 172, 172, 172, 52, 217, 212, 120, 55, 82, 82, - 82, 223, 82, 56, 82, 63, 63, 218, 61, 210, - 210, 82, 214, 114, 214, 82, 82, 215, 215, 215, - 82, 220, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 222, 224, 57, 221, 226, - 59, 82, 231, 227, 229, 225, 230, 82, 304, 61, - 235, 82, 247, 228, 236, 232, 239, 238, 240, 241, - - 233, 82, 242, 56, 52, 234, 113, 237, 55, 82, - 243, 82, 251, 52, 56, 82, 249, 55, 244, 244, - 211, 211, 211, 56, 215, 215, 215, 82, 82, 211, - 211, 211, 211, 211, 211, 52, 215, 215, 215, 55, - 82, 252, 82, 82, 246, 56, 114, 253, 57, 61, - 82, 211, 211, 211, 211, 211, 211, 57, 82, 82, - 254, 250, 59, 82, 82, 82, 82, 113, 113, 82, - 82, 61, 269, 82, 56, 120, 255, 82, 82, 57, - 82, 256, 257, 56, 213, 213, 213, 258, 259, 264, - 262, 261, 260, 213, 213, 213, 213, 213, 213, 265, - - 266, 263, 267, 271, 82, 56, 82, 114, 114, 82, - 270, 268, 82, 275, 82, 213, 213, 213, 213, 213, - 213, 113, 82, 82, 82, 272, 82, 82, 59, 296, - 82, 61, 82, 245, 245, 245, 274, 61, 273, 82, - 82, 281, 245, 245, 245, 245, 245, 245, 276, 82, - 82, 279, 284, 280, 283, 82, 291, 82, 82, 82, - 82, 114, 277, 82, 245, 245, 245, 245, 245, 245, - 278, 293, 59, 293, 295, 294, 82, 290, 282, 289, - 307, 61, 292, 82, 308, 308, 298, 288, 297, 312, - 82, 305, 294, 301, 61, 308, 310, 61, 52, 307, - - 82, 299, 52, 286, 52, 52, 52, 52, 52, 287, - 52, 52, 52, 52, 52, 310, 82, 311, 52, 52, - 52, 52, 52, 52, 82, 82, 82, 293, 59, 293, - 301, 294, 316, 302, 82, 82, 308, 61, 315, 303, - 82, 61, 52, 52, 52, 61, 314, 309, 294, 82, - 301, 313, 302, 302, 61, 82, 82, 314, 82, 303, - 82, 82, 317, 82, 82, 82, 82, 82, 52, 82, - 52, 52, 302, 82, 82, 52, 52, 52, 52, 52, - 52, 52, 287, 52, 52, 52, 52, 52, 82, 120, - 82, 52, 52, 52, 52, 52, 52, 61, 309, 303, - - 82, 82, 82, 82, 82, 61, 120, 59, 82, 125, - 121, 120, 59, 53, 80, 52, 52, 52, 67, 303, - 66, 53, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 52, 318, 52, 52, 52, 318, 52, 52, 318, - 52, 52, 52, 54, 54, 318, 54, 54, 54, 54, - 54, 54, 54, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 63, 63, 318, 63, 63, 63, 63, - 63, 63, 63, 82, 82, 318, 82, 82, 318, 82, - 82, 82, 56, 318, 318, 56, 56, 56, 56, 56, - - 56, 56, 117, 117, 117, 117, 117, 117, 117, 117, - 117, 117, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 127, 127, 318, 127, 127, 127, 127, 127, - 127, 127, 56, 318, 56, 318, 56, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 128, 128, 318, - 128, 128, 128, 128, 128, 128, 128, 209, 209, 285, - 285, 318, 285, 285, 285, 285, 285, 285, 287, 318, - 287, 318, 287, 287, 287, 287, 300, 300, 300, 300, - 300, 300, 300, 300, 300, 300, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 303, 303, 303, 303, - - 303, 303, 303, 303, 303, 303, 3, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318 - } ; - -static yyconst flex_int16_t yy_chk[1181] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 8, 11, 19, 9, 8, 9, 35, - 19, 11, 317, 8, 11, 9, 18, 29, 18, 18, - 18, 24, 24, 37, 20, 30, 20, 20, 20, 31, - - 21, 36, 21, 21, 21, 26, 26, 34, 29, 20, - 40, 31, 31, 35, 20, 21, 30, 8, 11, 38, - 21, 35, 20, 36, 39, 71, 83, 37, 135, 135, - 9, 20, 72, 72, 72, 83, 34, 21, 36, 34, - 38, 42, 34, 8, 11, 9, 43, 20, 27, 27, - 40, 27, 27, 27, 27, 27, 27, 27, 27, 39, - 27, 27, 27, 27, 27, 41, 45, 46, 27, 27, - 27, 27, 27, 27, 44, 47, 48, 42, 301, 56, - 58, 60, 86, 43, 299, 71, 43, 41, 84, 58, - 60, 84, 27, 27, 27, 45, 45, 301, 45, 62, - - 44, 88, 85, 86, 46, 45, 48, 54, 62, 47, - 46, 54, 85, 47, 91, 96, 87, 54, 27, 56, - 27, 28, 28, 88, 28, 28, 28, 28, 28, 28, - 28, 28, 87, 28, 28, 28, 28, 28, 99, 92, - 96, 28, 28, 28, 28, 28, 28, 28, 89, 58, - 60, 54, 90, 100, 91, 133, 93, 62, 97, 94, - 69, 69, 69, 98, 104, 28, 28, 28, 62, 133, - 89, 99, 73, 69, 73, 73, 73, 54, 92, 100, - 103, 74, 106, 74, 74, 74, 90, 73, 93, 94, - 95, 28, 97, 28, 57, 69, 74, 57, 75, 104, - - 75, 101, 98, 75, 75, 75, 57, 57, 78, 73, - 78, 78, 78, 105, 57, 108, 102, 106, 74, 103, - 111, 110, 95, 78, 109, 107, 112, 138, 78, 95, - 136, 101, 57, 127, 57, 298, 101, 57, 57, 102, - 136, 105, 57, 114, 114, 78, 134, 107, 134, 57, - 111, 141, 57, 307, 57, 108, 57, 57, 65, 110, - 109, 65, 107, 112, 138, 123, 130, 130, 130, 114, - 65, 65, 117, 115, 123, 123, 139, 115, 65, 119, - 126, 117, 126, 115, 141, 126, 126, 126, 119, 115, - 115, 137, 140, 127, 114, 137, 65, 149, 65, 142, - - 143, 65, 65, 131, 131, 131, 65, 151, 153, 145, - 154, 144, 148, 65, 139, 307, 65, 115, 65, 149, - 65, 65, 77, 77, 77, 142, 152, 119, 147, 156, - 140, 77, 77, 77, 77, 77, 77, 144, 143, 145, - 148, 117, 154, 115, 151, 155, 157, 153, 119, 129, - 129, 129, 147, 77, 77, 77, 77, 77, 77, 116, - 116, 116, 129, 150, 158, 159, 156, 152, 116, 116, - 116, 116, 116, 116, 160, 161, 162, 165, 164, 170, - 157, 163, 176, 218, 129, 155, 176, 218, 170, 150, - 116, 116, 116, 116, 116, 116, 124, 124, 124, 179, - - 179, 161, 162, 158, 159, 124, 124, 124, 124, 124, - 124, 163, 164, 166, 160, 186, 165, 173, 173, 173, - 174, 174, 174, 182, 177, 166, 166, 124, 124, 124, - 124, 124, 124, 168, 177, 170, 171, 168, 185, 183, - 178, 186, 187, 168, 189, 171, 171, 178, 170, 168, - 168, 188, 175, 166, 175, 192, 195, 175, 175, 175, - 191, 182, 193, 197, 194, 196, 198, 201, 199, 200, - 207, 205, 202, 204, 206, 185, 187, 168, 183, 189, - 212, 217, 195, 191, 193, 188, 194, 224, 296, 212, - 199, 295, 217, 192, 199, 196, 202, 201, 204, 205, - - 197, 292, 206, 168, 169, 198, 208, 200, 169, 219, - 207, 226, 224, 210, 169, 225, 219, 210, 208, 208, - 169, 169, 169, 210, 214, 214, 214, 222, 227, 169, - 169, 169, 169, 169, 169, 211, 215, 215, 215, 211, - 228, 225, 229, 230, 212, 211, 208, 226, 169, 212, - 239, 169, 169, 169, 169, 169, 169, 210, 233, 235, - 227, 222, 246, 231, 232, 236, 241, 244, 245, 290, - 248, 246, 248, 240, 169, 172, 228, 238, 256, 211, - 243, 229, 230, 210, 172, 172, 172, 231, 232, 239, - 236, 235, 233, 172, 172, 172, 172, 172, 172, 240, - - 241, 238, 243, 250, 253, 211, 249, 244, 245, 267, - 249, 246, 254, 256, 255, 172, 172, 172, 172, 172, - 172, 209, 257, 258, 265, 253, 250, 266, 268, 286, - 277, 246, 261, 209, 209, 209, 255, 268, 254, 269, - 275, 267, 209, 209, 209, 209, 209, 209, 257, 272, - 270, 265, 270, 266, 269, 274, 277, 280, 288, 284, - 289, 209, 258, 297, 209, 209, 209, 209, 209, 209, - 261, 282, 282, 282, 284, 282, 291, 275, 268, 274, - 306, 282, 280, 305, 310, 302, 289, 272, 288, 313, - 283, 297, 282, 303, 302, 314, 303, 268, 271, 306, - - 315, 291, 271, 271, 271, 271, 271, 271, 271, 271, - 271, 271, 271, 271, 271, 303, 311, 305, 271, 271, - 271, 271, 271, 271, 316, 281, 279, 293, 293, 293, - 294, 293, 315, 294, 278, 276, 309, 293, 311, 294, - 273, 282, 271, 271, 271, 309, 310, 302, 293, 264, - 300, 313, 294, 300, 302, 263, 262, 314, 260, 300, - 259, 252, 316, 251, 247, 242, 237, 234, 271, 223, - 271, 285, 300, 221, 220, 285, 285, 285, 285, 285, - 285, 285, 285, 285, 285, 285, 285, 285, 216, 213, - 203, 285, 285, 285, 285, 285, 285, 293, 309, 294, - - 190, 184, 181, 180, 146, 309, 122, 118, 82, 68, - 64, 63, 61, 25, 22, 285, 285, 285, 17, 300, - 14, 7, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 285, 0, 285, 319, 319, 0, 319, 319, 0, - 319, 319, 319, 320, 320, 0, 320, 320, 320, 320, - 320, 320, 320, 321, 321, 321, 321, 321, 321, 321, - 321, 321, 321, 322, 322, 0, 322, 322, 322, 322, - 322, 322, 322, 323, 323, 0, 323, 323, 0, 323, - 323, 323, 324, 0, 0, 324, 324, 324, 324, 324, - - 324, 324, 325, 325, 325, 325, 325, 325, 325, 325, - 325, 325, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 326, 327, 327, 0, 327, 327, 327, 327, 327, - 327, 327, 328, 0, 328, 0, 328, 329, 329, 329, - 329, 329, 329, 329, 329, 329, 329, 330, 330, 0, - 330, 330, 330, 330, 330, 330, 330, 331, 331, 332, - 332, 0, 332, 332, 332, 332, 332, 332, 333, 0, - 333, 0, 333, 333, 333, 333, 334, 334, 334, 334, - 334, 334, 334, 334, 334, 334, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 335, 336, 336, 336, 336, - - 336, 336, 336, 336, 336, 336, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318 - } ; - -extern int yy_flex_debug; -int yy_flex_debug = 0; - -static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; -static char *yy_full_match; -static int yy_lp; -#define REJECT \ -{ \ -*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \ -yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ -++(yy_lp); \ -goto find_rule; \ -} - -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "scanner.ll" -#line 2 "scanner.ll" -/***************************************************************** -Copyright (c) 1999 Torben Weis -Copyright (c) 2000 Matthias Ettrich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************/ - -#define YY_NO_UNPUT -#include -#include - -class TQString; - -#ifndef KDE_USE_FINAL -#include "yacc.cc.h" -#endif - -extern int idl_line_no; -int comment_mode; -int function_mode = 0; - -#include -#include - -static long ascii_to_longlong( long base, const char *s ) -{ - long ll = 0; - while( *s != '\0' ) { - char c = *s++; - if( c >= 'a' ) - c -= 'a' - 'A'; - c -= '0'; - if( c > 9 ) - c -= 'A' - '0' - 10; - ll = ll * base + c; - } - return ll; -} - -static double ascii_to_longdouble (const char *s) -{ - double d; -#ifdef HAVE_SCANF_LF - sscanf (s, "%Lf", &d); -#else - /* - * this is only an approximation and will probably break fixed<> - * parameter calculation on systems where - * sizeof(double) < sizeof(long double). but fortunately all - * systems where scanf("%Lf") is known to be broken (Linux/Alpha - * and HPUX) have sizeof(double) == sizeof(long double). - */ - d = strtod (s, NULL); -#endif - return d; -} - -static char translate_char( const char *s ) -{ - char c = *s++; - - if( c != '\\' ) - return c; - c = *s++; - switch( c ) { - case 'n': - return '\n'; - case 't': - return '\t'; - case 'v': - return '\v'; - case 'b': - return '\b'; - case 'r': - return '\r'; - case 'f': - return '\f'; - case 'a': - return '\a'; - case '\\': - return '\\'; - case '?': - return '\?'; - case '\'': - return '\''; - case '"': - return '"'; - case 'x': - case 'X': - return (char) ascii_to_longlong( 16, s ); - default: - // Gotta be an octal - return (char) ascii_to_longlong( 8, s ); - } -} - - -/*--------------------------------------------------------------------------*/ -/*--------------------------------------------------------------------------*/ -/*--------------------------------------------------------------------------*/ -#line 1030 "scanner.cc" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int yylex_destroy (void ); - -int yyget_debug (void ); - -void yyset_debug (int debug_flag ); - -YY_EXTRA_TYPE yyget_extra (void ); - -void yyset_extra (YY_EXTRA_TYPE user_defined ); - -FILE *yyget_in (void ); - -void yyset_in (FILE * in_str ); - -FILE *yyget_out (void ); - -void yyset_out (FILE * out_str ); - -int yyget_leng (void ); - -char *yyget_text (void ); - -int yyget_lineno (void ); - -void yyset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap (void ); -#else -extern int yywrap (void ); -#endif -#endif - - static void yyunput (int c,char *buf_ptr ); - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int yylex (void); - -#define YY_DECL int yylex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - -#line 148 "scanner.ll" - - -#line 1220 "scanner.cc" - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - /* Create the reject buffer large enough to save one state per allowed character. */ - if ( ! (yy_state_buf) ) - (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE ); - if ( ! (yy_state_buf) ) - YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer(yyin,YY_BUF_SIZE ); - } - - yy_load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); - - /* Support of yytext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); - - (yy_state_ptr) = (yy_state_buf); - *(yy_state_ptr)++ = yy_current_state; - -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 319 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - *(yy_state_ptr)++ = yy_current_state; - ++yy_cp; - } - while ( yy_current_state != 318 ); - -yy_find_action: - yy_current_state = *--(yy_state_ptr); - (yy_lp) = yy_accept[yy_current_state]; -find_rule: /* we branch to this label when backing up */ - for ( ; ; ) /* until we find what rule we matched */ - { - if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) - { - yy_act = yy_acclist[(yy_lp)]; - { - (yy_full_match) = yy_cp; - break; - } - } - --yy_cp; - yy_current_state = *--(yy_state_ptr); - (yy_lp) = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ -case 1: -YY_RULE_SETUP -#line 150 "scanner.ll" -; - YY_BREAK -case 2: -/* rule 2 can match eol */ -YY_RULE_SETUP -#line 151 "scanner.ll" -{ idl_line_no++; } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 153 "scanner.ll" -{ comment_mode = 1; } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 154 "scanner.ll" -{ if (!comment_mode) { REJECT; } else { comment_mode = 0; } } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 155 "scanner.ll" -{ - if (! comment_mode) { - if (!function_mode) { REJECT; } else { - function_mode = 0; - return T_RIGHT_CURLY_BRACKET; - } - } - } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 163 "scanner.ll" -{ if (!comment_mode && !function_mode) { REJECT; } } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 164 "scanner.ll" -{ if (!comment_mode) { REJECT; } } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 166 "scanner.ll" -; - YY_BREAK -case 9: -YY_RULE_SETUP -#line 167 "scanner.ll" -{ - exit( 1 ); - } - YY_BREAK -case 10: -/* rule 10 can match eol */ -YY_RULE_SETUP -#line 170 "scanner.ll" -{ - TQString s( yytext ); - int i = s.find(TQRegExp("[\"<]"))+1; - int j = s.find(TQRegExp("[\">]"), i); - yylval._str = new TQString( s.mid( i, j - i ) ); - idl_line_no++; - return T_INCLUDE; - } - YY_BREAK -case 11: -/* rule 11 can match eol */ -YY_RULE_SETUP -#line 178 "scanner.ll" -{ - idl_line_no++; - } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 181 "scanner.ll" -return T_LEFT_CURLY_BRACKET; - YY_BREAK -case 13: -YY_RULE_SETUP -#line 182 "scanner.ll" -return T_RIGHT_CURLY_BRACKET; - YY_BREAK -case 14: -YY_RULE_SETUP -#line 183 "scanner.ll" -return T_LEFT_PARANTHESIS; - YY_BREAK -case 15: -YY_RULE_SETUP -#line 184 "scanner.ll" -return T_RIGHT_PARANTHESIS; - YY_BREAK -case 16: -YY_RULE_SETUP -#line 185 "scanner.ll" -return T_COLON; - YY_BREAK -case 17: -YY_RULE_SETUP -#line 186 "scanner.ll" -return T_PLUS; - YY_BREAK -case 18: -YY_RULE_SETUP -#line 187 "scanner.ll" -return T_MINUS; - YY_BREAK -case 19: -YY_RULE_SETUP -#line 188 "scanner.ll" -return T_TILDE; - YY_BREAK -case 20: -YY_RULE_SETUP -#line 189 "scanner.ll" -return T_COMMA; - YY_BREAK -case 21: -YY_RULE_SETUP -#line 190 "scanner.ll" -return T_ASTERISK; - YY_BREAK -case 22: -YY_RULE_SETUP -#line 191 "scanner.ll" -return T_SEMICOLON; - YY_BREAK -case 23: -YY_RULE_SETUP -#line 192 "scanner.ll" -return T_AMPERSAND; - YY_BREAK -case 24: -YY_RULE_SETUP -#line 193 "scanner.ll" -return T_LESS; - YY_BREAK -case 25: -YY_RULE_SETUP -#line 194 "scanner.ll" -return T_GREATER; - YY_BREAK -case 26: -YY_RULE_SETUP -#line 195 "scanner.ll" -return T_SCOPE; - YY_BREAK -case 27: -YY_RULE_SETUP -#line 196 "scanner.ll" -return T_EQUAL; - YY_BREAK -case 28: -YY_RULE_SETUP -#line 197 "scanner.ll" -return T_ACCESS; - YY_BREAK -case 29: -YY_RULE_SETUP -#line 198 "scanner.ll" -return T_TRIPLE_DOT; - YY_BREAK -case 30: -YY_RULE_SETUP -#line 199 "scanner.ll" -return T_ARRAY_OPEN; - YY_BREAK -case 31: -YY_RULE_SETUP -#line 200 "scanner.ll" -return T_ARRAY_CLOSE; - YY_BREAK -case 32: -YY_RULE_SETUP -#line 201 "scanner.ll" -return T_ACCESS; - YY_BREAK -case 33: -YY_RULE_SETUP -#line 202 "scanner.ll" -return T_SHIFT; - YY_BREAK -case 34: -YY_RULE_SETUP -#line 203 "scanner.ll" -return T_MISCOPERATOR; - YY_BREAK -case 35: -YY_RULE_SETUP -#line 206 "scanner.ll" -return T_CONST; - YY_BREAK -case 36: -YY_RULE_SETUP -#line 207 "scanner.ll" -return T_ENUM; - YY_BREAK -case 37: -YY_RULE_SETUP -#line 208 "scanner.ll" -return T_NAMESPACE; - YY_BREAK -case 38: -YY_RULE_SETUP -#line 209 "scanner.ll" -return T_USING; - YY_BREAK -case 39: -YY_RULE_SETUP -#line 210 "scanner.ll" -return T_CLASS; - YY_BREAK -case 40: -YY_RULE_SETUP -#line 211 "scanner.ll" -return T_STRUCT; - YY_BREAK -case 41: -YY_RULE_SETUP -#line 212 "scanner.ll" -return T_FUNOPERATOR; - YY_BREAK -case 42: -YY_RULE_SETUP -#line 213 "scanner.ll" -return T_VIRTUAL; - YY_BREAK -case 43: -YY_RULE_SETUP -#line 214 "scanner.ll" -return T_PUBLIC; - YY_BREAK -case 44: -YY_RULE_SETUP -#line 215 "scanner.ll" -return T_INLINE; - YY_BREAK -case 45: -YY_RULE_SETUP -#line 216 "scanner.ll" -return T_STATIC; - YY_BREAK -case 46: -YY_RULE_SETUP -#line 217 "scanner.ll" -return T_MUTABLE; - YY_BREAK -case 47: -YY_RULE_SETUP -#line 218 "scanner.ll" -return T_SIGNED; - YY_BREAK -case 48: -YY_RULE_SETUP -#line 219 "scanner.ll" -return T_UNSIGNED; - YY_BREAK -case 49: -YY_RULE_SETUP -#line 220 "scanner.ll" -return T_SHORT; - YY_BREAK -case 50: -YY_RULE_SETUP -#line 221 "scanner.ll" -return T_LONG; - YY_BREAK -case 51: -YY_RULE_SETUP -#line 222 "scanner.ll" -return T_FRIEND; - YY_BREAK -case 52: -YY_RULE_SETUP -#line 223 "scanner.ll" -return T_PROTECTED; - YY_BREAK -case 53: -YY_RULE_SETUP -#line 224 "scanner.ll" -return T_PRIVATE; - YY_BREAK -case 54: -YY_RULE_SETUP -#line 225 "scanner.ll" -return T_SIGNAL; - YY_BREAK -case 55: -YY_RULE_SETUP -#line 226 "scanner.ll" -return T_RETURN; - YY_BREAK -case 56: -YY_RULE_SETUP -#line 227 "scanner.ll" -return T_SLOT; - YY_BREAK -case 57: -YY_RULE_SETUP -#line 228 "scanner.ll" -return T_TRUE; - YY_BREAK -case 58: -YY_RULE_SETUP -#line 229 "scanner.ll" -return T_INT; - YY_BREAK -case 59: -YY_RULE_SETUP -#line 230 "scanner.ll" -return T_CHAR; - YY_BREAK -case 60: -YY_RULE_SETUP -#line 231 "scanner.ll" -return T_FALSE; - YY_BREAK -case 61: -YY_RULE_SETUP -#line 232 "scanner.ll" -return T_TRUE; - YY_BREAK -case 62: -YY_RULE_SETUP -#line 233 "scanner.ll" -return T_FALSE; - YY_BREAK -case 63: -YY_RULE_SETUP -#line 234 "scanner.ll" -return T_DCOP_AREA; - YY_BREAK -case 64: -YY_RULE_SETUP -#line 235 "scanner.ll" -return T_DCOP_SIGNAL_AREA; - YY_BREAK -case 65: -YY_RULE_SETUP -#line 236 "scanner.ll" -return T_TYPEDEF; - YY_BREAK -case 66: -YY_RULE_SETUP -#line 237 "scanner.ll" -return T_DCOP; - YY_BREAK -case 67: -YY_RULE_SETUP -#line 238 "scanner.ll" -; - YY_BREAK -case 68: -YY_RULE_SETUP -#line 239 "scanner.ll" -; - YY_BREAK -case 69: -YY_RULE_SETUP -#line 240 "scanner.ll" -return T_NULL; - YY_BREAK -case 70: -YY_RULE_SETUP -#line 241 "scanner.ll" -return T_EXTERN; - YY_BREAK -case 71: -YY_RULE_SETUP -#line 242 "scanner.ll" -return T_EXTERN_C; - YY_BREAK -case 72: -YY_RULE_SETUP -#line 244 "scanner.ll" -{ - yylval._str = new TQString( yytext ); - return T_IDENTIFIER; - } - YY_BREAK -case 73: -#line 250 "scanner.ll" -case 74: -#line 251 "scanner.ll" -case 75: -#line 252 "scanner.ll" -case 76: -#line 253 "scanner.ll" -case 77: -YY_RULE_SETUP -#line 253 "scanner.ll" -{ - yylval._float = ascii_to_longdouble( yytext ); - return T_DOUBLE_LITERAL; - } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 257 "scanner.ll" -{ - yylval._int = ascii_to_longlong( 10, yytext ); - return T_INTEGER_LITERAL; - } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 261 "scanner.ll" -{ - yylval._int = ascii_to_longlong( 8, yytext ); - return T_INTEGER_LITERAL; - } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 265 "scanner.ll" -{ - yylval._int = ascii_to_longlong( 16, yytext + 2 ); - return T_INTEGER_LITERAL; - } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 269 "scanner.ll" -{ - TQCString s( yytext ); - s = s.mid( 1, s.length() - 2 ); - yylval._char = translate_char( s ); - return T_CHARACTER_LITERAL; - } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 275 "scanner.ll" -{ - TQString s( yytext ); - yylval._str = new TQString( s.mid( 1, s.length() - 2 ) ); - return T_STRING_LITERAL; - } - YY_BREAK -case 83: -YY_RULE_SETUP -#line 280 "scanner.ll" -{ - if (function_mode) - return yylex(); // call once again - - tqFatal("could not parse %c(%d) at line %d" , yytext[0], yytext[0], idl_line_no); - return T_UNKNOWN; - } - YY_BREAK -case 84: -YY_RULE_SETUP -#line 288 "scanner.ll" -ECHO; - YY_BREAK -#line 1771 "scanner.cc" - case YY_STATE_EOF(INITIAL): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( yywrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of yylex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = (yytext_ptr); - int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart(yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - yy_state_type yy_current_state; - char *yy_cp; - - yy_current_state = (yy_start); - - (yy_state_ptr) = (yy_state_buf); - *(yy_state_ptr)++ = yy_current_state; - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 319 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - *(yy_state_ptr)++ = yy_current_state; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - int yy_is_jam; - - YY_CHAR yy_c = 1; - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 319 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 318); - if ( ! yy_is_jam ) - *(yy_state_ptr)++ = yy_current_state; - - return yy_is_jam ? 0 : yy_current_state; -} - - static void yyunput (int c, char * yy_bp ) -{ - char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up yytext */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - int number_to_move = (yy_n_chars) + 2; - char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart(yyin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap( ) ) - return EOF; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve yytext */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer(yyin,YY_BUF_SIZE ); - } - - yy_init_buffer(YY_CURRENT_BUFFER,input_file ); - yy_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void yy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * - */ - void yy_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yyfree((void *) b->yy_ch_buf ); - - yyfree((void *) b ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. - */ - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - yy_flush_buffer(b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void yy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - yyensure_buffer_stack(); - - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void yypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void yyensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to yylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * yy_scan_bytes() instead. - */ -YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) -{ - - return yy_scan_bytes(yystr,strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) yyalloc(n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer(buf,n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "[dcopidl-scanner] %s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = (yy_hold_char); \ - (yy_c_buf_p) = yytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int yyget_lineno (void) -{ - - return yylineno; -} - -/** Get the input stream. - * - */ -FILE *yyget_in (void) -{ - return yyin; -} - -/** Get the output stream. - * - */ -FILE *yyget_out (void) -{ - return yyout; -} - -/** Get the length of the current token. - * - */ -int yyget_leng (void) -{ - return yyleng; -} - -/** Get the current token. - * - */ - -char *yyget_text (void) -{ - return yytext; -} - -/** Set the current line number. - * @param line_number - * - */ -void yyset_lineno (int line_number ) -{ - - yylineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see yy_switch_to_buffer - */ -void yyset_in (FILE * in_str ) -{ - yyin = in_str ; -} - -void yyset_out (FILE * out_str ) -{ - yyout = out_str ; -} - -int yyget_debug (void) -{ - return yy_flex_debug; -} - -void yyset_debug (int bdebug ) -{ - yy_flex_debug = bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from yylex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - - (yy_state_buf) = 0; - (yy_state_ptr) = 0; - (yy_full_match) = 0; - (yy_lp) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; -#else - yyin = (FILE *) 0; - yyout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * yylex_init() - */ - return 0; -} - -/* yylex_destroy is for both reentrant and non-reentrant scanners. */ -int yylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - yypop_buffer_state(); - } - - /* Destroy the stack itself. */ - yyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - yyfree ( (yy_state_buf) ); - (yy_state_buf) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * yylex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ - int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *yyalloc (yy_size_t size ) -{ - return (void *) malloc( size ); -} - -void *yyrealloc (void * ptr, yy_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void yyfree (void * ptr ) -{ - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 288 "scanner.ll" - - - -void dcopidlInitFlex( const char *_code ) -{ - comment_mode = 0; - yy_switch_to_buffer(yy_scan_string(_code ) ); -} - diff --git a/dcop/dcopidl/scanner.cpp b/dcop/dcopidl/scanner.cpp new file mode 100644 index 000000000..4ff8d1ac3 --- /dev/null +++ b/dcop/dcopidl/scanner.cpp @@ -0,0 +1,2747 @@ +#line 2 "scanner.cpp" + +#line 4 "scanner.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 84 +#define YY_END_OF_BUFFER 85 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_acclist[672] = + { 0, + 6, 6, 85, 6, 83, 84, 1, 6, 83, 84, + 2, 84, 6, 83, 84, 6, 83, 84, 6, 83, + 84, 6, 23, 83, 84, 6, 83, 84, 6, 14, + 83, 84, 6, 15, 83, 84, 7, 21, 83, 84, + 6, 17, 83, 84, 6, 20, 83, 84, 6, 18, + 83, 84, 6, 28, 83, 84, 6, 83, 84, 6, + 69, 79, 83, 84, 6, 78, 83, 84, 6, 16, + 83, 84, 6, 22, 83, 84, 6, 24, 83, 84, + 6, 27, 83, 84, 6, 25, 83, 84, 6, 72, + 83, 84, 6, 72, 83, 84, 6, 72, 83, 84, + + 6, 72, 83, 84, 6, 72, 83, 84, 6, 30, + 83, 84, 6, 31, 83, 84, 6, 72, 83, 84, + 6, 72, 83, 84, 6, 72, 83, 84, 6, 72, + 83, 84, 6, 72, 83, 84, 6, 72, 83, 84, + 6, 72, 83, 84, 6, 72, 83, 84, 6, 72, + 83, 84, 6, 72, 83, 84, 6, 72, 83, 84, + 6, 72, 83, 84, 6, 72, 83, 84, 6, 72, + 83, 84, 6, 72, 83, 84, 6, 12, 83, 84, + 5, 13, 83, 84, 6, 19, 83, 84, 6, 6, + 34, 6, 6, 82, 6, 6, 11, 6, 9, 6, + + 6, 6, 4, 6, 32, 6, 6, 76, 3, 6, + 8, 6, 6, 79, 6, 6, 6, 69, 6, 80, + 6, 78, 6, 78, 6, 26, 6, 33, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 82, 6, 6, 6, 9, 9, 6, 6, 81, 81, + + 6, 81, 6, 6, 6, 29, 6, 6, 8, 8, + 6, 75, 6, 6, 74, 6, 80, 6, 72, 6, + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + 72, 6, 72, 6, 58, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 6, 6, 6, 6, 6, + 6, 77, 6, 6, 72, 6, 72, 6, 72, 6, + + 72, 6, 61, 72, 6, 59, 72, 6, 72, 6, + 72, 6, 36, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 72, 6, 50, 72, 6, 72, 6, + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + 72, 6, 57, 72, 6, 72, 6, 72, 6, 72, + 6, 72, 6, 6, 6, 6, 6, 6, 73, 6, + 62, 72, 6, 72, 6, 72, 6, 72, 6, 39, + 72, 6, 35, 72, 6, 72, 6, 60, 72, 6, + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + 49, 72, 6, 72, 6, 72, 6, 56, 72, 6, + 72, 6, 72, 6, 72, 6, 72, 6, 38, 72, + 6, 72, 6, 6, 66, 72, 6, 72, 6, 72, + 6, 72, 6, 51, 72, 6, 44, 72, 6, 63, + 72, 6, 72, 6, 72, 6, 72, 6, 72, 6, + 72, 6, 43, 72, 6, 55, 72, 6, 72, 6, + 47, 72, 6, 45, 72, 6, 40, 72, 6, 72, + 6, 72, 6, 72, 6, 6, 72, 6, 72, 6, + 6, 72, 6, 46, 72, 6, 72, 6, 72, 6, + + 53, 72, 6, 72, 6, 54, 72, 6, 65, 72, + 6, 72, 6, 42, 72, 6, 6, 67, 72, 6, + 72, 6, 70, 6, 70, 6, 72, 6, 72, 6, + 41, 72, 6, 72, 6, 48, 72, 6, 6, 6, + 68, 72, 6, 6, 72, 6, 37, 72, 6, 52, + 72, 6, 11, 6, 6, 71, 6, 72, 10, 11, + 6, 6, 72, 10, 6, 72, 6, 72, 6, 64, + 72 + } ; + +static yyconst flex_int16_t yy_accept[320] = + { 0, + 1, 2, 3, 4, 7, 11, 13, 16, 19, 22, + 26, 29, 33, 37, 41, 45, 49, 53, 57, 60, + 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, + 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, + 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, + 185, 189, 190, 192, 193, 195, 195, 196, 197, 198, + 200, 200, 201, 202, 202, 203, 204, 206, 207, 209, + 210, 212, 213, 215, 216, 217, 219, 221, 223, 225, + 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, + 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, + + 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, + 287, 289, 291, 292, 292, 293, 294, 296, 297, 298, + 300, 301, 303, 304, 305, 307, 308, 310, 311, 313, + 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, + 334, 336, 338, 340, 342, 344, 347, 349, 351, 353, + 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, + 375, 377, 379, 381, 383, 385, 385, 385, 386, 387, + 388, 389, 390, 391, 393, 394, 396, 398, 400, 402, + 405, 408, 410, 412, 415, 417, 419, 421, 423, 425, + 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, + + 448, 450, 452, 455, 457, 459, 461, 463, 463, 463, + 464, 465, 466, 467, 468, 470, 473, 475, 477, 479, + 482, 485, 487, 490, 492, 494, 496, 498, 500, 502, + 504, 506, 508, 510, 513, 515, 517, 520, 522, 524, + 526, 528, 531, 533, 533, 533, 534, 537, 539, 541, + 543, 546, 549, 552, 554, 556, 558, 560, 562, 565, + 568, 570, 573, 576, 579, 581, 583, 585, 586, 588, + 590, 591, 593, 596, 598, 600, 603, 605, 608, 611, + 613, 616, 617, 620, 622, 624, 625, 626, 628, 630, + 633, 635, 638, 639, 640, 643, 644, 646, 649, 652, + + 653, 654, 655, 655, 657, 659, 659, 659, 661, 662, + 662, 664, 665, 665, 665, 667, 669, 672, 672 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 6, 7, 1, 1, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, + 19, 19, 19, 19, 19, 20, 20, 21, 22, 23, + 24, 25, 26, 1, 27, 28, 29, 30, 31, 32, + 33, 33, 33, 34, 35, 36, 33, 33, 37, 38, + 39, 40, 41, 42, 43, 33, 33, 44, 33, 33, + 45, 46, 47, 1, 48, 1, 49, 50, 51, 52, + + 53, 54, 55, 56, 57, 33, 58, 59, 60, 61, + 62, 63, 33, 64, 65, 66, 67, 68, 33, 69, + 70, 33, 71, 1, 72, 73, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[74] = + { 0, + 1, 2, 3, 4, 1, 5, 1, 1, 5, 1, + 1, 6, 1, 1, 1, 1, 1, 7, 7, 8, + 1, 1, 1, 1, 1, 5, 8, 8, 8, 8, + 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 9, 1, 5, 1, 4, 7, 7, + 8, 8, 8, 7, 4, 4, 4, 4, 4, 4, + 9, 4, 4, 9, 4, 9, 4, 9, 9, 4, + 1, 10, 1 + } ; + +static yyconst flex_int16_t yy_base[337] = + { 0, + 0, 0, 923, 0, 0, 1107, 898, 72, 74, 0, + 73, 0, 0, 904, 0, 0, 894, 71, 64, 79, + 85, 894, 0, 69, 890, 82, 148, 221, 61, 69, + 73, 0, 0, 81, 53, 75, 67, 93, 98, 84, + 139, 115, 120, 148, 140, 141, 149, 150, 0, 1107, + 0, 0, 0, 206, 0, 174, 289, 178, 1107, 179, + 910, 197, 903, 902, 353, 1107, 0, 894, 243, 1107, + 114, 115, 257, 266, 286, 0, 405, 293, 0, 0, + 0, 882, 100, 162, 176, 156, 190, 175, 222, 226, + 188, 213, 230, 233, 264, 189, 232, 237, 212, 227, + + 275, 290, 254, 238, 287, 256, 299, 289, 298, 295, + 294, 300, 1107, 326, 372, 442, 370, 905, 377, 0, + 1107, 898, 357, 479, 0, 368, 322, 0, 432, 349, + 386, 0, 229, 320, 102, 304, 365, 301, 350, 366, + 325, 373, 374, 385, 383, 878, 402, 386, 371, 437, + 381, 400, 382, 384, 419, 403, 420, 438, 439, 448, + 449, 450, 455, 452, 451, 508, 0, 532, 603, 477, + 528, 667, 500, 503, 540, 456, 498, 514, 473, 877, + 876, 497, 513, 875, 512, 489, 516, 525, 518, 874, + 534, 529, 536, 538, 530, 539, 537, 540, 542, 543, + + 541, 546, 864, 547, 545, 548, 544, 601, 716, 612, + 634, 578, 881, 607, 619, 862, 555, 457, 583, 848, + 847, 601, 843, 561, 589, 585, 602, 614, 616, 617, + 637, 638, 632, 841, 633, 639, 840, 651, 624, 647, + 640, 839, 654, 662, 663, 660, 838, 644, 680, 700, + 837, 835, 678, 686, 688, 652, 696, 697, 834, 832, + 706, 830, 829, 823, 698, 701, 683, 726, 713, 724, + 798, 723, 814, 729, 714, 809, 704, 808, 800, 731, + 799, 770, 764, 733, 871, 701, 0, 732, 734, 643, + 750, 575, 826, 828, 565, 583, 737, 309, 158, 848, + + 173, 783, 791, 0, 757, 775, 351, 1107, 834, 782, + 790, 1107, 787, 793, 774, 798, 56, 1107, 944, 953, + 963, 973, 983, 992, 1002, 1012, 1022, 1028, 1037, 1047, + 1051, 1059, 1067, 1076, 1086, 1096 + } ; + +static yyconst flex_int16_t yy_def[337] = + { 0, + 318, 1, 318, 319, 319, 318, 319, 320, 321, 319, + 322, 319, 319, 318, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 323, 323, 28, 28, + 28, 319, 319, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 319, 318, + 319, 319, 319, 320, 319, 324, 319, 321, 318, 325, + 326, 321, 319, 318, 319, 318, 319, 319, 319, 318, + 327, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 318, 328, 320, 319, 325, 329, 321, 319, + 318, 319, 319, 319, 319, 319, 327, 330, 319, 319, + 319, 77, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 324, 331, 320, 320, 321, + 319, 319, 319, 319, 319, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + + 28, 28, 28, 28, 28, 28, 28, 324, 324, 320, + 320, 321, 319, 319, 319, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 324, 324, 321, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 321, 28, 28, + 332, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 321, 28, 28, 332, 319, 333, 28, 28, 28, + 28, 28, 321, 334, 28, 319, 28, 28, 28, 334, + + 335, 321, 336, 319, 28, 335, 318, 318, 321, 326, + 28, 318, 318, 326, 28, 28, 28, 0, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318 + } ; + +static yyconst flex_int16_t yy_nxt[1181] = + { 0, + 4, 5, 6, 5, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, + 22, 23, 24, 25, 26, 4, 27, 27, 27, 27, + 27, 28, 27, 27, 29, 27, 27, 27, 30, 27, + 27, 31, 27, 27, 32, 4, 33, 27, 27, 27, + 34, 27, 35, 36, 27, 27, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 27, 27, + 49, 50, 51, 52, 52, 70, 59, 55, 60, 82, + 71, 52, 82, 56, 64, 61, 68, 82, 69, 69, + 69, 81, 53, 82, 72, 82, 73, 73, 74, 82, + + 72, 82, 78, 78, 78, 53, 81, 82, 84, 75, + 82, 86, 87, 91, 76, 75, 85, 57, 65, 82, + 79, 92, 77, 93, 82, 128, 82, 95, 82, 178, + 62, 75, 129, 129, 129, 133, 88, 75, 94, 89, + 96, 82, 90, 56, 64, 61, 82, 77, 52, 52, + 98, 52, 52, 52, 52, 52, 52, 52, 52, 97, + 52, 52, 52, 52, 52, 82, 82, 82, 52, 52, + 52, 52, 52, 52, 82, 82, 82, 100, 307, 113, + 59, 59, 82, 101, 82, 128, 102, 99, 82, 61, + 118, 134, 52, 52, 52, 104, 105, 307, 106, 59, + + 103, 82, 82, 136, 108, 107, 112, 52, 61, 110, + 109, 55, 135, 111, 82, 82, 82, 56, 52, 114, + 52, 52, 52, 138, 52, 52, 52, 52, 52, 52, + 52, 52, 137, 52, 52, 52, 52, 52, 82, 82, + 147, 52, 52, 52, 52, 52, 52, 83, 82, 61, + 118, 57, 82, 82, 141, 82, 82, 119, 82, 82, + 69, 69, 69, 82, 82, 52, 52, 52, 61, 176, + 139, 150, 72, 126, 73, 73, 74, 56, 142, 151, + 82, 72, 82, 74, 74, 74, 140, 75, 143, 144, + 82, 52, 148, 52, 54, 126, 75, 54, 130, 156, + + 130, 82, 149, 131, 131, 131, 115, 115, 72, 75, + 78, 78, 78, 82, 54, 82, 82, 158, 75, 155, + 82, 82, 145, 75, 82, 82, 82, 82, 79, 146, + 82, 152, 116, 128, 54, 82, 153, 54, 54, 154, + 179, 157, 54, 166, 166, 75, 82, 159, 177, 54, + 164, 82, 54, 312, 54, 161, 54, 116, 63, 163, + 162, 122, 160, 165, 181, 120, 131, 131, 131, 167, + 123, 123, 59, 52, 171, 171, 82, 55, 63, 59, + 173, 118, 173, 56, 184, 174, 174, 174, 61, 168, + 168, 82, 82, 128, 167, 180, 124, 82, 63, 82, + + 82, 63, 63, 131, 131, 131, 63, 82, 82, 82, + 82, 82, 82, 63, 182, 313, 63, 57, 63, 191, + 63, 124, 132, 132, 132, 185, 82, 170, 82, 82, + 183, 132, 132, 132, 132, 132, 132, 187, 186, 188, + 190, 118, 196, 56, 193, 82, 82, 195, 61, 129, + 129, 129, 189, 132, 132, 132, 132, 132, 132, 169, + 169, 169, 175, 82, 82, 82, 198, 194, 169, 169, + 169, 169, 169, 169, 82, 82, 82, 82, 82, 59, + 199, 82, 82, 82, 175, 197, 216, 248, 61, 192, + 169, 169, 169, 169, 169, 169, 172, 172, 172, 82, + + 219, 203, 204, 200, 201, 172, 172, 172, 172, 172, + 172, 205, 206, 113, 202, 82, 207, 174, 174, 174, + 174, 174, 174, 82, 82, 208, 208, 172, 172, 172, + 172, 172, 172, 52, 217, 212, 120, 55, 82, 82, + 82, 223, 82, 56, 82, 63, 63, 218, 61, 210, + 210, 82, 214, 114, 214, 82, 82, 215, 215, 215, + 82, 220, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 222, 224, 57, 221, 226, + 59, 82, 231, 227, 229, 225, 230, 82, 304, 61, + 235, 82, 247, 228, 236, 232, 239, 238, 240, 241, + + 233, 82, 242, 56, 52, 234, 113, 237, 55, 82, + 243, 82, 251, 52, 56, 82, 249, 55, 244, 244, + 211, 211, 211, 56, 215, 215, 215, 82, 82, 211, + 211, 211, 211, 211, 211, 52, 215, 215, 215, 55, + 82, 252, 82, 82, 246, 56, 114, 253, 57, 61, + 82, 211, 211, 211, 211, 211, 211, 57, 82, 82, + 254, 250, 59, 82, 82, 82, 82, 113, 113, 82, + 82, 61, 269, 82, 56, 120, 255, 82, 82, 57, + 82, 256, 257, 56, 213, 213, 213, 258, 259, 264, + 262, 261, 260, 213, 213, 213, 213, 213, 213, 265, + + 266, 263, 267, 271, 82, 56, 82, 114, 114, 82, + 270, 268, 82, 275, 82, 213, 213, 213, 213, 213, + 213, 113, 82, 82, 82, 272, 82, 82, 59, 296, + 82, 61, 82, 245, 245, 245, 274, 61, 273, 82, + 82, 281, 245, 245, 245, 245, 245, 245, 276, 82, + 82, 279, 284, 280, 283, 82, 291, 82, 82, 82, + 82, 114, 277, 82, 245, 245, 245, 245, 245, 245, + 278, 293, 59, 293, 295, 294, 82, 290, 282, 289, + 307, 61, 292, 82, 308, 308, 298, 288, 297, 312, + 82, 305, 294, 301, 61, 308, 310, 61, 52, 307, + + 82, 299, 52, 286, 52, 52, 52, 52, 52, 287, + 52, 52, 52, 52, 52, 310, 82, 311, 52, 52, + 52, 52, 52, 52, 82, 82, 82, 293, 59, 293, + 301, 294, 316, 302, 82, 82, 308, 61, 315, 303, + 82, 61, 52, 52, 52, 61, 314, 309, 294, 82, + 301, 313, 302, 302, 61, 82, 82, 314, 82, 303, + 82, 82, 317, 82, 82, 82, 82, 82, 52, 82, + 52, 52, 302, 82, 82, 52, 52, 52, 52, 52, + 52, 52, 287, 52, 52, 52, 52, 52, 82, 120, + 82, 52, 52, 52, 52, 52, 52, 61, 309, 303, + + 82, 82, 82, 82, 82, 61, 120, 59, 82, 125, + 121, 120, 59, 53, 80, 52, 52, 52, 67, 303, + 66, 53, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 52, 318, 52, 52, 52, 318, 52, 52, 318, + 52, 52, 52, 54, 54, 318, 54, 54, 54, 54, + 54, 54, 54, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 63, 63, 318, 63, 63, 63, 63, + 63, 63, 63, 82, 82, 318, 82, 82, 318, 82, + 82, 82, 56, 318, 318, 56, 56, 56, 56, 56, + + 56, 56, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 127, 127, 318, 127, 127, 127, 127, 127, + 127, 127, 56, 318, 56, 318, 56, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 128, 128, 318, + 128, 128, 128, 128, 128, 128, 128, 209, 209, 285, + 285, 318, 285, 285, 285, 285, 285, 285, 287, 318, + 287, 318, 287, 287, 287, 287, 300, 300, 300, 300, + 300, 300, 300, 300, 300, 300, 306, 306, 306, 306, + 306, 306, 306, 306, 306, 306, 303, 303, 303, 303, + + 303, 303, 303, 303, 303, 303, 3, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318 + } ; + +static yyconst flex_int16_t yy_chk[1181] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 8, 11, 19, 9, 8, 9, 35, + 19, 11, 317, 8, 11, 9, 18, 29, 18, 18, + 18, 24, 24, 37, 20, 30, 20, 20, 20, 31, + + 21, 36, 21, 21, 21, 26, 26, 34, 29, 20, + 40, 31, 31, 35, 20, 21, 30, 8, 11, 38, + 21, 35, 20, 36, 39, 71, 83, 37, 135, 135, + 9, 20, 72, 72, 72, 83, 34, 21, 36, 34, + 38, 42, 34, 8, 11, 9, 43, 20, 27, 27, + 40, 27, 27, 27, 27, 27, 27, 27, 27, 39, + 27, 27, 27, 27, 27, 41, 45, 46, 27, 27, + 27, 27, 27, 27, 44, 47, 48, 42, 301, 56, + 58, 60, 86, 43, 299, 71, 43, 41, 84, 58, + 60, 84, 27, 27, 27, 45, 45, 301, 45, 62, + + 44, 88, 85, 86, 46, 45, 48, 54, 62, 47, + 46, 54, 85, 47, 91, 96, 87, 54, 27, 56, + 27, 28, 28, 88, 28, 28, 28, 28, 28, 28, + 28, 28, 87, 28, 28, 28, 28, 28, 99, 92, + 96, 28, 28, 28, 28, 28, 28, 28, 89, 58, + 60, 54, 90, 100, 91, 133, 93, 62, 97, 94, + 69, 69, 69, 98, 104, 28, 28, 28, 62, 133, + 89, 99, 73, 69, 73, 73, 73, 54, 92, 100, + 103, 74, 106, 74, 74, 74, 90, 73, 93, 94, + 95, 28, 97, 28, 57, 69, 74, 57, 75, 104, + + 75, 101, 98, 75, 75, 75, 57, 57, 78, 73, + 78, 78, 78, 105, 57, 108, 102, 106, 74, 103, + 111, 110, 95, 78, 109, 107, 112, 138, 78, 95, + 136, 101, 57, 127, 57, 298, 101, 57, 57, 102, + 136, 105, 57, 114, 114, 78, 134, 107, 134, 57, + 111, 141, 57, 307, 57, 108, 57, 57, 65, 110, + 109, 65, 107, 112, 138, 123, 130, 130, 130, 114, + 65, 65, 117, 115, 123, 123, 139, 115, 65, 119, + 126, 117, 126, 115, 141, 126, 126, 126, 119, 115, + 115, 137, 140, 127, 114, 137, 65, 149, 65, 142, + + 143, 65, 65, 131, 131, 131, 65, 151, 153, 145, + 154, 144, 148, 65, 139, 307, 65, 115, 65, 149, + 65, 65, 77, 77, 77, 142, 152, 119, 147, 156, + 140, 77, 77, 77, 77, 77, 77, 144, 143, 145, + 148, 117, 154, 115, 151, 155, 157, 153, 119, 129, + 129, 129, 147, 77, 77, 77, 77, 77, 77, 116, + 116, 116, 129, 150, 158, 159, 156, 152, 116, 116, + 116, 116, 116, 116, 160, 161, 162, 165, 164, 170, + 157, 163, 176, 218, 129, 155, 176, 218, 170, 150, + 116, 116, 116, 116, 116, 116, 124, 124, 124, 179, + + 179, 161, 162, 158, 159, 124, 124, 124, 124, 124, + 124, 163, 164, 166, 160, 186, 165, 173, 173, 173, + 174, 174, 174, 182, 177, 166, 166, 124, 124, 124, + 124, 124, 124, 168, 177, 170, 171, 168, 185, 183, + 178, 186, 187, 168, 189, 171, 171, 178, 170, 168, + 168, 188, 175, 166, 175, 192, 195, 175, 175, 175, + 191, 182, 193, 197, 194, 196, 198, 201, 199, 200, + 207, 205, 202, 204, 206, 185, 187, 168, 183, 189, + 212, 217, 195, 191, 193, 188, 194, 224, 296, 212, + 199, 295, 217, 192, 199, 196, 202, 201, 204, 205, + + 197, 292, 206, 168, 169, 198, 208, 200, 169, 219, + 207, 226, 224, 210, 169, 225, 219, 210, 208, 208, + 169, 169, 169, 210, 214, 214, 214, 222, 227, 169, + 169, 169, 169, 169, 169, 211, 215, 215, 215, 211, + 228, 225, 229, 230, 212, 211, 208, 226, 169, 212, + 239, 169, 169, 169, 169, 169, 169, 210, 233, 235, + 227, 222, 246, 231, 232, 236, 241, 244, 245, 290, + 248, 246, 248, 240, 169, 172, 228, 238, 256, 211, + 243, 229, 230, 210, 172, 172, 172, 231, 232, 239, + 236, 235, 233, 172, 172, 172, 172, 172, 172, 240, + + 241, 238, 243, 250, 253, 211, 249, 244, 245, 267, + 249, 246, 254, 256, 255, 172, 172, 172, 172, 172, + 172, 209, 257, 258, 265, 253, 250, 266, 268, 286, + 277, 246, 261, 209, 209, 209, 255, 268, 254, 269, + 275, 267, 209, 209, 209, 209, 209, 209, 257, 272, + 270, 265, 270, 266, 269, 274, 277, 280, 288, 284, + 289, 209, 258, 297, 209, 209, 209, 209, 209, 209, + 261, 282, 282, 282, 284, 282, 291, 275, 268, 274, + 306, 282, 280, 305, 310, 302, 289, 272, 288, 313, + 283, 297, 282, 303, 302, 314, 303, 268, 271, 306, + + 315, 291, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 303, 311, 305, 271, 271, + 271, 271, 271, 271, 316, 281, 279, 293, 293, 293, + 294, 293, 315, 294, 278, 276, 309, 293, 311, 294, + 273, 282, 271, 271, 271, 309, 310, 302, 293, 264, + 300, 313, 294, 300, 302, 263, 262, 314, 260, 300, + 259, 252, 316, 251, 247, 242, 237, 234, 271, 223, + 271, 285, 300, 221, 220, 285, 285, 285, 285, 285, + 285, 285, 285, 285, 285, 285, 285, 285, 216, 213, + 203, 285, 285, 285, 285, 285, 285, 293, 309, 294, + + 190, 184, 181, 180, 146, 309, 122, 118, 82, 68, + 64, 63, 61, 25, 22, 285, 285, 285, 17, 300, + 14, 7, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 285, 0, 285, 319, 319, 0, 319, 319, 0, + 319, 319, 319, 320, 320, 0, 320, 320, 320, 320, + 320, 320, 320, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 322, 322, 0, 322, 322, 322, 322, + 322, 322, 322, 323, 323, 0, 323, 323, 0, 323, + 323, 323, 324, 0, 0, 324, 324, 324, 324, 324, + + 324, 324, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 327, 327, 0, 327, 327, 327, 327, 327, + 327, 327, 328, 0, 328, 0, 328, 329, 329, 329, + 329, 329, 329, 329, 329, 329, 329, 330, 330, 0, + 330, 330, 330, 330, 330, 330, 330, 331, 331, 332, + 332, 0, 332, 332, 332, 332, 332, 332, 333, 0, + 333, 0, 333, 333, 333, 333, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 336, 336, 336, 336, + + 336, 336, 336, 336, 336, 336, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, + 318, 318, 318, 318, 318, 318, 318, 318, 318, 318 + } ; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; +static char *yy_full_match; +static int yy_lp; +#define REJECT \ +{ \ +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \ +yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ +++(yy_lp); \ +goto find_rule; \ +} + +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "scanner.ll" +#line 2 "scanner.ll" +/***************************************************************** +Copyright (c) 1999 Torben Weis +Copyright (c) 2000 Matthias Ettrich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#define YY_NO_UNPUT +#include +#include + +class TQString; + +#ifndef KDE_USE_FINAL +#include "yacc.cpp.h" +#endif + +extern int idl_line_no; +int comment_mode; +int function_mode = 0; + +#include +#include + +static long ascii_to_longlong( long base, const char *s ) +{ + long ll = 0; + while( *s != '\0' ) { + char c = *s++; + if( c >= 'a' ) + c -= 'a' - 'A'; + c -= '0'; + if( c > 9 ) + c -= 'A' - '0' - 10; + ll = ll * base + c; + } + return ll; +} + +static double ascii_to_longdouble (const char *s) +{ + double d; +#ifdef HAVE_SCANF_LF + sscanf (s, "%Lf", &d); +#else + /* + * this is only an approximation and will probably break fixed<> + * parameter calculation on systems where + * sizeof(double) < sizeof(long double). but fortunately all + * systems where scanf("%Lf") is known to be broken (Linux/Alpha + * and HPUX) have sizeof(double) == sizeof(long double). + */ + d = strtod (s, NULL); +#endif + return d; +} + +static char translate_char( const char *s ) +{ + char c = *s++; + + if( c != '\\' ) + return c; + c = *s++; + switch( c ) { + case 'n': + return '\n'; + case 't': + return '\t'; + case 'v': + return '\v'; + case 'b': + return '\b'; + case 'r': + return '\r'; + case 'f': + return '\f'; + case 'a': + return '\a'; + case '\\': + return '\\'; + case '?': + return '\?'; + case '\'': + return '\''; + case '"': + return '"'; + case 'x': + case 'X': + return (char) ascii_to_longlong( 16, s ); + default: + // Gotta be an octal + return (char) ascii_to_longlong( 8, s ); + } +} + + +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +#line 1030 "scanner.cpp" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + +#line 148 "scanner.ll" + + +#line 1220 "scanner.cpp" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + /* Create the reject buffer large enough to save one state per allowed character. */ + if ( ! (yy_state_buf) ) + (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE ); + if ( ! (yy_state_buf) ) + YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); + + (yy_state_ptr) = (yy_state_buf); + *(yy_state_ptr)++ = yy_current_state; + +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 319 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *(yy_state_ptr)++ = yy_current_state; + ++yy_cp; + } + while ( yy_current_state != 318 ); + +yy_find_action: + yy_current_state = *--(yy_state_ptr); + (yy_lp) = yy_accept[yy_current_state]; +find_rule: /* we branch to this label when backing up */ + for ( ; ; ) /* until we find what rule we matched */ + { + if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) + { + yy_act = yy_acclist[(yy_lp)]; + { + (yy_full_match) = yy_cp; + break; + } + } + --yy_cp; + yy_current_state = *--(yy_state_ptr); + (yy_lp) = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +YY_RULE_SETUP +#line 150 "scanner.ll" +; + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 151 "scanner.ll" +{ idl_line_no++; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 153 "scanner.ll" +{ comment_mode = 1; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 154 "scanner.ll" +{ if (!comment_mode) { REJECT; } else { comment_mode = 0; } } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 155 "scanner.ll" +{ + if (! comment_mode) { + if (!function_mode) { REJECT; } else { + function_mode = 0; + return T_RIGHT_CURLY_BRACKET; + } + } + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 163 "scanner.ll" +{ if (!comment_mode && !function_mode) { REJECT; } } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 164 "scanner.ll" +{ if (!comment_mode) { REJECT; } } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 166 "scanner.ll" +; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 167 "scanner.ll" +{ + exit( 1 ); + } + YY_BREAK +case 10: +/* rule 10 can match eol */ +YY_RULE_SETUP +#line 170 "scanner.ll" +{ + TQString s( yytext ); + int i = s.find(TQRegExp("[\"<]"))+1; + int j = s.find(TQRegExp("[\">]"), i); + yylval._str = new TQString( s.mid( i, j - i ) ); + idl_line_no++; + return T_INCLUDE; + } + YY_BREAK +case 11: +/* rule 11 can match eol */ +YY_RULE_SETUP +#line 178 "scanner.ll" +{ + idl_line_no++; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 181 "scanner.ll" +return T_LEFT_CURLY_BRACKET; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 182 "scanner.ll" +return T_RIGHT_CURLY_BRACKET; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 183 "scanner.ll" +return T_LEFT_PARANTHESIS; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 184 "scanner.ll" +return T_RIGHT_PARANTHESIS; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 185 "scanner.ll" +return T_COLON; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 186 "scanner.ll" +return T_PLUS; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 187 "scanner.ll" +return T_MINUS; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 188 "scanner.ll" +return T_TILDE; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 189 "scanner.ll" +return T_COMMA; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 190 "scanner.ll" +return T_ASTERISK; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 191 "scanner.ll" +return T_SEMICOLON; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 192 "scanner.ll" +return T_AMPERSAND; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 193 "scanner.ll" +return T_LESS; + YY_BREAK +case 25: +YY_RULE_SETUP +#line 194 "scanner.ll" +return T_GREATER; + YY_BREAK +case 26: +YY_RULE_SETUP +#line 195 "scanner.ll" +return T_SCOPE; + YY_BREAK +case 27: +YY_RULE_SETUP +#line 196 "scanner.ll" +return T_EQUAL; + YY_BREAK +case 28: +YY_RULE_SETUP +#line 197 "scanner.ll" +return T_ACCESS; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 198 "scanner.ll" +return T_TRIPLE_DOT; + YY_BREAK +case 30: +YY_RULE_SETUP +#line 199 "scanner.ll" +return T_ARRAY_OPEN; + YY_BREAK +case 31: +YY_RULE_SETUP +#line 200 "scanner.ll" +return T_ARRAY_CLOSE; + YY_BREAK +case 32: +YY_RULE_SETUP +#line 201 "scanner.ll" +return T_ACCESS; + YY_BREAK +case 33: +YY_RULE_SETUP +#line 202 "scanner.ll" +return T_SHIFT; + YY_BREAK +case 34: +YY_RULE_SETUP +#line 203 "scanner.ll" +return T_MISCOPERATOR; + YY_BREAK +case 35: +YY_RULE_SETUP +#line 206 "scanner.ll" +return T_CONST; + YY_BREAK +case 36: +YY_RULE_SETUP +#line 207 "scanner.ll" +return T_ENUM; + YY_BREAK +case 37: +YY_RULE_SETUP +#line 208 "scanner.ll" +return T_NAMESPACE; + YY_BREAK +case 38: +YY_RULE_SETUP +#line 209 "scanner.ll" +return T_USING; + YY_BREAK +case 39: +YY_RULE_SETUP +#line 210 "scanner.ll" +return T_CLASS; + YY_BREAK +case 40: +YY_RULE_SETUP +#line 211 "scanner.ll" +return T_STRUCT; + YY_BREAK +case 41: +YY_RULE_SETUP +#line 212 "scanner.ll" +return T_FUNOPERATOR; + YY_BREAK +case 42: +YY_RULE_SETUP +#line 213 "scanner.ll" +return T_VIRTUAL; + YY_BREAK +case 43: +YY_RULE_SETUP +#line 214 "scanner.ll" +return T_PUBLIC; + YY_BREAK +case 44: +YY_RULE_SETUP +#line 215 "scanner.ll" +return T_INLINE; + YY_BREAK +case 45: +YY_RULE_SETUP +#line 216 "scanner.ll" +return T_STATIC; + YY_BREAK +case 46: +YY_RULE_SETUP +#line 217 "scanner.ll" +return T_MUTABLE; + YY_BREAK +case 47: +YY_RULE_SETUP +#line 218 "scanner.ll" +return T_SIGNED; + YY_BREAK +case 48: +YY_RULE_SETUP +#line 219 "scanner.ll" +return T_UNSIGNED; + YY_BREAK +case 49: +YY_RULE_SETUP +#line 220 "scanner.ll" +return T_SHORT; + YY_BREAK +case 50: +YY_RULE_SETUP +#line 221 "scanner.ll" +return T_LONG; + YY_BREAK +case 51: +YY_RULE_SETUP +#line 222 "scanner.ll" +return T_FRIEND; + YY_BREAK +case 52: +YY_RULE_SETUP +#line 223 "scanner.ll" +return T_PROTECTED; + YY_BREAK +case 53: +YY_RULE_SETUP +#line 224 "scanner.ll" +return T_PRIVATE; + YY_BREAK +case 54: +YY_RULE_SETUP +#line 225 "scanner.ll" +return T_SIGNAL; + YY_BREAK +case 55: +YY_RULE_SETUP +#line 226 "scanner.ll" +return T_RETURN; + YY_BREAK +case 56: +YY_RULE_SETUP +#line 227 "scanner.ll" +return T_SLOT; + YY_BREAK +case 57: +YY_RULE_SETUP +#line 228 "scanner.ll" +return T_TRUE; + YY_BREAK +case 58: +YY_RULE_SETUP +#line 229 "scanner.ll" +return T_INT; + YY_BREAK +case 59: +YY_RULE_SETUP +#line 230 "scanner.ll" +return T_CHAR; + YY_BREAK +case 60: +YY_RULE_SETUP +#line 231 "scanner.ll" +return T_FALSE; + YY_BREAK +case 61: +YY_RULE_SETUP +#line 232 "scanner.ll" +return T_TRUE; + YY_BREAK +case 62: +YY_RULE_SETUP +#line 233 "scanner.ll" +return T_FALSE; + YY_BREAK +case 63: +YY_RULE_SETUP +#line 234 "scanner.ll" +return T_DCOP_AREA; + YY_BREAK +case 64: +YY_RULE_SETUP +#line 235 "scanner.ll" +return T_DCOP_SIGNAL_AREA; + YY_BREAK +case 65: +YY_RULE_SETUP +#line 236 "scanner.ll" +return T_TYPEDEF; + YY_BREAK +case 66: +YY_RULE_SETUP +#line 237 "scanner.ll" +return T_DCOP; + YY_BREAK +case 67: +YY_RULE_SETUP +#line 238 "scanner.ll" +; + YY_BREAK +case 68: +YY_RULE_SETUP +#line 239 "scanner.ll" +; + YY_BREAK +case 69: +YY_RULE_SETUP +#line 240 "scanner.ll" +return T_NULL; + YY_BREAK +case 70: +YY_RULE_SETUP +#line 241 "scanner.ll" +return T_EXTERN; + YY_BREAK +case 71: +YY_RULE_SETUP +#line 242 "scanner.ll" +return T_EXTERN_C; + YY_BREAK +case 72: +YY_RULE_SETUP +#line 244 "scanner.ll" +{ + yylval._str = new TQString( yytext ); + return T_IDENTIFIER; + } + YY_BREAK +case 73: +#line 250 "scanner.ll" +case 74: +#line 251 "scanner.ll" +case 75: +#line 252 "scanner.ll" +case 76: +#line 253 "scanner.ll" +case 77: +YY_RULE_SETUP +#line 253 "scanner.ll" +{ + yylval._float = ascii_to_longdouble( yytext ); + return T_DOUBLE_LITERAL; + } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 257 "scanner.ll" +{ + yylval._int = ascii_to_longlong( 10, yytext ); + return T_INTEGER_LITERAL; + } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 261 "scanner.ll" +{ + yylval._int = ascii_to_longlong( 8, yytext ); + return T_INTEGER_LITERAL; + } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 265 "scanner.ll" +{ + yylval._int = ascii_to_longlong( 16, yytext + 2 ); + return T_INTEGER_LITERAL; + } + YY_BREAK +case 81: +YY_RULE_SETUP +#line 269 "scanner.ll" +{ + TQCString s( yytext ); + s = s.mid( 1, s.length() - 2 ); + yylval._char = translate_char( s ); + return T_CHARACTER_LITERAL; + } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 275 "scanner.ll" +{ + TQString s( yytext ); + yylval._str = new TQString( s.mid( 1, s.length() - 2 ) ); + return T_STRING_LITERAL; + } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 280 "scanner.ll" +{ + if (function_mode) + return yylex(); // call once again + + tqFatal("could not parse %c(%d) at line %d" , yytext[0], yytext[0], idl_line_no); + return T_UNKNOWN; + } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 288 "scanner.ll" +ECHO; + YY_BREAK +#line 1771 "scanner.cpp" + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + (yy_state_ptr) = (yy_state_buf); + *(yy_state_ptr)++ = yy_current_state; + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 319 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *(yy_state_ptr)++ = yy_current_state; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + + YY_CHAR yy_c = 1; + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 319 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 318); + if ( ! yy_is_jam ) + *(yy_state_ptr)++ = yy_current_state; + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, char * yy_bp ) +{ + char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + int number_to_move = (yy_n_chars) + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "[dcopidl-scanner] %s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + + (yy_state_buf) = 0; + (yy_state_ptr) = 0; + (yy_full_match) = 0; + (yy_lp) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + yyfree ( (yy_state_buf) ); + (yy_state_buf) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 288 "scanner.ll" + + + +void dcopidlInitFlex( const char *_code ) +{ + comment_mode = 0; + yy_switch_to_buffer(yy_scan_string(_code ) ); +} + diff --git a/dcop/dcopidl/scanner.ll b/dcop/dcopidl/scanner.ll index ad0f564e9..302da3e14 100644 --- a/dcop/dcopidl/scanner.ll +++ b/dcop/dcopidl/scanner.ll @@ -29,7 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class TQString; #ifndef KDE_USE_FINAL -#include "yacc.cc.h" +#include "yacc.cpp.h" #endif extern int idl_line_no; diff --git a/dcop/dcopidl/yacc.cc b/dcop/dcopidl/yacc.cc deleted file mode 100644 index 615af46ef..000000000 --- a/dcop/dcopidl/yacc.cc +++ /dev/null @@ -1,3390 +0,0 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.4.1" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - - - -/* Copy the first part of user declarations. */ - -/* Line 189 of yacc.c */ -#line 1 "yacc.yy" - -/***************************************************************** -Copyright (c) 1999 Torben Weis -Copyright (c) 2000 Matthias Ettrich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************/ - -#include - -// Workaround for a bison issue: -// bison.simple concludes from _GNU_SOURCE that stpcpy is available, -// while GNU string.h only exposes it if __USE_GNU is set. -#ifdef _GNU_SOURCE -#define __USE_GNU 1 -#endif - -#include -#include -#include - -#include - -#define AMP_ENTITY "&" -#define YYERROR_VERBOSE - -extern int yylex(); - -// extern QString idl_lexFile; -extern int idl_line_no; -extern int function_mode; - -static int dcop_area = 0; -static int dcop_signal_area = 0; - -static QString in_namespace( "" ); - -void dcopidlInitFlex( const char *_code ); - -void yyerror( const char *s ) -{ - tqDebug( "In line %i : %s", idl_line_no, s ); - exit(1); - // theParser->parse_error( idl_lexFile, s, idl_line_no ); -} - - - -/* Line 189 of yacc.c */ -#line 138 "yacc.cc" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - T_UNIMPORTANT = 258, - T_CHARACTER_LITERAL = 259, - T_DOUBLE_LITERAL = 260, - T_IDENTIFIER = 261, - T_INTEGER_LITERAL = 262, - T_STRING_LITERAL = 263, - T_INCLUDE = 264, - T_CLASS = 265, - T_STRUCT = 266, - T_LEFT_CURLY_BRACKET = 267, - T_LEFT_PARANTHESIS = 268, - T_RIGHT_CURLY_BRACKET = 269, - T_RIGHT_PARANTHESIS = 270, - T_COLON = 271, - T_SEMICOLON = 272, - T_PUBLIC = 273, - T_PROTECTED = 274, - T_TRIPE_DOT = 275, - T_PRIVATE = 276, - T_VIRTUAL = 277, - T_CONST = 278, - T_INLINE = 279, - T_FRIEND = 280, - T_RETURN = 281, - T_SIGNAL = 282, - T_SLOT = 283, - T_TYPEDEF = 284, - T_PLUS = 285, - T_MINUS = 286, - T_COMMA = 287, - T_ASTERISK = 288, - T_TILDE = 289, - T_LESS = 290, - T_GREATER = 291, - T_AMPERSAND = 292, - T_EXTERN = 293, - T_EXTERN_C = 294, - T_ACCESS = 295, - T_ENUM = 296, - T_NAMESPACE = 297, - T_USING = 298, - T_UNKNOWN = 299, - T_TRIPLE_DOT = 300, - T_TRUE = 301, - T_FALSE = 302, - T_STATIC = 303, - T_MUTABLE = 304, - T_EQUAL = 305, - T_SCOPE = 306, - T_NULL = 307, - T_INT = 308, - T_ARRAY_OPEN = 309, - T_ARRAY_CLOSE = 310, - T_CHAR = 311, - T_DCOP = 312, - T_DCOP_AREA = 313, - T_DCOP_SIGNAL_AREA = 314, - T_SIGNED = 315, - T_UNSIGNED = 316, - T_LONG = 317, - T_SHORT = 318, - T_FUNOPERATOR = 319, - T_MISCOPERATOR = 320, - T_SHIFT = 321 - }; -#endif - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - -/* Line 214 of yacc.c */ -#line 67 "yacc.yy" - - long _int; - QString *_str; - unsigned short _char; - double _float; - - - -/* Line 214 of yacc.c */ -#line 249 "yacc.cc" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - - -/* Copy the second part of user declarations. */ - - -/* Line 264 of yacc.c */ -#line 261 "yacc.cc" - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) -#else -# define YYUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; -#endif -{ - return yyi; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 5 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 559 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 67 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 53 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 185 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 374 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 321 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 7, 8, 11, 16, 17, 19, 20, - 27, 35, 39, 43, 49, 50, 58, 63, 69, 72, - 77, 85, 94, 97, 99, 101, 103, 106, 107, 109, - 111, 113, 115, 117, 119, 121, 122, 126, 129, 132, - 135, 137, 141, 143, 148, 152, 154, 157, 161, 164, - 166, 167, 169, 171, 174, 178, 181, 184, 187, 190, - 193, 196, 202, 207, 212, 217, 224, 229, 236, 243, - 251, 258, 265, 271, 275, 277, 281, 283, 285, 287, - 290, 292, 294, 296, 300, 304, 312, 322, 323, 325, - 327, 330, 332, 335, 338, 342, 345, 349, 352, 356, - 359, 363, 365, 367, 370, 372, 375, 377, 380, 383, - 386, 388, 389, 391, 395, 397, 399, 402, 405, 410, - 417, 421, 423, 426, 428, 432, 436, 439, 442, 446, - 449, 451, 454, 458, 460, 464, 467, 469, 470, 473, - 479, 481, 483, 485, 487, 492, 493, 495, 497, 499, - 501, 503, 505, 512, 520, 522, 526, 527, 532, 534, - 538, 541, 547, 551, 557, 565, 572, 576, 578, 580, - 584, 589, 592, 593, 595, 598, 599, 601, 605, 608, - 611, 615, 621, 627, 633, 640 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 68, 0, -1, 69, 71, 68, -1, -1, 69, 9, - -1, 39, 12, 68, 14, -1, -1, 57, -1, -1, - 10, 80, 84, 70, 86, 17, -1, 10, 6, 80, - 84, 70, 86, 17, -1, 10, 80, 17, -1, 11, - 80, 17, -1, 11, 80, 84, 86, 17, -1, -1, - 42, 6, 12, 72, 68, 14, 85, -1, 43, 42, - 6, 17, -1, 43, 6, 51, 6, 17, -1, 38, - 17, -1, 29, 100, 80, 17, -1, 29, 11, 12, - 73, 14, 80, 17, -1, 29, 11, 80, 12, 73, - 14, 80, 17, -1, 24, 111, -1, 111, -1, 119, - -1, 87, -1, 119, 73, -1, -1, 46, -1, 47, - -1, 21, -1, 19, -1, 18, -1, 27, -1, 28, - -1, -1, 75, 76, 16, -1, 76, 16, -1, 58, - 16, -1, 59, 16, -1, 6, -1, 6, 51, 80, - -1, 80, -1, 80, 35, 101, 36, -1, 105, 18, - 81, -1, 81, -1, 82, 12, -1, 82, 32, 83, - -1, 16, 83, -1, 12, -1, -1, 17, -1, 14, - -1, 92, 86, -1, 24, 111, 86, -1, 111, 86, - -1, 79, 86, -1, 87, 86, -1, 78, 86, -1, - 77, 86, -1, 119, 86, -1, 25, 10, 80, 17, - 86, -1, 25, 80, 17, 86, -1, 25, 107, 17, - 86, -1, 10, 80, 17, 86, -1, 10, 80, 84, - 86, 17, 86, -1, 11, 80, 17, 86, -1, 11, - 80, 84, 86, 17, 86, -1, 43, 6, 51, 6, - 17, 86, -1, 41, 6, 12, 88, 14, 6, 17, - -1, 41, 6, 12, 88, 14, 17, -1, 41, 12, - 88, 14, 6, 17, -1, 41, 12, 88, 14, 17, - -1, 89, 32, 88, -1, 89, -1, 6, 50, 91, - -1, 6, -1, 4, -1, 7, -1, 31, 7, -1, - 52, -1, 80, -1, 90, -1, 90, 30, 90, -1, - 90, 66, 90, -1, 29, 80, 35, 101, 36, 80, - 17, -1, 29, 80, 35, 101, 36, 51, 6, 80, - 17, -1, -1, 23, -1, 60, -1, 60, 53, -1, - 61, -1, 61, 53, -1, 60, 63, -1, 60, 63, - 53, -1, 60, 62, -1, 60, 62, 53, -1, 61, - 63, -1, 61, 63, 53, -1, 61, 62, -1, 61, - 62, 53, -1, 53, -1, 62, -1, 62, 53, -1, - 63, -1, 63, 53, -1, 56, -1, 60, 56, -1, - 61, 56, -1, 33, 95, -1, 33, -1, -1, 102, - -1, 96, 32, 102, -1, 94, -1, 80, -1, 11, - 80, -1, 10, 80, -1, 80, 35, 98, 36, -1, - 80, 35, 98, 36, 51, 80, -1, 99, 32, 98, - -1, 99, -1, 97, 95, -1, 97, -1, 23, 97, - 95, -1, 23, 97, 37, -1, 23, 97, -1, 97, - 23, -1, 97, 23, 37, -1, 97, 37, -1, 97, - -1, 97, 95, -1, 100, 32, 101, -1, 100, -1, - 100, 80, 103, -1, 100, 103, -1, 45, -1, -1, - 50, 104, -1, 50, 13, 100, 15, 104, -1, 8, - -1, 91, -1, 5, -1, 74, -1, 80, 13, 96, - 15, -1, -1, 22, -1, 65, -1, 66, -1, 36, - -1, 35, -1, 50, -1, 100, 80, 13, 96, 15, - 93, -1, 100, 64, 106, 13, 96, 15, 93, -1, - 104, -1, 104, 32, 108, -1, -1, 6, 13, 108, - 15, -1, 109, -1, 109, 32, 110, -1, 107, 113, - -1, 22, 107, 50, 52, 113, -1, 22, 107, 113, - -1, 80, 13, 96, 15, 113, -1, 80, 13, 96, - 15, 16, 110, 113, -1, 105, 34, 80, 13, 15, - 113, -1, 48, 107, 113, -1, 12, -1, 17, -1, - 112, 114, 14, -1, 112, 114, 14, 17, -1, 115, - 114, -1, -1, 17, -1, 32, 118, -1, -1, 6, - -1, 6, 50, 104, -1, 95, 6, -1, 117, 116, - -1, 100, 118, 17, -1, 100, 80, 16, 7, 17, - -1, 48, 100, 6, 103, 17, -1, 49, 100, 6, - 103, 17, -1, 100, 6, 54, 91, 55, 17, -1, - 48, 100, 6, 54, 91, 55, 17, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 164, 164, 167, 171, 175, 179, 184, 185, 189, - 198, 207, 210, 213, 217, 216, 228, 231, 234, 237, - 240, 243, 246, 249, 252, 255, 261, 262, 265, 265, - 267, 267, 267, 269, 269, 269, 272, 277, 285, 293, - 305, 308, 316, 322, 331, 335, 342, 346, 354, 358, - 366, 368, 372, 376, 380, 384, 388, 392, 396, 400, - 404, 408, 412, 416, 420, 424, 428, 432, 436, 443, - 444, 445, 446, 450, 451, 455, 456, 460, 461, 462, - 463, 464, 468, 469, 470, 474, 484, 493, 496, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 516, 517, 518, 519, 520, 521, 522, 526, - 527, 532, 535, 536, 544, 545, 546, 547, 548, 554, - 565, 569, 577, 582, 591, 596, 603, 608, 613, 620, - 625, 630, 638, 642, 649, 658, 666, 676, 678, 681, - 688, 691, 694, 697, 700, 706, 707, 711, 711, 711, - 711, 711, 715, 737, 748, 749, 750, 755, 760, 761, - 765, 769, 773, 777, 783, 789, 795, 808, 815, 816, - 817, 821, 822, 826, 830, 831, 834, 835, 836, 839, - 843, 844, 845, 846, 847, 848 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "T_UNIMPORTANT", "T_CHARACTER_LITERAL", - "T_DOUBLE_LITERAL", "T_IDENTIFIER", "T_INTEGER_LITERAL", - "T_STRING_LITERAL", "T_INCLUDE", "T_CLASS", "T_STRUCT", - "T_LEFT_CURLY_BRACKET", "T_LEFT_PARANTHESIS", "T_RIGHT_CURLY_BRACKET", - "T_RIGHT_PARANTHESIS", "T_COLON", "T_SEMICOLON", "T_PUBLIC", - "T_PROTECTED", "T_TRIPE_DOT", "T_PRIVATE", "T_VIRTUAL", "T_CONST", - "T_INLINE", "T_FRIEND", "T_RETURN", "T_SIGNAL", "T_SLOT", "T_TYPEDEF", - "T_PLUS", "T_MINUS", "T_COMMA", "T_ASTERISK", "T_TILDE", "T_LESS", - "T_GREATER", "T_AMPERSAND", "T_EXTERN", "T_EXTERN_C", "T_ACCESS", - "T_ENUM", "T_NAMESPACE", "T_USING", "T_UNKNOWN", "T_TRIPLE_DOT", - "T_TRUE", "T_FALSE", "T_STATIC", "T_MUTABLE", "T_EQUAL", "T_SCOPE", - "T_NULL", "T_INT", "T_ARRAY_OPEN", "T_ARRAY_CLOSE", "T_CHAR", "T_DCOP", - "T_DCOP_AREA", "T_DCOP_SIGNAL_AREA", "T_SIGNED", "T_UNSIGNED", "T_LONG", - "T_SHORT", "T_FUNOPERATOR", "T_MISCOPERATOR", "T_SHIFT", "$accept", - "main", "includes", "dcoptag", "declaration", "$@1", "member_list", - "bool_value", "nodcop_area", "sigslot", "nodcop_area_begin", - "dcop_area_begin", "dcop_signal_area_begin", "Identifier", - "super_class_name", "super_class", "super_classes", "class_header", - "opt_semicolon", "body", "enum", "enum_list", "enum_item", "number", - "int_expression", "typedef", "const_qualifier", "int_type", "asterisks", - "params", "type_name", "templ_type_list", "templ_type", "type", - "type_list", "param", "default", "value", "virtual_qualifier", - "operator", "function_header", "values", "init_item", "init_list", - "function", "function_begin", "function_body", "function_lines", - "function_line", "Identifier_list_rest", "Identifier_list_entry", - "Identifier_list", "member", 0 -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 67, 68, 68, 69, 69, 69, 70, 70, 71, - 71, 71, 71, 71, 72, 71, 71, 71, 71, 71, - 71, 71, 71, 71, 71, 71, 73, 73, 74, 74, - 75, 75, 75, 76, 76, 76, 77, 77, 78, 79, - 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, - 85, 85, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, - 87, 87, 87, 88, 88, 89, 89, 90, 90, 90, - 90, 90, 91, 91, 91, 92, 92, 93, 93, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, - 95, 96, 96, 96, 97, 97, 97, 97, 97, 97, - 98, 98, 99, 99, 100, 100, 100, 100, 100, 100, - 100, 100, 101, 101, 102, 102, 102, 103, 103, 103, - 104, 104, 104, 104, 104, 105, 105, 106, 106, 106, - 106, 106, 107, 107, 108, 108, 108, 109, 110, 110, - 111, 111, 111, 111, 111, 111, 111, 112, 113, 113, - 113, 114, 114, 115, 116, 116, 117, 117, 117, 118, - 119, 119, 119, 119, 119, 119 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 3, 0, 2, 4, 0, 1, 0, 6, - 7, 3, 3, 5, 0, 7, 4, 5, 2, 4, - 7, 8, 2, 1, 1, 1, 2, 0, 1, 1, - 1, 1, 1, 1, 1, 0, 3, 2, 2, 2, - 1, 3, 1, 4, 3, 1, 2, 3, 2, 1, - 0, 1, 1, 2, 3, 2, 2, 2, 2, 2, - 2, 5, 4, 4, 4, 6, 4, 6, 6, 7, - 6, 6, 5, 3, 1, 3, 1, 1, 1, 2, - 1, 1, 1, 3, 3, 7, 9, 0, 1, 1, - 2, 1, 2, 2, 3, 2, 3, 2, 3, 2, - 3, 1, 1, 2, 1, 2, 1, 2, 2, 2, - 1, 0, 1, 3, 1, 1, 2, 2, 4, 6, - 3, 1, 2, 1, 3, 3, 2, 2, 3, 2, - 1, 2, 3, 1, 3, 2, 1, 0, 2, 5, - 1, 1, 1, 1, 4, 0, 1, 1, 1, 1, - 1, 1, 6, 7, 1, 3, 0, 4, 1, 3, - 2, 5, 3, 5, 7, 6, 3, 1, 1, 3, - 4, 2, 0, 1, 2, 0, 1, 3, 2, 2, - 3, 5, 5, 5, 6, 7 -}; - -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 6, 0, 0, 145, 6, 1, 40, 4, 0, 0, - 146, 0, 145, 0, 0, 0, 0, 0, 0, 0, - 101, 106, 89, 91, 102, 104, 6, 115, 25, 114, - 130, 0, 0, 0, 23, 24, 0, 0, 40, 117, - 116, 0, 0, 115, 0, 0, 126, 0, 22, 0, - 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, - 90, 107, 95, 93, 92, 108, 99, 97, 103, 105, - 2, 111, 0, 127, 110, 129, 131, 40, 0, 0, - 0, 175, 0, 0, 167, 168, 172, 160, 5, 41, - 0, 49, 145, 11, 8, 12, 35, 117, 116, 0, - 0, 162, 125, 124, 27, 116, 0, 0, 76, 0, - 74, 14, 0, 0, 40, 166, 137, 96, 94, 100, - 98, 136, 0, 137, 112, 123, 0, 121, 128, 109, - 0, 0, 150, 149, 151, 147, 148, 0, 111, 0, - 178, 0, 179, 180, 0, 173, 0, 172, 8, 146, - 42, 45, 0, 48, 0, 7, 35, 0, 0, 52, - 32, 31, 30, 145, 0, 33, 34, 0, 0, 0, - 0, 35, 0, 35, 35, 35, 0, 35, 35, 35, - 35, 0, 0, 0, 0, 27, 27, 19, 0, 0, - 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, - 0, 137, 135, 122, 118, 0, 77, 142, 78, 140, - 0, 28, 29, 80, 143, 81, 82, 141, 177, 81, - 0, 111, 0, 0, 176, 174, 0, 169, 171, 35, - 0, 46, 145, 0, 0, 117, 116, 35, 0, 115, - 0, 0, 0, 38, 39, 0, 37, 59, 58, 56, - 13, 57, 53, 55, 60, 161, 0, 0, 0, 26, - 0, 0, 75, 0, 72, 73, 0, 17, 0, 138, - 0, 182, 183, 0, 163, 113, 134, 0, 120, 79, - 111, 0, 0, 0, 0, 87, 181, 0, 170, 0, - 133, 0, 47, 44, 9, 35, 35, 35, 35, 54, - 117, 35, 35, 0, 0, 36, 137, 0, 0, 0, - 70, 71, 50, 0, 0, 0, 158, 0, 119, 0, - 83, 84, 184, 87, 88, 152, 165, 10, 0, 43, - 64, 0, 66, 0, 35, 62, 63, 0, 0, 20, - 0, 69, 51, 15, 0, 185, 156, 0, 164, 144, - 153, 132, 35, 35, 61, 0, 35, 21, 139, 154, - 0, 159, 65, 67, 0, 0, 68, 156, 157, 0, - 85, 155, 0, 86 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 2, 3, 156, 26, 192, 183, 214, 171, 172, - 173, 174, 175, 27, 151, 152, 153, 94, 343, 176, - 177, 109, 110, 216, 217, 178, 325, 29, 80, 122, - 30, 126, 127, 31, 291, 124, 197, 359, 32, 137, - 33, 360, 316, 317, 179, 86, 87, 146, 147, 142, - 81, 82, 180 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -191 -static const yytype_int16 yypact[] = -{ - 28, 78, 99, 342, 80, -191, 67, -191, 115, 159, - 205, 81, 386, 463, 153, 44, 190, 32, 205, 205, - -191, -191, 181, 287, 154, 161, 47, 66, -191, -191, - 138, 19, 185, 143, -191, -191, 207, 159, 21, 183, - 219, 159, 159, 194, 16, 31, 152, 205, -191, 91, - 159, -191, 228, 236, 233, 202, 264, 18, 143, 272, - -191, -191, 231, 232, -191, -191, 246, 248, -191, -191, - -191, 445, 81, 249, 256, -191, -191, 85, 182, 42, - 296, 273, 290, 159, -191, -191, 291, -191, -191, -191, - 196, -191, 146, -191, 262, -191, 269, -191, -191, 300, - 252, -191, -191, -191, 404, 311, 307, 236, 276, 319, - 302, -191, 329, 320, 60, -191, 289, -191, -191, -191, - -191, -191, 114, 39, -191, 256, 305, 310, -191, -191, - 507, 101, -191, -191, -191, -191, -191, 332, 445, 339, - -191, 62, -191, -191, 341, -191, 343, 291, 262, -191, - 321, -191, 34, -191, 337, -191, 269, 159, 159, -191, - -191, -191, -191, 386, 474, -191, -191, 159, 352, 344, - 346, 211, 347, 269, 269, 269, 350, 269, 269, 269, - 269, 143, 205, 354, 87, 404, 404, -191, 356, 101, - 156, 236, 80, 359, -191, 120, 101, 360, 364, 247, - 445, 289, -191, -191, 331, 81, -191, -191, -191, -191, - 379, -191, -191, -191, -191, 374, 40, -191, -191, -191, - 333, 445, 116, 372, 349, -191, 378, 377, -191, 269, - 205, -191, 146, 159, 383, 265, 299, 269, 159, 27, - 384, 371, 361, -191, -191, 391, -191, -191, -191, -191, - -191, -191, -191, -191, -191, -191, 407, 159, 400, -191, - 403, 176, -191, 401, -191, -191, 405, -191, 205, -191, - 365, -191, -191, 415, -191, -191, -191, 159, -191, -191, - 445, 101, 101, 406, 132, 399, -191, 143, -191, 408, - 392, 390, -191, -191, -191, 269, 269, 269, 269, -191, - 411, 269, 269, 205, 425, -191, 144, 418, 159, 419, - -191, -191, 420, 417, 421, 427, 409, 143, -191, 148, - -191, -191, -191, 399, -191, -191, -191, -191, 205, -191, - -191, 426, -191, 428, 269, -191, -191, 414, 437, -191, - 441, -191, -191, -191, 507, -191, 507, 415, -191, -191, - -191, -191, 269, 269, -191, 25, 269, -191, -191, 412, - 444, -191, -191, -191, 455, 446, -191, 507, -191, 159, - -191, -191, 453, -191 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -191, 9, -191, 314, -191, -191, -2, -191, -191, 301, - -191, -191, -191, -8, 238, -191, 243, -33, -191, 77, - 473, -91, -191, -72, -111, -191, 155, -191, -9, -123, - 1, 274, -191, 41, -190, 277, -97, -124, -78, -191, - 22, 121, -191, 134, 6, -191, -41, 335, -191, -191, - -191, 348, 5 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -177 -static const yytype_int16 yytable[] = -{ - 39, 40, 43, 43, 101, 43, 218, 96, 35, 34, - 43, 43, 46, 36, 154, 222, 188, 115, 48, 198, - 220, 76, 6, 79, 114, 77, 202, 6, -3, 89, - 90, 6, 45, 97, 98, 70, 99, 103, 55, 43, - 58, 105, 106, 84, 301, 6, 231, -3, 85, 99, - 52, 44, 74, 44, 50, 138, 53, 148, 139, 57, - 59, -3, 72, 43, 43, 129, 232, 1, 224, 58, - 281, 269, 37, 125, 56, 144, 364, -137, 262, 71, - 78, 100, 78, 78, 150, 270, 1, 6, 44, 195, - 4, 41, 42, 77, -3, 74, 43, 6, 284, 5, - 265, 72, -176, 104, 276, 206, 282, 6, 208, 185, - 195, 37, 123, 337, 196, 201, 203, -176, 37, 1, - 74, 38, 215, 219, 206, 207, 6, 208, 209, 199, - 43, 285, 210, 268, 20, 130, 37, 21, 351, 131, - 255, 22, 23, 24, 25, 184, 200, 323, 200, 235, - 236, 210, 6, 213, 154, 84, 239, 319, 274, 241, - 85, 73, 263, 349, 200, 6, 211, 212, 149, 237, - 51, 74, 213, 264, 43, 75, 258, 43, 43, 123, - 200, 219, 309, 259, 260, 74, 240, 215, 219, 102, - 185, 185, 43, 310, 195, 91, 54, 43, 196, 92, - 93, 266, 296, 298, 44, 44, 125, 68, 91, 320, - 321, 6, 92, 43, 69, 41, 42, 132, 133, 83, - 358, 88, 43, 256, 150, 150, 184, 184, 11, 72, - 300, 91, 134, 234, 60, 92, 95, 61, 165, 166, - 107, 123, 108, 62, 63, 111, 326, 135, 136, 307, - 247, 248, 249, 112, 251, 252, 253, 254, 20, 84, - 43, 21, 123, 273, 85, 22, 23, 24, 25, 318, - 113, 290, 43, 219, 219, 6, 348, 91, 116, 157, - 158, 92, 295, 159, 117, 118, 128, 160, 161, 74, - 162, 10, 11, 163, 164, 43, 165, 166, 167, 119, - 340, 120, 140, -145, 181, 141, 289, 143, 145, 313, - 15, 91, 168, 138, 299, 92, 297, 18, 19, 155, - 43, 123, 20, 186, 187, 21, 189, 169, 170, 22, - 23, 24, 25, 190, 191, 193, 215, 194, 215, 195, - 64, 204, 205, 65, 290, 221, 223, 365, 6, 66, - 67, 7, 8, 9, 226, 233, 230, 227, 242, 215, - 243, 372, 244, 246, 10, 11, 12, 250, 257, 290, - 261, 13, 330, 331, 332, 333, 267, 271, 335, 336, - 14, 272, 277, 15, 16, 17, 279, 280, 283, 286, - 18, 19, 6, 287, 288, 20, 41, 42, 21, 130, - 294, 302, 22, 23, 24, 25, 303, 305, 10, 11, - 6, 354, 304, 306, 41, 42, 139, 308, 311, 312, - 314, 315, 324, 322, 328, 327, 329, 11, 334, 362, - 363, 338, 344, 366, 47, 339, 341, 342, 345, 20, - 346, 347, 21, 352, 367, 353, 22, 23, 24, 25, - 355, 6, 182, 19, 356, 41, 42, 20, 357, 368, - 21, 369, 229, 370, 22, 23, 24, 25, 11, 6, - 373, 293, 245, 41, 49, 292, 28, 275, 350, 278, - 6, 361, 228, 0, 238, 42, 11, 0, 371, 225, - 121, 0, 0, 0, 0, 0, 0, 11, 20, 0, - 0, 21, 0, 0, 0, 22, 23, 24, 25, 0, - 0, 206, 207, 6, 208, 209, 20, 0, 0, 21, - 0, 0, 0, 22, 23, 24, 25, 20, 0, 0, - 21, 0, 0, 0, 22, 23, 24, 25, 210, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 211, 212, 0, 0, 0, 0, 213 -}; - -static const yytype_int16 yycheck[] = -{ - 8, 9, 10, 11, 45, 13, 130, 40, 3, 3, - 18, 19, 11, 4, 92, 138, 107, 58, 12, 116, - 131, 30, 6, 31, 6, 6, 123, 6, 0, 37, - 38, 6, 10, 41, 42, 26, 44, 46, 6, 47, - 18, 49, 50, 12, 17, 6, 12, 0, 17, 57, - 6, 10, 33, 12, 13, 13, 12, 90, 16, 18, - 19, 14, 35, 71, 72, 74, 32, 39, 6, 47, - 30, 195, 51, 72, 42, 83, 51, 17, 189, 13, - 64, 50, 64, 64, 92, 196, 39, 6, 47, 50, - 12, 10, 11, 6, 14, 33, 104, 6, 221, 0, - 191, 35, 17, 12, 201, 4, 66, 6, 7, 104, - 50, 51, 71, 303, 54, 123, 125, 32, 51, 39, - 33, 6, 130, 131, 4, 5, 6, 7, 8, 15, - 138, 15, 31, 13, 53, 50, 51, 56, 328, 54, - 181, 60, 61, 62, 63, 104, 32, 15, 32, 157, - 158, 31, 6, 52, 232, 12, 164, 280, 199, 167, - 17, 23, 6, 15, 32, 6, 46, 47, 22, 163, - 17, 33, 52, 17, 182, 37, 184, 185, 186, 138, - 32, 189, 6, 185, 186, 33, 164, 195, 196, 37, - 185, 186, 200, 17, 50, 12, 6, 205, 54, 16, - 17, 192, 235, 236, 163, 164, 205, 53, 12, 281, - 282, 6, 16, 221, 53, 10, 11, 35, 36, 34, - 344, 14, 230, 182, 232, 233, 185, 186, 23, 35, - 238, 12, 50, 156, 53, 16, 17, 56, 27, 28, - 12, 200, 6, 62, 63, 12, 287, 65, 66, 257, - 173, 174, 175, 51, 177, 178, 179, 180, 53, 12, - 268, 56, 221, 16, 17, 60, 61, 62, 63, 277, - 6, 230, 280, 281, 282, 6, 317, 12, 6, 10, - 11, 16, 17, 14, 53, 53, 37, 18, 19, 33, - 21, 22, 23, 24, 25, 303, 27, 28, 29, 53, - 308, 53, 6, 34, 52, 32, 229, 17, 17, 268, - 41, 12, 43, 13, 237, 16, 17, 48, 49, 57, - 328, 280, 53, 12, 17, 56, 50, 58, 59, 60, - 61, 62, 63, 14, 32, 6, 344, 17, 346, 50, - 53, 36, 32, 56, 303, 13, 7, 355, 6, 62, - 63, 9, 10, 11, 13, 18, 35, 14, 6, 367, - 16, 369, 16, 16, 22, 23, 24, 17, 14, 328, - 14, 29, 295, 296, 297, 298, 17, 17, 301, 302, - 38, 17, 51, 41, 42, 43, 7, 13, 55, 17, - 48, 49, 6, 15, 17, 53, 10, 11, 56, 50, - 17, 17, 60, 61, 62, 63, 35, 16, 22, 23, - 6, 334, 51, 6, 10, 11, 16, 14, 17, 14, - 55, 6, 23, 17, 32, 17, 36, 23, 17, 352, - 353, 6, 15, 356, 48, 17, 17, 17, 17, 53, - 13, 32, 56, 17, 32, 17, 60, 61, 62, 63, - 36, 6, 48, 49, 17, 10, 11, 53, 17, 15, - 56, 6, 148, 17, 60, 61, 62, 63, 23, 6, - 17, 233, 171, 10, 11, 232, 3, 200, 323, 205, - 6, 347, 147, -1, 10, 11, 23, -1, 367, 141, - 45, -1, -1, -1, -1, -1, -1, 23, 53, -1, - -1, 56, -1, -1, -1, 60, 61, 62, 63, -1, - -1, 4, 5, 6, 7, 8, 53, -1, -1, 56, - -1, -1, -1, 60, 61, 62, 63, 53, -1, -1, - 56, -1, -1, -1, 60, 61, 62, 63, 31, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 46, 47, -1, -1, -1, -1, 52 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 39, 68, 69, 12, 0, 6, 9, 10, 11, - 22, 23, 24, 29, 38, 41, 42, 43, 48, 49, - 53, 56, 60, 61, 62, 63, 71, 80, 87, 94, - 97, 100, 105, 107, 111, 119, 68, 51, 6, 80, - 80, 10, 11, 80, 100, 107, 97, 48, 111, 11, - 100, 17, 6, 12, 6, 6, 42, 100, 107, 100, - 53, 56, 62, 63, 53, 56, 62, 63, 53, 53, - 68, 13, 35, 23, 33, 37, 95, 6, 64, 80, - 95, 117, 118, 34, 12, 17, 112, 113, 14, 80, - 80, 12, 16, 17, 84, 17, 84, 80, 80, 80, - 50, 113, 37, 95, 12, 80, 80, 12, 6, 88, - 89, 12, 51, 6, 6, 113, 6, 53, 53, 53, - 53, 45, 96, 100, 102, 97, 98, 99, 37, 95, - 50, 54, 35, 36, 50, 65, 66, 106, 13, 16, - 6, 32, 116, 17, 80, 17, 114, 115, 84, 22, - 80, 81, 82, 83, 105, 57, 70, 10, 11, 14, - 18, 19, 21, 24, 25, 27, 28, 29, 43, 58, - 59, 75, 76, 77, 78, 79, 86, 87, 92, 111, - 119, 52, 48, 73, 100, 119, 12, 17, 88, 50, - 14, 32, 72, 6, 17, 50, 54, 103, 103, 15, - 32, 80, 103, 95, 36, 32, 4, 5, 7, 8, - 31, 46, 47, 52, 74, 80, 90, 91, 104, 80, - 91, 13, 96, 7, 6, 118, 13, 14, 114, 70, - 35, 12, 32, 18, 86, 80, 80, 111, 10, 80, - 107, 80, 6, 16, 16, 76, 16, 86, 86, 86, - 17, 86, 86, 86, 86, 113, 100, 14, 80, 73, - 73, 14, 91, 6, 17, 88, 68, 17, 13, 104, - 91, 17, 17, 16, 113, 102, 103, 51, 98, 7, - 13, 30, 66, 55, 96, 15, 17, 15, 17, 86, - 100, 101, 83, 81, 17, 17, 84, 17, 84, 86, - 80, 17, 17, 35, 51, 16, 6, 80, 14, 6, - 17, 17, 14, 100, 55, 6, 109, 110, 80, 96, - 90, 90, 17, 15, 23, 93, 113, 17, 32, 36, - 86, 86, 86, 86, 17, 86, 86, 101, 6, 17, - 80, 17, 17, 85, 15, 17, 13, 32, 113, 15, - 93, 101, 17, 17, 86, 36, 17, 17, 104, 104, - 108, 110, 86, 86, 51, 80, 86, 32, 15, 6, - 17, 108, 80, 17 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define YYFAIL goto yyerrlab - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif -{ - YYUSE (yyvaluep); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - - default: - break; - } -} - -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - *++yyvsp = yylval; - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: - -/* Line 1455 of yacc.c */ -#line 165 "yacc.yy" - { - ;} - break; - - case 4: - -/* Line 1455 of yacc.c */ -#line 172 "yacc.yy" - { - printf("%s\n", (yyvsp[(2) - (2)]._str)->latin1() ); - ;} - break; - - case 5: - -/* Line 1455 of yacc.c */ -#line 176 "yacc.yy" - { - ;} - break; - - case 6: - -/* Line 1455 of yacc.c */ -#line 179 "yacc.yy" - { - ;} - break; - - case 7: - -/* Line 1455 of yacc.c */ -#line 184 "yacc.yy" - { (yyval._int) = 1; ;} - break; - - case 8: - -/* Line 1455 of yacc.c */ -#line 185 "yacc.yy" - { (yyval._int) = 0; ;} - break; - - case 9: - -/* Line 1455 of yacc.c */ -#line 190 "yacc.yy" - { - if ((yyvsp[(4) - (6)]._int)) - printf("\n %s\n%s%s\n", ( in_namespace + *(yyvsp[(2) - (6)]._str) ).latin1(), (yyvsp[(3) - (6)]._str)->latin1(), (yyvsp[(5) - (6)]._str)->latin1() ); - // default C++ visibility specifier is 'private' - dcop_area = 0; - dcop_signal_area = 0; - - ;} - break; - - case 10: - -/* Line 1455 of yacc.c */ -#line 199 "yacc.yy" - { - if ((yyvsp[(5) - (7)]._int)) - printf("\n %s\n %s\n%s%s\n", ( in_namespace + *(yyvsp[(3) - (7)]._str) ).latin1(),(yyvsp[(2) - (7)]._str)->latin1(), (yyvsp[(4) - (7)]._str)->latin1(), (yyvsp[(6) - (7)]._str)->latin1() ); - // default C++ visibility specifier is 'private' - dcop_area = 0; - dcop_signal_area = 0; - - ;} - break; - - case 11: - -/* Line 1455 of yacc.c */ -#line 208 "yacc.yy" - { - ;} - break; - - case 12: - -/* Line 1455 of yacc.c */ -#line 211 "yacc.yy" - { - ;} - break; - - case 13: - -/* Line 1455 of yacc.c */ -#line 214 "yacc.yy" - { - ;} - break; - - case 14: - -/* Line 1455 of yacc.c */ -#line 217 "yacc.yy" - { - in_namespace += *(yyvsp[(2) - (3)]._str); in_namespace += "::"; - ;} - break; - - case 15: - -/* Line 1455 of yacc.c */ -#line 221 "yacc.yy" - { - int pos = in_namespace.findRev( "::", -3 ); - if( pos >= 0 ) - in_namespace = in_namespace.left( pos + 2 ); - else - in_namespace = ""; - ;} - break; - - case 16: - -/* Line 1455 of yacc.c */ -#line 229 "yacc.yy" - { - ;} - break; - - case 17: - -/* Line 1455 of yacc.c */ -#line 232 "yacc.yy" - { - ;} - break; - - case 18: - -/* Line 1455 of yacc.c */ -#line 235 "yacc.yy" - { - ;} - break; - - case 19: - -/* Line 1455 of yacc.c */ -#line 238 "yacc.yy" - { - ;} - break; - - case 20: - -/* Line 1455 of yacc.c */ -#line 241 "yacc.yy" - { - ;} - break; - - case 21: - -/* Line 1455 of yacc.c */ -#line 244 "yacc.yy" - { - ;} - break; - - case 22: - -/* Line 1455 of yacc.c */ -#line 247 "yacc.yy" - { - ;} - break; - - case 23: - -/* Line 1455 of yacc.c */ -#line 250 "yacc.yy" - { - ;} - break; - - case 24: - -/* Line 1455 of yacc.c */ -#line 253 "yacc.yy" - { - ;} - break; - - case 25: - -/* Line 1455 of yacc.c */ -#line 256 "yacc.yy" - { - ;} - break; - - case 36: - -/* Line 1455 of yacc.c */ -#line 273 "yacc.yy" - { - dcop_area = 0; - dcop_signal_area = 0; - ;} - break; - - case 37: - -/* Line 1455 of yacc.c */ -#line 278 "yacc.yy" - { - dcop_area = 0; - dcop_signal_area = 0; - ;} - break; - - case 38: - -/* Line 1455 of yacc.c */ -#line 286 "yacc.yy" - { - dcop_area = 1; - dcop_signal_area = 0; - ;} - break; - - case 39: - -/* Line 1455 of yacc.c */ -#line 294 "yacc.yy" - { - /* - A dcop signals area needs all dcop area capabilities, - e.g. parsing of function parameters. - */ - dcop_area = 1; - dcop_signal_area = 1; - ;} - break; - - case 40: - -/* Line 1455 of yacc.c */ -#line 305 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (1)]._str); - ;} - break; - - case 41: - -/* Line 1455 of yacc.c */ -#line 308 "yacc.yy" - { - QString* tmp = new QString( "%1::%2" ); - *tmp = tmp->arg(*((yyvsp[(1) - (3)]._str))).arg(*((yyvsp[(3) - (3)]._str))); - (yyval._str) = tmp; - ;} - break; - - case 42: - -/* Line 1455 of yacc.c */ -#line 317 "yacc.yy" - { - QString* tmp = new QString( " %1\n" ); - *tmp = tmp->arg( *((yyvsp[(1) - (1)]._str)) ); - (yyval._str) = tmp; - ;} - break; - - case 43: - -/* Line 1455 of yacc.c */ -#line 323 "yacc.yy" - { - QString* tmp = new QString( " %1\n" ); - *tmp = tmp->arg( *((yyvsp[(1) - (4)]._str)) + "<" + *((yyvsp[(3) - (4)]._str)) + ">" ); - (yyval._str) = tmp; - ;} - break; - - case 44: - -/* Line 1455 of yacc.c */ -#line 332 "yacc.yy" - { - (yyval._str) = (yyvsp[(3) - (3)]._str); - ;} - break; - - case 45: - -/* Line 1455 of yacc.c */ -#line 336 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (1)]._str); - ;} - break; - - case 46: - -/* Line 1455 of yacc.c */ -#line 343 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (2)]._str); - ;} - break; - - case 47: - -/* Line 1455 of yacc.c */ -#line 347 "yacc.yy" - { - /* $$ = $1; */ - (yyval._str) = new QString( *((yyvsp[(1) - (3)]._str)) + *((yyvsp[(3) - (3)]._str)) ); - ;} - break; - - case 48: - -/* Line 1455 of yacc.c */ -#line 355 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (2)]._str); - ;} - break; - - case 49: - -/* Line 1455 of yacc.c */ -#line 359 "yacc.yy" - { - (yyval._str) = new QString( "" ); - ;} - break; - - case 50: - -/* Line 1455 of yacc.c */ -#line 366 "yacc.yy" - { - ;} - break; - - case 52: - -/* Line 1455 of yacc.c */ -#line 373 "yacc.yy" - { - (yyval._str) = new QString( "" ); - ;} - break; - - case 53: - -/* Line 1455 of yacc.c */ -#line 377 "yacc.yy" - { - (yyval._str) = new QString( *((yyvsp[(1) - (2)]._str)) + *((yyvsp[(2) - (2)]._str)) ); - ;} - break; - - case 54: - -/* Line 1455 of yacc.c */ -#line 381 "yacc.yy" - { - (yyval._str) = new QString( *((yyvsp[(2) - (3)]._str)) + *((yyvsp[(3) - (3)]._str)) ); - ;} - break; - - case 55: - -/* Line 1455 of yacc.c */ -#line 385 "yacc.yy" - { - (yyval._str) = new QString( *((yyvsp[(1) - (2)]._str)) + *((yyvsp[(2) - (2)]._str)) ); - ;} - break; - - case 56: - -/* Line 1455 of yacc.c */ -#line 389 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (2)]._str); - ;} - break; - - case 57: - -/* Line 1455 of yacc.c */ -#line 393 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (2)]._str); - ;} - break; - - case 58: - -/* Line 1455 of yacc.c */ -#line 397 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (2)]._str); - ;} - break; - - case 59: - -/* Line 1455 of yacc.c */ -#line 401 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (2)]._str); - ;} - break; - - case 60: - -/* Line 1455 of yacc.c */ -#line 405 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (2)]._str); - ;} - break; - - case 61: - -/* Line 1455 of yacc.c */ -#line 409 "yacc.yy" - { - (yyval._str) = (yyvsp[(5) - (5)]._str); - ;} - break; - - case 62: - -/* Line 1455 of yacc.c */ -#line 413 "yacc.yy" - { - (yyval._str) = (yyvsp[(4) - (4)]._str); - ;} - break; - - case 63: - -/* Line 1455 of yacc.c */ -#line 417 "yacc.yy" - { - (yyval._str) = (yyvsp[(4) - (4)]._str); - ;} - break; - - case 64: - -/* Line 1455 of yacc.c */ -#line 421 "yacc.yy" - { - (yyval._str) = (yyvsp[(4) - (4)]._str); - ;} - break; - - case 65: - -/* Line 1455 of yacc.c */ -#line 425 "yacc.yy" - { - (yyval._str) = (yyvsp[(6) - (6)]._str); - ;} - break; - - case 66: - -/* Line 1455 of yacc.c */ -#line 429 "yacc.yy" - { - (yyval._str) = (yyvsp[(4) - (4)]._str); - ;} - break; - - case 67: - -/* Line 1455 of yacc.c */ -#line 433 "yacc.yy" - { - (yyval._str) = (yyvsp[(6) - (6)]._str); - ;} - break; - - case 68: - -/* Line 1455 of yacc.c */ -#line 437 "yacc.yy" - { - (yyval._str) = (yyvsp[(6) - (6)]._str); - ;} - break; - - case 75: - -/* Line 1455 of yacc.c */ -#line 455 "yacc.yy" - {;} - break; - - case 76: - -/* Line 1455 of yacc.c */ -#line 456 "yacc.yy" - {;} - break; - - case 77: - -/* Line 1455 of yacc.c */ -#line 460 "yacc.yy" - {;} - break; - - case 78: - -/* Line 1455 of yacc.c */ -#line 461 "yacc.yy" - {;} - break; - - case 79: - -/* Line 1455 of yacc.c */ -#line 462 "yacc.yy" - {;} - break; - - case 80: - -/* Line 1455 of yacc.c */ -#line 463 "yacc.yy" - {;} - break; - - case 81: - -/* Line 1455 of yacc.c */ -#line 464 "yacc.yy" - {;} - break; - - case 82: - -/* Line 1455 of yacc.c */ -#line 468 "yacc.yy" - {;} - break; - - case 83: - -/* Line 1455 of yacc.c */ -#line 469 "yacc.yy" - {;} - break; - - case 84: - -/* Line 1455 of yacc.c */ -#line 470 "yacc.yy" - {;} - break; - - case 85: - -/* Line 1455 of yacc.c */ -#line 475 "yacc.yy" - { - if (dcop_area) { - QString* tmp = new QString("\n"); - *tmp = tmp->arg( *((yyvsp[(6) - (7)]._str)) ).arg( *((yyvsp[(2) - (7)]._str)) ).arg( *((yyvsp[(4) - (7)]._str)) ); - (yyval._str) = tmp; - } else { - (yyval._str) = new QString(""); - } - ;} - break; - - case 86: - -/* Line 1455 of yacc.c */ -#line 485 "yacc.yy" - { - if (dcop_area) - yyerror("scoped template typedefs are not supported in dcop areas!"); - ;} - break; - - case 87: - -/* Line 1455 of yacc.c */ -#line 493 "yacc.yy" - { - (yyval._int) = 0; - ;} - break; - - case 88: - -/* Line 1455 of yacc.c */ -#line 497 "yacc.yy" - { - (yyval._int) = 1; - ;} - break; - - case 89: - -/* Line 1455 of yacc.c */ -#line 503 "yacc.yy" - { (yyval._str) = new QString("signed int"); ;} - break; - - case 90: - -/* Line 1455 of yacc.c */ -#line 504 "yacc.yy" - { (yyval._str) = new QString("signed int"); ;} - break; - - case 91: - -/* Line 1455 of yacc.c */ -#line 505 "yacc.yy" - { (yyval._str) = new QString("unsigned int"); ;} - break; - - case 92: - -/* Line 1455 of yacc.c */ -#line 506 "yacc.yy" - { (yyval._str) = new QString("unsigned int"); ;} - break; - - case 93: - -/* Line 1455 of yacc.c */ -#line 507 "yacc.yy" - { (yyval._str) = new QString("signed short int"); ;} - break; - - case 94: - -/* Line 1455 of yacc.c */ -#line 508 "yacc.yy" - { (yyval._str) = new QString("signed short int"); ;} - break; - - case 95: - -/* Line 1455 of yacc.c */ -#line 509 "yacc.yy" - { (yyval._str) = new QString("signed long int"); ;} - break; - - case 96: - -/* Line 1455 of yacc.c */ -#line 510 "yacc.yy" - { (yyval._str) = new QString("signed long int"); ;} - break; - - case 97: - -/* Line 1455 of yacc.c */ -#line 511 "yacc.yy" - { (yyval._str) = new QString("unsigned short int"); ;} - break; - - case 98: - -/* Line 1455 of yacc.c */ -#line 512 "yacc.yy" - { (yyval._str) = new QString("unsigned short int"); ;} - break; - - case 99: - -/* Line 1455 of yacc.c */ -#line 513 "yacc.yy" - { (yyval._str) = new QString("unsigned long int"); ;} - break; - - case 100: - -/* Line 1455 of yacc.c */ -#line 514 "yacc.yy" - { (yyval._str) = new QString("unsigned long int"); ;} - break; - - case 101: - -/* Line 1455 of yacc.c */ -#line 515 "yacc.yy" - { (yyval._str) = new QString("int"); ;} - break; - - case 102: - -/* Line 1455 of yacc.c */ -#line 516 "yacc.yy" - { (yyval._str) = new QString("long int"); ;} - break; - - case 103: - -/* Line 1455 of yacc.c */ -#line 517 "yacc.yy" - { (yyval._str) = new QString("long int"); ;} - break; - - case 104: - -/* Line 1455 of yacc.c */ -#line 518 "yacc.yy" - { (yyval._str) = new QString("short int"); ;} - break; - - case 105: - -/* Line 1455 of yacc.c */ -#line 519 "yacc.yy" - { (yyval._str) = new QString("short int"); ;} - break; - - case 106: - -/* Line 1455 of yacc.c */ -#line 520 "yacc.yy" - { (yyval._str) = new QString("char"); ;} - break; - - case 107: - -/* Line 1455 of yacc.c */ -#line 521 "yacc.yy" - { (yyval._str) = new QString("signed char"); ;} - break; - - case 108: - -/* Line 1455 of yacc.c */ -#line 522 "yacc.yy" - { (yyval._str) = new QString("unsigned char"); ;} - break; - - case 111: - -/* Line 1455 of yacc.c */ -#line 532 "yacc.yy" - { - (yyval._str) = new QString( "" ); - ;} - break; - - case 113: - -/* Line 1455 of yacc.c */ -#line 537 "yacc.yy" - { - (yyval._str) = new QString( *((yyvsp[(1) - (3)]._str)) + *((yyvsp[(3) - (3)]._str)) ); - ;} - break; - - case 115: - -/* Line 1455 of yacc.c */ -#line 545 "yacc.yy" - { (yyval._str) = (yyvsp[(1) - (1)]._str); ;} - break; - - case 116: - -/* Line 1455 of yacc.c */ -#line 546 "yacc.yy" - { (yyval._str) = (yyvsp[(2) - (2)]._str); ;} - break; - - case 117: - -/* Line 1455 of yacc.c */ -#line 547 "yacc.yy" - { (yyval._str) = (yyvsp[(2) - (2)]._str); ;} - break; - - case 118: - -/* Line 1455 of yacc.c */ -#line 548 "yacc.yy" - { - QString *tmp = new QString("%1<%2>"); - *tmp = tmp->arg(*((yyvsp[(1) - (4)]._str))); - *tmp = tmp->arg(*((yyvsp[(3) - (4)]._str))); - (yyval._str) = tmp; - ;} - break; - - case 119: - -/* Line 1455 of yacc.c */ -#line 554 "yacc.yy" - { - QString *tmp = new QString("%1<%2>::%3"); - *tmp = tmp->arg(*((yyvsp[(1) - (6)]._str))); - *tmp = tmp->arg(*((yyvsp[(3) - (6)]._str))); - *tmp = tmp->arg(*((yyvsp[(6) - (6)]._str))); - (yyval._str) = tmp; - ;} - break; - - case 120: - -/* Line 1455 of yacc.c */ -#line 566 "yacc.yy" - { - (yyval._str) = new QString(*((yyvsp[(1) - (3)]._str)) + "," + *((yyvsp[(3) - (3)]._str))); - ;} - break; - - case 121: - -/* Line 1455 of yacc.c */ -#line 570 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (1)]._str); - ;} - break; - - case 122: - -/* Line 1455 of yacc.c */ -#line 578 "yacc.yy" - { - if (dcop_area) - yyerror("in dcop areas are no pointers allowed"); - ;} - break; - - case 123: - -/* Line 1455 of yacc.c */ -#line 583 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (1)]._str); - ;} - break; - - case 124: - -/* Line 1455 of yacc.c */ -#line 592 "yacc.yy" - { - if (dcop_area) - yyerror("in dcop areas are no pointers allowed"); - ;} - break; - - case 125: - -/* Line 1455 of yacc.c */ -#line 596 "yacc.yy" - { - if (dcop_area) { - QString* tmp = new QString("%1"); - *tmp = tmp->arg( *((yyvsp[(2) - (3)]._str)) ); - (yyval._str) = tmp; - } - ;} - break; - - case 126: - -/* Line 1455 of yacc.c */ -#line 603 "yacc.yy" - { - QString* tmp = new QString("%1"); - *tmp = tmp->arg( *((yyvsp[(2) - (2)]._str)) ); - (yyval._str) = tmp; - ;} - break; - - case 127: - -/* Line 1455 of yacc.c */ -#line 608 "yacc.yy" - { - QString* tmp = new QString("%1"); - *tmp = tmp->arg( *((yyvsp[(1) - (2)]._str)) ); - (yyval._str) = tmp; - ;} - break; - - case 128: - -/* Line 1455 of yacc.c */ -#line 613 "yacc.yy" - { - if (dcop_area) { - QString* tmp = new QString("%1"); - *tmp = tmp->arg( *((yyvsp[(1) - (3)]._str)) ); - (yyval._str) = tmp; - } - ;} - break; - - case 129: - -/* Line 1455 of yacc.c */ -#line 620 "yacc.yy" - { - if (dcop_area) - yyerror("in dcop areas are only const references allowed!"); - ;} - break; - - case 130: - -/* Line 1455 of yacc.c */ -#line 625 "yacc.yy" - { - QString* tmp = new QString("%1"); - *tmp = tmp->arg( *((yyvsp[(1) - (1)]._str)) ); - (yyval._str) = tmp; - ;} - break; - - case 131: - -/* Line 1455 of yacc.c */ -#line 631 "yacc.yy" - { - if (dcop_area) - yyerror("in dcop areas are no pointers allowed"); - ;} - break; - - case 132: - -/* Line 1455 of yacc.c */ -#line 639 "yacc.yy" - { - (yyval._str) = new QString(*((yyvsp[(1) - (3)]._str)) + "," + *((yyvsp[(3) - (3)]._str))); - ;} - break; - - case 133: - -/* Line 1455 of yacc.c */ -#line 643 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (1)]._str); - ;} - break; - - case 134: - -/* Line 1455 of yacc.c */ -#line 650 "yacc.yy" - { - if (dcop_area) { - QString* tmp = new QString("\n %1%2"); - *tmp = tmp->arg( *((yyvsp[(1) - (3)]._str)) ); - *tmp = tmp->arg( *((yyvsp[(2) - (3)]._str)) ); - (yyval._str) = tmp; - } else (yyval._str) = new QString(); - ;} - break; - - case 135: - -/* Line 1455 of yacc.c */ -#line 659 "yacc.yy" - { - if (dcop_area) { - QString* tmp = new QString("\n %1"); - *tmp = tmp->arg( *((yyvsp[(1) - (2)]._str)) ); - (yyval._str) = tmp; - } else (yyval._str) = new QString(); - ;} - break; - - case 136: - -/* Line 1455 of yacc.c */ -#line 667 "yacc.yy" - { - if (dcop_area) - yyerror("variable arguments not supported in dcop area."); - (yyval._str) = new QString(""); - ;} - break; - - case 137: - -/* Line 1455 of yacc.c */ -#line 676 "yacc.yy" - { - ;} - break; - - case 138: - -/* Line 1455 of yacc.c */ -#line 679 "yacc.yy" - { - ;} - break; - - case 139: - -/* Line 1455 of yacc.c */ -#line 682 "yacc.yy" - { - ;} - break; - - case 140: - -/* Line 1455 of yacc.c */ -#line 689 "yacc.yy" - { - ;} - break; - - case 141: - -/* Line 1455 of yacc.c */ -#line 692 "yacc.yy" - { - ;} - break; - - case 142: - -/* Line 1455 of yacc.c */ -#line 695 "yacc.yy" - { - ;} - break; - - case 143: - -/* Line 1455 of yacc.c */ -#line 698 "yacc.yy" - { - ;} - break; - - case 144: - -/* Line 1455 of yacc.c */ -#line 701 "yacc.yy" - { - ;} - break; - - case 145: - -/* Line 1455 of yacc.c */ -#line 706 "yacc.yy" - { (yyval._int) = 0; ;} - break; - - case 146: - -/* Line 1455 of yacc.c */ -#line 707 "yacc.yy" - { (yyval._int) = 1; ;} - break; - - case 152: - -/* Line 1455 of yacc.c */ -#line 716 "yacc.yy" - { - if (dcop_area || dcop_signal_area) { - QString* tmp = 0; - tmp = new QString( - " <%4>\n" - " %2\n" - " %1" - "%3\n" - " \n"); - *tmp = tmp->arg( *((yyvsp[(2) - (6)]._str)) ); - *tmp = tmp->arg( *((yyvsp[(1) - (6)]._str)) ); - *tmp = tmp->arg( *((yyvsp[(4) - (6)]._str)) ); - - QString tagname = (dcop_signal_area) ? "SIGNAL" : "FUNC"; - QString attr = ((yyvsp[(6) - (6)]._int)) ? " qual=\"const\"" : ""; - *tmp = tmp->arg( QString("%1%2").arg(tagname).arg(attr) ); - *tmp = tmp->arg( QString("%1").arg(tagname) ); - (yyval._str) = tmp; - } else - (yyval._str) = new QString(""); - ;} - break; - - case 153: - -/* Line 1455 of yacc.c */ -#line 738 "yacc.yy" - { - if (dcop_area) - yyerror("operators aren't allowed in dcop areas!"); - (yyval._str) = new QString(""); - ;} - break; - - case 154: - -/* Line 1455 of yacc.c */ -#line 748 "yacc.yy" - {;} - break; - - case 155: - -/* Line 1455 of yacc.c */ -#line 749 "yacc.yy" - {;} - break; - - case 156: - -/* Line 1455 of yacc.c */ -#line 750 "yacc.yy" - {;} - break; - - case 157: - -/* Line 1455 of yacc.c */ -#line 755 "yacc.yy" - {;} - break; - - case 158: - -/* Line 1455 of yacc.c */ -#line 760 "yacc.yy" - {;} - break; - - case 159: - -/* Line 1455 of yacc.c */ -#line 761 "yacc.yy" - {;} - break; - - case 160: - -/* Line 1455 of yacc.c */ -#line 766 "yacc.yy" - { - (yyval._str) = (yyvsp[(1) - (2)]._str); - ;} - break; - - case 161: - -/* Line 1455 of yacc.c */ -#line 770 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (5)]._str); - ;} - break; - - case 162: - -/* Line 1455 of yacc.c */ -#line 774 "yacc.yy" - { - (yyval._str) = (yyvsp[(2) - (3)]._str); - ;} - break; - - case 163: - -/* Line 1455 of yacc.c */ -#line 778 "yacc.yy" - { - /* The constructor */ - assert(!dcop_area); - (yyval._str) = new QString(""); - ;} - break; - - case 164: - -/* Line 1455 of yacc.c */ -#line 784 "yacc.yy" - { - /* The constructor */ - assert(!dcop_area); - (yyval._str) = new QString(""); - ;} - break; - - case 165: - -/* Line 1455 of yacc.c */ -#line 790 "yacc.yy" - { - /* The destructor */ - assert(!dcop_area); - (yyval._str) = new QString(""); - ;} - break; - - case 166: - -/* Line 1455 of yacc.c */ -#line 796 "yacc.yy" - { - if (dcop_area) { - if (dcop_signal_area) - yyerror("DCOP signals cannot be static"); - else - yyerror("DCOP functions cannot be static"); - } else { - (yyval._str) = new QString(); - } - ;} - break; - - case 167: - -/* Line 1455 of yacc.c */ -#line 809 "yacc.yy" - { - function_mode = 1; - ;} - break; - - case 171: - -/* Line 1455 of yacc.c */ -#line 821 "yacc.yy" - {;} - break; - - case 172: - -/* Line 1455 of yacc.c */ -#line 822 "yacc.yy" - {;} - break; - - case 176: - -/* Line 1455 of yacc.c */ -#line 834 "yacc.yy" - {;} - break; - - case 177: - -/* Line 1455 of yacc.c */ -#line 835 "yacc.yy" - {;} - break; - - case 178: - -/* Line 1455 of yacc.c */ -#line 836 "yacc.yy" - {;} - break; - - case 179: - -/* Line 1455 of yacc.c */ -#line 839 "yacc.yy" - {;} - break; - - case 180: - -/* Line 1455 of yacc.c */ -#line 843 "yacc.yy" - {;} - break; - - case 181: - -/* Line 1455 of yacc.c */ -#line 844 "yacc.yy" - {;} - break; - - case 182: - -/* Line 1455 of yacc.c */ -#line 845 "yacc.yy" - {;} - break; - - case 183: - -/* Line 1455 of yacc.c */ -#line 846 "yacc.yy" - {;} - break; - - case 184: - -/* Line 1455 of yacc.c */ -#line 847 "yacc.yy" - {;} - break; - - case 185: - -/* Line 1455 of yacc.c */ -#line 848 "yacc.yy" - {;} - break; - - - -/* Line 1455 of yacc.c */ -#line 3171 "yacc.cc" - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - *++yyvsp = yylval; - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined(yyoverflow) || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - - -/* Line 1675 of yacc.c */ -#line 851 "yacc.yy" - - -void dcopidlParse( const char *_code ) -{ - dcopidlInitFlex( _code ); - yyparse(); -} - diff --git a/dcop/dcopidl/yacc.cc.h b/dcop/dcopidl/yacc.cc.h deleted file mode 100644 index 2a6c1b403..000000000 --- a/dcop/dcopidl/yacc.cc.h +++ /dev/null @@ -1,135 +0,0 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - T_UNIMPORTANT = 258, - T_CHARACTER_LITERAL = 259, - T_DOUBLE_LITERAL = 260, - T_IDENTIFIER = 261, - T_INTEGER_LITERAL = 262, - T_STRING_LITERAL = 263, - T_INCLUDE = 264, - T_CLASS = 265, - T_STRUCT = 266, - T_LEFT_CURLY_BRACKET = 267, - T_LEFT_PARANTHESIS = 268, - T_RIGHT_CURLY_BRACKET = 269, - T_RIGHT_PARANTHESIS = 270, - T_COLON = 271, - T_SEMICOLON = 272, - T_PUBLIC = 273, - T_PROTECTED = 274, - T_TRIPE_DOT = 275, - T_PRIVATE = 276, - T_VIRTUAL = 277, - T_CONST = 278, - T_INLINE = 279, - T_FRIEND = 280, - T_RETURN = 281, - T_SIGNAL = 282, - T_SLOT = 283, - T_TYPEDEF = 284, - T_PLUS = 285, - T_MINUS = 286, - T_COMMA = 287, - T_ASTERISK = 288, - T_TILDE = 289, - T_LESS = 290, - T_GREATER = 291, - T_AMPERSAND = 292, - T_EXTERN = 293, - T_EXTERN_C = 294, - T_ACCESS = 295, - T_ENUM = 296, - T_NAMESPACE = 297, - T_USING = 298, - T_UNKNOWN = 299, - T_TRIPLE_DOT = 300, - T_TRUE = 301, - T_FALSE = 302, - T_STATIC = 303, - T_MUTABLE = 304, - T_EQUAL = 305, - T_SCOPE = 306, - T_NULL = 307, - T_INT = 308, - T_ARRAY_OPEN = 309, - T_ARRAY_CLOSE = 310, - T_CHAR = 311, - T_DCOP = 312, - T_DCOP_AREA = 313, - T_DCOP_SIGNAL_AREA = 314, - T_SIGNED = 315, - T_UNSIGNED = 316, - T_LONG = 317, - T_SHORT = 318, - T_FUNOPERATOR = 319, - T_MISCOPERATOR = 320, - T_SHIFT = 321 - }; -#endif - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - -/* Line 1676 of yacc.c */ -#line 67 "yacc.yy" - - long _int; - QString *_str; - unsigned short _char; - double _float; - - - -/* Line 1676 of yacc.c */ -#line 127 "yacc.hh" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - -extern YYSTYPE yylval; - - diff --git a/dcop/dcopidl/yacc.cpp b/dcop/dcopidl/yacc.cpp new file mode 100644 index 000000000..4be32edd0 --- /dev/null +++ b/dcop/dcopidl/yacc.cpp @@ -0,0 +1,3390 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Copy the first part of user declarations. */ + +/* Line 189 of yacc.c */ +#line 1 "yacc.yy" + +/***************************************************************** +Copyright (c) 1999 Torben Weis +Copyright (c) 2000 Matthias Ettrich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include + +// Workaround for a bison issue: +// bison.simple concludes from _GNU_SOURCE that stpcpy is available, +// while GNU string.h only exposes it if __USE_GNU is set. +#ifdef _GNU_SOURCE +#define __USE_GNU 1 +#endif + +#include +#include +#include + +#include + +#define AMP_ENTITY "&" +#define YYERROR_VERBOSE + +extern int yylex(); + +// extern QString idl_lexFile; +extern int idl_line_no; +extern int function_mode; + +static int dcop_area = 0; +static int dcop_signal_area = 0; + +static QString in_namespace( "" ); + +void dcopidlInitFlex( const char *_code ); + +void yyerror( const char *s ) +{ + tqDebug( "In line %i : %s", idl_line_no, s ); + exit(1); + // theParser->parse_error( idl_lexFile, s, idl_line_no ); +} + + + +/* Line 189 of yacc.c */ +#line 138 "yacc.cpp" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_UNIMPORTANT = 258, + T_CHARACTER_LITERAL = 259, + T_DOUBLE_LITERAL = 260, + T_IDENTIFIER = 261, + T_INTEGER_LITERAL = 262, + T_STRING_LITERAL = 263, + T_INCLUDE = 264, + T_CLASS = 265, + T_STRUCT = 266, + T_LEFT_CURLY_BRACKET = 267, + T_LEFT_PARANTHESIS = 268, + T_RIGHT_CURLY_BRACKET = 269, + T_RIGHT_PARANTHESIS = 270, + T_COLON = 271, + T_SEMICOLON = 272, + T_PUBLIC = 273, + T_PROTECTED = 274, + T_TRIPE_DOT = 275, + T_PRIVATE = 276, + T_VIRTUAL = 277, + T_CONST = 278, + T_INLINE = 279, + T_FRIEND = 280, + T_RETURN = 281, + T_SIGNAL = 282, + T_SLOT = 283, + T_TYPEDEF = 284, + T_PLUS = 285, + T_MINUS = 286, + T_COMMA = 287, + T_ASTERISK = 288, + T_TILDE = 289, + T_LESS = 290, + T_GREATER = 291, + T_AMPERSAND = 292, + T_EXTERN = 293, + T_EXTERN_C = 294, + T_ACCESS = 295, + T_ENUM = 296, + T_NAMESPACE = 297, + T_USING = 298, + T_UNKNOWN = 299, + T_TRIPLE_DOT = 300, + T_TRUE = 301, + T_FALSE = 302, + T_STATIC = 303, + T_MUTABLE = 304, + T_EQUAL = 305, + T_SCOPE = 306, + T_NULL = 307, + T_INT = 308, + T_ARRAY_OPEN = 309, + T_ARRAY_CLOSE = 310, + T_CHAR = 311, + T_DCOP = 312, + T_DCOP_AREA = 313, + T_DCOP_SIGNAL_AREA = 314, + T_SIGNED = 315, + T_UNSIGNED = 316, + T_LONG = 317, + T_SHORT = 318, + T_FUNOPERATOR = 319, + T_MISCOPERATOR = 320, + T_SHIFT = 321 + }; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 214 of yacc.c */ +#line 67 "yacc.yy" + + long _int; + QString *_str; + unsigned short _char; + double _float; + + + +/* Line 214 of yacc.c */ +#line 249 "yacc.cpp" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 264 of yacc.c */ +#line 261 "yacc.cpp" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 5 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 559 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 67 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 53 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 185 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 374 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 321 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 7, 8, 11, 16, 17, 19, 20, + 27, 35, 39, 43, 49, 50, 58, 63, 69, 72, + 77, 85, 94, 97, 99, 101, 103, 106, 107, 109, + 111, 113, 115, 117, 119, 121, 122, 126, 129, 132, + 135, 137, 141, 143, 148, 152, 154, 157, 161, 164, + 166, 167, 169, 171, 174, 178, 181, 184, 187, 190, + 193, 196, 202, 207, 212, 217, 224, 229, 236, 243, + 251, 258, 265, 271, 275, 277, 281, 283, 285, 287, + 290, 292, 294, 296, 300, 304, 312, 322, 323, 325, + 327, 330, 332, 335, 338, 342, 345, 349, 352, 356, + 359, 363, 365, 367, 370, 372, 375, 377, 380, 383, + 386, 388, 389, 391, 395, 397, 399, 402, 405, 410, + 417, 421, 423, 426, 428, 432, 436, 439, 442, 446, + 449, 451, 454, 458, 460, 464, 467, 469, 470, 473, + 479, 481, 483, 485, 487, 492, 493, 495, 497, 499, + 501, 503, 505, 512, 520, 522, 526, 527, 532, 534, + 538, 541, 547, 551, 557, 565, 572, 576, 578, 580, + 584, 589, 592, 593, 595, 598, 599, 601, 605, 608, + 611, 615, 621, 627, 633, 640 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 68, 0, -1, 69, 71, 68, -1, -1, 69, 9, + -1, 39, 12, 68, 14, -1, -1, 57, -1, -1, + 10, 80, 84, 70, 86, 17, -1, 10, 6, 80, + 84, 70, 86, 17, -1, 10, 80, 17, -1, 11, + 80, 17, -1, 11, 80, 84, 86, 17, -1, -1, + 42, 6, 12, 72, 68, 14, 85, -1, 43, 42, + 6, 17, -1, 43, 6, 51, 6, 17, -1, 38, + 17, -1, 29, 100, 80, 17, -1, 29, 11, 12, + 73, 14, 80, 17, -1, 29, 11, 80, 12, 73, + 14, 80, 17, -1, 24, 111, -1, 111, -1, 119, + -1, 87, -1, 119, 73, -1, -1, 46, -1, 47, + -1, 21, -1, 19, -1, 18, -1, 27, -1, 28, + -1, -1, 75, 76, 16, -1, 76, 16, -1, 58, + 16, -1, 59, 16, -1, 6, -1, 6, 51, 80, + -1, 80, -1, 80, 35, 101, 36, -1, 105, 18, + 81, -1, 81, -1, 82, 12, -1, 82, 32, 83, + -1, 16, 83, -1, 12, -1, -1, 17, -1, 14, + -1, 92, 86, -1, 24, 111, 86, -1, 111, 86, + -1, 79, 86, -1, 87, 86, -1, 78, 86, -1, + 77, 86, -1, 119, 86, -1, 25, 10, 80, 17, + 86, -1, 25, 80, 17, 86, -1, 25, 107, 17, + 86, -1, 10, 80, 17, 86, -1, 10, 80, 84, + 86, 17, 86, -1, 11, 80, 17, 86, -1, 11, + 80, 84, 86, 17, 86, -1, 43, 6, 51, 6, + 17, 86, -1, 41, 6, 12, 88, 14, 6, 17, + -1, 41, 6, 12, 88, 14, 17, -1, 41, 12, + 88, 14, 6, 17, -1, 41, 12, 88, 14, 17, + -1, 89, 32, 88, -1, 89, -1, 6, 50, 91, + -1, 6, -1, 4, -1, 7, -1, 31, 7, -1, + 52, -1, 80, -1, 90, -1, 90, 30, 90, -1, + 90, 66, 90, -1, 29, 80, 35, 101, 36, 80, + 17, -1, 29, 80, 35, 101, 36, 51, 6, 80, + 17, -1, -1, 23, -1, 60, -1, 60, 53, -1, + 61, -1, 61, 53, -1, 60, 63, -1, 60, 63, + 53, -1, 60, 62, -1, 60, 62, 53, -1, 61, + 63, -1, 61, 63, 53, -1, 61, 62, -1, 61, + 62, 53, -1, 53, -1, 62, -1, 62, 53, -1, + 63, -1, 63, 53, -1, 56, -1, 60, 56, -1, + 61, 56, -1, 33, 95, -1, 33, -1, -1, 102, + -1, 96, 32, 102, -1, 94, -1, 80, -1, 11, + 80, -1, 10, 80, -1, 80, 35, 98, 36, -1, + 80, 35, 98, 36, 51, 80, -1, 99, 32, 98, + -1, 99, -1, 97, 95, -1, 97, -1, 23, 97, + 95, -1, 23, 97, 37, -1, 23, 97, -1, 97, + 23, -1, 97, 23, 37, -1, 97, 37, -1, 97, + -1, 97, 95, -1, 100, 32, 101, -1, 100, -1, + 100, 80, 103, -1, 100, 103, -1, 45, -1, -1, + 50, 104, -1, 50, 13, 100, 15, 104, -1, 8, + -1, 91, -1, 5, -1, 74, -1, 80, 13, 96, + 15, -1, -1, 22, -1, 65, -1, 66, -1, 36, + -1, 35, -1, 50, -1, 100, 80, 13, 96, 15, + 93, -1, 100, 64, 106, 13, 96, 15, 93, -1, + 104, -1, 104, 32, 108, -1, -1, 6, 13, 108, + 15, -1, 109, -1, 109, 32, 110, -1, 107, 113, + -1, 22, 107, 50, 52, 113, -1, 22, 107, 113, + -1, 80, 13, 96, 15, 113, -1, 80, 13, 96, + 15, 16, 110, 113, -1, 105, 34, 80, 13, 15, + 113, -1, 48, 107, 113, -1, 12, -1, 17, -1, + 112, 114, 14, -1, 112, 114, 14, 17, -1, 115, + 114, -1, -1, 17, -1, 32, 118, -1, -1, 6, + -1, 6, 50, 104, -1, 95, 6, -1, 117, 116, + -1, 100, 118, 17, -1, 100, 80, 16, 7, 17, + -1, 48, 100, 6, 103, 17, -1, 49, 100, 6, + 103, 17, -1, 100, 6, 54, 91, 55, 17, -1, + 48, 100, 6, 54, 91, 55, 17, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 164, 164, 167, 171, 175, 179, 184, 185, 189, + 198, 207, 210, 213, 217, 216, 228, 231, 234, 237, + 240, 243, 246, 249, 252, 255, 261, 262, 265, 265, + 267, 267, 267, 269, 269, 269, 272, 277, 285, 293, + 305, 308, 316, 322, 331, 335, 342, 346, 354, 358, + 366, 368, 372, 376, 380, 384, 388, 392, 396, 400, + 404, 408, 412, 416, 420, 424, 428, 432, 436, 443, + 444, 445, 446, 450, 451, 455, 456, 460, 461, 462, + 463, 464, 468, 469, 470, 474, 484, 493, 496, 503, + 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, + 514, 515, 516, 517, 518, 519, 520, 521, 522, 526, + 527, 532, 535, 536, 544, 545, 546, 547, 548, 554, + 565, 569, 577, 582, 591, 596, 603, 608, 613, 620, + 625, 630, 638, 642, 649, 658, 666, 676, 678, 681, + 688, 691, 694, 697, 700, 706, 707, 711, 711, 711, + 711, 711, 715, 737, 748, 749, 750, 755, 760, 761, + 765, 769, 773, 777, 783, 789, 795, 808, 815, 816, + 817, 821, 822, 826, 830, 831, 834, 835, 836, 839, + 843, 844, 845, 846, 847, 848 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_UNIMPORTANT", "T_CHARACTER_LITERAL", + "T_DOUBLE_LITERAL", "T_IDENTIFIER", "T_INTEGER_LITERAL", + "T_STRING_LITERAL", "T_INCLUDE", "T_CLASS", "T_STRUCT", + "T_LEFT_CURLY_BRACKET", "T_LEFT_PARANTHESIS", "T_RIGHT_CURLY_BRACKET", + "T_RIGHT_PARANTHESIS", "T_COLON", "T_SEMICOLON", "T_PUBLIC", + "T_PROTECTED", "T_TRIPE_DOT", "T_PRIVATE", "T_VIRTUAL", "T_CONST", + "T_INLINE", "T_FRIEND", "T_RETURN", "T_SIGNAL", "T_SLOT", "T_TYPEDEF", + "T_PLUS", "T_MINUS", "T_COMMA", "T_ASTERISK", "T_TILDE", "T_LESS", + "T_GREATER", "T_AMPERSAND", "T_EXTERN", "T_EXTERN_C", "T_ACCESS", + "T_ENUM", "T_NAMESPACE", "T_USING", "T_UNKNOWN", "T_TRIPLE_DOT", + "T_TRUE", "T_FALSE", "T_STATIC", "T_MUTABLE", "T_EQUAL", "T_SCOPE", + "T_NULL", "T_INT", "T_ARRAY_OPEN", "T_ARRAY_CLOSE", "T_CHAR", "T_DCOP", + "T_DCOP_AREA", "T_DCOP_SIGNAL_AREA", "T_SIGNED", "T_UNSIGNED", "T_LONG", + "T_SHORT", "T_FUNOPERATOR", "T_MISCOPERATOR", "T_SHIFT", "$accept", + "main", "includes", "dcoptag", "declaration", "$@1", "member_list", + "bool_value", "nodcop_area", "sigslot", "nodcop_area_begin", + "dcop_area_begin", "dcop_signal_area_begin", "Identifier", + "super_class_name", "super_class", "super_classes", "class_header", + "opt_semicolon", "body", "enum", "enum_list", "enum_item", "number", + "int_expression", "typedef", "const_qualifier", "int_type", "asterisks", + "params", "type_name", "templ_type_list", "templ_type", "type", + "type_list", "param", "default", "value", "virtual_qualifier", + "operator", "function_header", "values", "init_item", "init_list", + "function", "function_begin", "function_body", "function_lines", + "function_line", "Identifier_list_rest", "Identifier_list_entry", + "Identifier_list", "member", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 67, 68, 68, 69, 69, 69, 70, 70, 71, + 71, 71, 71, 71, 72, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 73, 73, 74, 74, + 75, 75, 75, 76, 76, 76, 77, 77, 78, 79, + 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, + 85, 85, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, + 87, 87, 87, 88, 88, 89, 89, 90, 90, 90, + 90, 90, 91, 91, 91, 92, 92, 93, 93, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, + 95, 96, 96, 96, 97, 97, 97, 97, 97, 97, + 98, 98, 99, 99, 100, 100, 100, 100, 100, 100, + 100, 100, 101, 101, 102, 102, 102, 103, 103, 103, + 104, 104, 104, 104, 104, 105, 105, 106, 106, 106, + 106, 106, 107, 107, 108, 108, 108, 109, 110, 110, + 111, 111, 111, 111, 111, 111, 111, 112, 113, 113, + 113, 114, 114, 115, 116, 116, 117, 117, 117, 118, + 119, 119, 119, 119, 119, 119 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 3, 0, 2, 4, 0, 1, 0, 6, + 7, 3, 3, 5, 0, 7, 4, 5, 2, 4, + 7, 8, 2, 1, 1, 1, 2, 0, 1, 1, + 1, 1, 1, 1, 1, 0, 3, 2, 2, 2, + 1, 3, 1, 4, 3, 1, 2, 3, 2, 1, + 0, 1, 1, 2, 3, 2, 2, 2, 2, 2, + 2, 5, 4, 4, 4, 6, 4, 6, 6, 7, + 6, 6, 5, 3, 1, 3, 1, 1, 1, 2, + 1, 1, 1, 3, 3, 7, 9, 0, 1, 1, + 2, 1, 2, 2, 3, 2, 3, 2, 3, 2, + 3, 1, 1, 2, 1, 2, 1, 2, 2, 2, + 1, 0, 1, 3, 1, 1, 2, 2, 4, 6, + 3, 1, 2, 1, 3, 3, 2, 2, 3, 2, + 1, 2, 3, 1, 3, 2, 1, 0, 2, 5, + 1, 1, 1, 1, 4, 0, 1, 1, 1, 1, + 1, 1, 6, 7, 1, 3, 0, 4, 1, 3, + 2, 5, 3, 5, 7, 6, 3, 1, 1, 3, + 4, 2, 0, 1, 2, 0, 1, 3, 2, 2, + 3, 5, 5, 5, 6, 7 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 6, 0, 0, 145, 6, 1, 40, 4, 0, 0, + 146, 0, 145, 0, 0, 0, 0, 0, 0, 0, + 101, 106, 89, 91, 102, 104, 6, 115, 25, 114, + 130, 0, 0, 0, 23, 24, 0, 0, 40, 117, + 116, 0, 0, 115, 0, 0, 126, 0, 22, 0, + 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 107, 95, 93, 92, 108, 99, 97, 103, 105, + 2, 111, 0, 127, 110, 129, 131, 40, 0, 0, + 0, 175, 0, 0, 167, 168, 172, 160, 5, 41, + 0, 49, 145, 11, 8, 12, 35, 117, 116, 0, + 0, 162, 125, 124, 27, 116, 0, 0, 76, 0, + 74, 14, 0, 0, 40, 166, 137, 96, 94, 100, + 98, 136, 0, 137, 112, 123, 0, 121, 128, 109, + 0, 0, 150, 149, 151, 147, 148, 0, 111, 0, + 178, 0, 179, 180, 0, 173, 0, 172, 8, 146, + 42, 45, 0, 48, 0, 7, 35, 0, 0, 52, + 32, 31, 30, 145, 0, 33, 34, 0, 0, 0, + 0, 35, 0, 35, 35, 35, 0, 35, 35, 35, + 35, 0, 0, 0, 0, 27, 27, 19, 0, 0, + 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, + 0, 137, 135, 122, 118, 0, 77, 142, 78, 140, + 0, 28, 29, 80, 143, 81, 82, 141, 177, 81, + 0, 111, 0, 0, 176, 174, 0, 169, 171, 35, + 0, 46, 145, 0, 0, 117, 116, 35, 0, 115, + 0, 0, 0, 38, 39, 0, 37, 59, 58, 56, + 13, 57, 53, 55, 60, 161, 0, 0, 0, 26, + 0, 0, 75, 0, 72, 73, 0, 17, 0, 138, + 0, 182, 183, 0, 163, 113, 134, 0, 120, 79, + 111, 0, 0, 0, 0, 87, 181, 0, 170, 0, + 133, 0, 47, 44, 9, 35, 35, 35, 35, 54, + 117, 35, 35, 0, 0, 36, 137, 0, 0, 0, + 70, 71, 50, 0, 0, 0, 158, 0, 119, 0, + 83, 84, 184, 87, 88, 152, 165, 10, 0, 43, + 64, 0, 66, 0, 35, 62, 63, 0, 0, 20, + 0, 69, 51, 15, 0, 185, 156, 0, 164, 144, + 153, 132, 35, 35, 61, 0, 35, 21, 139, 154, + 0, 159, 65, 67, 0, 0, 68, 156, 157, 0, + 85, 155, 0, 86 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 2, 3, 156, 26, 192, 183, 214, 171, 172, + 173, 174, 175, 27, 151, 152, 153, 94, 343, 176, + 177, 109, 110, 216, 217, 178, 325, 29, 80, 122, + 30, 126, 127, 31, 291, 124, 197, 359, 32, 137, + 33, 360, 316, 317, 179, 86, 87, 146, 147, 142, + 81, 82, 180 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -191 +static const yytype_int16 yypact[] = +{ + 28, 78, 99, 342, 80, -191, 67, -191, 115, 159, + 205, 81, 386, 463, 153, 44, 190, 32, 205, 205, + -191, -191, 181, 287, 154, 161, 47, 66, -191, -191, + 138, 19, 185, 143, -191, -191, 207, 159, 21, 183, + 219, 159, 159, 194, 16, 31, 152, 205, -191, 91, + 159, -191, 228, 236, 233, 202, 264, 18, 143, 272, + -191, -191, 231, 232, -191, -191, 246, 248, -191, -191, + -191, 445, 81, 249, 256, -191, -191, 85, 182, 42, + 296, 273, 290, 159, -191, -191, 291, -191, -191, -191, + 196, -191, 146, -191, 262, -191, 269, -191, -191, 300, + 252, -191, -191, -191, 404, 311, 307, 236, 276, 319, + 302, -191, 329, 320, 60, -191, 289, -191, -191, -191, + -191, -191, 114, 39, -191, 256, 305, 310, -191, -191, + 507, 101, -191, -191, -191, -191, -191, 332, 445, 339, + -191, 62, -191, -191, 341, -191, 343, 291, 262, -191, + 321, -191, 34, -191, 337, -191, 269, 159, 159, -191, + -191, -191, -191, 386, 474, -191, -191, 159, 352, 344, + 346, 211, 347, 269, 269, 269, 350, 269, 269, 269, + 269, 143, 205, 354, 87, 404, 404, -191, 356, 101, + 156, 236, 80, 359, -191, 120, 101, 360, 364, 247, + 445, 289, -191, -191, 331, 81, -191, -191, -191, -191, + 379, -191, -191, -191, -191, 374, 40, -191, -191, -191, + 333, 445, 116, 372, 349, -191, 378, 377, -191, 269, + 205, -191, 146, 159, 383, 265, 299, 269, 159, 27, + 384, 371, 361, -191, -191, 391, -191, -191, -191, -191, + -191, -191, -191, -191, -191, -191, 407, 159, 400, -191, + 403, 176, -191, 401, -191, -191, 405, -191, 205, -191, + 365, -191, -191, 415, -191, -191, -191, 159, -191, -191, + 445, 101, 101, 406, 132, 399, -191, 143, -191, 408, + 392, 390, -191, -191, -191, 269, 269, 269, 269, -191, + 411, 269, 269, 205, 425, -191, 144, 418, 159, 419, + -191, -191, 420, 417, 421, 427, 409, 143, -191, 148, + -191, -191, -191, 399, -191, -191, -191, -191, 205, -191, + -191, 426, -191, 428, 269, -191, -191, 414, 437, -191, + 441, -191, -191, -191, 507, -191, 507, 415, -191, -191, + -191, -191, 269, 269, -191, 25, 269, -191, -191, 412, + 444, -191, -191, -191, 455, 446, -191, 507, -191, 159, + -191, -191, 453, -191 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -191, 9, -191, 314, -191, -191, -2, -191, -191, 301, + -191, -191, -191, -8, 238, -191, 243, -33, -191, 77, + 473, -91, -191, -72, -111, -191, 155, -191, -9, -123, + 1, 274, -191, 41, -190, 277, -97, -124, -78, -191, + 22, 121, -191, 134, 6, -191, -41, 335, -191, -191, + -191, 348, 5 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -177 +static const yytype_int16 yytable[] = +{ + 39, 40, 43, 43, 101, 43, 218, 96, 35, 34, + 43, 43, 46, 36, 154, 222, 188, 115, 48, 198, + 220, 76, 6, 79, 114, 77, 202, 6, -3, 89, + 90, 6, 45, 97, 98, 70, 99, 103, 55, 43, + 58, 105, 106, 84, 301, 6, 231, -3, 85, 99, + 52, 44, 74, 44, 50, 138, 53, 148, 139, 57, + 59, -3, 72, 43, 43, 129, 232, 1, 224, 58, + 281, 269, 37, 125, 56, 144, 364, -137, 262, 71, + 78, 100, 78, 78, 150, 270, 1, 6, 44, 195, + 4, 41, 42, 77, -3, 74, 43, 6, 284, 5, + 265, 72, -176, 104, 276, 206, 282, 6, 208, 185, + 195, 37, 123, 337, 196, 201, 203, -176, 37, 1, + 74, 38, 215, 219, 206, 207, 6, 208, 209, 199, + 43, 285, 210, 268, 20, 130, 37, 21, 351, 131, + 255, 22, 23, 24, 25, 184, 200, 323, 200, 235, + 236, 210, 6, 213, 154, 84, 239, 319, 274, 241, + 85, 73, 263, 349, 200, 6, 211, 212, 149, 237, + 51, 74, 213, 264, 43, 75, 258, 43, 43, 123, + 200, 219, 309, 259, 260, 74, 240, 215, 219, 102, + 185, 185, 43, 310, 195, 91, 54, 43, 196, 92, + 93, 266, 296, 298, 44, 44, 125, 68, 91, 320, + 321, 6, 92, 43, 69, 41, 42, 132, 133, 83, + 358, 88, 43, 256, 150, 150, 184, 184, 11, 72, + 300, 91, 134, 234, 60, 92, 95, 61, 165, 166, + 107, 123, 108, 62, 63, 111, 326, 135, 136, 307, + 247, 248, 249, 112, 251, 252, 253, 254, 20, 84, + 43, 21, 123, 273, 85, 22, 23, 24, 25, 318, + 113, 290, 43, 219, 219, 6, 348, 91, 116, 157, + 158, 92, 295, 159, 117, 118, 128, 160, 161, 74, + 162, 10, 11, 163, 164, 43, 165, 166, 167, 119, + 340, 120, 140, -145, 181, 141, 289, 143, 145, 313, + 15, 91, 168, 138, 299, 92, 297, 18, 19, 155, + 43, 123, 20, 186, 187, 21, 189, 169, 170, 22, + 23, 24, 25, 190, 191, 193, 215, 194, 215, 195, + 64, 204, 205, 65, 290, 221, 223, 365, 6, 66, + 67, 7, 8, 9, 226, 233, 230, 227, 242, 215, + 243, 372, 244, 246, 10, 11, 12, 250, 257, 290, + 261, 13, 330, 331, 332, 333, 267, 271, 335, 336, + 14, 272, 277, 15, 16, 17, 279, 280, 283, 286, + 18, 19, 6, 287, 288, 20, 41, 42, 21, 130, + 294, 302, 22, 23, 24, 25, 303, 305, 10, 11, + 6, 354, 304, 306, 41, 42, 139, 308, 311, 312, + 314, 315, 324, 322, 328, 327, 329, 11, 334, 362, + 363, 338, 344, 366, 47, 339, 341, 342, 345, 20, + 346, 347, 21, 352, 367, 353, 22, 23, 24, 25, + 355, 6, 182, 19, 356, 41, 42, 20, 357, 368, + 21, 369, 229, 370, 22, 23, 24, 25, 11, 6, + 373, 293, 245, 41, 49, 292, 28, 275, 350, 278, + 6, 361, 228, 0, 238, 42, 11, 0, 371, 225, + 121, 0, 0, 0, 0, 0, 0, 11, 20, 0, + 0, 21, 0, 0, 0, 22, 23, 24, 25, 0, + 0, 206, 207, 6, 208, 209, 20, 0, 0, 21, + 0, 0, 0, 22, 23, 24, 25, 20, 0, 0, + 21, 0, 0, 0, 22, 23, 24, 25, 210, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 211, 212, 0, 0, 0, 0, 213 +}; + +static const yytype_int16 yycheck[] = +{ + 8, 9, 10, 11, 45, 13, 130, 40, 3, 3, + 18, 19, 11, 4, 92, 138, 107, 58, 12, 116, + 131, 30, 6, 31, 6, 6, 123, 6, 0, 37, + 38, 6, 10, 41, 42, 26, 44, 46, 6, 47, + 18, 49, 50, 12, 17, 6, 12, 0, 17, 57, + 6, 10, 33, 12, 13, 13, 12, 90, 16, 18, + 19, 14, 35, 71, 72, 74, 32, 39, 6, 47, + 30, 195, 51, 72, 42, 83, 51, 17, 189, 13, + 64, 50, 64, 64, 92, 196, 39, 6, 47, 50, + 12, 10, 11, 6, 14, 33, 104, 6, 221, 0, + 191, 35, 17, 12, 201, 4, 66, 6, 7, 104, + 50, 51, 71, 303, 54, 123, 125, 32, 51, 39, + 33, 6, 130, 131, 4, 5, 6, 7, 8, 15, + 138, 15, 31, 13, 53, 50, 51, 56, 328, 54, + 181, 60, 61, 62, 63, 104, 32, 15, 32, 157, + 158, 31, 6, 52, 232, 12, 164, 280, 199, 167, + 17, 23, 6, 15, 32, 6, 46, 47, 22, 163, + 17, 33, 52, 17, 182, 37, 184, 185, 186, 138, + 32, 189, 6, 185, 186, 33, 164, 195, 196, 37, + 185, 186, 200, 17, 50, 12, 6, 205, 54, 16, + 17, 192, 235, 236, 163, 164, 205, 53, 12, 281, + 282, 6, 16, 221, 53, 10, 11, 35, 36, 34, + 344, 14, 230, 182, 232, 233, 185, 186, 23, 35, + 238, 12, 50, 156, 53, 16, 17, 56, 27, 28, + 12, 200, 6, 62, 63, 12, 287, 65, 66, 257, + 173, 174, 175, 51, 177, 178, 179, 180, 53, 12, + 268, 56, 221, 16, 17, 60, 61, 62, 63, 277, + 6, 230, 280, 281, 282, 6, 317, 12, 6, 10, + 11, 16, 17, 14, 53, 53, 37, 18, 19, 33, + 21, 22, 23, 24, 25, 303, 27, 28, 29, 53, + 308, 53, 6, 34, 52, 32, 229, 17, 17, 268, + 41, 12, 43, 13, 237, 16, 17, 48, 49, 57, + 328, 280, 53, 12, 17, 56, 50, 58, 59, 60, + 61, 62, 63, 14, 32, 6, 344, 17, 346, 50, + 53, 36, 32, 56, 303, 13, 7, 355, 6, 62, + 63, 9, 10, 11, 13, 18, 35, 14, 6, 367, + 16, 369, 16, 16, 22, 23, 24, 17, 14, 328, + 14, 29, 295, 296, 297, 298, 17, 17, 301, 302, + 38, 17, 51, 41, 42, 43, 7, 13, 55, 17, + 48, 49, 6, 15, 17, 53, 10, 11, 56, 50, + 17, 17, 60, 61, 62, 63, 35, 16, 22, 23, + 6, 334, 51, 6, 10, 11, 16, 14, 17, 14, + 55, 6, 23, 17, 32, 17, 36, 23, 17, 352, + 353, 6, 15, 356, 48, 17, 17, 17, 17, 53, + 13, 32, 56, 17, 32, 17, 60, 61, 62, 63, + 36, 6, 48, 49, 17, 10, 11, 53, 17, 15, + 56, 6, 148, 17, 60, 61, 62, 63, 23, 6, + 17, 233, 171, 10, 11, 232, 3, 200, 323, 205, + 6, 347, 147, -1, 10, 11, 23, -1, 367, 141, + 45, -1, -1, -1, -1, -1, -1, 23, 53, -1, + -1, 56, -1, -1, -1, 60, 61, 62, 63, -1, + -1, 4, 5, 6, 7, 8, 53, -1, -1, 56, + -1, -1, -1, 60, 61, 62, 63, 53, -1, -1, + 56, -1, -1, -1, 60, 61, 62, 63, 31, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 46, 47, -1, -1, -1, -1, 52 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 39, 68, 69, 12, 0, 6, 9, 10, 11, + 22, 23, 24, 29, 38, 41, 42, 43, 48, 49, + 53, 56, 60, 61, 62, 63, 71, 80, 87, 94, + 97, 100, 105, 107, 111, 119, 68, 51, 6, 80, + 80, 10, 11, 80, 100, 107, 97, 48, 111, 11, + 100, 17, 6, 12, 6, 6, 42, 100, 107, 100, + 53, 56, 62, 63, 53, 56, 62, 63, 53, 53, + 68, 13, 35, 23, 33, 37, 95, 6, 64, 80, + 95, 117, 118, 34, 12, 17, 112, 113, 14, 80, + 80, 12, 16, 17, 84, 17, 84, 80, 80, 80, + 50, 113, 37, 95, 12, 80, 80, 12, 6, 88, + 89, 12, 51, 6, 6, 113, 6, 53, 53, 53, + 53, 45, 96, 100, 102, 97, 98, 99, 37, 95, + 50, 54, 35, 36, 50, 65, 66, 106, 13, 16, + 6, 32, 116, 17, 80, 17, 114, 115, 84, 22, + 80, 81, 82, 83, 105, 57, 70, 10, 11, 14, + 18, 19, 21, 24, 25, 27, 28, 29, 43, 58, + 59, 75, 76, 77, 78, 79, 86, 87, 92, 111, + 119, 52, 48, 73, 100, 119, 12, 17, 88, 50, + 14, 32, 72, 6, 17, 50, 54, 103, 103, 15, + 32, 80, 103, 95, 36, 32, 4, 5, 7, 8, + 31, 46, 47, 52, 74, 80, 90, 91, 104, 80, + 91, 13, 96, 7, 6, 118, 13, 14, 114, 70, + 35, 12, 32, 18, 86, 80, 80, 111, 10, 80, + 107, 80, 6, 16, 16, 76, 16, 86, 86, 86, + 17, 86, 86, 86, 86, 113, 100, 14, 80, 73, + 73, 14, 91, 6, 17, 88, 68, 17, 13, 104, + 91, 17, 17, 16, 113, 102, 103, 51, 98, 7, + 13, 30, 66, 55, 96, 15, 17, 15, 17, 86, + 100, 101, 83, 81, 17, 17, 84, 17, 84, 86, + 80, 17, 17, 35, 51, 16, 6, 80, 14, 6, + 17, 17, 14, 100, 55, 6, 109, 110, 80, 96, + 90, 90, 17, 15, 23, 93, 113, 17, 32, 36, + 86, 86, 86, 86, 17, 86, 86, 101, 6, 17, + 80, 17, 17, 85, 15, 17, 13, 32, 113, 15, + 93, 101, 17, 17, 86, 36, 17, 17, 104, 104, + 108, 110, 86, 86, 51, 80, 86, 32, 15, 6, + 17, 108, 80, 17 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: + +/* Line 1455 of yacc.c */ +#line 165 "yacc.yy" + { + ;} + break; + + case 4: + +/* Line 1455 of yacc.c */ +#line 172 "yacc.yy" + { + printf("%s\n", (yyvsp[(2) - (2)]._str)->latin1() ); + ;} + break; + + case 5: + +/* Line 1455 of yacc.c */ +#line 176 "yacc.yy" + { + ;} + break; + + case 6: + +/* Line 1455 of yacc.c */ +#line 179 "yacc.yy" + { + ;} + break; + + case 7: + +/* Line 1455 of yacc.c */ +#line 184 "yacc.yy" + { (yyval._int) = 1; ;} + break; + + case 8: + +/* Line 1455 of yacc.c */ +#line 185 "yacc.yy" + { (yyval._int) = 0; ;} + break; + + case 9: + +/* Line 1455 of yacc.c */ +#line 190 "yacc.yy" + { + if ((yyvsp[(4) - (6)]._int)) + printf("\n %s\n%s%s\n", ( in_namespace + *(yyvsp[(2) - (6)]._str) ).latin1(), (yyvsp[(3) - (6)]._str)->latin1(), (yyvsp[(5) - (6)]._str)->latin1() ); + // default C++ visibility specifier is 'private' + dcop_area = 0; + dcop_signal_area = 0; + + ;} + break; + + case 10: + +/* Line 1455 of yacc.c */ +#line 199 "yacc.yy" + { + if ((yyvsp[(5) - (7)]._int)) + printf("\n %s\n %s\n%s%s\n", ( in_namespace + *(yyvsp[(3) - (7)]._str) ).latin1(),(yyvsp[(2) - (7)]._str)->latin1(), (yyvsp[(4) - (7)]._str)->latin1(), (yyvsp[(6) - (7)]._str)->latin1() ); + // default C++ visibility specifier is 'private' + dcop_area = 0; + dcop_signal_area = 0; + + ;} + break; + + case 11: + +/* Line 1455 of yacc.c */ +#line 208 "yacc.yy" + { + ;} + break; + + case 12: + +/* Line 1455 of yacc.c */ +#line 211 "yacc.yy" + { + ;} + break; + + case 13: + +/* Line 1455 of yacc.c */ +#line 214 "yacc.yy" + { + ;} + break; + + case 14: + +/* Line 1455 of yacc.c */ +#line 217 "yacc.yy" + { + in_namespace += *(yyvsp[(2) - (3)]._str); in_namespace += "::"; + ;} + break; + + case 15: + +/* Line 1455 of yacc.c */ +#line 221 "yacc.yy" + { + int pos = in_namespace.findRev( "::", -3 ); + if( pos >= 0 ) + in_namespace = in_namespace.left( pos + 2 ); + else + in_namespace = ""; + ;} + break; + + case 16: + +/* Line 1455 of yacc.c */ +#line 229 "yacc.yy" + { + ;} + break; + + case 17: + +/* Line 1455 of yacc.c */ +#line 232 "yacc.yy" + { + ;} + break; + + case 18: + +/* Line 1455 of yacc.c */ +#line 235 "yacc.yy" + { + ;} + break; + + case 19: + +/* Line 1455 of yacc.c */ +#line 238 "yacc.yy" + { + ;} + break; + + case 20: + +/* Line 1455 of yacc.c */ +#line 241 "yacc.yy" + { + ;} + break; + + case 21: + +/* Line 1455 of yacc.c */ +#line 244 "yacc.yy" + { + ;} + break; + + case 22: + +/* Line 1455 of yacc.c */ +#line 247 "yacc.yy" + { + ;} + break; + + case 23: + +/* Line 1455 of yacc.c */ +#line 250 "yacc.yy" + { + ;} + break; + + case 24: + +/* Line 1455 of yacc.c */ +#line 253 "yacc.yy" + { + ;} + break; + + case 25: + +/* Line 1455 of yacc.c */ +#line 256 "yacc.yy" + { + ;} + break; + + case 36: + +/* Line 1455 of yacc.c */ +#line 273 "yacc.yy" + { + dcop_area = 0; + dcop_signal_area = 0; + ;} + break; + + case 37: + +/* Line 1455 of yacc.c */ +#line 278 "yacc.yy" + { + dcop_area = 0; + dcop_signal_area = 0; + ;} + break; + + case 38: + +/* Line 1455 of yacc.c */ +#line 286 "yacc.yy" + { + dcop_area = 1; + dcop_signal_area = 0; + ;} + break; + + case 39: + +/* Line 1455 of yacc.c */ +#line 294 "yacc.yy" + { + /* + A dcop signals area needs all dcop area capabilities, + e.g. parsing of function parameters. + */ + dcop_area = 1; + dcop_signal_area = 1; + ;} + break; + + case 40: + +/* Line 1455 of yacc.c */ +#line 305 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (1)]._str); + ;} + break; + + case 41: + +/* Line 1455 of yacc.c */ +#line 308 "yacc.yy" + { + QString* tmp = new QString( "%1::%2" ); + *tmp = tmp->arg(*((yyvsp[(1) - (3)]._str))).arg(*((yyvsp[(3) - (3)]._str))); + (yyval._str) = tmp; + ;} + break; + + case 42: + +/* Line 1455 of yacc.c */ +#line 317 "yacc.yy" + { + QString* tmp = new QString( " %1\n" ); + *tmp = tmp->arg( *((yyvsp[(1) - (1)]._str)) ); + (yyval._str) = tmp; + ;} + break; + + case 43: + +/* Line 1455 of yacc.c */ +#line 323 "yacc.yy" + { + QString* tmp = new QString( " %1\n" ); + *tmp = tmp->arg( *((yyvsp[(1) - (4)]._str)) + "<" + *((yyvsp[(3) - (4)]._str)) + ">" ); + (yyval._str) = tmp; + ;} + break; + + case 44: + +/* Line 1455 of yacc.c */ +#line 332 "yacc.yy" + { + (yyval._str) = (yyvsp[(3) - (3)]._str); + ;} + break; + + case 45: + +/* Line 1455 of yacc.c */ +#line 336 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (1)]._str); + ;} + break; + + case 46: + +/* Line 1455 of yacc.c */ +#line 343 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (2)]._str); + ;} + break; + + case 47: + +/* Line 1455 of yacc.c */ +#line 347 "yacc.yy" + { + /* $$ = $1; */ + (yyval._str) = new QString( *((yyvsp[(1) - (3)]._str)) + *((yyvsp[(3) - (3)]._str)) ); + ;} + break; + + case 48: + +/* Line 1455 of yacc.c */ +#line 355 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (2)]._str); + ;} + break; + + case 49: + +/* Line 1455 of yacc.c */ +#line 359 "yacc.yy" + { + (yyval._str) = new QString( "" ); + ;} + break; + + case 50: + +/* Line 1455 of yacc.c */ +#line 366 "yacc.yy" + { + ;} + break; + + case 52: + +/* Line 1455 of yacc.c */ +#line 373 "yacc.yy" + { + (yyval._str) = new QString( "" ); + ;} + break; + + case 53: + +/* Line 1455 of yacc.c */ +#line 377 "yacc.yy" + { + (yyval._str) = new QString( *((yyvsp[(1) - (2)]._str)) + *((yyvsp[(2) - (2)]._str)) ); + ;} + break; + + case 54: + +/* Line 1455 of yacc.c */ +#line 381 "yacc.yy" + { + (yyval._str) = new QString( *((yyvsp[(2) - (3)]._str)) + *((yyvsp[(3) - (3)]._str)) ); + ;} + break; + + case 55: + +/* Line 1455 of yacc.c */ +#line 385 "yacc.yy" + { + (yyval._str) = new QString( *((yyvsp[(1) - (2)]._str)) + *((yyvsp[(2) - (2)]._str)) ); + ;} + break; + + case 56: + +/* Line 1455 of yacc.c */ +#line 389 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (2)]._str); + ;} + break; + + case 57: + +/* Line 1455 of yacc.c */ +#line 393 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (2)]._str); + ;} + break; + + case 58: + +/* Line 1455 of yacc.c */ +#line 397 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (2)]._str); + ;} + break; + + case 59: + +/* Line 1455 of yacc.c */ +#line 401 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (2)]._str); + ;} + break; + + case 60: + +/* Line 1455 of yacc.c */ +#line 405 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (2)]._str); + ;} + break; + + case 61: + +/* Line 1455 of yacc.c */ +#line 409 "yacc.yy" + { + (yyval._str) = (yyvsp[(5) - (5)]._str); + ;} + break; + + case 62: + +/* Line 1455 of yacc.c */ +#line 413 "yacc.yy" + { + (yyval._str) = (yyvsp[(4) - (4)]._str); + ;} + break; + + case 63: + +/* Line 1455 of yacc.c */ +#line 417 "yacc.yy" + { + (yyval._str) = (yyvsp[(4) - (4)]._str); + ;} + break; + + case 64: + +/* Line 1455 of yacc.c */ +#line 421 "yacc.yy" + { + (yyval._str) = (yyvsp[(4) - (4)]._str); + ;} + break; + + case 65: + +/* Line 1455 of yacc.c */ +#line 425 "yacc.yy" + { + (yyval._str) = (yyvsp[(6) - (6)]._str); + ;} + break; + + case 66: + +/* Line 1455 of yacc.c */ +#line 429 "yacc.yy" + { + (yyval._str) = (yyvsp[(4) - (4)]._str); + ;} + break; + + case 67: + +/* Line 1455 of yacc.c */ +#line 433 "yacc.yy" + { + (yyval._str) = (yyvsp[(6) - (6)]._str); + ;} + break; + + case 68: + +/* Line 1455 of yacc.c */ +#line 437 "yacc.yy" + { + (yyval._str) = (yyvsp[(6) - (6)]._str); + ;} + break; + + case 75: + +/* Line 1455 of yacc.c */ +#line 455 "yacc.yy" + {;} + break; + + case 76: + +/* Line 1455 of yacc.c */ +#line 456 "yacc.yy" + {;} + break; + + case 77: + +/* Line 1455 of yacc.c */ +#line 460 "yacc.yy" + {;} + break; + + case 78: + +/* Line 1455 of yacc.c */ +#line 461 "yacc.yy" + {;} + break; + + case 79: + +/* Line 1455 of yacc.c */ +#line 462 "yacc.yy" + {;} + break; + + case 80: + +/* Line 1455 of yacc.c */ +#line 463 "yacc.yy" + {;} + break; + + case 81: + +/* Line 1455 of yacc.c */ +#line 464 "yacc.yy" + {;} + break; + + case 82: + +/* Line 1455 of yacc.c */ +#line 468 "yacc.yy" + {;} + break; + + case 83: + +/* Line 1455 of yacc.c */ +#line 469 "yacc.yy" + {;} + break; + + case 84: + +/* Line 1455 of yacc.c */ +#line 470 "yacc.yy" + {;} + break; + + case 85: + +/* Line 1455 of yacc.c */ +#line 475 "yacc.yy" + { + if (dcop_area) { + QString* tmp = new QString("\n"); + *tmp = tmp->arg( *((yyvsp[(6) - (7)]._str)) ).arg( *((yyvsp[(2) - (7)]._str)) ).arg( *((yyvsp[(4) - (7)]._str)) ); + (yyval._str) = tmp; + } else { + (yyval._str) = new QString(""); + } + ;} + break; + + case 86: + +/* Line 1455 of yacc.c */ +#line 485 "yacc.yy" + { + if (dcop_area) + yyerror("scoped template typedefs are not supported in dcop areas!"); + ;} + break; + + case 87: + +/* Line 1455 of yacc.c */ +#line 493 "yacc.yy" + { + (yyval._int) = 0; + ;} + break; + + case 88: + +/* Line 1455 of yacc.c */ +#line 497 "yacc.yy" + { + (yyval._int) = 1; + ;} + break; + + case 89: + +/* Line 1455 of yacc.c */ +#line 503 "yacc.yy" + { (yyval._str) = new QString("signed int"); ;} + break; + + case 90: + +/* Line 1455 of yacc.c */ +#line 504 "yacc.yy" + { (yyval._str) = new QString("signed int"); ;} + break; + + case 91: + +/* Line 1455 of yacc.c */ +#line 505 "yacc.yy" + { (yyval._str) = new QString("unsigned int"); ;} + break; + + case 92: + +/* Line 1455 of yacc.c */ +#line 506 "yacc.yy" + { (yyval._str) = new QString("unsigned int"); ;} + break; + + case 93: + +/* Line 1455 of yacc.c */ +#line 507 "yacc.yy" + { (yyval._str) = new QString("signed short int"); ;} + break; + + case 94: + +/* Line 1455 of yacc.c */ +#line 508 "yacc.yy" + { (yyval._str) = new QString("signed short int"); ;} + break; + + case 95: + +/* Line 1455 of yacc.c */ +#line 509 "yacc.yy" + { (yyval._str) = new QString("signed long int"); ;} + break; + + case 96: + +/* Line 1455 of yacc.c */ +#line 510 "yacc.yy" + { (yyval._str) = new QString("signed long int"); ;} + break; + + case 97: + +/* Line 1455 of yacc.c */ +#line 511 "yacc.yy" + { (yyval._str) = new QString("unsigned short int"); ;} + break; + + case 98: + +/* Line 1455 of yacc.c */ +#line 512 "yacc.yy" + { (yyval._str) = new QString("unsigned short int"); ;} + break; + + case 99: + +/* Line 1455 of yacc.c */ +#line 513 "yacc.yy" + { (yyval._str) = new QString("unsigned long int"); ;} + break; + + case 100: + +/* Line 1455 of yacc.c */ +#line 514 "yacc.yy" + { (yyval._str) = new QString("unsigned long int"); ;} + break; + + case 101: + +/* Line 1455 of yacc.c */ +#line 515 "yacc.yy" + { (yyval._str) = new QString("int"); ;} + break; + + case 102: + +/* Line 1455 of yacc.c */ +#line 516 "yacc.yy" + { (yyval._str) = new QString("long int"); ;} + break; + + case 103: + +/* Line 1455 of yacc.c */ +#line 517 "yacc.yy" + { (yyval._str) = new QString("long int"); ;} + break; + + case 104: + +/* Line 1455 of yacc.c */ +#line 518 "yacc.yy" + { (yyval._str) = new QString("short int"); ;} + break; + + case 105: + +/* Line 1455 of yacc.c */ +#line 519 "yacc.yy" + { (yyval._str) = new QString("short int"); ;} + break; + + case 106: + +/* Line 1455 of yacc.c */ +#line 520 "yacc.yy" + { (yyval._str) = new QString("char"); ;} + break; + + case 107: + +/* Line 1455 of yacc.c */ +#line 521 "yacc.yy" + { (yyval._str) = new QString("signed char"); ;} + break; + + case 108: + +/* Line 1455 of yacc.c */ +#line 522 "yacc.yy" + { (yyval._str) = new QString("unsigned char"); ;} + break; + + case 111: + +/* Line 1455 of yacc.c */ +#line 532 "yacc.yy" + { + (yyval._str) = new QString( "" ); + ;} + break; + + case 113: + +/* Line 1455 of yacc.c */ +#line 537 "yacc.yy" + { + (yyval._str) = new QString( *((yyvsp[(1) - (3)]._str)) + *((yyvsp[(3) - (3)]._str)) ); + ;} + break; + + case 115: + +/* Line 1455 of yacc.c */ +#line 545 "yacc.yy" + { (yyval._str) = (yyvsp[(1) - (1)]._str); ;} + break; + + case 116: + +/* Line 1455 of yacc.c */ +#line 546 "yacc.yy" + { (yyval._str) = (yyvsp[(2) - (2)]._str); ;} + break; + + case 117: + +/* Line 1455 of yacc.c */ +#line 547 "yacc.yy" + { (yyval._str) = (yyvsp[(2) - (2)]._str); ;} + break; + + case 118: + +/* Line 1455 of yacc.c */ +#line 548 "yacc.yy" + { + QString *tmp = new QString("%1<%2>"); + *tmp = tmp->arg(*((yyvsp[(1) - (4)]._str))); + *tmp = tmp->arg(*((yyvsp[(3) - (4)]._str))); + (yyval._str) = tmp; + ;} + break; + + case 119: + +/* Line 1455 of yacc.c */ +#line 554 "yacc.yy" + { + QString *tmp = new QString("%1<%2>::%3"); + *tmp = tmp->arg(*((yyvsp[(1) - (6)]._str))); + *tmp = tmp->arg(*((yyvsp[(3) - (6)]._str))); + *tmp = tmp->arg(*((yyvsp[(6) - (6)]._str))); + (yyval._str) = tmp; + ;} + break; + + case 120: + +/* Line 1455 of yacc.c */ +#line 566 "yacc.yy" + { + (yyval._str) = new QString(*((yyvsp[(1) - (3)]._str)) + "," + *((yyvsp[(3) - (3)]._str))); + ;} + break; + + case 121: + +/* Line 1455 of yacc.c */ +#line 570 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (1)]._str); + ;} + break; + + case 122: + +/* Line 1455 of yacc.c */ +#line 578 "yacc.yy" + { + if (dcop_area) + yyerror("in dcop areas are no pointers allowed"); + ;} + break; + + case 123: + +/* Line 1455 of yacc.c */ +#line 583 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (1)]._str); + ;} + break; + + case 124: + +/* Line 1455 of yacc.c */ +#line 592 "yacc.yy" + { + if (dcop_area) + yyerror("in dcop areas are no pointers allowed"); + ;} + break; + + case 125: + +/* Line 1455 of yacc.c */ +#line 596 "yacc.yy" + { + if (dcop_area) { + QString* tmp = new QString("%1"); + *tmp = tmp->arg( *((yyvsp[(2) - (3)]._str)) ); + (yyval._str) = tmp; + } + ;} + break; + + case 126: + +/* Line 1455 of yacc.c */ +#line 603 "yacc.yy" + { + QString* tmp = new QString("%1"); + *tmp = tmp->arg( *((yyvsp[(2) - (2)]._str)) ); + (yyval._str) = tmp; + ;} + break; + + case 127: + +/* Line 1455 of yacc.c */ +#line 608 "yacc.yy" + { + QString* tmp = new QString("%1"); + *tmp = tmp->arg( *((yyvsp[(1) - (2)]._str)) ); + (yyval._str) = tmp; + ;} + break; + + case 128: + +/* Line 1455 of yacc.c */ +#line 613 "yacc.yy" + { + if (dcop_area) { + QString* tmp = new QString("%1"); + *tmp = tmp->arg( *((yyvsp[(1) - (3)]._str)) ); + (yyval._str) = tmp; + } + ;} + break; + + case 129: + +/* Line 1455 of yacc.c */ +#line 620 "yacc.yy" + { + if (dcop_area) + yyerror("in dcop areas are only const references allowed!"); + ;} + break; + + case 130: + +/* Line 1455 of yacc.c */ +#line 625 "yacc.yy" + { + QString* tmp = new QString("%1"); + *tmp = tmp->arg( *((yyvsp[(1) - (1)]._str)) ); + (yyval._str) = tmp; + ;} + break; + + case 131: + +/* Line 1455 of yacc.c */ +#line 631 "yacc.yy" + { + if (dcop_area) + yyerror("in dcop areas are no pointers allowed"); + ;} + break; + + case 132: + +/* Line 1455 of yacc.c */ +#line 639 "yacc.yy" + { + (yyval._str) = new QString(*((yyvsp[(1) - (3)]._str)) + "," + *((yyvsp[(3) - (3)]._str))); + ;} + break; + + case 133: + +/* Line 1455 of yacc.c */ +#line 643 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (1)]._str); + ;} + break; + + case 134: + +/* Line 1455 of yacc.c */ +#line 650 "yacc.yy" + { + if (dcop_area) { + QString* tmp = new QString("\n %1%2"); + *tmp = tmp->arg( *((yyvsp[(1) - (3)]._str)) ); + *tmp = tmp->arg( *((yyvsp[(2) - (3)]._str)) ); + (yyval._str) = tmp; + } else (yyval._str) = new QString(); + ;} + break; + + case 135: + +/* Line 1455 of yacc.c */ +#line 659 "yacc.yy" + { + if (dcop_area) { + QString* tmp = new QString("\n %1"); + *tmp = tmp->arg( *((yyvsp[(1) - (2)]._str)) ); + (yyval._str) = tmp; + } else (yyval._str) = new QString(); + ;} + break; + + case 136: + +/* Line 1455 of yacc.c */ +#line 667 "yacc.yy" + { + if (dcop_area) + yyerror("variable arguments not supported in dcop area."); + (yyval._str) = new QString(""); + ;} + break; + + case 137: + +/* Line 1455 of yacc.c */ +#line 676 "yacc.yy" + { + ;} + break; + + case 138: + +/* Line 1455 of yacc.c */ +#line 679 "yacc.yy" + { + ;} + break; + + case 139: + +/* Line 1455 of yacc.c */ +#line 682 "yacc.yy" + { + ;} + break; + + case 140: + +/* Line 1455 of yacc.c */ +#line 689 "yacc.yy" + { + ;} + break; + + case 141: + +/* Line 1455 of yacc.c */ +#line 692 "yacc.yy" + { + ;} + break; + + case 142: + +/* Line 1455 of yacc.c */ +#line 695 "yacc.yy" + { + ;} + break; + + case 143: + +/* Line 1455 of yacc.c */ +#line 698 "yacc.yy" + { + ;} + break; + + case 144: + +/* Line 1455 of yacc.c */ +#line 701 "yacc.yy" + { + ;} + break; + + case 145: + +/* Line 1455 of yacc.c */ +#line 706 "yacc.yy" + { (yyval._int) = 0; ;} + break; + + case 146: + +/* Line 1455 of yacc.c */ +#line 707 "yacc.yy" + { (yyval._int) = 1; ;} + break; + + case 152: + +/* Line 1455 of yacc.c */ +#line 716 "yacc.yy" + { + if (dcop_area || dcop_signal_area) { + QString* tmp = 0; + tmp = new QString( + " <%4>\n" + " %2\n" + " %1" + "%3\n" + " \n"); + *tmp = tmp->arg( *((yyvsp[(2) - (6)]._str)) ); + *tmp = tmp->arg( *((yyvsp[(1) - (6)]._str)) ); + *tmp = tmp->arg( *((yyvsp[(4) - (6)]._str)) ); + + QString tagname = (dcop_signal_area) ? "SIGNAL" : "FUNC"; + QString attr = ((yyvsp[(6) - (6)]._int)) ? " qual=\"const\"" : ""; + *tmp = tmp->arg( QString("%1%2").arg(tagname).arg(attr) ); + *tmp = tmp->arg( QString("%1").arg(tagname) ); + (yyval._str) = tmp; + } else + (yyval._str) = new QString(""); + ;} + break; + + case 153: + +/* Line 1455 of yacc.c */ +#line 738 "yacc.yy" + { + if (dcop_area) + yyerror("operators aren't allowed in dcop areas!"); + (yyval._str) = new QString(""); + ;} + break; + + case 154: + +/* Line 1455 of yacc.c */ +#line 748 "yacc.yy" + {;} + break; + + case 155: + +/* Line 1455 of yacc.c */ +#line 749 "yacc.yy" + {;} + break; + + case 156: + +/* Line 1455 of yacc.c */ +#line 750 "yacc.yy" + {;} + break; + + case 157: + +/* Line 1455 of yacc.c */ +#line 755 "yacc.yy" + {;} + break; + + case 158: + +/* Line 1455 of yacc.c */ +#line 760 "yacc.yy" + {;} + break; + + case 159: + +/* Line 1455 of yacc.c */ +#line 761 "yacc.yy" + {;} + break; + + case 160: + +/* Line 1455 of yacc.c */ +#line 766 "yacc.yy" + { + (yyval._str) = (yyvsp[(1) - (2)]._str); + ;} + break; + + case 161: + +/* Line 1455 of yacc.c */ +#line 770 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (5)]._str); + ;} + break; + + case 162: + +/* Line 1455 of yacc.c */ +#line 774 "yacc.yy" + { + (yyval._str) = (yyvsp[(2) - (3)]._str); + ;} + break; + + case 163: + +/* Line 1455 of yacc.c */ +#line 778 "yacc.yy" + { + /* The constructor */ + assert(!dcop_area); + (yyval._str) = new QString(""); + ;} + break; + + case 164: + +/* Line 1455 of yacc.c */ +#line 784 "yacc.yy" + { + /* The constructor */ + assert(!dcop_area); + (yyval._str) = new QString(""); + ;} + break; + + case 165: + +/* Line 1455 of yacc.c */ +#line 790 "yacc.yy" + { + /* The destructor */ + assert(!dcop_area); + (yyval._str) = new QString(""); + ;} + break; + + case 166: + +/* Line 1455 of yacc.c */ +#line 796 "yacc.yy" + { + if (dcop_area) { + if (dcop_signal_area) + yyerror("DCOP signals cannot be static"); + else + yyerror("DCOP functions cannot be static"); + } else { + (yyval._str) = new QString(); + } + ;} + break; + + case 167: + +/* Line 1455 of yacc.c */ +#line 809 "yacc.yy" + { + function_mode = 1; + ;} + break; + + case 171: + +/* Line 1455 of yacc.c */ +#line 821 "yacc.yy" + {;} + break; + + case 172: + +/* Line 1455 of yacc.c */ +#line 822 "yacc.yy" + {;} + break; + + case 176: + +/* Line 1455 of yacc.c */ +#line 834 "yacc.yy" + {;} + break; + + case 177: + +/* Line 1455 of yacc.c */ +#line 835 "yacc.yy" + {;} + break; + + case 178: + +/* Line 1455 of yacc.c */ +#line 836 "yacc.yy" + {;} + break; + + case 179: + +/* Line 1455 of yacc.c */ +#line 839 "yacc.yy" + {;} + break; + + case 180: + +/* Line 1455 of yacc.c */ +#line 843 "yacc.yy" + {;} + break; + + case 181: + +/* Line 1455 of yacc.c */ +#line 844 "yacc.yy" + {;} + break; + + case 182: + +/* Line 1455 of yacc.c */ +#line 845 "yacc.yy" + {;} + break; + + case 183: + +/* Line 1455 of yacc.c */ +#line 846 "yacc.yy" + {;} + break; + + case 184: + +/* Line 1455 of yacc.c */ +#line 847 "yacc.yy" + {;} + break; + + case 185: + +/* Line 1455 of yacc.c */ +#line 848 "yacc.yy" + {;} + break; + + + +/* Line 1455 of yacc.c */ +#line 3171 "yacc.cpp" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + +/* Line 1675 of yacc.c */ +#line 851 "yacc.yy" + + +void dcopidlParse( const char *_code ) +{ + dcopidlInitFlex( _code ); + yyparse(); +} + diff --git a/dcop/dcopidl/yacc.cpp.h b/dcop/dcopidl/yacc.cpp.h new file mode 100644 index 000000000..2a6c1b403 --- /dev/null +++ b/dcop/dcopidl/yacc.cpp.h @@ -0,0 +1,135 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_UNIMPORTANT = 258, + T_CHARACTER_LITERAL = 259, + T_DOUBLE_LITERAL = 260, + T_IDENTIFIER = 261, + T_INTEGER_LITERAL = 262, + T_STRING_LITERAL = 263, + T_INCLUDE = 264, + T_CLASS = 265, + T_STRUCT = 266, + T_LEFT_CURLY_BRACKET = 267, + T_LEFT_PARANTHESIS = 268, + T_RIGHT_CURLY_BRACKET = 269, + T_RIGHT_PARANTHESIS = 270, + T_COLON = 271, + T_SEMICOLON = 272, + T_PUBLIC = 273, + T_PROTECTED = 274, + T_TRIPE_DOT = 275, + T_PRIVATE = 276, + T_VIRTUAL = 277, + T_CONST = 278, + T_INLINE = 279, + T_FRIEND = 280, + T_RETURN = 281, + T_SIGNAL = 282, + T_SLOT = 283, + T_TYPEDEF = 284, + T_PLUS = 285, + T_MINUS = 286, + T_COMMA = 287, + T_ASTERISK = 288, + T_TILDE = 289, + T_LESS = 290, + T_GREATER = 291, + T_AMPERSAND = 292, + T_EXTERN = 293, + T_EXTERN_C = 294, + T_ACCESS = 295, + T_ENUM = 296, + T_NAMESPACE = 297, + T_USING = 298, + T_UNKNOWN = 299, + T_TRIPLE_DOT = 300, + T_TRUE = 301, + T_FALSE = 302, + T_STATIC = 303, + T_MUTABLE = 304, + T_EQUAL = 305, + T_SCOPE = 306, + T_NULL = 307, + T_INT = 308, + T_ARRAY_OPEN = 309, + T_ARRAY_CLOSE = 310, + T_CHAR = 311, + T_DCOP = 312, + T_DCOP_AREA = 313, + T_DCOP_SIGNAL_AREA = 314, + T_SIGNED = 315, + T_UNSIGNED = 316, + T_LONG = 317, + T_SHORT = 318, + T_FUNOPERATOR = 319, + T_MISCOPERATOR = 320, + T_SHIFT = 321 + }; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 1676 of yacc.c */ +#line 67 "yacc.yy" + + long _int; + QString *_str; + unsigned short _char; + double _float; + + + +/* Line 1676 of yacc.c */ +#line 127 "yacc.hh" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +extern YYSTYPE yylval; + + diff --git a/doc/common/Doxyfile.global b/doc/common/Doxyfile.global index 67abce073..f7d85dcc7 100644 --- a/doc/common/Doxyfile.global +++ b/doc/common/Doxyfile.global @@ -46,13 +46,7 @@ WARN_LOGFILE = INPUT = FILE_PATTERNS = *.h \ *.cpp \ - *.cc \ - *.hpp \ - *.dox \ - *.c++ \ - *.cxx \ - *.h++ \ - *.hh + *.dox RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO diff --git a/interfaces/terminal/test/Makefile.am b/interfaces/terminal/test/Makefile.am index 03a04301b..414159af1 100644 --- a/interfaces/terminal/test/Makefile.am +++ b/interfaces/terminal/test/Makefile.am @@ -1,6 +1,6 @@ INCLUDES=$(all_includes) check_PROGRAMS=test -test_SOURCES=main.cc +test_SOURCES=main.cpp test_LDADD=$(LIB_TQT) $(LIB_TDECORE) $(LIB_TDEUI) -ltdeio test_LDFLAGS=$(all_libraries) METASOURCES=AUTO diff --git a/interfaces/terminal/test/main.cc b/interfaces/terminal/test/main.cc deleted file mode 100644 index 8130f85d6..000000000 --- a/interfaces/terminal/test/main.cc +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "main.h" -#include "main.moc" - -Win::Win() -{ - KLibFactory* factory = KLibLoader::self()->factory( "libkonsolepart" ); - assert( factory ); - KParts::Part* p = static_cast( factory->create( this, "tralala", TQOBJECT_OBJECT_NAME_STRING, "KParts::ReadOnlyPart" ) ); - setCentralWidget( p->widget() ); - - TerminalInterface* t = ::tqqt_cast( p ); - t->showShellInDir( TQDir::home().path() ); -// TQStrList l; -// l.append( "python" ); -// t->startProgram( TQString::fromUtf8( "/usr/bin/python" ), l ); - - connect( p, TQT_SIGNAL( processExited( int ) ), - this, TQT_SLOT( pythonExited( int ) ) ); -} - - -int main( int argc, char** argv ) -{ - TDEAboutData* about = new TDEAboutData( "tetest", "TETest", "0.1" ); - TDECmdLineArgs::init( argc, argv, about ); - TDEApplication a; - Win* win = new Win(); - win->show(); - return a.exec(); -}; - -#include - -void Win::pythonExited() -{ - std::cerr << "hee, " << p << std::endl; - std::cerr << ( ::tqqt_cast(p) ) << std::endl; - // KMessageBox::sorry( this, TQString::fromUtf8( "Exited, status was %1" ).arg( status ) ); - disconnect(p, TQT_SIGNAL( processExited() ), - this, TQT_SLOT( pythonExited() )); - TerminalInterface* t = ::tqqt_cast( p ); - TQStrList l; - l.append( "echo" ); - l.append( "hello world" ); - t->startProgram( TQString::fromUtf8( "/bin/echo" ), l ); -} - -void Win::forked() -{ - std::cerr << "hello from the child process!" << std::endl; -} diff --git a/interfaces/terminal/test/main.cpp b/interfaces/terminal/test/main.cpp new file mode 100644 index 000000000..8130f85d6 --- /dev/null +++ b/interfaces/terminal/test/main.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "main.h" +#include "main.moc" + +Win::Win() +{ + KLibFactory* factory = KLibLoader::self()->factory( "libkonsolepart" ); + assert( factory ); + KParts::Part* p = static_cast( factory->create( this, "tralala", TQOBJECT_OBJECT_NAME_STRING, "KParts::ReadOnlyPart" ) ); + setCentralWidget( p->widget() ); + + TerminalInterface* t = ::tqqt_cast( p ); + t->showShellInDir( TQDir::home().path() ); +// TQStrList l; +// l.append( "python" ); +// t->startProgram( TQString::fromUtf8( "/usr/bin/python" ), l ); + + connect( p, TQT_SIGNAL( processExited( int ) ), + this, TQT_SLOT( pythonExited( int ) ) ); +} + + +int main( int argc, char** argv ) +{ + TDEAboutData* about = new TDEAboutData( "tetest", "TETest", "0.1" ); + TDECmdLineArgs::init( argc, argv, about ); + TDEApplication a; + Win* win = new Win(); + win->show(); + return a.exec(); +}; + +#include + +void Win::pythonExited() +{ + std::cerr << "hee, " << p << std::endl; + std::cerr << ( ::tqqt_cast(p) ) << std::endl; + // KMessageBox::sorry( this, TQString::fromUtf8( "Exited, status was %1" ).arg( status ) ); + disconnect(p, TQT_SIGNAL( processExited() ), + this, TQT_SLOT( pythonExited() )); + TerminalInterface* t = ::tqqt_cast( p ); + TQStrList l; + l.append( "echo" ); + l.append( "hello world" ); + t->startProgram( TQString::fromUtf8( "/bin/echo" ), l ); +} + +void Win::forked() +{ + std::cerr << "hello from the child process!" << std::endl; +} diff --git a/kab/CMakeLists.txt b/kab/CMakeLists.txt index 76c781467..a4e881466 100644 --- a/kab/CMakeLists.txt +++ b/kab/CMakeLists.txt @@ -27,7 +27,7 @@ link_directories( set( target kab ) set( ${target}_SRCS - kabapi.cc addressbook.cc qconfigDB.cc + kabapi.cpp addressbook.cpp qconfigDB.cpp ) tde_add_library( ${target} STATIC_PIC AUTOMOC diff --git a/kab/ChangeLog b/kab/ChangeLog index d3e36fcc1..51715a70d 100644 --- a/kab/ChangeLog +++ b/kab/ChangeLog @@ -11,7 +11,7 @@ Tue Dec 22 22:56:58 1998 Mirko Boehm * businesscard.h (class BusinessCard): Hopefully remove trigraph. - * datepickerdialog.cc (DateLabel): Removed default value + * datepickerdialog.cpp (DateLabel): Removed default value in the implementation. * keyvaluemap.h: Removed a default value for a function diff --git a/kab/Makefile.am b/kab/Makefile.am index 89e1aab8e..66018aed5 100644 --- a/kab/Makefile.am +++ b/kab/Makefile.am @@ -5,9 +5,9 @@ KABVERSION= 4.0.0 KABPATCH= 0 libkab_la_SOURCES = \ - kabapi.cc \ - addressbook.cc \ - qconfigDB.cc + kabapi.cpp \ + addressbook.cpp \ + qconfigDB.cpp libkab_la_LDFLAGS = $(KDE_MT_LDFLAGS) -no-undefined libkab_la_LIBADD = ../tdeui/libtdeui.la diff --git a/kab/addressbook.cc b/kab/addressbook.cc deleted file mode 100644 index 017621ac7..000000000 --- a/kab/addressbook.cc +++ /dev/null @@ -1,2040 +0,0 @@ -/* - This file implements the basic personal information management class - used in the TDE addressbook. - - the TDE addressbook - - $ Author: Mirko Boehm $ - $ Copyright: (C) 1996-2001, Mirko Boehm $ - $ Contact: mirko@kde.org - http://www.kde.org $ - $ License: GPL with the following explicit clarification: - This code may be linked against any version of the Qt toolkit - from Troll Tech, Norway. $ - - $Id$ -*/ - -#include "addressbook.h" -#include "qconfigDB.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -extern "C" { -#include -#include -#include -#include -} - -// ----- some defines: -#ifdef KAB_KDEBUG_AREA -#undef KAB_KDEBUG_AREA -#endif - -#define KAB_KDEBUG_AREA 800 - -#ifdef STD_USERFILENAME -#undef STD_USERFILENAME -#endif -#define STD_USERFILENAME "kab/addressbook.kab" - -#ifdef STD_CONFIGFILENAME -#undef STD_CONFIGFILENAME -#endif -#define STD_CONFIGFILENAME "kab/kab.config" - -#ifdef ENTRY_SECTION -#undef ENTRY_SECTION -#endif -#define ENTRY_SECTION "entries" - -// the name of the file-local configuration section -#ifdef LOCAL_CONFIG_SECTION -#undef LOCAL_CONFIG_SECTION -#endif -#define LOCAL_CONFIG_SECTION "config" - -// the name of the subsection for each entry -#ifdef ADDRESS_SUBSECTION -#undef ADDRESS_SUBSECTION -#endif -#define ADDRESS_SUBSECTION "addresses" - -#ifdef KAB_TEMPLATEFILE -#undef KAB_TEMPLATEFILE -#endif -#define KAB_TEMPLATEFILE "kab/template.kab" - -#ifdef KAB_CONFIGTEMPLATE -#undef KAB_CONFIGTEMPLATE -#endif -#define KAB_CONFIGTEMPLATE "kab/template.config" - -#ifdef KAB_CATEGORY_KEY -#undef KAB_CATEGORY_KEY -#endif -#define KAB_CATEGORY_KEY "categories" - -const char* AddressBook::Entry::Address::Fields[]= { - "headline", "position", - "org", "orgunit", "orgsubunit", - "deliverylabel", "address", "zip", "town", "country", "state" }; -const int AddressBook::Entry::Address::NoOfFields -=sizeof(AddressBook::Entry::Address::Fields) -/sizeof(AddressBook::Entry::Address::Fields[0]); - -const char* AddressBook::Entry::Fields[]= { - "title", "rank", "fn", "nameprefix", "firstname", "middlename", "lastname", - "birthday", "comment", "talk", "emails", "keywords", "telephone", - "urls", "user1", "user2", "user3", "user4", "custom", "categories" }; -const int AddressBook::Entry::NoOfFields -=sizeof(AddressBook::Entry::Fields)/sizeof(AddressBook::Entry::Fields[0]); - -struct QStringLess - : public binary_function -{ - /** The function operator, inline. */ - bool operator()(const TQString& x, const TQString& y) const - { - return x < y; // make one Qt operator fit exactly - } -}; - -// ----- the derived map class: -class StringKabKeyMap : public map -{ /* Same as map, but a class for compilation reasons. This way we do not need - * to include the QStringLess class into the addressbook header file. */ -}; - -// ----- another derived map class: -class KeyNameMap : public map > -{ // same thing -}; - -KeyNameMap* AddressBook::Entry::fields; -KeyNameMap* AddressBook::Entry::Address::fields; - -bool -KabKey::operator == (const KabKey& key) const -{ - // ########################################################################### - return key.getKey()==getKey(); - // ########################################################################### -} - -void -KabKey::setKey(const TQCString& text) -{ - // ########################################################################### - key=text; - // ########################################################################### -} - -TQCString -KabKey::getKey() const -{ - // ########################################################################### - return key; - // ########################################################################### -} - - - -AddressBook::Entry::Address::Address() -{ -} - -bool AddressBook::Entry::Address::nameOfField(const char* key, TQString& value) -{ - KeyNameMap::iterator pos; - // ----- - if(fields==0) - { // this is executed exactly one time per application instance, - // as fields is static - int counter=0; - fields=new KeyNameMap; - TQ_CHECK_PTR(fields); - if(!fields->insert - (map >::value_type - (Fields[counter++], i18n("Headline"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Position"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Organization"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Department"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Sub-Department"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Delivery Label"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("street/postal","Address"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Zipcode"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("City"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Country"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("As in addresses", "State"))).second) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::Entry::Address::nameOfField (while " - << " creating field-name map): TYPO, correct this." - << endl; - } else { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::Entry::Address::nameOfField: " - << "inserted field names." << endl; - } -#if ! defined NDEBUG - TQString name; - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::Entry::Address::nameOfField:" << endl - << "Created key-fieldname-map. Defined fields are:" - << endl; - for(counter=0; counterfind(Fields[counter]); - if(pos==fields->end()) - { - kdDebug(KAB_KDEBUG_AREA) << " UNDEFINED" << endl; - } else { - kdDebug(KAB_KDEBUG_AREA) - << " " << Fields[counter] << " (" - << (*pos).second.utf8() << ")" << endl; - } - } -#endif - } - // ----- now finally do the lookup: - pos=fields->find(key); - if(pos==fields->end()) - { - return false; - } else { - value=(*pos).second; - return true; - } -} - -bool AddressBook::Entry::nameOfField(const char* key, TQString& value) -{ - KeyNameMap::iterator pos; - // ----- - if(fields==0) - { // this is executed exactly one time per application instance, - // as fields is static - int counter=0; - fields=new KeyNameMap; - TQ_CHECK_PTR(fields); - if(!fields->insert - (map >::value_type - (Fields[counter++], i18n("person","Title"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Rank"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Formatted Name"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Name Prefix"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("First Name"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Middle Name"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Last Name"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Birthday"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Comment"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Talk Addresses"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Email Addresses"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Keywords"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Telephone Number"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("URLs"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("User Field 1"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("User Field 2"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("User Field 3"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("User Field 4"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Custom"))).second - || - !fields->insert - (map >::value_type - (Fields[counter++], i18n("Categories"))).second) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::Entry::Address::nameOfField (while " - << " creating field-name map): TYPO, correct this." << endl; - } else { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::Entry::Address::nameOfField: " - << "inserted field names." << endl; - } -#if ! defined NDEBUG - TQString name; - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::Entry::nameOfField:" << endl - << "Created key-fieldname-map. Defined fields are:" << endl; - for(counter=0; counterfind(Fields[counter]); - if(pos==fields->end()) - { - kdDebug(KAB_KDEBUG_AREA) << " UNDEFINED" << endl; - } else { - kdDebug(KAB_KDEBUG_AREA) - << " " << Fields[counter] << " (" - << (*pos).second.utf8() << ")" << endl; - } - } -#endif - } - // ----- now finally do the lookup: - pos=fields->find(key); - if(pos==fields->end()) - { - return false; - } else { - value=(*pos).second; - return true; - } -} - -AddressBook::ErrorCode -AddressBook::Entry::getAddress(int index, Address& address) const -{ - // ########################################################################### - list
::const_iterator pos; - // ----- - if(index>=0 && (unsigned)indexquit(); // It is critical, but will possibly never happen. - } - connect(data, TQT_SIGNAL(fileChanged()), TQT_SLOT(dataFileChanged())); - connect(data, TQT_SIGNAL(changed(QConfigDB*)), - TQT_SLOT(reloaded(QConfigDB*))); - connect(config, TQT_SIGNAL(fileChanged()), TQT_SLOT(configFileChanged())); - // ----- set style: - - filename = locate( "data", STD_CONFIGFILENAME); - if (filename.isEmpty()) - { - filename = locateLocal( "data", STD_CONFIGFILENAME ); - // config does not exist yet - if(createConfigFile()!=NoError) - { - KMessageBox::sorry(this, - i18n("Your local kab configuration file " - "\"%1\" " - "could not be created. kab will probably not " - "work correctly without it.\n" - "Make sure you have not removed write permission " - "from your local TDE directory (usually ~/.trinity).").arg(filename)); - state=PermDenied; - } - } - loadConfigFile(); - // ----- now get some configuration settings: - if(config->get("config", keys)) - { - keys->get("CreateBackupOnStartup", createBackup); - } - // ----- check and possibly create user standard file: - filename = locate( "data", STD_USERFILENAME ); - - if(filename.isEmpty()) // if it does not exist - { - filename = locateLocal( "data", STD_USERFILENAME); - if(createNew(filename)!=NoError) // ...and we cannot create it - { - KMessageBox::sorry(this, - i18n("Your standard kab database file " - "\"%1\" " - "could not be created. kab will probably not " - "work correctly without it.\n" - "Make sure you have not removed write permission " - "from your local TDE directory (usually ~/.trinity).").arg(filename)); - state=PermDenied; - } else { - KMessageBox::information - (this, - i18n("kab has created your standard addressbook in\n\"%1\"") - .arg(filename)); - } - } - // ----- load the user standard file: - if(loadit) - { - if(load(filename)!=NoError) - { // ----- the standard file could not be loaded - state=PermDenied; - } else { - if(createBackup) - { - // ----- create the backup file: - TQString temp=data->fileName(); - if(data->setFileName(temp+".backup", false, false)) - { - if(!data->save()) - { - KMessageBox::information - (this, - i18n("Cannot create backup file (permission denied)."), - i18n("File Error")); - } - } else { - KMessageBox::error - (this, - i18n("Cannot open backup file for " - "writing (permission denied)."), - i18n("File Error")); - } - // ----- reset the filename: - if(!data->setFileName(temp, true, true)) - { - KMessageBox::error - (this, - i18n("Critical error:\n" - "Permissions changed in local directory!"), - i18n("File Error")); - closeFile(false); - state=PermDenied; - } else { - state=NoError; - } - } - } - } - // ----- - data->watch(true); - // ########################################################################### -} - -AddressBook::~AddressBook() -{ - // ########################################################################### - delete data; - delete config; - delete entries; - // ########################################################################### -} - -QConfigDB* AddressBook::getConfig() -{ - // ########################################################################### - return config; - // ########################################################################### -} - -AddressBook::ErrorCode AddressBook::getState() -{ - // ########################################################################### - return state; - // ########################################################################### -} - -AddressBook::ErrorCode AddressBook::load(const TQString& filename) -{ - // ----- Remark: Close the file if it could not be loaded! - // ########################################################################### - ErrorCode rc=NoError; - TQFileInfo newfile, oldfile; - // ----- - TQString fname = (filename.isEmpty()) ? data->fileName() : filename ; - if(fname.isEmpty()) // there was never a filename set: - { - state=NoFile; - return NoFile; - } - // ----- - newfile.setFile(fname); - oldfile.setFile(data->fileName()); - if(isSameFile(fname, data->fileName())) - { // ----- possibly deleted file: - if(data->load()) - { - emit(setStatus(i18n("File reloaded."))); - state=NoError; - } else { - switch - (KMessageBox::questionYesNo - (this, - i18n("The currently loaded file " - "\"%1\" " - "cannot be reloaded. kab may close or save it.\n" - "Save it if you accidentally deleted your data file.\n" - "Close it if you intended to do so.\n" - "Your file will be closed by default.") - .arg(oldfile.absFilePath()), - i18n("File Error"), - KStdGuiItem::close(), KStdGuiItem::save())) - { - case KMessageBox::No: // save - if(!data->save(i18n("(Safety copy on file error)").ascii(), true)) - { - KMessageBox::information(this, - i18n("Cannot save the file; will close it now."), - i18n("File Error")); - closeFile(false); - state=NoFile; - rc=PermDenied; - } else { - state=NoError; - rc=NoError; - } - break; // no error if we could save the file - default: // close - closeFile(false); - state=NoFile; - rc=NoSuchFile; - break; - } - } - } else { // ----- set new filename - if(data->setFileName(fname, true, true)) - { - if(data->load()) - { - emit(changed()); - emit(setStatus(i18n("File opened."))); - state=NoError; - } else { - KMessageBox::information(this, - i18n("Could not load the file."), - i18n("File Error")); - closeFile(false); - emit(setStatus(i18n("No such file."))); - rc=NoSuchFile; - } - } else { - if(KMessageBox::questionYesNo - (this, - i18n("The file \"%1\" cannot be found. " - "Create a new one?").arg(fname), - i18n("No Such File"), - i18n("Create"), KStdGuiItem::cancel())==KMessageBox::Yes) - { - if(createNew(fname)==NoError) - { - emit(setStatus(i18n("New file."))); - } else { // ----- do not close here, stick with the old file: - emit(setStatus(i18n("Canceled."))); - } - } - } - } - // ----- - if(rc==NoError) - { - data->watch(true); - updateMirrorMap(); - } - // ----- - return rc; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::getListOfNames(TQStringList* strings, bool reverse, bool initials) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::getListOfNames: called.\n"; - StringKabKeyMap::iterator pos; - TQString desc; - ErrorCode rc=NoError; - ErrorCode temp; - // ----- erase the list contents: - strings->clear(); - // ----- ...and fill it: - for(pos=entries->begin(); pos!=entries->end(); ++pos) - { - temp=literalName((*pos).second, desc, reverse, initials); - if(temp!=AddressBook::NoError) - { - desc=i18n("(Internal error in kab)"); - rc=InternError; - } - if(desc.isEmpty()) - { - desc=i18n("(empty entry)"); - } - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "AddressBook::getListOfNames: adding " << desc << endl; - strings->append(desc); - } - // ----- any problems? - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::getListOfNames: done, " - << strings->count() - << " entries.\n"; - return rc; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::literalName(const KabKey& key, TQString& text, bool rev, bool init) -{ - // ########################################################################### - Entry entry; - ErrorCode rc; - // ----- get the entry: - rc=getEntry(key, entry); - if(rc!=NoError) - { - return rc; - } - // ----- - return literalName(entry, text, rev, init); - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::literalName(const Entry& entry, TQString& text, bool rev, bool init) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::literalName: called.\n"; - TQString firstname, middlename, lastname, nameprefix; - // ----- is the formatted name set? - if(!entry.fn.isEmpty()) - { - text=entry.fn; - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "AddressBook::literalName: done (fn).\n"; - return NoError; - } - // ----- prepare the strings: - firstname=entry.firstname.simplifyWhiteSpace(); - middlename=entry.middlename.simplifyWhiteSpace(); - lastname=entry.lastname.simplifyWhiteSpace(); - nameprefix=entry.nameprefix.simplifyWhiteSpace(); - // ----- create the initials: - if(init) - { - if(!firstname.isEmpty()) firstname=firstname.mid(0, 1)+'.'; - if(!middlename.isEmpty()) middlename=middlename.mid(0, 1)+'.'; - // if(!lastname.isEmpty()) lastname=lastname.mid(0, 1)+'.'; - } - // ----- assemble the string: - text=""; - if(rev) - { // name, firstname - add. name - name prefix - if(!lastname.isEmpty()) - { - text=lastname; - } - if(!firstname.isEmpty() || !middlename.isEmpty() || !nameprefix.isEmpty()) - { - text+=','; - } - if(!firstname.isEmpty()) - { - if(!text.isEmpty()) - { - text+=' '; - } - text+=firstname; - } - if(!middlename.isEmpty()) - { - if(!text.isEmpty()) - { - text+=' '; - } - text+=middlename; - } - if(!nameprefix.isEmpty()) - { - if(!text.isEmpty()) - { - text+=' '; - } - text+=nameprefix; - } - } else { - // firstname - add. name - name prefix - name - text=firstname; - if(!middlename.isEmpty()) - { - if(!text.isEmpty()) - { - text+=' '; - } - text+=middlename; - } - if(!nameprefix.isEmpty()) - { - if(!text.isEmpty()) - { - text+=' '; - } - text+=nameprefix; - } - if(!lastname.isEmpty()) - { - if(!text.isEmpty()) - { - text+=' '; - } - text+=lastname; - } - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::literalName: done: " - << text << ".\n"; - return NoError; - // ########################################################################### -} - -unsigned int -AddressBook::noOfEntries() -{ - // ########################################################################### - return entries->size(); - // ########################################################################### -} - -void -AddressBook::dataFileChanged() -{ - // ########################################################################### - data->watch(false); // will be restarted after successful load - load(); - // ########################################################################### -} - -void -AddressBook::configFileChanged() -{ - bool GUARD; GUARD=true; - // ########################################################################### - if(!config->load()) - { - KMessageBox::error(this, - i18n("Cannot reload configuration file!"), - i18n("File Error")); - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::configFileChanged: " - "config file reloaded.\n"; - emit(setStatus(i18n("Configuration file reloaded."))); - } - // ########################################################################### -} - -void -AddressBook::reloaded(QConfigDB* db) -{ - bool GUARD; GUARD=false; - // ########################################################################### - if(db==data) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::reloaded: file has been " - "reloaded.\n"; - updateMirrorMap(); // WORK_TO_DO: what's up with the return value? - changed(); - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::save(const TQString& filename, bool force) -{ - // ########################################################################### - if(filename.isEmpty()) - { - if(data->save(0, force)) - { - emit(setStatus(i18n("File saved."))); - return NoError; - } else { - return PermDenied; - } - } else { - if(data->setFileName(filename, false, false)) - { - if(data->save(0, true)) - { - emit(newFile(filename)); - return NoError; - } else { - return PermDenied; - } - } else { - return PermDenied; - } - } - // ########################################################################### -} - -bool -AddressBook::isSameFile(const TQString& a, const TQString& b) -{ - // ########################################################################### - TQFileInfo filea(a), fileb(b); - // ----- - return filea.absFilePath()==fileb.absFilePath(); - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::closeFile(bool saveit) -{ - // ########################################################################### - if(saveit) - { - if(save()!=NoError) - { - emit(setStatus(i18n("Permission denied."))); - return PermDenied; - } - } - data->clear(); - // data->reset(); WORK_TO_DO: File name is not reset by now. - emit(setStatus(i18n("File closed."))); - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::getEntry(const KabKey& key, Entry& entry) -{ - // ########################################################################### - Section *section; - // ----- - if(getEntry(key, section)==NoError) - { - return makeEntryFromSection(section, entry); - } else { - return NoSuchEntry; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::getEntry(const KabKey& key, Section*& section) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::getEntry: searching entry " - "with key " << key.getKey().data() << endl; - StringKabKeyMap::iterator pos; - // ----- - for(pos=entries->begin(); pos!=entries->end(); ++pos) - { - if((*pos).second==key) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "AddressBook::getEntry: key exists." << endl; - break; - } - } - if(pos==entries->end()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "AddressBook::getEntry: no such entry.\n"; - return NoSuchEntry; - } else { - if(data->get((TQCString)ENTRY_SECTION+'/'+key.getKey(), section)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "AddressBook::getEntry: done." << endl; - return NoError; - } else { - return InternError; - } - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::getEntries(list& thelist) -{ - // ########################################################################### - StringKabKeyMap::iterator pos; - Entry entry; - ErrorCode rc; - // ----- - kdDebug(!thelist.empty(), KAB_KDEBUG_AREA) - << "AddressBook::getEntries: warning - non-empty value list!" << endl; - thelist.erase(thelist.begin(), thelist.end()); - for(pos=entries->begin(); pos!=entries->end(); ++pos) - { - rc=getEntry((*pos).second, entry); - if(rc==NoError) - { - thelist.push_back(entry); - } else { - return InternError; - } - } - // ----- - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::getKey(int index, KabKey& key) -{ - // ########################################################################### - StringKabKeyMap::iterator pos; - // ----- - if((unsigned)indexsize()) - { - pos=entries->begin(); - advance(pos, index); - key=(*pos).second; - return NoError; - } else { - return NoSuchEntry; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::getIndex(const KabKey& key, int& index) -{ - bool GUARD; GUARD=true; - // ########################################################################### - StringKabKeyMap::iterator pos; - // ----- - index=0; - for(pos=entries->begin(); pos!=entries->end(); ++pos) - { - // kdDebug(KAB_KDEBUG_AREA) << (*pos).second.getKey().data() << " <--> " << - // key.getKey().data() << endl; - if((*pos).second==key) break; - ++index; - } - kdDebug(pos==entries->end(), KAB_KDEBUG_AREA) << - "AddressBook::getIndex: no such key." << endl; - if(pos==entries->end()) - { - return NoSuchEntry; - } else { - return NoError; - } - // ########################################################################### -} - -Section* -AddressBook::entrySection() -{ - // ########################################################################### - Section* section; - // ----- - if(!data->get(ENTRY_SECTION, section)) - { - return 0; - } else { - return section; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::add(const Entry& entry, KabKey& key, bool update) -{ - bool GUARD; GUARD=true; - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::add: called." << endl; - // ########################################################################### - Section* theEntries=entrySection(); - Section* newEntry; - KabKey nextKey; - ErrorCode locked; - ErrorCode rc; - // ----- - if(theEntries==0) - { - kdDebug(KAB_KDEBUG_AREA) << "AddressBook::add: no entries section." - << endl; - return NoFile; - } - newEntry=new Section; - if(newEntry==0) - { - KMessageBox::error(this, - i18n("Cannot initialize local variables."), - i18n("Out of Memory")); - kapp->quit(); // It is critical, but will possibly never happen. - return InternError; // shut the compiler up... - } - // ----- lock the file: - locked=lock(); - switch(locked) - { - case PermDenied: - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::add: permission denied." << endl; - return PermDenied; // cannot get r/w mode - case Locked: - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::add: db is already in r/w mode." << endl; - break; - case NoError: - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::add: got writing permissions." << endl; - break; - default: - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::add: unknown response, exiting." << endl; - return InternError; - } - // ----- - if(makeSectionFromEntry(entry, *newEntry)==NoError) - { - nextKey=nextAvailEntryKey(); - if(!theEntries->add(nextKey.getKey(), newEntry)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::add: Cannot insert section.\n"; - rc=InternError; - } else { - key=nextKey; - emit(changed()); - rc=NoError; - } - if(update) updateMirrorMap(); - } else { - rc=InternError; - } - if(locked!=Locked) - { // ----- unlock the file here: - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::add: dropped writing permissions." << endl; - locked=unlock(); - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::add: done." << endl; - if(locked!=NoError) - { - return locked; - } - if(rc!=NoError) - { - return rc; - } - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::change(const KabKey& key, const Entry& entry) -{ - // ########################################################################### - Section* theEntries=entrySection(); - Section* oldEntry; - ErrorCode locked; - ErrorCode rc; - // ----- - if(theEntries==0) - { - return NoFile; - } - // ----- lock the file: - locked=lock(); - if(locked==PermDenied) - { - return PermDenied; // cannot get r/w mode - } - // ----- - if(!theEntries->find(key.getKey(), oldEntry)) - { - rc=NoSuchEntry; - } else { - oldEntry->clear(); - rc=makeSectionFromEntry(entry, *oldEntry); - emit(changed()); - } - // ----- - if(locked!=PermDenied) - { // ----- unlock the file here: - locked=unlock(); - } - if(locked==NoError) - { - return rc; - } else { - return locked; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::remove(const KabKey& key) -{ - // ########################################################################### - Section *theEntries=entrySection(); - ErrorCode locked; - ErrorCode rc; - // ----- - if(theEntries==0) - { - return NoFile; - } - // ----- lock the file: - locked=lock(); - if(locked==PermDenied) - { - return PermDenied; // cannot get r/w mode - } - // ----- - if(theEntries->remove(key.getKey())) - { - rc=NoError; - emit(changed()); - } else { - rc=NoSuchEntry; - } - // ----- - if(locked!=PermDenied) - { // ----- unlock the file here: - locked=unlock(); - } - if(locked==NoError) - { - return rc; - } else { - return locked; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::lock() -{ - // ########################################################################### - if(!data->isRO()) return Locked; - if(data->setFileName(data->fileName(), false, false)) - { - return NoError; - } else { - KMessageBox::information(this, - i18n("The file you wanted to change could not be locked.\n" - "It is probably in use by another application or read-only."), - i18n("File Error")); - return PermDenied; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::unlock() -{ - // ########################################################################### - if(data->isRO()) return PermDenied; - if(data->setFileName(data->fileName(), true, true)) - { - return NoError; - } else { - return InternError; - } - // ########################################################################### -} - -KabKey -AddressBook::nextAvailEntryKey() -{ - // ########################################################################### - int max=0; - int temp; - Section::StringSectionMap::iterator pos; - Section *section=entrySection(); - KabKey key; - TQCString dummy; - bool good=true; - // ----- - if(section!=0) - { - for(pos=section->sectionsBegin(); pos!=section->sectionsEnd(); ++pos) - { - temp=0; - temp=(*pos).first.toInt(&good); - if(!good) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::nextAvailEntryKey: non-integer entry " - << endl; - } - if(temp>max) - { - max=temp; - } - } - } - // ----- - dummy.setNum(++max); - key.setKey(dummy); - // CHECK(key.getKey().toInt(&good)==max); - return key; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::updateMirrorMap() -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) - << "AddressBook::updateMirrorMap: updating mirror map.\n"; - TQString key; - Entry entry; - ErrorCode ec; - KabKey kk; - Section *section=entrySection(); - Section::StringSectionMap::iterator pos; - // ----- - entries->erase(entries->begin(), entries->end()); - if(section==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::updateMirrorMap: done, " - "no file loaded." << endl; - return NoError; - } - for(pos=section->sectionsBegin(); pos!=section->sectionsEnd(); ++pos) - { - if(makeEntryFromSection((*pos).second, entry)!=NoError) - { - // return InternError; // it is saver to continue without a key - } - key=""; - ec=literalName(entry, key, true, false); - if(key.isEmpty() || ec!=NoError) - { - key=i18n("(empty entry)"); - } - key+=(*pos).first; // append the section name to make the key unique - kk.setKey((*pos).first); - entries->insert(StringKabKeyMap::value_type(key, kk)); - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::updateMirrorMap: done." - << endl; - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::makeEntryFromSection(Section* section, Entry& entry) -{ - // ########################################################################### - Section *addresses; - Section *addressSection; - Section::StringSectionMap::iterator pos; - KeyValueMap *keys; - Entry temp; - Entry::Address address; - Entry::Address addressDummy; - int count; - // ----- create the aggregats: - const TQCString StringKeys[]= { - "title", - "rank", - "fn", - "nameprefix", - "firstname", - "middlename", - "lastname", - "comment", - "user1", - "user2", - "user3", - "user4" - }; - TQString* StringValues[]= { - &temp.title, - &temp.rank, - &temp.fn, - &temp.nameprefix, - &temp.firstname, - &temp.middlename, - &temp.lastname, - &temp.comment, - &temp.user1, - &temp.user2, - &temp.user3, - &temp.user4 - }; - const int StringKeySize=sizeof(StringKeys)/sizeof(StringKeys[0]); - const TQCString StringListKeys[]= { - "talk", - "emails", - "keywords", - "telephone", - "URLs", - "custom", - "categories" - }; - TQStringList* StringListValues[]= { - &temp.talk, - &temp.emails, - &temp.keywords, - &temp.telephone, - &temp.URLs, - &temp.custom, - &temp.categories - }; - const int StringListKeySize=sizeof(StringListKeys)/sizeof(StringListKeys[0]); - // ----- first parse "addresses" subsection: - if(!section->find(ADDRESS_SUBSECTION, addresses)) - { - return InternError; // no subsection called "addresses" - } - for(pos=addresses->sectionsBegin(); pos!=addresses->sectionsEnd(); ++pos) - { - if(!addresses->find((*pos).first, addressSection)) - { - return InternError; // no section we have an iterator for? - } - keys=addressSection->getKeys(); - address=addressDummy; // clean it up - if(makeAddressFromMap(keys, address)==AddressBook::NoError) - { - // ----- add the address to the list of addresses: - temp.addresses.push_back(address); - } else { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeEntryFromSection: cannot find all fields " - << "in an address subsection." << endl; - } - } - // ----- now parse all other fields directly: - keys=section->getKeys(); - for(count=0; countget(StringKeys[count], *StringValues[count])) - { - /* Spits out lots of warnings: - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeEntryFromSection: error: could not get " - << "value for key " << (const char*)StringKeys[count] - << "." << endl; - */ - } - } - for(count=0; countget(StringListKeys[count], *StringListValues[count])) - { - /* Spits out lots of warnings: - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeEntryFromSection: error: could not get " - << "value for key " << (const char*)StringListKeys[count] - << "." << endl; - */ - } - } - // ----- finally get the birthday: - keys->get("birthday", temp.birthday); // this may return false (no date) - // ----- - entry=temp; - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::makeAddressFromMap(KeyValueMap* keys, Entry::Address& address) -{ - // ########################################################################### - const TQCString Keys[]= { - "headline", - "position", - "org", - "orgunit", - "orgsubunit", - // "role", - "deliverylabel", - "address", - "zip", - "town", - "country", - "state" - }; - TQString* strings[]= { - &address.headline, - &address.position, - &address.org, - &address.orgUnit, - &address.orgSubUnit, - // &address.role, - &address.deliveryLabel, - &address.address, - &address.zip, - &address.town, - &address.country, - &address.state - }; - const int Size=sizeof(Keys)/sizeof(Keys[0]); - int count; - // ----- - for(count=0; countget(Keys[count], *strings[count]); - } - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::makeSectionFromEntry(const Entry& entry, Section& section) -{ - // ########################################################################### - list::const_iterator addPos; - Section *addresses=0; - Section *address=0; - TQCString key; // used for creating address subsection keys - int count=0; // counts the addresses - KeyValueMap *keys; - // ----- prepare the section object: - section.clear(); - // ----- first create "addresses" subsection: - if(!section.add(ADDRESS_SUBSECTION)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeSectionFromEntry: cannot create " << "subsection." - << " " << endl; - return InternError; - } - if(!section.find(ADDRESS_SUBSECTION, addresses)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeSectionFromEntry: cannot get new section." << endl; - return InternError; - } - // ----- now insert addresses: - for(addPos=entry.addresses.begin(); addPos!=entry.addresses.end(); ++addPos) - { - ++count; - key.setNum(count); - if(!addresses->add(key)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeSectionFromEntry: cannot create address " << endl; - return InternError; - } - if(!addresses->find(key, address)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeSectionFromEntry: cannot get new " << endl; - return InternError; - } - keys=address->getKeys(); - // ----- now insert keys into address: - if(!keys->insert("headline", (*addPos).headline) || - !keys->insert("position", (*addPos).position) || - !keys->insert("org", (*addPos).org) || - !keys->insert("orgunit", (*addPos).orgUnit) || - !keys->insert("orgsubunit", (*addPos).orgSubUnit) || - // !keys->insert("role", (*addPos).role) || - !keys->insert("deliverylabel", (*addPos).deliveryLabel) || - !keys->insert("address", (*addPos).address) || - !keys->insert("zip", (*addPos).zip) || - !keys->insert("town", (*addPos).town) || - !keys->insert("country", (*addPos).country) || - !keys->insert("state", (*addPos).state)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeSectionFromEntry: cannot completely " - << "insert this address." << endl; - return InternError; - } - } - // ----- now add the other fields: - keys=section.getKeys(); - if(!keys->insert("title", entry.title) || - !keys->insert("rank", entry.rank) || - !keys->insert("fn", entry.fn) || - !keys->insert("nameprefix", entry.nameprefix) || - !keys->insert("firstname", entry.firstname) || - !keys->insert("middlename", entry.middlename) || - !keys->insert("lastname", entry.lastname) || - !keys->insert("birthday", entry.birthday) || - !keys->insert("comment", entry.comment) || - !keys->insert("talk", entry.talk) || - !keys->insert("emails", entry.emails) || - !keys->insert("keywords", entry.keywords) || - !keys->insert("telephone", entry.telephone) || - !keys->insert("URLs", entry.URLs) || - !keys->insert("user1", entry.user1) || - !keys->insert("user2", entry.user2) || - !keys->insert("user3", entry.user3) || - !keys->insert("user4", entry.user4) || - !keys->insert("custom", entry.custom) || - !keys->insert("categories", entry.categories)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::makeEntryFromSection: cannot insert " - << "all fields of the entry." << endl; - return InternError; - } - // ----- - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::createNew(const TQString& filename) -{ - // ########################################################################### - const TQString KabTemplateFile=locate("data", "kab/template.kab"); - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::createNew: template file is \"" - << (const char*)KabTemplateFile.utf8() << "\"." << endl; - QConfigDB db; - // ----- - if(KabTemplateFile.isEmpty() - || !db.setFileName(KabTemplateFile, true, true)) - { - KMessageBox::error(this, - i18n("Cannot find kab's template file.\n" - "You cannot create new files."), - i18n("File Error")); - return InternError; - } - if(!db.load()) - { - KMessageBox::error(this, - i18n("Cannot read kab's template file.\n" - "You cannot create new files."), - i18n("Format Error")); - - return InternError; - } - if(!db.setFileName(filename, false, false)) - { - KMessageBox::error(this, - i18n("Cannot create the file\n\"") - +filename+"\"\n"+ - i18n("Could not create the new file."), - i18n("File Error")); - return PermDenied; - } - if(!db.save()) - { - KMessageBox::error(this, - i18n("Cannot save the file\n\"") - +filename+"\"\n"+ - i18n("Could not create the new file."), - i18n("File Error")); - return InternError; - } - // ----- - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::createConfigFile() -{ - // ########################################################################### - const TQString ConfigTemplateFile=locate("data", "kab/template.config"); - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::createConfigFile: config template file is \"" - << (const char*)ConfigTemplateFile.utf8() << "\"." << endl; - const TQString filename= locateLocal( "data", STD_CONFIGFILENAME); - QConfigDB db; - // ----- - if(ConfigTemplateFile.isEmpty() - || !db.setFileName(ConfigTemplateFile, true, true)) - { - KMessageBox::error(this, - i18n("Cannot find kab's configuration template file.\n" - "kab cannot be configured."), - i18n("File Error")); - - return InternError; - } - if(!db.load()) - { - KMessageBox::error(this, - i18n("Cannot read kab's configuration template file.\n" - "kab cannot be configured."), - i18n("File Error")); - return InternError; - } - if(!db.setFileName(filename, false, false)) - { - KMessageBox::error(this, - i18n("Cannot create the file\n\"") - +filename+"\"\n"+ - i18n("Could not create the new configuration file."), - i18n("File Error")); - return PermDenied; - } - if(!db.save()) - { - KMessageBox::error(this, - i18n("Cannot save the file\n\"") - +filename+"\"\n"+ - i18n("Could not create the new configuration file."), - i18n("File Error")); - return InternError; - } - // ----- - return NoError; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::loadConfigFile() -{ - // ########################################################################### - TQString file = locateLocal( "data", STD_CONFIGFILENAME); - if(config->setFileName(file, true, true)) - { - if(config->load()) - { - return NoError; - } else { - KMessageBox::information(this, - i18n("Cannot load kab's local configuration file.\n" - "There may be a formatting error.\n" - "kab cannot be configured."), - i18n("File Error")); - return InternError; - } - } else { - KMessageBox::information(this, - i18n("Cannot find kab's local configuration file.\n" - "kab cannot be configured."), - i18n("File Error")); - return NoSuchFile; - } - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::makeVCardFromEntry(const Entry&, const TQString&) -{ - // ########################################################################### - return NotImplemented; - // ########################################################################### -} - -AddressBook::ErrorCode -AddressBook::makeEntryFromVCard(const TQString&, Entry&) -{ - // ########################################################################### - return NotImplemented; - // ########################################################################### -} - -TQString -AddressBook::getStandardFileName() -{ - // ########################################################################### - return locateLocal( "data", STD_USERFILENAME); - // ########################################################################### -} - -TQString AddressBook::phoneType(AddressBook::Telephone phone) -{ - switch(phone) - { - case Fixed: return i18n("fixed"); break; - case Mobile: return i18n("mobile"); break; - case Fax: return i18n("fax"); break; - case Modem: return i18n("modem"); break; - default: return i18n("general"); - } -} - -void AddressBook::externalChange() -{ - updateMirrorMap(); -} - -Section* AddressBook::configurationSection() -{ - Section *section; - if(data!=0) - { - if(data->get(LOCAL_CONFIG_SECTION, section)) - { - return section; - } else { - return 0; - } - } else { - return 0; - } -} - -AddressBook::ErrorCode AddressBook::Entry::get(const char* fieldname, TQVariant& field) -{ - // "title", "rank", "fn", "nameprefix", "firstname", "middlename", "lastname", - // "birthday", "comment", "talk", "emails", "keywords", "telephone", - // "urls", "user1", "user2", "user3", "user4", "custom" - int dummy=0; - // ----- - if(fieldname==Fields[dummy++]) - { // the title - field=title; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the rank - field=rank; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the formatted name - field=fn; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the nameprefix - field=nameprefix; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the firstname - field=firstname; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the middle name - field=middlename; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the last name - field=lastname; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the birthday - field=TQString(birthday.toString()); - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the comment - field=comment; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the talk addresses - field=talk; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the email addresses - field=emails; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the keywords - field=keywords; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the telephones - field=telephone; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the urls - field=URLs; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the user field 1 - field=user1; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the user field 2 - field=user2; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the user field 3 - field=user3; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the user field 4 - field=user4; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the custom fields (app specific) - field=custom; - return NoError; - } - // ----- we did not find that field: - return NoSuchField; -} - -AddressBook::ErrorCode AddressBook::Entry::Address::get(const char* fieldname, - TQVariant& field) -{ - // "headline", "position", - // "org", "orgunit", "orgsubunit", - // "deliverylabel", "address", "zip", "town", "country", "state" - int dummy=0; - // ----- - if(fieldname==Fields[dummy++]) - { // the headline - field=headline; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the position - field=position; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the organization - field=org; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the organizational unit - field=orgUnit; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the organizational subunit - field=orgSubUnit; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the delivery label - field=deliveryLabel; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the address - field=address; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the zip code - field=zip; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the town - field=town; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the country - field=country; - return NoError; - } - if(fieldname==Fields[dummy++]) - { // the state - field=state; - return NoError; - } - // ----- we did not find that field: - return NoSuchField; -} - -Section* AddressBook::categoriesSection() -{ - const TQString Predefines[]= { - i18n("Business"), - i18n("Private"), - i18n("Dates") }; - size_t Size=sizeof(Predefines)/sizeof(Predefines[0]); - Section* section; - Section* categories; - KeyValueMap *keys; - // ----- - if(data->get(KAB_CATEGORY_KEY, section)) - { - // it exists, go ahead - return section; - } else { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::categoriesSection: creating categories structure." << endl; - // it does not exist - create it - if(!data->createSection(KAB_CATEGORY_KEY)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::categoriesSection: error creating categories section." - << endl; - return 0; - } - data->get(KAB_CATEGORY_KEY, section); - // add the predefined categories: - categories=new Section; - keys=categories->getKeys(); - for(size_t count=0; countinsert(TQCString().setNum(count), values); - } - section->add(KAB_CATEGORY_KEY, categories); - keys=section->getKeys(); - keys->insert("NextAvailableCatKey", (long)Size); - } - save(); - if(data->get(KAB_CATEGORY_KEY, section)) - return section; - return 0; // might not happen -} - -AddressBook::ErrorCode AddressBook::categories(CategoriesMap& cat) -{ // WORK_TO_DO: use a permanent cached map and update on changed() - kdDebug(KAB_KDEBUG_AREA, !cat.isEmpty()) - << "AddressBook::categories: warning - categories map is supposed to be empty!" - << endl; - Section *section; - Section *categories; - KeyValueMap* keys; - int key; - bool rc; - TQStringList values; - StringStringMap::iterator pos; - // ----- query categories section: - section=categoriesSection(); - TQ_CHECK_PTR(section); - // ----- - if(!section->find(KAB_CATEGORY_KEY, categories)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::categories: error in database structure." - << endl; - return InternError; - } - // ----- everything is set up, create the categories map: - // use an iterator to walk over all elements of categories key-value-map: - keys=categories->getKeys(); - for(pos=keys->begin(); pos!=keys->end(); ++pos) - { - if(!keys->get((*pos).first, values)) - { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::categories: internal error querying categories." - << endl; - } else { - key=(*pos).first.toInt(&rc); - if(rc) - { - cat.insert(key, values[0]); - } else { - kdDebug(KAB_KDEBUG_AREA) - << "AddressBook::categories: error - non-integer category key - ignored." - << endl; - } - } - } - return NoError; -} - -#include "addressbook.moc" diff --git a/kab/addressbook.cpp b/kab/addressbook.cpp new file mode 100644 index 000000000..017621ac7 --- /dev/null +++ b/kab/addressbook.cpp @@ -0,0 +1,2040 @@ +/* + This file implements the basic personal information management class + used in the TDE addressbook. + + the TDE addressbook + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2001, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org $ + $ License: GPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ +*/ + +#include "addressbook.h" +#include "qconfigDB.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +#include +} + +// ----- some defines: +#ifdef KAB_KDEBUG_AREA +#undef KAB_KDEBUG_AREA +#endif + +#define KAB_KDEBUG_AREA 800 + +#ifdef STD_USERFILENAME +#undef STD_USERFILENAME +#endif +#define STD_USERFILENAME "kab/addressbook.kab" + +#ifdef STD_CONFIGFILENAME +#undef STD_CONFIGFILENAME +#endif +#define STD_CONFIGFILENAME "kab/kab.config" + +#ifdef ENTRY_SECTION +#undef ENTRY_SECTION +#endif +#define ENTRY_SECTION "entries" + +// the name of the file-local configuration section +#ifdef LOCAL_CONFIG_SECTION +#undef LOCAL_CONFIG_SECTION +#endif +#define LOCAL_CONFIG_SECTION "config" + +// the name of the subsection for each entry +#ifdef ADDRESS_SUBSECTION +#undef ADDRESS_SUBSECTION +#endif +#define ADDRESS_SUBSECTION "addresses" + +#ifdef KAB_TEMPLATEFILE +#undef KAB_TEMPLATEFILE +#endif +#define KAB_TEMPLATEFILE "kab/template.kab" + +#ifdef KAB_CONFIGTEMPLATE +#undef KAB_CONFIGTEMPLATE +#endif +#define KAB_CONFIGTEMPLATE "kab/template.config" + +#ifdef KAB_CATEGORY_KEY +#undef KAB_CATEGORY_KEY +#endif +#define KAB_CATEGORY_KEY "categories" + +const char* AddressBook::Entry::Address::Fields[]= { + "headline", "position", + "org", "orgunit", "orgsubunit", + "deliverylabel", "address", "zip", "town", "country", "state" }; +const int AddressBook::Entry::Address::NoOfFields +=sizeof(AddressBook::Entry::Address::Fields) +/sizeof(AddressBook::Entry::Address::Fields[0]); + +const char* AddressBook::Entry::Fields[]= { + "title", "rank", "fn", "nameprefix", "firstname", "middlename", "lastname", + "birthday", "comment", "talk", "emails", "keywords", "telephone", + "urls", "user1", "user2", "user3", "user4", "custom", "categories" }; +const int AddressBook::Entry::NoOfFields +=sizeof(AddressBook::Entry::Fields)/sizeof(AddressBook::Entry::Fields[0]); + +struct QStringLess + : public binary_function +{ + /** The function operator, inline. */ + bool operator()(const TQString& x, const TQString& y) const + { + return x < y; // make one Qt operator fit exactly + } +}; + +// ----- the derived map class: +class StringKabKeyMap : public map +{ /* Same as map, but a class for compilation reasons. This way we do not need + * to include the QStringLess class into the addressbook header file. */ +}; + +// ----- another derived map class: +class KeyNameMap : public map > +{ // same thing +}; + +KeyNameMap* AddressBook::Entry::fields; +KeyNameMap* AddressBook::Entry::Address::fields; + +bool +KabKey::operator == (const KabKey& key) const +{ + // ########################################################################### + return key.getKey()==getKey(); + // ########################################################################### +} + +void +KabKey::setKey(const TQCString& text) +{ + // ########################################################################### + key=text; + // ########################################################################### +} + +TQCString +KabKey::getKey() const +{ + // ########################################################################### + return key; + // ########################################################################### +} + + + +AddressBook::Entry::Address::Address() +{ +} + +bool AddressBook::Entry::Address::nameOfField(const char* key, TQString& value) +{ + KeyNameMap::iterator pos; + // ----- + if(fields==0) + { // this is executed exactly one time per application instance, + // as fields is static + int counter=0; + fields=new KeyNameMap; + TQ_CHECK_PTR(fields); + if(!fields->insert + (map >::value_type + (Fields[counter++], i18n("Headline"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Position"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Organization"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Department"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Sub-Department"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Delivery Label"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("street/postal","Address"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Zipcode"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("City"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Country"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("As in addresses", "State"))).second) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::Entry::Address::nameOfField (while " + << " creating field-name map): TYPO, correct this." + << endl; + } else { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::Entry::Address::nameOfField: " + << "inserted field names." << endl; + } +#if ! defined NDEBUG + TQString name; + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::Entry::Address::nameOfField:" << endl + << "Created key-fieldname-map. Defined fields are:" + << endl; + for(counter=0; counterfind(Fields[counter]); + if(pos==fields->end()) + { + kdDebug(KAB_KDEBUG_AREA) << " UNDEFINED" << endl; + } else { + kdDebug(KAB_KDEBUG_AREA) + << " " << Fields[counter] << " (" + << (*pos).second.utf8() << ")" << endl; + } + } +#endif + } + // ----- now finally do the lookup: + pos=fields->find(key); + if(pos==fields->end()) + { + return false; + } else { + value=(*pos).second; + return true; + } +} + +bool AddressBook::Entry::nameOfField(const char* key, TQString& value) +{ + KeyNameMap::iterator pos; + // ----- + if(fields==0) + { // this is executed exactly one time per application instance, + // as fields is static + int counter=0; + fields=new KeyNameMap; + TQ_CHECK_PTR(fields); + if(!fields->insert + (map >::value_type + (Fields[counter++], i18n("person","Title"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Rank"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Formatted Name"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Name Prefix"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("First Name"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Middle Name"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Last Name"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Birthday"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Comment"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Talk Addresses"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Email Addresses"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Keywords"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Telephone Number"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("URLs"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("User Field 1"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("User Field 2"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("User Field 3"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("User Field 4"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Custom"))).second + || + !fields->insert + (map >::value_type + (Fields[counter++], i18n("Categories"))).second) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::Entry::Address::nameOfField (while " + << " creating field-name map): TYPO, correct this." << endl; + } else { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::Entry::Address::nameOfField: " + << "inserted field names." << endl; + } +#if ! defined NDEBUG + TQString name; + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::Entry::nameOfField:" << endl + << "Created key-fieldname-map. Defined fields are:" << endl; + for(counter=0; counterfind(Fields[counter]); + if(pos==fields->end()) + { + kdDebug(KAB_KDEBUG_AREA) << " UNDEFINED" << endl; + } else { + kdDebug(KAB_KDEBUG_AREA) + << " " << Fields[counter] << " (" + << (*pos).second.utf8() << ")" << endl; + } + } +#endif + } + // ----- now finally do the lookup: + pos=fields->find(key); + if(pos==fields->end()) + { + return false; + } else { + value=(*pos).second; + return true; + } +} + +AddressBook::ErrorCode +AddressBook::Entry::getAddress(int index, Address& address) const +{ + // ########################################################################### + list
::const_iterator pos; + // ----- + if(index>=0 && (unsigned)indexquit(); // It is critical, but will possibly never happen. + } + connect(data, TQT_SIGNAL(fileChanged()), TQT_SLOT(dataFileChanged())); + connect(data, TQT_SIGNAL(changed(QConfigDB*)), + TQT_SLOT(reloaded(QConfigDB*))); + connect(config, TQT_SIGNAL(fileChanged()), TQT_SLOT(configFileChanged())); + // ----- set style: + + filename = locate( "data", STD_CONFIGFILENAME); + if (filename.isEmpty()) + { + filename = locateLocal( "data", STD_CONFIGFILENAME ); + // config does not exist yet + if(createConfigFile()!=NoError) + { + KMessageBox::sorry(this, + i18n("Your local kab configuration file " + "\"%1\" " + "could not be created. kab will probably not " + "work correctly without it.\n" + "Make sure you have not removed write permission " + "from your local TDE directory (usually ~/.trinity).").arg(filename)); + state=PermDenied; + } + } + loadConfigFile(); + // ----- now get some configuration settings: + if(config->get("config", keys)) + { + keys->get("CreateBackupOnStartup", createBackup); + } + // ----- check and possibly create user standard file: + filename = locate( "data", STD_USERFILENAME ); + + if(filename.isEmpty()) // if it does not exist + { + filename = locateLocal( "data", STD_USERFILENAME); + if(createNew(filename)!=NoError) // ...and we cannot create it + { + KMessageBox::sorry(this, + i18n("Your standard kab database file " + "\"%1\" " + "could not be created. kab will probably not " + "work correctly without it.\n" + "Make sure you have not removed write permission " + "from your local TDE directory (usually ~/.trinity).").arg(filename)); + state=PermDenied; + } else { + KMessageBox::information + (this, + i18n("kab has created your standard addressbook in\n\"%1\"") + .arg(filename)); + } + } + // ----- load the user standard file: + if(loadit) + { + if(load(filename)!=NoError) + { // ----- the standard file could not be loaded + state=PermDenied; + } else { + if(createBackup) + { + // ----- create the backup file: + TQString temp=data->fileName(); + if(data->setFileName(temp+".backup", false, false)) + { + if(!data->save()) + { + KMessageBox::information + (this, + i18n("Cannot create backup file (permission denied)."), + i18n("File Error")); + } + } else { + KMessageBox::error + (this, + i18n("Cannot open backup file for " + "writing (permission denied)."), + i18n("File Error")); + } + // ----- reset the filename: + if(!data->setFileName(temp, true, true)) + { + KMessageBox::error + (this, + i18n("Critical error:\n" + "Permissions changed in local directory!"), + i18n("File Error")); + closeFile(false); + state=PermDenied; + } else { + state=NoError; + } + } + } + } + // ----- + data->watch(true); + // ########################################################################### +} + +AddressBook::~AddressBook() +{ + // ########################################################################### + delete data; + delete config; + delete entries; + // ########################################################################### +} + +QConfigDB* AddressBook::getConfig() +{ + // ########################################################################### + return config; + // ########################################################################### +} + +AddressBook::ErrorCode AddressBook::getState() +{ + // ########################################################################### + return state; + // ########################################################################### +} + +AddressBook::ErrorCode AddressBook::load(const TQString& filename) +{ + // ----- Remark: Close the file if it could not be loaded! + // ########################################################################### + ErrorCode rc=NoError; + TQFileInfo newfile, oldfile; + // ----- + TQString fname = (filename.isEmpty()) ? data->fileName() : filename ; + if(fname.isEmpty()) // there was never a filename set: + { + state=NoFile; + return NoFile; + } + // ----- + newfile.setFile(fname); + oldfile.setFile(data->fileName()); + if(isSameFile(fname, data->fileName())) + { // ----- possibly deleted file: + if(data->load()) + { + emit(setStatus(i18n("File reloaded."))); + state=NoError; + } else { + switch + (KMessageBox::questionYesNo + (this, + i18n("The currently loaded file " + "\"%1\" " + "cannot be reloaded. kab may close or save it.\n" + "Save it if you accidentally deleted your data file.\n" + "Close it if you intended to do so.\n" + "Your file will be closed by default.") + .arg(oldfile.absFilePath()), + i18n("File Error"), + KStdGuiItem::close(), KStdGuiItem::save())) + { + case KMessageBox::No: // save + if(!data->save(i18n("(Safety copy on file error)").ascii(), true)) + { + KMessageBox::information(this, + i18n("Cannot save the file; will close it now."), + i18n("File Error")); + closeFile(false); + state=NoFile; + rc=PermDenied; + } else { + state=NoError; + rc=NoError; + } + break; // no error if we could save the file + default: // close + closeFile(false); + state=NoFile; + rc=NoSuchFile; + break; + } + } + } else { // ----- set new filename + if(data->setFileName(fname, true, true)) + { + if(data->load()) + { + emit(changed()); + emit(setStatus(i18n("File opened."))); + state=NoError; + } else { + KMessageBox::information(this, + i18n("Could not load the file."), + i18n("File Error")); + closeFile(false); + emit(setStatus(i18n("No such file."))); + rc=NoSuchFile; + } + } else { + if(KMessageBox::questionYesNo + (this, + i18n("The file \"%1\" cannot be found. " + "Create a new one?").arg(fname), + i18n("No Such File"), + i18n("Create"), KStdGuiItem::cancel())==KMessageBox::Yes) + { + if(createNew(fname)==NoError) + { + emit(setStatus(i18n("New file."))); + } else { // ----- do not close here, stick with the old file: + emit(setStatus(i18n("Canceled."))); + } + } + } + } + // ----- + if(rc==NoError) + { + data->watch(true); + updateMirrorMap(); + } + // ----- + return rc; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::getListOfNames(TQStringList* strings, bool reverse, bool initials) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::getListOfNames: called.\n"; + StringKabKeyMap::iterator pos; + TQString desc; + ErrorCode rc=NoError; + ErrorCode temp; + // ----- erase the list contents: + strings->clear(); + // ----- ...and fill it: + for(pos=entries->begin(); pos!=entries->end(); ++pos) + { + temp=literalName((*pos).second, desc, reverse, initials); + if(temp!=AddressBook::NoError) + { + desc=i18n("(Internal error in kab)"); + rc=InternError; + } + if(desc.isEmpty()) + { + desc=i18n("(empty entry)"); + } + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "AddressBook::getListOfNames: adding " << desc << endl; + strings->append(desc); + } + // ----- any problems? + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::getListOfNames: done, " + << strings->count() + << " entries.\n"; + return rc; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::literalName(const KabKey& key, TQString& text, bool rev, bool init) +{ + // ########################################################################### + Entry entry; + ErrorCode rc; + // ----- get the entry: + rc=getEntry(key, entry); + if(rc!=NoError) + { + return rc; + } + // ----- + return literalName(entry, text, rev, init); + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::literalName(const Entry& entry, TQString& text, bool rev, bool init) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::literalName: called.\n"; + TQString firstname, middlename, lastname, nameprefix; + // ----- is the formatted name set? + if(!entry.fn.isEmpty()) + { + text=entry.fn; + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "AddressBook::literalName: done (fn).\n"; + return NoError; + } + // ----- prepare the strings: + firstname=entry.firstname.simplifyWhiteSpace(); + middlename=entry.middlename.simplifyWhiteSpace(); + lastname=entry.lastname.simplifyWhiteSpace(); + nameprefix=entry.nameprefix.simplifyWhiteSpace(); + // ----- create the initials: + if(init) + { + if(!firstname.isEmpty()) firstname=firstname.mid(0, 1)+'.'; + if(!middlename.isEmpty()) middlename=middlename.mid(0, 1)+'.'; + // if(!lastname.isEmpty()) lastname=lastname.mid(0, 1)+'.'; + } + // ----- assemble the string: + text=""; + if(rev) + { // name, firstname - add. name - name prefix + if(!lastname.isEmpty()) + { + text=lastname; + } + if(!firstname.isEmpty() || !middlename.isEmpty() || !nameprefix.isEmpty()) + { + text+=','; + } + if(!firstname.isEmpty()) + { + if(!text.isEmpty()) + { + text+=' '; + } + text+=firstname; + } + if(!middlename.isEmpty()) + { + if(!text.isEmpty()) + { + text+=' '; + } + text+=middlename; + } + if(!nameprefix.isEmpty()) + { + if(!text.isEmpty()) + { + text+=' '; + } + text+=nameprefix; + } + } else { + // firstname - add. name - name prefix - name + text=firstname; + if(!middlename.isEmpty()) + { + if(!text.isEmpty()) + { + text+=' '; + } + text+=middlename; + } + if(!nameprefix.isEmpty()) + { + if(!text.isEmpty()) + { + text+=' '; + } + text+=nameprefix; + } + if(!lastname.isEmpty()) + { + if(!text.isEmpty()) + { + text+=' '; + } + text+=lastname; + } + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::literalName: done: " + << text << ".\n"; + return NoError; + // ########################################################################### +} + +unsigned int +AddressBook::noOfEntries() +{ + // ########################################################################### + return entries->size(); + // ########################################################################### +} + +void +AddressBook::dataFileChanged() +{ + // ########################################################################### + data->watch(false); // will be restarted after successful load + load(); + // ########################################################################### +} + +void +AddressBook::configFileChanged() +{ + bool GUARD; GUARD=true; + // ########################################################################### + if(!config->load()) + { + KMessageBox::error(this, + i18n("Cannot reload configuration file!"), + i18n("File Error")); + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::configFileChanged: " + "config file reloaded.\n"; + emit(setStatus(i18n("Configuration file reloaded."))); + } + // ########################################################################### +} + +void +AddressBook::reloaded(QConfigDB* db) +{ + bool GUARD; GUARD=false; + // ########################################################################### + if(db==data) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::reloaded: file has been " + "reloaded.\n"; + updateMirrorMap(); // WORK_TO_DO: what's up with the return value? + changed(); + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::save(const TQString& filename, bool force) +{ + // ########################################################################### + if(filename.isEmpty()) + { + if(data->save(0, force)) + { + emit(setStatus(i18n("File saved."))); + return NoError; + } else { + return PermDenied; + } + } else { + if(data->setFileName(filename, false, false)) + { + if(data->save(0, true)) + { + emit(newFile(filename)); + return NoError; + } else { + return PermDenied; + } + } else { + return PermDenied; + } + } + // ########################################################################### +} + +bool +AddressBook::isSameFile(const TQString& a, const TQString& b) +{ + // ########################################################################### + TQFileInfo filea(a), fileb(b); + // ----- + return filea.absFilePath()==fileb.absFilePath(); + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::closeFile(bool saveit) +{ + // ########################################################################### + if(saveit) + { + if(save()!=NoError) + { + emit(setStatus(i18n("Permission denied."))); + return PermDenied; + } + } + data->clear(); + // data->reset(); WORK_TO_DO: File name is not reset by now. + emit(setStatus(i18n("File closed."))); + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::getEntry(const KabKey& key, Entry& entry) +{ + // ########################################################################### + Section *section; + // ----- + if(getEntry(key, section)==NoError) + { + return makeEntryFromSection(section, entry); + } else { + return NoSuchEntry; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::getEntry(const KabKey& key, Section*& section) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::getEntry: searching entry " + "with key " << key.getKey().data() << endl; + StringKabKeyMap::iterator pos; + // ----- + for(pos=entries->begin(); pos!=entries->end(); ++pos) + { + if((*pos).second==key) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "AddressBook::getEntry: key exists." << endl; + break; + } + } + if(pos==entries->end()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "AddressBook::getEntry: no such entry.\n"; + return NoSuchEntry; + } else { + if(data->get((TQCString)ENTRY_SECTION+'/'+key.getKey(), section)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "AddressBook::getEntry: done." << endl; + return NoError; + } else { + return InternError; + } + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::getEntries(list& thelist) +{ + // ########################################################################### + StringKabKeyMap::iterator pos; + Entry entry; + ErrorCode rc; + // ----- + kdDebug(!thelist.empty(), KAB_KDEBUG_AREA) + << "AddressBook::getEntries: warning - non-empty value list!" << endl; + thelist.erase(thelist.begin(), thelist.end()); + for(pos=entries->begin(); pos!=entries->end(); ++pos) + { + rc=getEntry((*pos).second, entry); + if(rc==NoError) + { + thelist.push_back(entry); + } else { + return InternError; + } + } + // ----- + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::getKey(int index, KabKey& key) +{ + // ########################################################################### + StringKabKeyMap::iterator pos; + // ----- + if((unsigned)indexsize()) + { + pos=entries->begin(); + advance(pos, index); + key=(*pos).second; + return NoError; + } else { + return NoSuchEntry; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::getIndex(const KabKey& key, int& index) +{ + bool GUARD; GUARD=true; + // ########################################################################### + StringKabKeyMap::iterator pos; + // ----- + index=0; + for(pos=entries->begin(); pos!=entries->end(); ++pos) + { + // kdDebug(KAB_KDEBUG_AREA) << (*pos).second.getKey().data() << " <--> " << + // key.getKey().data() << endl; + if((*pos).second==key) break; + ++index; + } + kdDebug(pos==entries->end(), KAB_KDEBUG_AREA) << + "AddressBook::getIndex: no such key." << endl; + if(pos==entries->end()) + { + return NoSuchEntry; + } else { + return NoError; + } + // ########################################################################### +} + +Section* +AddressBook::entrySection() +{ + // ########################################################################### + Section* section; + // ----- + if(!data->get(ENTRY_SECTION, section)) + { + return 0; + } else { + return section; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::add(const Entry& entry, KabKey& key, bool update) +{ + bool GUARD; GUARD=true; + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::add: called." << endl; + // ########################################################################### + Section* theEntries=entrySection(); + Section* newEntry; + KabKey nextKey; + ErrorCode locked; + ErrorCode rc; + // ----- + if(theEntries==0) + { + kdDebug(KAB_KDEBUG_AREA) << "AddressBook::add: no entries section." + << endl; + return NoFile; + } + newEntry=new Section; + if(newEntry==0) + { + KMessageBox::error(this, + i18n("Cannot initialize local variables."), + i18n("Out of Memory")); + kapp->quit(); // It is critical, but will possibly never happen. + return InternError; // shut the compiler up... + } + // ----- lock the file: + locked=lock(); + switch(locked) + { + case PermDenied: + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::add: permission denied." << endl; + return PermDenied; // cannot get r/w mode + case Locked: + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::add: db is already in r/w mode." << endl; + break; + case NoError: + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::add: got writing permissions." << endl; + break; + default: + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::add: unknown response, exiting." << endl; + return InternError; + } + // ----- + if(makeSectionFromEntry(entry, *newEntry)==NoError) + { + nextKey=nextAvailEntryKey(); + if(!theEntries->add(nextKey.getKey(), newEntry)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::add: Cannot insert section.\n"; + rc=InternError; + } else { + key=nextKey; + emit(changed()); + rc=NoError; + } + if(update) updateMirrorMap(); + } else { + rc=InternError; + } + if(locked!=Locked) + { // ----- unlock the file here: + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::add: dropped writing permissions." << endl; + locked=unlock(); + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::add: done." << endl; + if(locked!=NoError) + { + return locked; + } + if(rc!=NoError) + { + return rc; + } + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::change(const KabKey& key, const Entry& entry) +{ + // ########################################################################### + Section* theEntries=entrySection(); + Section* oldEntry; + ErrorCode locked; + ErrorCode rc; + // ----- + if(theEntries==0) + { + return NoFile; + } + // ----- lock the file: + locked=lock(); + if(locked==PermDenied) + { + return PermDenied; // cannot get r/w mode + } + // ----- + if(!theEntries->find(key.getKey(), oldEntry)) + { + rc=NoSuchEntry; + } else { + oldEntry->clear(); + rc=makeSectionFromEntry(entry, *oldEntry); + emit(changed()); + } + // ----- + if(locked!=PermDenied) + { // ----- unlock the file here: + locked=unlock(); + } + if(locked==NoError) + { + return rc; + } else { + return locked; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::remove(const KabKey& key) +{ + // ########################################################################### + Section *theEntries=entrySection(); + ErrorCode locked; + ErrorCode rc; + // ----- + if(theEntries==0) + { + return NoFile; + } + // ----- lock the file: + locked=lock(); + if(locked==PermDenied) + { + return PermDenied; // cannot get r/w mode + } + // ----- + if(theEntries->remove(key.getKey())) + { + rc=NoError; + emit(changed()); + } else { + rc=NoSuchEntry; + } + // ----- + if(locked!=PermDenied) + { // ----- unlock the file here: + locked=unlock(); + } + if(locked==NoError) + { + return rc; + } else { + return locked; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::lock() +{ + // ########################################################################### + if(!data->isRO()) return Locked; + if(data->setFileName(data->fileName(), false, false)) + { + return NoError; + } else { + KMessageBox::information(this, + i18n("The file you wanted to change could not be locked.\n" + "It is probably in use by another application or read-only."), + i18n("File Error")); + return PermDenied; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::unlock() +{ + // ########################################################################### + if(data->isRO()) return PermDenied; + if(data->setFileName(data->fileName(), true, true)) + { + return NoError; + } else { + return InternError; + } + // ########################################################################### +} + +KabKey +AddressBook::nextAvailEntryKey() +{ + // ########################################################################### + int max=0; + int temp; + Section::StringSectionMap::iterator pos; + Section *section=entrySection(); + KabKey key; + TQCString dummy; + bool good=true; + // ----- + if(section!=0) + { + for(pos=section->sectionsBegin(); pos!=section->sectionsEnd(); ++pos) + { + temp=0; + temp=(*pos).first.toInt(&good); + if(!good) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::nextAvailEntryKey: non-integer entry " + << endl; + } + if(temp>max) + { + max=temp; + } + } + } + // ----- + dummy.setNum(++max); + key.setKey(dummy); + // CHECK(key.getKey().toInt(&good)==max); + return key; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::updateMirrorMap() +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) + << "AddressBook::updateMirrorMap: updating mirror map.\n"; + TQString key; + Entry entry; + ErrorCode ec; + KabKey kk; + Section *section=entrySection(); + Section::StringSectionMap::iterator pos; + // ----- + entries->erase(entries->begin(), entries->end()); + if(section==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::updateMirrorMap: done, " + "no file loaded." << endl; + return NoError; + } + for(pos=section->sectionsBegin(); pos!=section->sectionsEnd(); ++pos) + { + if(makeEntryFromSection((*pos).second, entry)!=NoError) + { + // return InternError; // it is saver to continue without a key + } + key=""; + ec=literalName(entry, key, true, false); + if(key.isEmpty() || ec!=NoError) + { + key=i18n("(empty entry)"); + } + key+=(*pos).first; // append the section name to make the key unique + kk.setKey((*pos).first); + entries->insert(StringKabKeyMap::value_type(key, kk)); + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "AddressBook::updateMirrorMap: done." + << endl; + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::makeEntryFromSection(Section* section, Entry& entry) +{ + // ########################################################################### + Section *addresses; + Section *addressSection; + Section::StringSectionMap::iterator pos; + KeyValueMap *keys; + Entry temp; + Entry::Address address; + Entry::Address addressDummy; + int count; + // ----- create the aggregats: + const TQCString StringKeys[]= { + "title", + "rank", + "fn", + "nameprefix", + "firstname", + "middlename", + "lastname", + "comment", + "user1", + "user2", + "user3", + "user4" + }; + TQString* StringValues[]= { + &temp.title, + &temp.rank, + &temp.fn, + &temp.nameprefix, + &temp.firstname, + &temp.middlename, + &temp.lastname, + &temp.comment, + &temp.user1, + &temp.user2, + &temp.user3, + &temp.user4 + }; + const int StringKeySize=sizeof(StringKeys)/sizeof(StringKeys[0]); + const TQCString StringListKeys[]= { + "talk", + "emails", + "keywords", + "telephone", + "URLs", + "custom", + "categories" + }; + TQStringList* StringListValues[]= { + &temp.talk, + &temp.emails, + &temp.keywords, + &temp.telephone, + &temp.URLs, + &temp.custom, + &temp.categories + }; + const int StringListKeySize=sizeof(StringListKeys)/sizeof(StringListKeys[0]); + // ----- first parse "addresses" subsection: + if(!section->find(ADDRESS_SUBSECTION, addresses)) + { + return InternError; // no subsection called "addresses" + } + for(pos=addresses->sectionsBegin(); pos!=addresses->sectionsEnd(); ++pos) + { + if(!addresses->find((*pos).first, addressSection)) + { + return InternError; // no section we have an iterator for? + } + keys=addressSection->getKeys(); + address=addressDummy; // clean it up + if(makeAddressFromMap(keys, address)==AddressBook::NoError) + { + // ----- add the address to the list of addresses: + temp.addresses.push_back(address); + } else { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeEntryFromSection: cannot find all fields " + << "in an address subsection." << endl; + } + } + // ----- now parse all other fields directly: + keys=section->getKeys(); + for(count=0; countget(StringKeys[count], *StringValues[count])) + { + /* Spits out lots of warnings: + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeEntryFromSection: error: could not get " + << "value for key " << (const char*)StringKeys[count] + << "." << endl; + */ + } + } + for(count=0; countget(StringListKeys[count], *StringListValues[count])) + { + /* Spits out lots of warnings: + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeEntryFromSection: error: could not get " + << "value for key " << (const char*)StringListKeys[count] + << "." << endl; + */ + } + } + // ----- finally get the birthday: + keys->get("birthday", temp.birthday); // this may return false (no date) + // ----- + entry=temp; + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::makeAddressFromMap(KeyValueMap* keys, Entry::Address& address) +{ + // ########################################################################### + const TQCString Keys[]= { + "headline", + "position", + "org", + "orgunit", + "orgsubunit", + // "role", + "deliverylabel", + "address", + "zip", + "town", + "country", + "state" + }; + TQString* strings[]= { + &address.headline, + &address.position, + &address.org, + &address.orgUnit, + &address.orgSubUnit, + // &address.role, + &address.deliveryLabel, + &address.address, + &address.zip, + &address.town, + &address.country, + &address.state + }; + const int Size=sizeof(Keys)/sizeof(Keys[0]); + int count; + // ----- + for(count=0; countget(Keys[count], *strings[count]); + } + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::makeSectionFromEntry(const Entry& entry, Section& section) +{ + // ########################################################################### + list::const_iterator addPos; + Section *addresses=0; + Section *address=0; + TQCString key; // used for creating address subsection keys + int count=0; // counts the addresses + KeyValueMap *keys; + // ----- prepare the section object: + section.clear(); + // ----- first create "addresses" subsection: + if(!section.add(ADDRESS_SUBSECTION)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeSectionFromEntry: cannot create " << "subsection." + << " " << endl; + return InternError; + } + if(!section.find(ADDRESS_SUBSECTION, addresses)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeSectionFromEntry: cannot get new section." << endl; + return InternError; + } + // ----- now insert addresses: + for(addPos=entry.addresses.begin(); addPos!=entry.addresses.end(); ++addPos) + { + ++count; + key.setNum(count); + if(!addresses->add(key)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeSectionFromEntry: cannot create address " << endl; + return InternError; + } + if(!addresses->find(key, address)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeSectionFromEntry: cannot get new " << endl; + return InternError; + } + keys=address->getKeys(); + // ----- now insert keys into address: + if(!keys->insert("headline", (*addPos).headline) || + !keys->insert("position", (*addPos).position) || + !keys->insert("org", (*addPos).org) || + !keys->insert("orgunit", (*addPos).orgUnit) || + !keys->insert("orgsubunit", (*addPos).orgSubUnit) || + // !keys->insert("role", (*addPos).role) || + !keys->insert("deliverylabel", (*addPos).deliveryLabel) || + !keys->insert("address", (*addPos).address) || + !keys->insert("zip", (*addPos).zip) || + !keys->insert("town", (*addPos).town) || + !keys->insert("country", (*addPos).country) || + !keys->insert("state", (*addPos).state)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeSectionFromEntry: cannot completely " + << "insert this address." << endl; + return InternError; + } + } + // ----- now add the other fields: + keys=section.getKeys(); + if(!keys->insert("title", entry.title) || + !keys->insert("rank", entry.rank) || + !keys->insert("fn", entry.fn) || + !keys->insert("nameprefix", entry.nameprefix) || + !keys->insert("firstname", entry.firstname) || + !keys->insert("middlename", entry.middlename) || + !keys->insert("lastname", entry.lastname) || + !keys->insert("birthday", entry.birthday) || + !keys->insert("comment", entry.comment) || + !keys->insert("talk", entry.talk) || + !keys->insert("emails", entry.emails) || + !keys->insert("keywords", entry.keywords) || + !keys->insert("telephone", entry.telephone) || + !keys->insert("URLs", entry.URLs) || + !keys->insert("user1", entry.user1) || + !keys->insert("user2", entry.user2) || + !keys->insert("user3", entry.user3) || + !keys->insert("user4", entry.user4) || + !keys->insert("custom", entry.custom) || + !keys->insert("categories", entry.categories)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::makeEntryFromSection: cannot insert " + << "all fields of the entry." << endl; + return InternError; + } + // ----- + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::createNew(const TQString& filename) +{ + // ########################################################################### + const TQString KabTemplateFile=locate("data", "kab/template.kab"); + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::createNew: template file is \"" + << (const char*)KabTemplateFile.utf8() << "\"." << endl; + QConfigDB db; + // ----- + if(KabTemplateFile.isEmpty() + || !db.setFileName(KabTemplateFile, true, true)) + { + KMessageBox::error(this, + i18n("Cannot find kab's template file.\n" + "You cannot create new files."), + i18n("File Error")); + return InternError; + } + if(!db.load()) + { + KMessageBox::error(this, + i18n("Cannot read kab's template file.\n" + "You cannot create new files."), + i18n("Format Error")); + + return InternError; + } + if(!db.setFileName(filename, false, false)) + { + KMessageBox::error(this, + i18n("Cannot create the file\n\"") + +filename+"\"\n"+ + i18n("Could not create the new file."), + i18n("File Error")); + return PermDenied; + } + if(!db.save()) + { + KMessageBox::error(this, + i18n("Cannot save the file\n\"") + +filename+"\"\n"+ + i18n("Could not create the new file."), + i18n("File Error")); + return InternError; + } + // ----- + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::createConfigFile() +{ + // ########################################################################### + const TQString ConfigTemplateFile=locate("data", "kab/template.config"); + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::createConfigFile: config template file is \"" + << (const char*)ConfigTemplateFile.utf8() << "\"." << endl; + const TQString filename= locateLocal( "data", STD_CONFIGFILENAME); + QConfigDB db; + // ----- + if(ConfigTemplateFile.isEmpty() + || !db.setFileName(ConfigTemplateFile, true, true)) + { + KMessageBox::error(this, + i18n("Cannot find kab's configuration template file.\n" + "kab cannot be configured."), + i18n("File Error")); + + return InternError; + } + if(!db.load()) + { + KMessageBox::error(this, + i18n("Cannot read kab's configuration template file.\n" + "kab cannot be configured."), + i18n("File Error")); + return InternError; + } + if(!db.setFileName(filename, false, false)) + { + KMessageBox::error(this, + i18n("Cannot create the file\n\"") + +filename+"\"\n"+ + i18n("Could not create the new configuration file."), + i18n("File Error")); + return PermDenied; + } + if(!db.save()) + { + KMessageBox::error(this, + i18n("Cannot save the file\n\"") + +filename+"\"\n"+ + i18n("Could not create the new configuration file."), + i18n("File Error")); + return InternError; + } + // ----- + return NoError; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::loadConfigFile() +{ + // ########################################################################### + TQString file = locateLocal( "data", STD_CONFIGFILENAME); + if(config->setFileName(file, true, true)) + { + if(config->load()) + { + return NoError; + } else { + KMessageBox::information(this, + i18n("Cannot load kab's local configuration file.\n" + "There may be a formatting error.\n" + "kab cannot be configured."), + i18n("File Error")); + return InternError; + } + } else { + KMessageBox::information(this, + i18n("Cannot find kab's local configuration file.\n" + "kab cannot be configured."), + i18n("File Error")); + return NoSuchFile; + } + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::makeVCardFromEntry(const Entry&, const TQString&) +{ + // ########################################################################### + return NotImplemented; + // ########################################################################### +} + +AddressBook::ErrorCode +AddressBook::makeEntryFromVCard(const TQString&, Entry&) +{ + // ########################################################################### + return NotImplemented; + // ########################################################################### +} + +TQString +AddressBook::getStandardFileName() +{ + // ########################################################################### + return locateLocal( "data", STD_USERFILENAME); + // ########################################################################### +} + +TQString AddressBook::phoneType(AddressBook::Telephone phone) +{ + switch(phone) + { + case Fixed: return i18n("fixed"); break; + case Mobile: return i18n("mobile"); break; + case Fax: return i18n("fax"); break; + case Modem: return i18n("modem"); break; + default: return i18n("general"); + } +} + +void AddressBook::externalChange() +{ + updateMirrorMap(); +} + +Section* AddressBook::configurationSection() +{ + Section *section; + if(data!=0) + { + if(data->get(LOCAL_CONFIG_SECTION, section)) + { + return section; + } else { + return 0; + } + } else { + return 0; + } +} + +AddressBook::ErrorCode AddressBook::Entry::get(const char* fieldname, TQVariant& field) +{ + // "title", "rank", "fn", "nameprefix", "firstname", "middlename", "lastname", + // "birthday", "comment", "talk", "emails", "keywords", "telephone", + // "urls", "user1", "user2", "user3", "user4", "custom" + int dummy=0; + // ----- + if(fieldname==Fields[dummy++]) + { // the title + field=title; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the rank + field=rank; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the formatted name + field=fn; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the nameprefix + field=nameprefix; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the firstname + field=firstname; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the middle name + field=middlename; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the last name + field=lastname; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the birthday + field=TQString(birthday.toString()); + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the comment + field=comment; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the talk addresses + field=talk; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the email addresses + field=emails; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the keywords + field=keywords; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the telephones + field=telephone; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the urls + field=URLs; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the user field 1 + field=user1; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the user field 2 + field=user2; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the user field 3 + field=user3; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the user field 4 + field=user4; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the custom fields (app specific) + field=custom; + return NoError; + } + // ----- we did not find that field: + return NoSuchField; +} + +AddressBook::ErrorCode AddressBook::Entry::Address::get(const char* fieldname, + TQVariant& field) +{ + // "headline", "position", + // "org", "orgunit", "orgsubunit", + // "deliverylabel", "address", "zip", "town", "country", "state" + int dummy=0; + // ----- + if(fieldname==Fields[dummy++]) + { // the headline + field=headline; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the position + field=position; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the organization + field=org; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the organizational unit + field=orgUnit; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the organizational subunit + field=orgSubUnit; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the delivery label + field=deliveryLabel; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the address + field=address; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the zip code + field=zip; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the town + field=town; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the country + field=country; + return NoError; + } + if(fieldname==Fields[dummy++]) + { // the state + field=state; + return NoError; + } + // ----- we did not find that field: + return NoSuchField; +} + +Section* AddressBook::categoriesSection() +{ + const TQString Predefines[]= { + i18n("Business"), + i18n("Private"), + i18n("Dates") }; + size_t Size=sizeof(Predefines)/sizeof(Predefines[0]); + Section* section; + Section* categories; + KeyValueMap *keys; + // ----- + if(data->get(KAB_CATEGORY_KEY, section)) + { + // it exists, go ahead + return section; + } else { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::categoriesSection: creating categories structure." << endl; + // it does not exist - create it + if(!data->createSection(KAB_CATEGORY_KEY)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::categoriesSection: error creating categories section." + << endl; + return 0; + } + data->get(KAB_CATEGORY_KEY, section); + // add the predefined categories: + categories=new Section; + keys=categories->getKeys(); + for(size_t count=0; countinsert(TQCString().setNum(count), values); + } + section->add(KAB_CATEGORY_KEY, categories); + keys=section->getKeys(); + keys->insert("NextAvailableCatKey", (long)Size); + } + save(); + if(data->get(KAB_CATEGORY_KEY, section)) + return section; + return 0; // might not happen +} + +AddressBook::ErrorCode AddressBook::categories(CategoriesMap& cat) +{ // WORK_TO_DO: use a permanent cached map and update on changed() + kdDebug(KAB_KDEBUG_AREA, !cat.isEmpty()) + << "AddressBook::categories: warning - categories map is supposed to be empty!" + << endl; + Section *section; + Section *categories; + KeyValueMap* keys; + int key; + bool rc; + TQStringList values; + StringStringMap::iterator pos; + // ----- query categories section: + section=categoriesSection(); + TQ_CHECK_PTR(section); + // ----- + if(!section->find(KAB_CATEGORY_KEY, categories)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::categories: error in database structure." + << endl; + return InternError; + } + // ----- everything is set up, create the categories map: + // use an iterator to walk over all elements of categories key-value-map: + keys=categories->getKeys(); + for(pos=keys->begin(); pos!=keys->end(); ++pos) + { + if(!keys->get((*pos).first, values)) + { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::categories: internal error querying categories." + << endl; + } else { + key=(*pos).first.toInt(&rc); + if(rc) + { + cat.insert(key, values[0]); + } else { + kdDebug(KAB_KDEBUG_AREA) + << "AddressBook::categories: error - non-integer category key - ignored." + << endl; + } + } + } + return NoError; +} + +#include "addressbook.moc" diff --git a/kab/kabapi.cc b/kab/kabapi.cc deleted file mode 100644 index 62a50f162..000000000 --- a/kab/kabapi.cc +++ /dev/null @@ -1,220 +0,0 @@ -/* - This file implements the application programming interface - for using kab's addressbook files within other programs. - Parse it with kdoc to get the API documentation. - - the TDE addressbook - - $ Author: Mirko Boehm $ - $ Copyright: (C) 1996-2001, Mirko Boehm $ - $ Contact: mirko@kde.org - http://www.kde.org $ - $ License: GPL with the following explicit clarification: - This code may be linked against any version of the Qt toolkit - from Troll Tech, Norway. $ - - $Id$ -*/ - -#include "kabapi.h" -#include -#include -#include -#include - - -#include "kabapi.moc" - -#ifdef KAB_KDEBUG_AREA -#undef KAB_KDEBUG_AREA -#endif - -#define KAB_KDEBUG_AREA 800 - -using namespace std; - -KabAPI::KabAPI(TQWidget* parent, const char* name) - : KDialogBase(parent, name), - book(0), - listbox(new TDEListBox(this)), - selection(-1) -{ - TQ_CHECK_PTR(listbox); - setMainWidget(listbox); - showButtonApply(false); - enableButtonSeparator(true); - connect(listbox, TQT_SIGNAL(highlighted(int)), TQT_SLOT(entrySelected(int))); - connect(listbox, TQT_SIGNAL(doubleClicked ( TQListBoxItem * )),TQT_SLOT(slotDoubleClicked ( TQListBoxItem * ))); -} - - -void KabAPI::slotDoubleClicked ( TQListBoxItem * ) -{ - accept(); -} - -int KabAPI::exec() -{ - TQStringList names; - // ----- - if(book==0) - { - kdDebug(KAB_KDEBUG_AREA) - << "KabAPI::exec: you have to call init before using the API." - << endl; - return -1; - } else { - if(book->getListOfNames(&names, true, false)==AddressBook::NoError) - { - listbox->clear(); - listbox->insertStringList(names); - if(names.count()>0) - { - listbox->setCurrentItem(0); - } - listbox->setMinimumSize(listbox->sizeHint()); - adjustSize(); - resize(minimumSize()); - return KDialogBase::exec(); - } else { - kdDebug(KAB_KDEBUG_AREA) << "KabAPI::exec: error creating interface." - << endl; - return -1; - } - } -} - -AddressBook::ErrorCode KabAPI::init() -{ - // ############################################################################ - book=new AddressBook(0, "KABAPI::book", true); //change parent from "this" to "0" //dsweet - if(book->getState()==AddressBook::NoError) - { - connect(book, TQT_SIGNAL(setStatus(const TQString&)), - TQT_SLOT(setStatusSlot(const TQString&))); - return AddressBook::NoError; - } else { - return AddressBook::InternError; - } - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::getEntry(AddressBook::Entry& entry, KabKey& key) -{ - // ############################################################################ - if(book->noOfEntries()==0) - { - return AddressBook::NoEntry; - } - if(selection>=0) - { - if(book->getKey(selection, key)==AddressBook::NoError) - { - if(book->getEntry(key, entry)==AddressBook::NoError) - { - return AddressBook::NoError; - } else { - return AddressBook::InternError; // this may not happen - } - } else { - return AddressBook::NoEntry; - } - } else { - return AddressBook::InternError; - } - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::add(const AddressBook::Entry& entry, KabKey& key, - bool update) -{ - // ############################################################################ - if(book->add(entry, key, update)!=AddressBook::NoError) - { - KMessageBox::sorry(this, i18n("Your new entry could not be added.")); - return AddressBook::InternError; - } else { - return AddressBook::NoError; - } - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::remove(const KabKey& key) -{ - TQ_CHECK_PTR(book); - // ############################################################################ - if(book->AddressBook::remove(key)==AddressBook::NoError) - { - return AddressBook::NoError; - } else { - return AddressBook::NoEntry; - } - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::getEntryByName(const TQString&, - list&, const int) -{ - // ############################################################################ - return AddressBook::NotImplemented; - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::getEntryByName(const AddressBook::Entry&, - list&, const int) -{ - // ############################################################################ - return AddressBook::NotImplemented; - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::getEntries(list& entries) -{ - kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: called." << endl; - // ############################################################################ - if(book->noOfEntries()==0) - { // ----- database is valid, but empty: - kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: no entries." << endl; - return AddressBook::NoEntry; - } - if(book->getEntries(entries)!=AddressBook::NoError) - { - kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: intern error." << endl; - return AddressBook::InternError; - } else { - kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: done." << endl; - return AddressBook::NoError; - } - // ############################################################################ -} - -AddressBook* KabAPI::addressbook() -{ - // ############################################################################ - return book; - // ############################################################################ -} - -AddressBook::ErrorCode KabAPI::save(bool force) -{ - // ############################################################################ - if(book->save("", force)!=AddressBook::NoError) - { - return AddressBook::PermDenied; - } else { - return AddressBook::NoError; - } - // ############################################################################ -} - -void KabAPI::entrySelected(int index) -{ - kdDebug(KAB_KDEBUG_AREA) << "KabAPI::entrySelected: entry " << index - <<" selected." << endl; - selection=index; -} - -void KabAPI::setStatusSlot(const TQString& text) -{ - emit(setStatus(text)); -} diff --git a/kab/kabapi.cpp b/kab/kabapi.cpp new file mode 100644 index 000000000..62a50f162 --- /dev/null +++ b/kab/kabapi.cpp @@ -0,0 +1,220 @@ +/* + This file implements the application programming interface + for using kab's addressbook files within other programs. + Parse it with kdoc to get the API documentation. + + the TDE addressbook + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2001, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org $ + $ License: GPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ +*/ + +#include "kabapi.h" +#include +#include +#include +#include + + +#include "kabapi.moc" + +#ifdef KAB_KDEBUG_AREA +#undef KAB_KDEBUG_AREA +#endif + +#define KAB_KDEBUG_AREA 800 + +using namespace std; + +KabAPI::KabAPI(TQWidget* parent, const char* name) + : KDialogBase(parent, name), + book(0), + listbox(new TDEListBox(this)), + selection(-1) +{ + TQ_CHECK_PTR(listbox); + setMainWidget(listbox); + showButtonApply(false); + enableButtonSeparator(true); + connect(listbox, TQT_SIGNAL(highlighted(int)), TQT_SLOT(entrySelected(int))); + connect(listbox, TQT_SIGNAL(doubleClicked ( TQListBoxItem * )),TQT_SLOT(slotDoubleClicked ( TQListBoxItem * ))); +} + + +void KabAPI::slotDoubleClicked ( TQListBoxItem * ) +{ + accept(); +} + +int KabAPI::exec() +{ + TQStringList names; + // ----- + if(book==0) + { + kdDebug(KAB_KDEBUG_AREA) + << "KabAPI::exec: you have to call init before using the API." + << endl; + return -1; + } else { + if(book->getListOfNames(&names, true, false)==AddressBook::NoError) + { + listbox->clear(); + listbox->insertStringList(names); + if(names.count()>0) + { + listbox->setCurrentItem(0); + } + listbox->setMinimumSize(listbox->sizeHint()); + adjustSize(); + resize(minimumSize()); + return KDialogBase::exec(); + } else { + kdDebug(KAB_KDEBUG_AREA) << "KabAPI::exec: error creating interface." + << endl; + return -1; + } + } +} + +AddressBook::ErrorCode KabAPI::init() +{ + // ############################################################################ + book=new AddressBook(0, "KABAPI::book", true); //change parent from "this" to "0" //dsweet + if(book->getState()==AddressBook::NoError) + { + connect(book, TQT_SIGNAL(setStatus(const TQString&)), + TQT_SLOT(setStatusSlot(const TQString&))); + return AddressBook::NoError; + } else { + return AddressBook::InternError; + } + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::getEntry(AddressBook::Entry& entry, KabKey& key) +{ + // ############################################################################ + if(book->noOfEntries()==0) + { + return AddressBook::NoEntry; + } + if(selection>=0) + { + if(book->getKey(selection, key)==AddressBook::NoError) + { + if(book->getEntry(key, entry)==AddressBook::NoError) + { + return AddressBook::NoError; + } else { + return AddressBook::InternError; // this may not happen + } + } else { + return AddressBook::NoEntry; + } + } else { + return AddressBook::InternError; + } + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::add(const AddressBook::Entry& entry, KabKey& key, + bool update) +{ + // ############################################################################ + if(book->add(entry, key, update)!=AddressBook::NoError) + { + KMessageBox::sorry(this, i18n("Your new entry could not be added.")); + return AddressBook::InternError; + } else { + return AddressBook::NoError; + } + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::remove(const KabKey& key) +{ + TQ_CHECK_PTR(book); + // ############################################################################ + if(book->AddressBook::remove(key)==AddressBook::NoError) + { + return AddressBook::NoError; + } else { + return AddressBook::NoEntry; + } + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::getEntryByName(const TQString&, + list&, const int) +{ + // ############################################################################ + return AddressBook::NotImplemented; + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::getEntryByName(const AddressBook::Entry&, + list&, const int) +{ + // ############################################################################ + return AddressBook::NotImplemented; + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::getEntries(list& entries) +{ + kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: called." << endl; + // ############################################################################ + if(book->noOfEntries()==0) + { // ----- database is valid, but empty: + kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: no entries." << endl; + return AddressBook::NoEntry; + } + if(book->getEntries(entries)!=AddressBook::NoError) + { + kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: intern error." << endl; + return AddressBook::InternError; + } else { + kdDebug(KAB_KDEBUG_AREA) << "KabAPI::getEntries: done." << endl; + return AddressBook::NoError; + } + // ############################################################################ +} + +AddressBook* KabAPI::addressbook() +{ + // ############################################################################ + return book; + // ############################################################################ +} + +AddressBook::ErrorCode KabAPI::save(bool force) +{ + // ############################################################################ + if(book->save("", force)!=AddressBook::NoError) + { + return AddressBook::PermDenied; + } else { + return AddressBook::NoError; + } + // ############################################################################ +} + +void KabAPI::entrySelected(int index) +{ + kdDebug(KAB_KDEBUG_AREA) << "KabAPI::entrySelected: entry " << index + <<" selected." << endl; + selection=index; +} + +void KabAPI::setStatusSlot(const TQString& text) +{ + emit(setStatus(text)); +} diff --git a/kab/qconfigDB.cc b/kab/qconfigDB.cc deleted file mode 100644 index dc77a1e1b..000000000 --- a/kab/qconfigDB.cc +++ /dev/null @@ -1,2547 +0,0 @@ -/* the Configuration Database library, Version II - - the TDE addressbook - - $ Author: Mirko Boehm $ - $ Copyright: (C) 1996-2001, Mirko Boehm $ - $ Contact: mirko@kde.org - http://www.kde.org $ - $ License: GPL with the following explicit clarification: - This code may be linked against any version of the Qt toolkit - from Troll Tech, Norway. $ - - $Id$ -*/ - -#include "qconfigDB.h" -// #include "debug.h" - -extern "C" { -#include -#include -#include -#include -#include -} - -// #include -#include -#include -#include -#include -#include - -#include "qconfigDB.moc" -#include - -#ifdef KAB_KDEBUG_AREA -#undef KAB_KDEBUG_AREA -#endif - -#define KAB_KDEBUG_AREA 800 - -static bool isComment(TQCString line) -{ - // ############################################################################ - line=line.stripWhiteSpace(); - if(line.isEmpty()) - { - return false; // line is empty but not a comment - } else { - return(line[0]=='#'); - } - // ############################################################################ -} - -static void tokenize(list& res, const TQCString& text, char tr, bool strict=false) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: called." << endl; - int eins=0, zwei=0; - TQCString teil; - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: partening -->%" << text.data() << "<--." << endl; - res.erase(res.begin(), res.end()); - // ----- - if(text.isEmpty()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "tokenize: text is an empty string, done." << endl; - return; - } - while(zwei!=-1) - { - teil=""; - zwei=text.find(tr, eins); - if(zwei!=-1) - { - teil=text.mid(eins, zwei-eins); - res.push_back(teil); - } else { // last element - if(!strict) // nur wenn dazwischen Zeichen sind - { - teil=text.mid(eins, text.length()-eins); - res.push_back(teil); - } - } - eins=zwei+1; - // if((unsigned)eins>=text.length()) break; - } - kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: partened in " - << res.size() << " parts.\n"; - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: done." << endl; - // ############################################################################ -} - -// TQCString AuthorEmailAddress; // assign your email address to this string - -static TQCString ReadLineFromStream(TQTextStream& stream) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "ReadLineFromStream:: reading line." << endl; - TQCString line; - // ----- - while(!stream.eof()) - { - line=stream.readLine().ascii(); - if(!line.isEmpty()) - { - if(isComment(line)) - { - line=""; - continue; - } - } - break; - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "ReadLineFromStream:: line \"" << line.data() << "\" read.\n"; - return line; - // ############################################################################ -} - -// class implementations: - -list QConfigDB::LockFiles; // the lockfiles created by this session - -KeyValueMap::KeyValueMap() - : data(new StringStringMap) -{ - // ########################################################################### - // ########################################################################### -} - -KeyValueMap::KeyValueMap(const KeyValueMap& orig) - : data(new StringStringMap(*orig.data)) -{ - // ########################################################################### - // ########################################################################### -} - -KeyValueMap::~KeyValueMap() -{ - // ########################################################################### - delete data; - // ########################################################################### -} - -bool KeyValueMap::invariant() -{ - return true; -} - -StringStringMap::iterator KeyValueMap::begin() -{ - return data->begin(); -} - -StringStringMap::iterator KeyValueMap::end() -{ - return data->end(); -} - -unsigned int -KeyValueMap::size() const -{ - // ########################################################################### - return data->size(); - // ########################################################################### -} - -void -KeyValueMap::clear() -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::clear: erasing map contents ... " << endl; - // ----- - if(!data->empty()) // erase fails on empty containers! - { - data->erase(data->begin(), data->end()); - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "done." << endl; - // ########################################################################### -} - -bool -KeyValueMap::fill(const TQString& filename, bool force, bool relax) -{ - bool GUARD; GUARD=false; - // ########################################################################### - TQFile file(filename); - TQCString line; - // ----- - if(file.open(IO_ReadOnly)) - { - TQTextStream stream(&file); - // We read/write utf8 strings, so we don't want that TQTextStream uses local8bit - // Latin1 means : no conversion, when giving char*s to a TQTextStream. (DF) - stream.setEncoding(TQTextStream::Latin1); - // ----- - while(!stream.eof()) - { - line=stream.readLine().ascii(); - if(!line.isEmpty() /* && !stream.eof() */ && !isComment(line)) - { - if(!insertLine(line, force, relax, false)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::fill: could not insert line " - << line << ".\n"; // ignore this case further - } - } - } - file.close(); - // ----- - return true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::fill: cannot open file " << - filename << endl; - return false; - } - // ########################################################################### -} - -bool -KeyValueMap::save(const TQString& filename, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::save: saving data to -->" << - filename << "<--.\n"; - StringStringMap::iterator pos; - TQFile file(filename); - // ----- open file, regarding existence: - if(!force) - { - if(file.exists()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::save: file exists but may not." << endl; - return false; - } - } - if(file.open(IO_WriteOnly)) - { - TQTextStream stream(&file); - stream.setEncoding(TQTextStream::Latin1); // no conversion - stream << "# saved by KeyValueMap object ($Revision$)" << endl; - for(pos=data->begin(); pos!=data->end(); ++pos) - { // values do not get coded here - stream << (*pos).first << '=' << (*pos).second << endl; - } - file.close(); - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::save: could not open file -->%s<-- for saving." << - filename.utf8() << endl; - return false; - } - // ########################################################################### - return true; -} - -bool -KeyValueMap::save(TQTextStream& file, int count) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::save: saving data to given output stream." << endl; - StringStringMap::iterator pos; - bool ret=true; - char* prefix=new char[count+1]; - memset(prefix, ' ', count); - prefix[count]=0; - // ----- - for(pos=data->begin(); pos!=data->end(); ++pos) - { - file << prefix << (*pos).first << '=' << (*pos).second << endl; - } - delete [] prefix; - // ----- - return ret; - // ########################################################################### -} - - -bool -KeyValueMap::erase(const TQCString& key) -{ - // ########################################################################### - bool rc=(data->erase(key)>0); - return rc; - // ########################################################################### -} - - -bool -KeyValueMap::empty() -{ - // ########################################################################### - return data->empty(); - // ########################################################################### -} - -bool -KeyValueMap::parseComplexString -(const TQCString& orig, - int index, // first char to parse - TQCString& result, // string without leading and trailing ".." - int& noOfChars) // no of chars that represented the - const // complex string in the original -{ - bool GUARD; GUARD=false; - // ########################################################################### - int first; - TQCString temp(2*orig.length()); - TQCString mod; - int count=1; - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::parseComplexString: parsing the string -->" - << orig << "<--.\n"; - // ----- - if(orig.isEmpty()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::parseComplexString: string is empty.\n" - " " - "This is no valid complex string." << endl; - return false; - } - // ----- prepare the string: - temp=orig.mid(index, orig.length()-index); // remove everything before index - mod=temp.stripWhiteSpace(); // remove leading and trailing white spaces - // ----- test some conditions: - if(mod.length()<2) - { - kdDebug() << "KeyValueMap::parseComplexString: no pair of brackets " << endl; - return false; - } - if(mod[0]!='"') - { - kdDebug() << "KeyValueMap::parseComplexString: no opening bracket." << endl; - return false; - } - // ----- now parse it: - first=1; // first character after opening bracket - temp=""; - for(;;) - { - if(mod[first]=='\\') - { // handle special characters - ++first; - kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::parseComplexString: found " - "a special character \"%c\".", mod[first]) << endl; - if((unsigned)first==mod.length()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::parseComplexString: " - "string lacks the closing \".\n " - " This is no valid " - "complex string." << endl; - return false; - } - switch(mod[first]) - { - case 't': temp+='\t'; break; - case 'n': temp+='\n'; break; - case '"': temp+='"'; break; - case 'e': temp+="\\e"; break; - case '\\': temp+='\\'; break; - default: - // WORK_TO_DO: implement octal coding here! - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::parseComplexString: " - "invalid control character.\n " - " This is no valid complex string." << endl; - return false; - } - count+=2; // this took 2 characters - ++first; - } else { // it is a character - ++count; - if(mod[first]=='"') // end of coded string? - { - break; - } - temp+=mod[first]; - ++first; - } - if((unsigned)first>=mod.length()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::parseComplexString: " - "string lacks the closing \".\n " - " This is no valid complex string.\n"; - return false; - } - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA).form( - "KeyValueMap::parseComplexString: finished parsing, no errors, " - "%i characters, %i in string.", count, temp.length()) << endl; - noOfChars=count; - result=temp; - // ########################################################################### - return true; -} - -TQCString -KeyValueMap::makeComplexString(const TQCString& orig) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::makeComplexString: coding the string\n -->" - << orig << - "<--\n into a complex string.\n"; - TQCString temp(2*orig.length()); - unsigned int count; - // ----- - temp+='"'; // opening bracket - for(count=0; count" - <find(key); - // ----- - if(pos==data->end()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "not in KeyValueMap." << endl; - return false; - } else { - value=(*pos).second; - kdDebug(GUARD, KAB_KDEBUG_AREA) << "in KeyValueMap, value is " - << value << endl; - return true; - } - // ########################################################################### -} - -bool -KeyValueMap::insertRaw(const TQCString& key, const TQCString& value, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::insertRaw: inserting uncoded value " - << value << - " for key " << key << endl; - int n=0; - // ----- - if(key.isEmpty()) // empty KEYS are errors: - { - kdDebug() << "KeyValueMap::insertRaw: tried to insert empty key." << endl; - return false; - } - if(force) // entry will be replaced - { - n=data->erase(key); - } - if(data->insert(StringStringMap::value_type(key, value)).second) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertRaw: success" - << (n==0 ? "" : " (forced)") << endl; - return true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertRaw: failed, " - "key already in KeyValueMap." << endl; - return false; - } - // ########################################################################### -} - - -// ----------------------------------------------------------------------------- -// HUGE SEPARATOR BETWEEN INTERNAL LOGIC AND EXTENDABLE PAIRS OF GET- AND INSERT -// -METHODS. -// EXTENDABLE MEANS: OTHER DATATYPES CAN BE ADDED HERE. -// ----------------------------------------------------------------------------- - -/* The following functions are the pairs of insert-get-methods for different - * data types. See keyvaluemap.h for the declarations. */ - -// ascii strings: - -bool -KeyValueMap::insert(const TQCString& key, const TQCString& value, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::insert: inserting value\n -->" - << value << - "<-- \"" - " for key\n -->" - << key << - "<--.\n"; - return insertRaw(key, makeComplexString(value), force); - // ########################################################################### -} - -/* Attention: - * This is another insert function that partens lines like "key=value"! - * It is used for reading files and command line parameters easily. - */ - -bool -KeyValueMap::insertLine(TQCString line, bool force, bool relax, bool encode) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::insertLine: inserting line -->"<& values, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int list]: trying to " - "insert int list into map." << endl; - TQCString temp; - TQCString value; - list::const_iterator pos; - // ----- - for(pos=values.begin(); pos!=values.end(); ++pos) - { - temp.setNum(*pos); - value=value+temp+", "; - } - if(!value.isEmpty()) - { // remove last comma and space: - value.remove(value.length()-2, 2); - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int list]: " - "constructed string value is " << value << endl; - return insert(key, value, force); - // ########################################################################### -} - -bool -KeyValueMap::get(const TQCString& key, list& values) const -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: trying to " - "decode int list for key " << key << endl; - kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: " - "attention - list should be empty but is not.\n"; - TQCString value; - list tokens; - list::iterator pos; - int temp; - bool ok; - // ----- - if(!get(key, value)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[int list]: no such key." << endl; - return false; - } - tokenize(tokens, value, ','); - if(tokens.empty()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[int list]: no tokens." << endl; - return false; - } - // ----- - for(pos=tokens.begin(); pos!=tokens.end(); ++pos) - { - temp=(*pos).toInt(&ok); - if(ok) - { - values.push_back(temp); - } else { - kdDebug() << "KeyValueMap::get[int list]: conversion error for " << *pos << endl; - } - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[long int list]: done." << endl; - // ########################################################################### - return true; -} - -// (^^^ int lists) -// doubles: - -bool -KeyValueMap::insert(const TQCString& key, const double& value, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::insert[double]: trying to " - "insert value \"%f\" for key\n -->", value) << key << "<--.\n"; - TQCString temp; - // ----- - temp.setNum(value); - return insert(key, temp, force); - // ########################################################################### -} - -bool -KeyValueMap::get(const TQCString& key, double& value) const -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[double]: trying to get " - "FLOAT value for key " << key << endl; - TQCString v; - bool ok; - double temp; - // ----- - if(!get(key, v)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int]: key " - <& values) const -{ - bool GUARD; GUARD=false; - kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[string list]: " - "attention!\n \"values\" list reference is not " - "empty!" << endl; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[string list]: trying to " - "decode string list for key " << key << endl; - TQCString raw, part, value; - int first=1, second=1, i; - // ----- get the string value as a whole: - if(!getRaw(key, raw)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[list]: key " - << key << " not in KeyValueMap." << endl; - return false; - } - // ----- - for(;;) - { // ----- parten the string down into a list, find special characters: - second=first; - for(;;) - { - second=raw.find('\\', second); - // ----- this may never be the last and also not the second last - // character in a complex string: - if(second!=-1) - { // ----- check for string end: - // we use "\e" as token for the string-delimiter - if(raw[second+1]=='e' // the right character - && raw[second-1]!='\\') // not escaped - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get" - "[list]: found string end at pos " << - second << endl; - break; - } else { - ++second; - } - } else { - break; - } - } - if(second!=-1) - { - // ----- now second points to the end of the substring: - part="\""+raw.mid(first, second-first)+"\""; - // ----- insert decoded value into the list: - if(parseComplexString(part, 0, value, i)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get" - "[list]: found item " << value << endl; - values.push_back(value); - } else { - kdDebug() << "KeyValueMap::get[list]: parse error." << endl; - return false; - } - if((unsigned)second]: list end found." << endl; - break; - } - } else { // ----- finished: - break; - } - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[list]: done." << endl; - return true; - // ########################################################################### -} - -bool -KeyValueMap::insert(const TQCString& key, const list& values, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[string list]: " - "coding string list." << endl; - TQCString value="\""; - TQCString temp; - list::const_iterator pos; - // ----- create coded string list: - for(pos=values.begin(); - pos!=values.end(); - pos++) - { // create strings like "abc\efgh\eijk": - temp=makeComplexString(*pos); - temp.remove(0, 1); // remove the leading "\"" - temp.remove(temp.length()-1, 1); // the trailing "\"" - value+=temp; - value+="\\e"; - } - value+="\""; // finish the string - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[string list]: result " - "of coding is " << value << endl; - // ----- insert it without coding: - return insertRaw(key, value, force); - // ########################################################################### -} - -// (^^^ lists of strings) -// QStrList-s: - -bool -KeyValueMap::get(const TQCString& key, TQStrList& values) const -{ - bool GUARD; GUARD=false; - kdDebug(!values.isEmpty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: " - "attention!\n \"values\" list reference is not " - "empty!" << endl; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: trying to " - "decode string list for key " << key << endl; - TQCString raw, part, value; - int first=1, second=1, i; - // ----- get the string value as a whole: - if(!getRaw(key, raw)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: key " - << key <<" not in KeyValueMap." << endl; - return false; - } - // ----- - for(;;) - { // ----- parten the string down into a list, find special characters: - second=first; - for(;;) - { - second=raw.find('\\', second); - // ----- this may never be the last and also not the second last - // character in a complex string: - if(second!=-1) - { // ----- check for string end: - // we use "\e" as token for the string-delimiter - if(raw[second+1]=='e' // the right character - && raw[second-1]!='\\') // not escaped - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]:" - " found string end at pos %i." << second << endl; - break; - } else { - ++second; - } - } else { - break; - } - } - if(second!=-1) - { - // ----- now second points to the end of the substring: - part="\""+raw.mid(first, second-first)+"\""; - // ----- insert decoded value into the list: - if(parseComplexString(part, 0, value, i)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: " - "found item " << value << endl; - values.append(value); - } else { - kdDebug() << "KeyValueMap::get[QStrList]: parse error." << endl; - return false; - } - if((unsigned)second& values, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[double list]: trying " - "to insert double list into map." << endl; - TQCString buffer; - // TQCString value(30*values.size()); // not usable with Qt 2 - TQCString value; // WORK_TO_DO: how to reserve enough space to avoid growing? - list::const_iterator pos; - // ----- - for(pos=values.begin(); pos!=values.end(); ++pos) - { - buffer.setNum(*pos); - value=value+buffer+", "; - } - if(!value.isEmpty()) - { // remove last comma and space: - value.remove(value.length()-2, 2); - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[double list]: " - "constructed string value is " << value << endl; - return insert(key, value, force); - // ########################################################################### -} - -bool -KeyValueMap::get(const TQCString& key, list& values) const -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[double list]: trying to " - "decode double list for key " << key << endl; - kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[double list]: " - "attention - list should be empty but is not." << endl; - TQCString value; - list tokens; - list::iterator pos; - double temp; - bool ok; - // ----- - if(!get(key, value)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[double list]: no such key." << endl; - return false; - } - // ----- - tokenize(tokens, value, ','); - for(pos=tokens.begin(); pos!=tokens.end(); ++pos) - { - temp=(*pos).toDouble(&ok); - if(ok) - { - values.push_back(temp); - } else { - kdDebug() << "KeyValueMap::get[double list]: conversion error for " - << *pos << endl; - } - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: done." << endl; - // ########################################################################### - return true; -} - -// (^^^ lists of doubles) -// QDates: - -bool -KeyValueMap::insert(const TQCString& key, const TQDate& value, bool force) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QDate]: trying to " - "insert TQDate into map." << endl; - list values; - // ----- - if(!value.isValid()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QDate]: invalid " - "date, inserting a null date." << endl; - for(int i=0; i<3; ++i) values.push_back(0); - } else { - values.push_back(value.year()); - values.push_back(value.month()); - values.push_back(value.day()); - } - // ----- - return insert(key, values, force); - // ########################################################################### -} - -bool -KeyValueMap::get(const TQCString& key, TQDate& date) const -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QDate]: trying to decode" - " TQDate for key " << key << endl; - list values; - long y, m, d; - TQDate temp; - // ----- - if(!get(key, values)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[QDate]: no such key." << endl; - return false; - } - if(values.size()!=3) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[QDate]: more or less than 3 values." << endl; - return false; - } - y=values.front(); values.pop_front(); - m=values.front(); values.pop_front(); - d=values.front(); - // ----- - if(y!=0 || m!=0 || d!=0) temp.setYMD(y, m, d); // avoid TQDate messages - if(!temp.isValid() && !temp.isNull()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[QDate]: no valid date." << endl; - return false; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "KeyValueMap::get[QDate]: done." << endl; - date=temp; - return true; - } - // ########################################################################### -} - -// (^^^ QDates) -// Section class: - -const int Section::indent_width=2; - -Section::Section() -{ - // ########################################################################### - // ########################################################################### -} - -Section::Section(const KeyValueMap& contents) -{ - // ########################################################################### - keys=contents; - // ########################################################################### -} - -bool -Section::add(const TQCString& name) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::add: adding section \"" - <save(stream, level+1)) - { - kdDebug() << "Section::save: error saving child section \"" << (*pos).first.data() << "\"." << endl; - return false; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::save: saved section \"" - << (*pos).first - << "\".\n"; - } - insertIndentSpace(stream, level); - stream << "[END " << (*pos).first << ']' << endl; - } - if(!keys.empty()) - { - insertIndentSpace(stream, level); - stream << "# key-value-pairs:" << endl; - if(!keys.save(stream, level*indent_width)) - { - kdDebug() << "Section::save: error saving key-value-pairs." << endl; - return false; - } - } - // ----- - return true; - // ########################################################################### -} - -bool -Section::readSection(TQTextStream& file, bool finish) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::readSection: reading section." << endl; - TQCString line; - TQCString name; - Section* temp; - // ----- - for(;;) - { - line=""; - line=ReadLineFromStream(file); - if(isEndOfSection(line)) - { // ----- eof does not matter: - return true; - } else { // ----- verify it: - if(file.eof()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "Section::readSection: EOF, line is \""<readSection(file)) - { - kdDebug() << "Section::readSection: unable to read " - "subsection \"" << name << "\".\n"; - return false; - } - } else { // ----- it has to be a key-value-pair: - if(!keys.insertLine(line, false, true, false)) - { - kdWarning() << "Attention: unable to parse key-value-pair " << endl - << "\t\"" << line << "\"," << endl - << "ignoring and continuing (maybe duplicate declaration of" - << " the key)." - << endl; - } - } - } - // ########################################################################### -} - -bool -Section::isBeginOfSection(TQCString line) -{ - bool GUARD; GUARD=false; - // ########################################################################### - line=line.simplifyWhiteSpace(); - if(line.isEmpty() || line.length()<2) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isBeginOfSection: too short " - "or empty line." << endl; - return false; - } - if(line[0]!='[' || line[line.length()-1]!=']') - { - return false; - } - // ----- - if(line.contains("END")) - { - return false; - } else { - return true; - } - // ########################################################################### -} - -bool -Section::isEndOfSection(TQCString line) -{ - bool GUARD; GUARD=false; - // ########################################################################### - kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isEndOfSection: is " - << line <<" the end of" - " a section?" << endl; - int first=1, second; - TQCString temp; - // ----- - line=line.simplifyWhiteSpace(); - if(line.isEmpty() || line.length()<2) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isBeginOfSection: too short " - "or empty line." << endl; - return false; - } - if(line[0]!='[' || line[line.length()-1]!=']') - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "Section::isBeginOfSection: does not match." << endl; - return false; - } - // ----- find the word inside the brackets: - for(first=1; line[first]==' '; ++first); // find first non-whitespace character - for(second=first; line[second]!=' ' && line[second]!=']'; ++second); - temp=line.mid(first, second-first); - if(temp=="END") - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "Section::isBeginOfSection: yes, it is." << endl; - return true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "Section::isBeginOfSection: no, it is not." << endl; - return false; - } - // ########################################################################### -} - -TQCString -Section::nameOfSection(const TQCString& line) -{ - bool GUARD; GUARD=false; - // ########################################################################### - int first=1, second; - TQCString temp; - // ----- - temp=line.simplifyWhiteSpace(); - if(temp.isEmpty() || temp.length()<=2) - { // empty section names are not allowed - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "Section::isBeginOfSection: too short or empty line." << endl; - return ""; - } - if(temp[0]!='[' || temp[temp.length()-1]!=']') - { - return ""; - } - // ----- find the word inside the brackets: - for(first=1; temp[first]==' '; ++first); // find first non-whitespace character - for(second=first; temp[second]!=' ' && temp[second]!=']'; ++second); - temp=temp.mid(first, second-first); - if(temp=="END") - { - return ""; - } else { - return temp; - } - // ########################################################################### -} - -bool -Section::clear() -{ - // ########################################################################### - StringSectionMap::iterator pos; - // ----- - for(pos=sections.begin(); pos!=sections.end(); ++pos) - { - if(!(*pos).second->clear()) return false; - delete(*pos).second; - } - // sections.clear(); // seems to be not implemented - sections.erase(sections.begin(), sections.end()); - keys.clear(); - // ----- - return true; - // ########################################################################### -} - -bool -Section::empty() -{ - // ########################################################################### - return keys.empty() && sections.empty(); - // ########################################################################### -} - -Section::StringSectionMap::iterator -Section::sectionsBegin() -{ - // ########################################################################### - return sections.begin(); - // ########################################################################### -} - -Section::StringSectionMap::iterator -Section::sectionsEnd() -{ - // ########################################################################### - return sections.end(); - // ########################################################################### -} - -unsigned int -Section::noOfSections() -{ - // ########################################################################### - return sections.size(); - // ########################################################################### -} - -QConfigDB::QConfigDB(TQWidget* parent, const char* name) - : TQWidget(parent, name), - timer(0), - readonly(true), - locked(false), - mtime(new TQDateTime) -{ - // ########################################################################### - hide(); - // ########################################################################### -} - - -QConfigDB::~QConfigDB() -{ - // ############################################################################ - // disconnect(); - // ----- - if(timer!=0) - { - delete timer; timer=0; - } - if(!clear()) // this will emit changed() a last time - { - kdDebug() << "QConfigDB destructor: cannot remove me." << endl; - } - if(locked) - { - unlock(); - } - // ############################################################################ -} - -bool QConfigDB::invariant() -{ - return true; -} - -bool -QConfigDB::get(const list& key, KeyValueMap*& map) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::get: trying to get keys ... " << endl; - Section* section=⊤ - list::const_iterator pos; - // ----- - if(key.empty()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "ConfigDB::get: path is empty, returning toplevel section." << endl; - map=top.getKeys(); - return true; - } - for(pos=key.begin(); pos!=key.end(); ++pos) - { - if(!section->find(*pos, section)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "failed,\n at least the element \"" - << *pos << - "\" of " - "the key-list is not declared." << endl; - return false; - } - } - // ----- - map=section->getKeys(); - kdDebug(GUARD, KAB_KDEBUG_AREA) << "success." << endl; - return true; - // ############################################################################ -} - -KeyValueMap* -QConfigDB::get() -{ - // ############################################################################ - return top.getKeys(); - // ############################################################################ -} - -bool -QConfigDB::createSection(const list& key) -{ - // ############################################################################ - Section* section=⊤ - unsigned int index; - list::const_iterator pos; - Section* thenewone; - bool rc; - // ----- - pos=key.begin(); - for(index=0; indexfind(*pos, section)) - { // this section is not declared - Section* temp=new Section; // WORK_TO_DO: memory hole? - if(section->add(*pos, temp)) - { - section=temp; - } else { - delete temp; - return false; - } - } - ++pos; - } - // pos now points to the last element of key, - // section to the parent of the section that will be inserted - thenewone=new Section; - rc=section->add(*pos, thenewone); - return rc; // missing error report! WORK_TO_DO - // ############################################################################ -} - -bool -QConfigDB::clear() -{ - // ############################################################################ - bool rc=top.clear(); - emit(changed(this)); - return rc; - // ############################################################################ -} - -bool -QConfigDB::empty() -{ - // ############################################################################ - return top.empty(); - // ############################################################################ -} - -bool -QConfigDB::createSection(const TQCString& desc) -{ - // ############################################################################ - return createSection(stringToKeylist(desc)); - // ############################################################################ -} - -bool -QConfigDB::get(const TQCString& key, KeyValueMap*& map) -{ - // ############################################################################ - return get(stringToKeylist(key), map); - // ############################################################################ -} - -list -QConfigDB::stringToKeylist(const TQCString& desc) -{ - bool GUARD; GUARD=false; - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::stringToKeylist: parsing path " << desc << endl; - // ############################################################################ - list key; - int first=0, second; - TQCString temp; - // ----- - if(desc.isEmpty()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::stringToKeylist: path is empty." << endl; - return key; - } - for(;;) - { - second=desc.find('/', first); - if(second==-1) - { - if((unsigned)first& key, Section*& section) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::get: searching section ... " << endl; - Section* temp=⊤ - list::const_iterator pos; - // ----- - for(pos=key.begin(); pos!=key.end(); ++pos) - { - if(!temp->find(*pos, temp)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "failure, no such section."; - return false; - } - } - // ----- - section=temp; - kdDebug(GUARD, KAB_KDEBUG_AREA) << "success, section found." << endl; - return true; - // ############################################################################ -} - -bool -QConfigDB::isRO() -{ - // ############################################################################ - return readonly; - // ############################################################################ -} - -int -QConfigDB::IsLocked(const TQString& file) -{ - bool GUARD; GUARD=false; - // ############################################################################ - TQString lockfile=file+".lock"; - int pid=-1; - // ----- - if(access(TQFile::encodeName(lockfile), F_OK)==0) - { - TQFile f(lockfile); - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file\n" - << file << - "\nhas a lockfile.\n"; - if(f.open(IO_ReadOnly)) - { - TQTextStream stream(&f); - stream.setEncoding(TQTextStream::Latin1); // no conversion - // ----- - stream >> pid; - if(pid==-1) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file " - "does not contain the ID\n of the process that " - "created it." << endl; - return -1; - } - f.close(); - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::IsLocked: cannot open the lockfile." << endl; - return -1; - } - return pid; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file\n" - << file << "\nhas no lockfile.\n"; - return 0; - } - // ############################################################################ -} - -bool -QConfigDB::lock() -{ - bool GUARD; GUARD=false; - // ############################################################################ - if(locked) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock (current file): file " - "is already locked by this object." << endl; - return false; - } - if(lock(filename)) - { - locked=true; - return true; - } else { - return false; - } - // ############################################################################ -} - -bool -QConfigDB::lock(const TQString& file) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: locking the file " - << file << endl; - TQString lockfile=file+".lock"; - TQFile f(lockfile); - // ----- - if(access(TQFile::encodeName(lockfile), F_OK)==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: the file is locked by" - " another process." << endl; - return false; - } else { - if(f.open(IO_WriteOnly)) - { - TQTextStream stream(&f); - stream.setEncoding(TQTextStream::Latin1); // no conversion - // ----- - stream << getpid() << endl; - f.close(); - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: unable to create" - " lockfile." << endl; - return false; - } - } - // ----- - LockFiles.push_back(lockfile); - return true; - // ############################################################################ -} - -bool -QConfigDB::unlock() -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: unlocking the file " - << filename << endl; - TQString lockfile=filename+".lock"; - list::iterator pos; - // ----- - if(!locked) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: this app did not " - "lock the file!" << endl; - return false; - } - if(access(TQFile::encodeName(lockfile), F_OK | W_OK)==0) - { - if(::remove(TQFile::encodeName(lockfile))==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::unlock: lockfile deleted." << endl; - for(pos=LockFiles.begin(); pos!=LockFiles.end(); ++pos) - { - if((*pos)==lockfile) break; - } - if(pos!=LockFiles.end()) - { - LockFiles.erase(pos); --pos; - } else { - kdDebug() << "QConfigDB::unlock: file not mentioned in lockfile" << endl; - } - locked=false; - return true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: unable to " - "delete lockfile.n" << endl; - return false; - } - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: the file is not" - " locked or permission has been denied." << endl; - return false; - } - // ############################################################################ -} - -void -QConfigDB::CleanLockFiles(int) -{ - bool GUARD; GUARD=false; - // ############################################################################ - list::iterator pos; - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA).form("QConfigDB::CleanLockFiles: removing %i " - "remaining lockfiles.", LockFiles.size()) << endl; - for(pos=LockFiles.begin(); pos!=LockFiles.end(); ++pos) - { - if(::remove(TQFile::encodeName(*pos))==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - " " << *pos << " removed.\n"; - LockFiles.erase(pos); --pos; - } else { - kdDebug() << " could not remove " << *pos << endl; - } - } - // ----- - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CleanLockFiles: done." << endl; - // ############################################################################ -} - -void -QConfigDB::watch(bool state) -{ - // ############################################################################ - if(state) - { // start timer - if(timer==0) - { - timer=new TQTimer(this); - connect(timer, TQT_SIGNAL(timeout()), TQT_SLOT(checkFileChanged())); - } - timer->start(1000); - } else { // stop timer - if(timer!=0) - { - timer->stop(); - } - } - // ############################################################################ -} - -bool -QConfigDB::CheckLockFile(const TQString& file) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: called." << endl; - int pid; - // ----- - pid=IsLocked(file); - if(pid==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: the file is " - "not locked." << endl; - return false; - } - if(pid>0) - { - if(kill(pid, 0)!=0) - { // ----- no such process, we may remove the lockfile: - return false; - } - } - if(pid<0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: the file has " - "not been created by QConfigDB::lock." << endl; - } - // ----- check system time and creation time of lockfile: - // WORK_TO_DO: not implemented - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: done." << endl; - return true; - // ############################################################################ -} - -bool -QConfigDB::checkFileChanged() -{ - bool GUARD; GUARD=false; - // ############################################################################ - // kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: called." << endl; - if(filename.isEmpty()) - { // ----- false, as file does not exist and thus may be stored anyway - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: no filename." << endl; - return false; - } - TQFileInfo file(filename); - // ----- - if(file.exists()) - { - if(file.lastModified() > *mtime) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::checkFileChanged: file has been changed.n" << endl; - emit(fileChanged()); - return true; - } else { - return false; - } - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: could " - "not stat file, file does not exist." << endl; - if(!mtime->isValid()) - { // the file did never exist for us: - return false; // ... so it has not changed - } else { // it existed, and now it does no more - emit(fileChanged()); - return true; - } - } - // ############################################################################ -} - -bool -QConfigDB::storeFileAge() -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::storeFileAge: called." << endl; - TQFileInfo file(filename); - // ----- - if(file.exists()) - { - *mtime=file.lastModified(); - return true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::save: could not stat file." << endl; - *mtime=TQDateTime(); // a null date - return false; - } - // ############################################################################ -} - - -bool -QConfigDB::setFileName(const TQString& filename_, bool mustexist, bool readonly_) -{ - bool GUARD; GUARD=false; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: setting filename " - "to \"" - << filename_ <<"\"" << (readonly_ ? " (read only)" : "") << endl; - // ----- remove previous lock: - if(locked) - { - if(!unlock()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: cannot " - "release previous lock." << endl; - return false; - } - } - // ----- remove possible stale lockfile: - if(IsLocked(filename_)!=0 && !CheckLockFile(filename_)) - { // ----- it is stale: - if(::remove(TQFile::encodeName(filename_+".lock"))==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::setFileName: removed stale lockfile." << endl; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::setFileName: cannot remove stale lockfile." << endl; - return false; - } - } - // ----- - if(mustexist) - { - if(access(TQFile::encodeName(filename_), readonly_==true ? R_OK : W_OK | R_OK)==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::setFileName: permission granted." << endl; - if(!readonly_) - { // we need r/w access: - if(lock(filename_)) - { - locked=true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: " - "could not lock the file." << endl; - return false; - } - } - readonly=readonly_; - filename=filename_; - storeFileAge(); - return true; - } else { - kdDebug() << "QConfigDB::setFileName: permission denied, " << endl; - return false; - } - } else { - if(access(TQFile::encodeName(filename_), F_OK)==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: file exists." << endl; - if(access(TQFile::encodeName(filename_), W_OK | R_OK)==0) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::setFileName: permission granted." << endl; - if(!readonly_) - { // we need r/w access: - if(lock(filename_)) - { - locked=true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: " - "could not lock the file." << endl; - return false; - } - } - readonly=readonly_; - filename=filename_; - storeFileAge(); - return true; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: " - "permission denied, filename not set." << endl; - return false; - } - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::setFileName: permission granted, new file." << endl; - readonly=readonly_; - filename=filename_; - if(!readonly) - { - if(!lock()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::setFileName: could not lock the file." << endl; - return false; - } - } - storeFileAge(); - return true; - } - } - // ############################################################################ -} - -TQString -QConfigDB::fileName() -{ - // ############################################################################ - return filename; - // ############################################################################ -} - -bool -QConfigDB::save(const char* header, bool force) -{ - bool GUARD; GUARD=true; - // ############################################################################ - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: saving database -->" << filename << "<--.\n"; - bool wasRO=false; - bool rc; - // ----- - if(checkFileChanged()) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: file is newer, not saving." << endl; - return false; - } - if(force && isRO()) - { - if(setFileName(fileName(), true, false)) - { - wasRO=true; - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: switched to (forced) r/w mode." << endl; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: cannot switch to (forced) r/w mode." << endl; - return false; - } - } - // ----- now save it: - if(!isRO()) - { - TQFile file(filename); - if(file.open(IO_WriteOnly)) - { - TQTextStream stream(&file); - stream.setEncoding(TQTextStream::Latin1); // no conversion - // ----- - if(header!=0) - { - stream << "# " << header << endl; - } - stream << '#' << " [File created by QConfigDB object " - << version() << "]" << endl; - if(!top.save(stream)) // traverse tree - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: error saving subsections." << endl; - } - storeFileAge(); - file.close(); - rc=true; - } else { - kdDebug() << "QConfigDB::save: error opening file \"" - << filename << - "\" for writing.\n"; - rc=false; - } - } else { - rc=false; - } - // ----- reset r/o mode: - if(wasRO) // only true if we switched to forced r/w mode here - { - if(setFileName(fileName(), false, true)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: reset (forced) r/w mode." << endl; - } else { - kdDebug(GUARD, KAB_KDEBUG_AREA) << - "QConfigDB::save: cannot reset (forced) r/w mode." << endl; - rc=false; - } - } - // ----- - return rc; - // ############################################################################ -} - -bool -QConfigDB::load() -{ - bool GUARD; GUARD=false ; - // ############################################################################ - TQFile file(filename); - // ----- - if(file.open(IO_ReadOnly)) - { - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::load: file access OK." << endl; - TQTextStream stream(&file); - stream.setEncoding(TQTextStream::Latin1); // no conversion - // ----- - clear(); - bool rc=top.readSection(stream, false); - storeFileAge(); - file.close(); - emit(changed(this)); - kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::load: done." << endl; - return rc; - } else { - kdDebug() << "QConfigDB::load: error opening file \"" << filename << "\" for reading." << endl; - return false; - } - // ############################################################################ -} diff --git a/kab/qconfigDB.cpp b/kab/qconfigDB.cpp new file mode 100644 index 000000000..dc77a1e1b --- /dev/null +++ b/kab/qconfigDB.cpp @@ -0,0 +1,2547 @@ +/* the Configuration Database library, Version II + + the TDE addressbook + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2001, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org $ + $ License: GPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ +*/ + +#include "qconfigDB.h" +// #include "debug.h" + +extern "C" { +#include +#include +#include +#include +#include +} + +// #include +#include +#include +#include +#include +#include + +#include "qconfigDB.moc" +#include + +#ifdef KAB_KDEBUG_AREA +#undef KAB_KDEBUG_AREA +#endif + +#define KAB_KDEBUG_AREA 800 + +static bool isComment(TQCString line) +{ + // ############################################################################ + line=line.stripWhiteSpace(); + if(line.isEmpty()) + { + return false; // line is empty but not a comment + } else { + return(line[0]=='#'); + } + // ############################################################################ +} + +static void tokenize(list& res, const TQCString& text, char tr, bool strict=false) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: called." << endl; + int eins=0, zwei=0; + TQCString teil; + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: partening -->%" << text.data() << "<--." << endl; + res.erase(res.begin(), res.end()); + // ----- + if(text.isEmpty()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "tokenize: text is an empty string, done." << endl; + return; + } + while(zwei!=-1) + { + teil=""; + zwei=text.find(tr, eins); + if(zwei!=-1) + { + teil=text.mid(eins, zwei-eins); + res.push_back(teil); + } else { // last element + if(!strict) // nur wenn dazwischen Zeichen sind + { + teil=text.mid(eins, text.length()-eins); + res.push_back(teil); + } + } + eins=zwei+1; + // if((unsigned)eins>=text.length()) break; + } + kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: partened in " + << res.size() << " parts.\n"; + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "tokenize: done." << endl; + // ############################################################################ +} + +// TQCString AuthorEmailAddress; // assign your email address to this string + +static TQCString ReadLineFromStream(TQTextStream& stream) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "ReadLineFromStream:: reading line." << endl; + TQCString line; + // ----- + while(!stream.eof()) + { + line=stream.readLine().ascii(); + if(!line.isEmpty()) + { + if(isComment(line)) + { + line=""; + continue; + } + } + break; + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "ReadLineFromStream:: line \"" << line.data() << "\" read.\n"; + return line; + // ############################################################################ +} + +// class implementations: + +list QConfigDB::LockFiles; // the lockfiles created by this session + +KeyValueMap::KeyValueMap() + : data(new StringStringMap) +{ + // ########################################################################### + // ########################################################################### +} + +KeyValueMap::KeyValueMap(const KeyValueMap& orig) + : data(new StringStringMap(*orig.data)) +{ + // ########################################################################### + // ########################################################################### +} + +KeyValueMap::~KeyValueMap() +{ + // ########################################################################### + delete data; + // ########################################################################### +} + +bool KeyValueMap::invariant() +{ + return true; +} + +StringStringMap::iterator KeyValueMap::begin() +{ + return data->begin(); +} + +StringStringMap::iterator KeyValueMap::end() +{ + return data->end(); +} + +unsigned int +KeyValueMap::size() const +{ + // ########################################################################### + return data->size(); + // ########################################################################### +} + +void +KeyValueMap::clear() +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::clear: erasing map contents ... " << endl; + // ----- + if(!data->empty()) // erase fails on empty containers! + { + data->erase(data->begin(), data->end()); + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "done." << endl; + // ########################################################################### +} + +bool +KeyValueMap::fill(const TQString& filename, bool force, bool relax) +{ + bool GUARD; GUARD=false; + // ########################################################################### + TQFile file(filename); + TQCString line; + // ----- + if(file.open(IO_ReadOnly)) + { + TQTextStream stream(&file); + // We read/write utf8 strings, so we don't want that TQTextStream uses local8bit + // Latin1 means : no conversion, when giving char*s to a TQTextStream. (DF) + stream.setEncoding(TQTextStream::Latin1); + // ----- + while(!stream.eof()) + { + line=stream.readLine().ascii(); + if(!line.isEmpty() /* && !stream.eof() */ && !isComment(line)) + { + if(!insertLine(line, force, relax, false)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::fill: could not insert line " + << line << ".\n"; // ignore this case further + } + } + } + file.close(); + // ----- + return true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::fill: cannot open file " << + filename << endl; + return false; + } + // ########################################################################### +} + +bool +KeyValueMap::save(const TQString& filename, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::save: saving data to -->" << + filename << "<--.\n"; + StringStringMap::iterator pos; + TQFile file(filename); + // ----- open file, regarding existence: + if(!force) + { + if(file.exists()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::save: file exists but may not." << endl; + return false; + } + } + if(file.open(IO_WriteOnly)) + { + TQTextStream stream(&file); + stream.setEncoding(TQTextStream::Latin1); // no conversion + stream << "# saved by KeyValueMap object ($Revision$)" << endl; + for(pos=data->begin(); pos!=data->end(); ++pos) + { // values do not get coded here + stream << (*pos).first << '=' << (*pos).second << endl; + } + file.close(); + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::save: could not open file -->%s<-- for saving." << + filename.utf8() << endl; + return false; + } + // ########################################################################### + return true; +} + +bool +KeyValueMap::save(TQTextStream& file, int count) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::save: saving data to given output stream." << endl; + StringStringMap::iterator pos; + bool ret=true; + char* prefix=new char[count+1]; + memset(prefix, ' ', count); + prefix[count]=0; + // ----- + for(pos=data->begin(); pos!=data->end(); ++pos) + { + file << prefix << (*pos).first << '=' << (*pos).second << endl; + } + delete [] prefix; + // ----- + return ret; + // ########################################################################### +} + + +bool +KeyValueMap::erase(const TQCString& key) +{ + // ########################################################################### + bool rc=(data->erase(key)>0); + return rc; + // ########################################################################### +} + + +bool +KeyValueMap::empty() +{ + // ########################################################################### + return data->empty(); + // ########################################################################### +} + +bool +KeyValueMap::parseComplexString +(const TQCString& orig, + int index, // first char to parse + TQCString& result, // string without leading and trailing ".." + int& noOfChars) // no of chars that represented the + const // complex string in the original +{ + bool GUARD; GUARD=false; + // ########################################################################### + int first; + TQCString temp(2*orig.length()); + TQCString mod; + int count=1; + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::parseComplexString: parsing the string -->" + << orig << "<--.\n"; + // ----- + if(orig.isEmpty()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::parseComplexString: string is empty.\n" + " " + "This is no valid complex string." << endl; + return false; + } + // ----- prepare the string: + temp=orig.mid(index, orig.length()-index); // remove everything before index + mod=temp.stripWhiteSpace(); // remove leading and trailing white spaces + // ----- test some conditions: + if(mod.length()<2) + { + kdDebug() << "KeyValueMap::parseComplexString: no pair of brackets " << endl; + return false; + } + if(mod[0]!='"') + { + kdDebug() << "KeyValueMap::parseComplexString: no opening bracket." << endl; + return false; + } + // ----- now parse it: + first=1; // first character after opening bracket + temp=""; + for(;;) + { + if(mod[first]=='\\') + { // handle special characters + ++first; + kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::parseComplexString: found " + "a special character \"%c\".", mod[first]) << endl; + if((unsigned)first==mod.length()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::parseComplexString: " + "string lacks the closing \".\n " + " This is no valid " + "complex string." << endl; + return false; + } + switch(mod[first]) + { + case 't': temp+='\t'; break; + case 'n': temp+='\n'; break; + case '"': temp+='"'; break; + case 'e': temp+="\\e"; break; + case '\\': temp+='\\'; break; + default: + // WORK_TO_DO: implement octal coding here! + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::parseComplexString: " + "invalid control character.\n " + " This is no valid complex string." << endl; + return false; + } + count+=2; // this took 2 characters + ++first; + } else { // it is a character + ++count; + if(mod[first]=='"') // end of coded string? + { + break; + } + temp+=mod[first]; + ++first; + } + if((unsigned)first>=mod.length()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::parseComplexString: " + "string lacks the closing \".\n " + " This is no valid complex string.\n"; + return false; + } + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA).form( + "KeyValueMap::parseComplexString: finished parsing, no errors, " + "%i characters, %i in string.", count, temp.length()) << endl; + noOfChars=count; + result=temp; + // ########################################################################### + return true; +} + +TQCString +KeyValueMap::makeComplexString(const TQCString& orig) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::makeComplexString: coding the string\n -->" + << orig << + "<--\n into a complex string.\n"; + TQCString temp(2*orig.length()); + unsigned int count; + // ----- + temp+='"'; // opening bracket + for(count=0; count" + <find(key); + // ----- + if(pos==data->end()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "not in KeyValueMap." << endl; + return false; + } else { + value=(*pos).second; + kdDebug(GUARD, KAB_KDEBUG_AREA) << "in KeyValueMap, value is " + << value << endl; + return true; + } + // ########################################################################### +} + +bool +KeyValueMap::insertRaw(const TQCString& key, const TQCString& value, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::insertRaw: inserting uncoded value " + << value << + " for key " << key << endl; + int n=0; + // ----- + if(key.isEmpty()) // empty KEYS are errors: + { + kdDebug() << "KeyValueMap::insertRaw: tried to insert empty key." << endl; + return false; + } + if(force) // entry will be replaced + { + n=data->erase(key); + } + if(data->insert(StringStringMap::value_type(key, value)).second) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertRaw: success" + << (n==0 ? "" : " (forced)") << endl; + return true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insertRaw: failed, " + "key already in KeyValueMap." << endl; + return false; + } + // ########################################################################### +} + + +// ----------------------------------------------------------------------------- +// HUGE SEPARATOR BETWEEN INTERNAL LOGIC AND EXTENDABLE PAIRS OF GET- AND INSERT +// -METHODS. +// EXTENDABLE MEANS: OTHER DATATYPES CAN BE ADDED HERE. +// ----------------------------------------------------------------------------- + +/* The following functions are the pairs of insert-get-methods for different + * data types. See keyvaluemap.h for the declarations. */ + +// ascii strings: + +bool +KeyValueMap::insert(const TQCString& key, const TQCString& value, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::insert: inserting value\n -->" + << value << + "<-- \"" + " for key\n -->" + << key << + "<--.\n"; + return insertRaw(key, makeComplexString(value), force); + // ########################################################################### +} + +/* Attention: + * This is another insert function that partens lines like "key=value"! + * It is used for reading files and command line parameters easily. + */ + +bool +KeyValueMap::insertLine(TQCString line, bool force, bool relax, bool encode) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::insertLine: inserting line -->"<& values, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int list]: trying to " + "insert int list into map." << endl; + TQCString temp; + TQCString value; + list::const_iterator pos; + // ----- + for(pos=values.begin(); pos!=values.end(); ++pos) + { + temp.setNum(*pos); + value=value+temp+", "; + } + if(!value.isEmpty()) + { // remove last comma and space: + value.remove(value.length()-2, 2); + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[int list]: " + "constructed string value is " << value << endl; + return insert(key, value, force); + // ########################################################################### +} + +bool +KeyValueMap::get(const TQCString& key, list& values) const +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: trying to " + "decode int list for key " << key << endl; + kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: " + "attention - list should be empty but is not.\n"; + TQCString value; + list tokens; + list::iterator pos; + int temp; + bool ok; + // ----- + if(!get(key, value)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[int list]: no such key." << endl; + return false; + } + tokenize(tokens, value, ','); + if(tokens.empty()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[int list]: no tokens." << endl; + return false; + } + // ----- + for(pos=tokens.begin(); pos!=tokens.end(); ++pos) + { + temp=(*pos).toInt(&ok); + if(ok) + { + values.push_back(temp); + } else { + kdDebug() << "KeyValueMap::get[int list]: conversion error for " << *pos << endl; + } + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[long int list]: done." << endl; + // ########################################################################### + return true; +} + +// (^^^ int lists) +// doubles: + +bool +KeyValueMap::insert(const TQCString& key, const double& value, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA).form("KeyValueMap::insert[double]: trying to " + "insert value \"%f\" for key\n -->", value) << key << "<--.\n"; + TQCString temp; + // ----- + temp.setNum(value); + return insert(key, temp, force); + // ########################################################################### +} + +bool +KeyValueMap::get(const TQCString& key, double& value) const +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[double]: trying to get " + "FLOAT value for key " << key << endl; + TQCString v; + bool ok; + double temp; + // ----- + if(!get(key, v)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int]: key " + <& values) const +{ + bool GUARD; GUARD=false; + kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[string list]: " + "attention!\n \"values\" list reference is not " + "empty!" << endl; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[string list]: trying to " + "decode string list for key " << key << endl; + TQCString raw, part, value; + int first=1, second=1, i; + // ----- get the string value as a whole: + if(!getRaw(key, raw)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[list]: key " + << key << " not in KeyValueMap." << endl; + return false; + } + // ----- + for(;;) + { // ----- parten the string down into a list, find special characters: + second=first; + for(;;) + { + second=raw.find('\\', second); + // ----- this may never be the last and also not the second last + // character in a complex string: + if(second!=-1) + { // ----- check for string end: + // we use "\e" as token for the string-delimiter + if(raw[second+1]=='e' // the right character + && raw[second-1]!='\\') // not escaped + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get" + "[list]: found string end at pos " << + second << endl; + break; + } else { + ++second; + } + } else { + break; + } + } + if(second!=-1) + { + // ----- now second points to the end of the substring: + part="\""+raw.mid(first, second-first)+"\""; + // ----- insert decoded value into the list: + if(parseComplexString(part, 0, value, i)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get" + "[list]: found item " << value << endl; + values.push_back(value); + } else { + kdDebug() << "KeyValueMap::get[list]: parse error." << endl; + return false; + } + if((unsigned)second]: list end found." << endl; + break; + } + } else { // ----- finished: + break; + } + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[list]: done." << endl; + return true; + // ########################################################################### +} + +bool +KeyValueMap::insert(const TQCString& key, const list& values, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[string list]: " + "coding string list." << endl; + TQCString value="\""; + TQCString temp; + list::const_iterator pos; + // ----- create coded string list: + for(pos=values.begin(); + pos!=values.end(); + pos++) + { // create strings like "abc\efgh\eijk": + temp=makeComplexString(*pos); + temp.remove(0, 1); // remove the leading "\"" + temp.remove(temp.length()-1, 1); // the trailing "\"" + value+=temp; + value+="\\e"; + } + value+="\""; // finish the string + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[string list]: result " + "of coding is " << value << endl; + // ----- insert it without coding: + return insertRaw(key, value, force); + // ########################################################################### +} + +// (^^^ lists of strings) +// QStrList-s: + +bool +KeyValueMap::get(const TQCString& key, TQStrList& values) const +{ + bool GUARD; GUARD=false; + kdDebug(!values.isEmpty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: " + "attention!\n \"values\" list reference is not " + "empty!" << endl; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: trying to " + "decode string list for key " << key << endl; + TQCString raw, part, value; + int first=1, second=1, i; + // ----- get the string value as a whole: + if(!getRaw(key, raw)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: key " + << key <<" not in KeyValueMap." << endl; + return false; + } + // ----- + for(;;) + { // ----- parten the string down into a list, find special characters: + second=first; + for(;;) + { + second=raw.find('\\', second); + // ----- this may never be the last and also not the second last + // character in a complex string: + if(second!=-1) + { // ----- check for string end: + // we use "\e" as token for the string-delimiter + if(raw[second+1]=='e' // the right character + && raw[second-1]!='\\') // not escaped + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]:" + " found string end at pos %i." << second << endl; + break; + } else { + ++second; + } + } else { + break; + } + } + if(second!=-1) + { + // ----- now second points to the end of the substring: + part="\""+raw.mid(first, second-first)+"\""; + // ----- insert decoded value into the list: + if(parseComplexString(part, 0, value, i)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QStrList]: " + "found item " << value << endl; + values.append(value); + } else { + kdDebug() << "KeyValueMap::get[QStrList]: parse error." << endl; + return false; + } + if((unsigned)second& values, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[double list]: trying " + "to insert double list into map." << endl; + TQCString buffer; + // TQCString value(30*values.size()); // not usable with Qt 2 + TQCString value; // WORK_TO_DO: how to reserve enough space to avoid growing? + list::const_iterator pos; + // ----- + for(pos=values.begin(); pos!=values.end(); ++pos) + { + buffer.setNum(*pos); + value=value+buffer+", "; + } + if(!value.isEmpty()) + { // remove last comma and space: + value.remove(value.length()-2, 2); + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[double list]: " + "constructed string value is " << value << endl; + return insert(key, value, force); + // ########################################################################### +} + +bool +KeyValueMap::get(const TQCString& key, list& values) const +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[double list]: trying to " + "decode double list for key " << key << endl; + kdDebug(!values.empty(), KAB_KDEBUG_AREA) << "KeyValueMap::get[double list]: " + "attention - list should be empty but is not." << endl; + TQCString value; + list tokens; + list::iterator pos; + double temp; + bool ok; + // ----- + if(!get(key, value)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[double list]: no such key." << endl; + return false; + } + // ----- + tokenize(tokens, value, ','); + for(pos=tokens.begin(); pos!=tokens.end(); ++pos) + { + temp=(*pos).toDouble(&ok); + if(ok) + { + values.push_back(temp); + } else { + kdDebug() << "KeyValueMap::get[double list]: conversion error for " + << *pos << endl; + } + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[int list]: done." << endl; + // ########################################################################### + return true; +} + +// (^^^ lists of doubles) +// QDates: + +bool +KeyValueMap::insert(const TQCString& key, const TQDate& value, bool force) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QDate]: trying to " + "insert TQDate into map." << endl; + list values; + // ----- + if(!value.isValid()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::insert[QDate]: invalid " + "date, inserting a null date." << endl; + for(int i=0; i<3; ++i) values.push_back(0); + } else { + values.push_back(value.year()); + values.push_back(value.month()); + values.push_back(value.day()); + } + // ----- + return insert(key, values, force); + // ########################################################################### +} + +bool +KeyValueMap::get(const TQCString& key, TQDate& date) const +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "KeyValueMap::get[QDate]: trying to decode" + " TQDate for key " << key << endl; + list values; + long y, m, d; + TQDate temp; + // ----- + if(!get(key, values)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[QDate]: no such key." << endl; + return false; + } + if(values.size()!=3) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[QDate]: more or less than 3 values." << endl; + return false; + } + y=values.front(); values.pop_front(); + m=values.front(); values.pop_front(); + d=values.front(); + // ----- + if(y!=0 || m!=0 || d!=0) temp.setYMD(y, m, d); // avoid TQDate messages + if(!temp.isValid() && !temp.isNull()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[QDate]: no valid date." << endl; + return false; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "KeyValueMap::get[QDate]: done." << endl; + date=temp; + return true; + } + // ########################################################################### +} + +// (^^^ QDates) +// Section class: + +const int Section::indent_width=2; + +Section::Section() +{ + // ########################################################################### + // ########################################################################### +} + +Section::Section(const KeyValueMap& contents) +{ + // ########################################################################### + keys=contents; + // ########################################################################### +} + +bool +Section::add(const TQCString& name) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::add: adding section \"" + <save(stream, level+1)) + { + kdDebug() << "Section::save: error saving child section \"" << (*pos).first.data() << "\"." << endl; + return false; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::save: saved section \"" + << (*pos).first + << "\".\n"; + } + insertIndentSpace(stream, level); + stream << "[END " << (*pos).first << ']' << endl; + } + if(!keys.empty()) + { + insertIndentSpace(stream, level); + stream << "# key-value-pairs:" << endl; + if(!keys.save(stream, level*indent_width)) + { + kdDebug() << "Section::save: error saving key-value-pairs." << endl; + return false; + } + } + // ----- + return true; + // ########################################################################### +} + +bool +Section::readSection(TQTextStream& file, bool finish) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::readSection: reading section." << endl; + TQCString line; + TQCString name; + Section* temp; + // ----- + for(;;) + { + line=""; + line=ReadLineFromStream(file); + if(isEndOfSection(line)) + { // ----- eof does not matter: + return true; + } else { // ----- verify it: + if(file.eof()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "Section::readSection: EOF, line is \""<readSection(file)) + { + kdDebug() << "Section::readSection: unable to read " + "subsection \"" << name << "\".\n"; + return false; + } + } else { // ----- it has to be a key-value-pair: + if(!keys.insertLine(line, false, true, false)) + { + kdWarning() << "Attention: unable to parse key-value-pair " << endl + << "\t\"" << line << "\"," << endl + << "ignoring and continuing (maybe duplicate declaration of" + << " the key)." + << endl; + } + } + } + // ########################################################################### +} + +bool +Section::isBeginOfSection(TQCString line) +{ + bool GUARD; GUARD=false; + // ########################################################################### + line=line.simplifyWhiteSpace(); + if(line.isEmpty() || line.length()<2) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isBeginOfSection: too short " + "or empty line." << endl; + return false; + } + if(line[0]!='[' || line[line.length()-1]!=']') + { + return false; + } + // ----- + if(line.contains("END")) + { + return false; + } else { + return true; + } + // ########################################################################### +} + +bool +Section::isEndOfSection(TQCString line) +{ + bool GUARD; GUARD=false; + // ########################################################################### + kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isEndOfSection: is " + << line <<" the end of" + " a section?" << endl; + int first=1, second; + TQCString temp; + // ----- + line=line.simplifyWhiteSpace(); + if(line.isEmpty() || line.length()<2) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "Section::isBeginOfSection: too short " + "or empty line." << endl; + return false; + } + if(line[0]!='[' || line[line.length()-1]!=']') + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "Section::isBeginOfSection: does not match." << endl; + return false; + } + // ----- find the word inside the brackets: + for(first=1; line[first]==' '; ++first); // find first non-whitespace character + for(second=first; line[second]!=' ' && line[second]!=']'; ++second); + temp=line.mid(first, second-first); + if(temp=="END") + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "Section::isBeginOfSection: yes, it is." << endl; + return true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "Section::isBeginOfSection: no, it is not." << endl; + return false; + } + // ########################################################################### +} + +TQCString +Section::nameOfSection(const TQCString& line) +{ + bool GUARD; GUARD=false; + // ########################################################################### + int first=1, second; + TQCString temp; + // ----- + temp=line.simplifyWhiteSpace(); + if(temp.isEmpty() || temp.length()<=2) + { // empty section names are not allowed + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "Section::isBeginOfSection: too short or empty line." << endl; + return ""; + } + if(temp[0]!='[' || temp[temp.length()-1]!=']') + { + return ""; + } + // ----- find the word inside the brackets: + for(first=1; temp[first]==' '; ++first); // find first non-whitespace character + for(second=first; temp[second]!=' ' && temp[second]!=']'; ++second); + temp=temp.mid(first, second-first); + if(temp=="END") + { + return ""; + } else { + return temp; + } + // ########################################################################### +} + +bool +Section::clear() +{ + // ########################################################################### + StringSectionMap::iterator pos; + // ----- + for(pos=sections.begin(); pos!=sections.end(); ++pos) + { + if(!(*pos).second->clear()) return false; + delete(*pos).second; + } + // sections.clear(); // seems to be not implemented + sections.erase(sections.begin(), sections.end()); + keys.clear(); + // ----- + return true; + // ########################################################################### +} + +bool +Section::empty() +{ + // ########################################################################### + return keys.empty() && sections.empty(); + // ########################################################################### +} + +Section::StringSectionMap::iterator +Section::sectionsBegin() +{ + // ########################################################################### + return sections.begin(); + // ########################################################################### +} + +Section::StringSectionMap::iterator +Section::sectionsEnd() +{ + // ########################################################################### + return sections.end(); + // ########################################################################### +} + +unsigned int +Section::noOfSections() +{ + // ########################################################################### + return sections.size(); + // ########################################################################### +} + +QConfigDB::QConfigDB(TQWidget* parent, const char* name) + : TQWidget(parent, name), + timer(0), + readonly(true), + locked(false), + mtime(new TQDateTime) +{ + // ########################################################################### + hide(); + // ########################################################################### +} + + +QConfigDB::~QConfigDB() +{ + // ############################################################################ + // disconnect(); + // ----- + if(timer!=0) + { + delete timer; timer=0; + } + if(!clear()) // this will emit changed() a last time + { + kdDebug() << "QConfigDB destructor: cannot remove me." << endl; + } + if(locked) + { + unlock(); + } + // ############################################################################ +} + +bool QConfigDB::invariant() +{ + return true; +} + +bool +QConfigDB::get(const list& key, KeyValueMap*& map) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::get: trying to get keys ... " << endl; + Section* section=⊤ + list::const_iterator pos; + // ----- + if(key.empty()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "ConfigDB::get: path is empty, returning toplevel section." << endl; + map=top.getKeys(); + return true; + } + for(pos=key.begin(); pos!=key.end(); ++pos) + { + if(!section->find(*pos, section)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "failed,\n at least the element \"" + << *pos << + "\" of " + "the key-list is not declared." << endl; + return false; + } + } + // ----- + map=section->getKeys(); + kdDebug(GUARD, KAB_KDEBUG_AREA) << "success." << endl; + return true; + // ############################################################################ +} + +KeyValueMap* +QConfigDB::get() +{ + // ############################################################################ + return top.getKeys(); + // ############################################################################ +} + +bool +QConfigDB::createSection(const list& key) +{ + // ############################################################################ + Section* section=⊤ + unsigned int index; + list::const_iterator pos; + Section* thenewone; + bool rc; + // ----- + pos=key.begin(); + for(index=0; indexfind(*pos, section)) + { // this section is not declared + Section* temp=new Section; // WORK_TO_DO: memory hole? + if(section->add(*pos, temp)) + { + section=temp; + } else { + delete temp; + return false; + } + } + ++pos; + } + // pos now points to the last element of key, + // section to the parent of the section that will be inserted + thenewone=new Section; + rc=section->add(*pos, thenewone); + return rc; // missing error report! WORK_TO_DO + // ############################################################################ +} + +bool +QConfigDB::clear() +{ + // ############################################################################ + bool rc=top.clear(); + emit(changed(this)); + return rc; + // ############################################################################ +} + +bool +QConfigDB::empty() +{ + // ############################################################################ + return top.empty(); + // ############################################################################ +} + +bool +QConfigDB::createSection(const TQCString& desc) +{ + // ############################################################################ + return createSection(stringToKeylist(desc)); + // ############################################################################ +} + +bool +QConfigDB::get(const TQCString& key, KeyValueMap*& map) +{ + // ############################################################################ + return get(stringToKeylist(key), map); + // ############################################################################ +} + +list +QConfigDB::stringToKeylist(const TQCString& desc) +{ + bool GUARD; GUARD=false; + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::stringToKeylist: parsing path " << desc << endl; + // ############################################################################ + list key; + int first=0, second; + TQCString temp; + // ----- + if(desc.isEmpty()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::stringToKeylist: path is empty." << endl; + return key; + } + for(;;) + { + second=desc.find('/', first); + if(second==-1) + { + if((unsigned)first& key, Section*& section) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::get: searching section ... " << endl; + Section* temp=⊤ + list::const_iterator pos; + // ----- + for(pos=key.begin(); pos!=key.end(); ++pos) + { + if(!temp->find(*pos, temp)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "failure, no such section."; + return false; + } + } + // ----- + section=temp; + kdDebug(GUARD, KAB_KDEBUG_AREA) << "success, section found." << endl; + return true; + // ############################################################################ +} + +bool +QConfigDB::isRO() +{ + // ############################################################################ + return readonly; + // ############################################################################ +} + +int +QConfigDB::IsLocked(const TQString& file) +{ + bool GUARD; GUARD=false; + // ############################################################################ + TQString lockfile=file+".lock"; + int pid=-1; + // ----- + if(access(TQFile::encodeName(lockfile), F_OK)==0) + { + TQFile f(lockfile); + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file\n" + << file << + "\nhas a lockfile.\n"; + if(f.open(IO_ReadOnly)) + { + TQTextStream stream(&f); + stream.setEncoding(TQTextStream::Latin1); // no conversion + // ----- + stream >> pid; + if(pid==-1) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file " + "does not contain the ID\n of the process that " + "created it." << endl; + return -1; + } + f.close(); + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::IsLocked: cannot open the lockfile." << endl; + return -1; + } + return pid; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::IsLocked: the file\n" + << file << "\nhas no lockfile.\n"; + return 0; + } + // ############################################################################ +} + +bool +QConfigDB::lock() +{ + bool GUARD; GUARD=false; + // ############################################################################ + if(locked) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock (current file): file " + "is already locked by this object." << endl; + return false; + } + if(lock(filename)) + { + locked=true; + return true; + } else { + return false; + } + // ############################################################################ +} + +bool +QConfigDB::lock(const TQString& file) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: locking the file " + << file << endl; + TQString lockfile=file+".lock"; + TQFile f(lockfile); + // ----- + if(access(TQFile::encodeName(lockfile), F_OK)==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: the file is locked by" + " another process." << endl; + return false; + } else { + if(f.open(IO_WriteOnly)) + { + TQTextStream stream(&f); + stream.setEncoding(TQTextStream::Latin1); // no conversion + // ----- + stream << getpid() << endl; + f.close(); + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::lock: unable to create" + " lockfile." << endl; + return false; + } + } + // ----- + LockFiles.push_back(lockfile); + return true; + // ############################################################################ +} + +bool +QConfigDB::unlock() +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: unlocking the file " + << filename << endl; + TQString lockfile=filename+".lock"; + list::iterator pos; + // ----- + if(!locked) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: this app did not " + "lock the file!" << endl; + return false; + } + if(access(TQFile::encodeName(lockfile), F_OK | W_OK)==0) + { + if(::remove(TQFile::encodeName(lockfile))==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::unlock: lockfile deleted." << endl; + for(pos=LockFiles.begin(); pos!=LockFiles.end(); ++pos) + { + if((*pos)==lockfile) break; + } + if(pos!=LockFiles.end()) + { + LockFiles.erase(pos); --pos; + } else { + kdDebug() << "QConfigDB::unlock: file not mentioned in lockfile" << endl; + } + locked=false; + return true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: unable to " + "delete lockfile.n" << endl; + return false; + } + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::unlock: the file is not" + " locked or permission has been denied." << endl; + return false; + } + // ############################################################################ +} + +void +QConfigDB::CleanLockFiles(int) +{ + bool GUARD; GUARD=false; + // ############################################################################ + list::iterator pos; + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA).form("QConfigDB::CleanLockFiles: removing %i " + "remaining lockfiles.", LockFiles.size()) << endl; + for(pos=LockFiles.begin(); pos!=LockFiles.end(); ++pos) + { + if(::remove(TQFile::encodeName(*pos))==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + " " << *pos << " removed.\n"; + LockFiles.erase(pos); --pos; + } else { + kdDebug() << " could not remove " << *pos << endl; + } + } + // ----- + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CleanLockFiles: done." << endl; + // ############################################################################ +} + +void +QConfigDB::watch(bool state) +{ + // ############################################################################ + if(state) + { // start timer + if(timer==0) + { + timer=new TQTimer(this); + connect(timer, TQT_SIGNAL(timeout()), TQT_SLOT(checkFileChanged())); + } + timer->start(1000); + } else { // stop timer + if(timer!=0) + { + timer->stop(); + } + } + // ############################################################################ +} + +bool +QConfigDB::CheckLockFile(const TQString& file) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: called." << endl; + int pid; + // ----- + pid=IsLocked(file); + if(pid==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: the file is " + "not locked." << endl; + return false; + } + if(pid>0) + { + if(kill(pid, 0)!=0) + { // ----- no such process, we may remove the lockfile: + return false; + } + } + if(pid<0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: the file has " + "not been created by QConfigDB::lock." << endl; + } + // ----- check system time and creation time of lockfile: + // WORK_TO_DO: not implemented + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::CheckLockFile: done." << endl; + return true; + // ############################################################################ +} + +bool +QConfigDB::checkFileChanged() +{ + bool GUARD; GUARD=false; + // ############################################################################ + // kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: called." << endl; + if(filename.isEmpty()) + { // ----- false, as file does not exist and thus may be stored anyway + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: no filename." << endl; + return false; + } + TQFileInfo file(filename); + // ----- + if(file.exists()) + { + if(file.lastModified() > *mtime) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::checkFileChanged: file has been changed.n" << endl; + emit(fileChanged()); + return true; + } else { + return false; + } + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::checkFileChanged: could " + "not stat file, file does not exist." << endl; + if(!mtime->isValid()) + { // the file did never exist for us: + return false; // ... so it has not changed + } else { // it existed, and now it does no more + emit(fileChanged()); + return true; + } + } + // ############################################################################ +} + +bool +QConfigDB::storeFileAge() +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::storeFileAge: called." << endl; + TQFileInfo file(filename); + // ----- + if(file.exists()) + { + *mtime=file.lastModified(); + return true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::save: could not stat file." << endl; + *mtime=TQDateTime(); // a null date + return false; + } + // ############################################################################ +} + + +bool +QConfigDB::setFileName(const TQString& filename_, bool mustexist, bool readonly_) +{ + bool GUARD; GUARD=false; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: setting filename " + "to \"" + << filename_ <<"\"" << (readonly_ ? " (read only)" : "") << endl; + // ----- remove previous lock: + if(locked) + { + if(!unlock()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: cannot " + "release previous lock." << endl; + return false; + } + } + // ----- remove possible stale lockfile: + if(IsLocked(filename_)!=0 && !CheckLockFile(filename_)) + { // ----- it is stale: + if(::remove(TQFile::encodeName(filename_+".lock"))==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::setFileName: removed stale lockfile." << endl; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::setFileName: cannot remove stale lockfile." << endl; + return false; + } + } + // ----- + if(mustexist) + { + if(access(TQFile::encodeName(filename_), readonly_==true ? R_OK : W_OK | R_OK)==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::setFileName: permission granted." << endl; + if(!readonly_) + { // we need r/w access: + if(lock(filename_)) + { + locked=true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: " + "could not lock the file." << endl; + return false; + } + } + readonly=readonly_; + filename=filename_; + storeFileAge(); + return true; + } else { + kdDebug() << "QConfigDB::setFileName: permission denied, " << endl; + return false; + } + } else { + if(access(TQFile::encodeName(filename_), F_OK)==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: file exists." << endl; + if(access(TQFile::encodeName(filename_), W_OK | R_OK)==0) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::setFileName: permission granted." << endl; + if(!readonly_) + { // we need r/w access: + if(lock(filename_)) + { + locked=true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: " + "could not lock the file." << endl; + return false; + } + } + readonly=readonly_; + filename=filename_; + storeFileAge(); + return true; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::setFileName: " + "permission denied, filename not set." << endl; + return false; + } + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::setFileName: permission granted, new file." << endl; + readonly=readonly_; + filename=filename_; + if(!readonly) + { + if(!lock()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::setFileName: could not lock the file." << endl; + return false; + } + } + storeFileAge(); + return true; + } + } + // ############################################################################ +} + +TQString +QConfigDB::fileName() +{ + // ############################################################################ + return filename; + // ############################################################################ +} + +bool +QConfigDB::save(const char* header, bool force) +{ + bool GUARD; GUARD=true; + // ############################################################################ + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: saving database -->" << filename << "<--.\n"; + bool wasRO=false; + bool rc; + // ----- + if(checkFileChanged()) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: file is newer, not saving." << endl; + return false; + } + if(force && isRO()) + { + if(setFileName(fileName(), true, false)) + { + wasRO=true; + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: switched to (forced) r/w mode." << endl; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: cannot switch to (forced) r/w mode." << endl; + return false; + } + } + // ----- now save it: + if(!isRO()) + { + TQFile file(filename); + if(file.open(IO_WriteOnly)) + { + TQTextStream stream(&file); + stream.setEncoding(TQTextStream::Latin1); // no conversion + // ----- + if(header!=0) + { + stream << "# " << header << endl; + } + stream << '#' << " [File created by QConfigDB object " + << version() << "]" << endl; + if(!top.save(stream)) // traverse tree + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: error saving subsections." << endl; + } + storeFileAge(); + file.close(); + rc=true; + } else { + kdDebug() << "QConfigDB::save: error opening file \"" + << filename << + "\" for writing.\n"; + rc=false; + } + } else { + rc=false; + } + // ----- reset r/o mode: + if(wasRO) // only true if we switched to forced r/w mode here + { + if(setFileName(fileName(), false, true)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: reset (forced) r/w mode." << endl; + } else { + kdDebug(GUARD, KAB_KDEBUG_AREA) << + "QConfigDB::save: cannot reset (forced) r/w mode." << endl; + rc=false; + } + } + // ----- + return rc; + // ############################################################################ +} + +bool +QConfigDB::load() +{ + bool GUARD; GUARD=false ; + // ############################################################################ + TQFile file(filename); + // ----- + if(file.open(IO_ReadOnly)) + { + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::load: file access OK." << endl; + TQTextStream stream(&file); + stream.setEncoding(TQTextStream::Latin1); // no conversion + // ----- + clear(); + bool rc=top.readSection(stream, false); + storeFileAge(); + file.close(); + emit(changed(this)); + kdDebug(GUARD, KAB_KDEBUG_AREA) << "QConfigDB::load: done." << endl; + return rc; + } else { + kdDebug() << "QConfigDB::load: error opening file \"" << filename << "\" for reading." << endl; + return false; + } + // ############################################################################ +} diff --git a/libtdemid/CMakeLists.txt b/libtdemid/CMakeLists.txt index 21338aac1..0cfce2c70 100644 --- a/libtdemid/CMakeLists.txt +++ b/libtdemid/CMakeLists.txt @@ -37,10 +37,10 @@ install( FILES set( target tdemid ) set( ${target}_SRCS - midiout.cc player.cc track.cc midimapper.cc - midfile.cc dattypes.cc midistat.cc deviceman.cc - synthout.cc fmout.cc gusout.cc alsaout.cc voiceman.cc - mt32togm.cc notearray.cc libtdemid.cc + midiout.cpp player.cpp track.cpp midimapper.cpp + midfile.cpp dattypes.cpp midistat.cpp deviceman.cpp + synthout.cpp fmout.cpp gusout.cpp alsaout.cpp voiceman.cpp + mt32togm.cpp notearray.cpp libtdemid.cpp ) tde_add_library( ${target} SHARED diff --git a/libtdemid/Makefile.am b/libtdemid/Makefile.am index 8cb347b01..2c1baf726 100644 --- a/libtdemid/Makefile.am +++ b/libtdemid/Makefile.am @@ -12,10 +12,10 @@ libtdemidinclude_HEADERS = midiout.h player.h track.h midimapper.h \ midispec.h libtdemid.h lib_LTLIBRARIES = libtdemid.la -libtdemid_la_SOURCES = midiout.cc player.cc track.cc midimapper.cc \ - midfile.cc dattypes.cc midistat.cc deviceman.cc synthout.cc \ - fmout.cc gusout.cc alsaout.cc voiceman.cc mt32togm.cc notearray.cc \ - libtdemid.cc +libtdemid_la_SOURCES = midiout.cpp player.cpp track.cpp midimapper.cpp \ + midfile.cpp dattypes.cpp midistat.cpp deviceman.cpp synthout.cpp \ + fmout.cpp gusout.cpp alsaout.cpp voiceman.cpp mt32togm.cpp notearray.cpp \ + libtdemid.cpp libtdemid_la_LDFLAGS = $(KDE_MT_LDFLAGS) -version-info 0:95 -no-undefined libtdemid_la_LIBADD = $(LIBASOUND) ../tdecore/libtdecore.la $(LIB_TQT) diff --git a/libtdemid/alsaout.cc b/libtdemid/alsaout.cc deleted file mode 100644 index 517852b25..000000000 --- a/libtdemid/alsaout.cc +++ /dev/null @@ -1,571 +0,0 @@ -/************************************************************************** - - alsaout.cc - class AlsaOut which represents an alsa client/port pair - This file is part of LibKMid 0.9.5 - Copyright (C) 2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "alsaout.h" -#include -#include -#include -#include "sndcard.h" -#include -#include -#include -#include -#include "midispec.h" - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_ALSA_ASOUNDLIB_H -# include -#elif defined(HAVE_SYS_ASOUNDLIB_H) -# include -#endif - -#ifdef HAVE_LIBASOUND2 -# define HAVE_ALSA_SEQ 1 -# define snd_seq_flush_output(x) snd_seq_drain_output(x) -#elif defined(HAVE_LIBASOUND) -# define HAVE_ALSA_SEQ 1 -# include -#endif - - -SEQ_USE_EXTBUF(); - -class AlsaOut::AlsaOutPrivate -{ -public: -#ifdef HAVE_ALSA_SEQ - AlsaOutPrivate(int _client, int _port, const char *cname,const char *pname) - { - handle=0L; - src=tgt=0L; - queue=0; - tPCN=1; - tgtclient=_client; - tgtport=_port; - tgtname=new char[strlen(cname)+strlen(pname)+3]; - strcpy(tgtname, cname); - strcat(tgtname, " "); - strcat(tgtname, pname); - ev=new snd_seq_event_t; - timerStarted=false; - } -#else - AlsaOutPrivate(int, int, const char *,const char *) - { - } -#endif - - ~AlsaOutPrivate() - { -#ifdef HAVE_ALSA_SEQ - delete ev; - delete tgtname; -#endif - } - -#ifdef HAVE_ALSA_SEQ - snd_seq_t *handle; - int client; - int queue; - snd_seq_addr_t *src; - snd_seq_addr_t *tgt; - - snd_seq_event_t *ev; - int tPCN; - - int tgtclient; - int tgtport; - char *tgtname; - - bool timerStarted; - -#endif -}; - -AlsaOut::AlsaOut(int d,int _client, int _port, const char *cname,const char *pname) : MidiOut (d) -{ - di = new AlsaOutPrivate( _client, _port, cname, pname); - seqfd = 0; - devicetype=KMID_ALSA; - device= d; - - volumepercentage=100; -#ifdef HAVE_ALSA_SEQ -// printf("%d %d %d (%s)\n",device, di->tgtclient, di->tgtport, di->tgtname); -#endif - - _ok=1; -} - -AlsaOut::~AlsaOut() -{ - closeDev(); - delete di; -} - -void AlsaOut::openDev (int) -{ -#ifndef HAVE_ALSA_SEQ - return; -#else - _ok=1; -#ifdef HAVE_LIBASOUND2 - if (snd_seq_open(&di->handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) - fprintf(stderr, "Couldn't open sequencer: %s", snd_strerror(errno)); -#else - if (snd_seq_open(&di->handle, SND_SEQ_OPEN) < 0) - fprintf(stderr, "Couldn't open sequencer: %s", snd_strerror(errno)); -#endif - - di->queue = snd_seq_alloc_queue(di->handle); - if (di->queue < 0) {fprintf(stderr, "Couldn't allocate queue"); return; }; - di->client = snd_seq_client_id(di->handle); - if (di->client < 0) {fprintf(stderr, "Couldn't get client id"); return; }; - di->tgt = new snd_seq_addr_t; - di->tgt->client=di->tgtclient; - di->tgt->port=di->tgtport; - - di->src = new snd_seq_addr_t; - di->src->client = di->client; - int port = snd_seq_create_simple_port(di->handle, NULL, - SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE - | SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC); - if ( port < 0 ) - { - delete di->src; - delete di->tgt; - di->src=0; - di->tgt=0; - _ok=0; - time=0; - snd_seq_free_queue(di->handle, di->queue); - snd_seq_close(di->handle); - fprintf(stderr, "Cannot connect to %d:%d\n",di->tgtclient,di->tgtport); - return; - } - di->src->port = port; - - - int r=snd_seq_connect_to(di->handle, di->src->port, di->tgt->client, di->tgt->port); - if (r < 0) { _ok=0; fprintf(stderr, "Cannot connect to %d:%d\n",di->tgtclient,di->tgtport); } - time=0; -#endif -} - -void AlsaOut::closeDev (void) -{ - if (!ok()) return; -#ifdef HAVE_ALSA_SEQ - if (di->handle) - { - if (di->src) - { - snd_seq_delete_simple_port(di->handle,di->src->port); - delete di->src; - di->src=0; - } - if (di->tgt) - { - delete di->tgt; - di->tgt=0; - } - if (di->queue) - { - snd_seq_free_queue(di->handle, di->queue); - snd_seq_close(di->handle); - } - di->handle=0; - } - -#endif -} - -void AlsaOut::initDev (void) -{ -#ifdef HAVE_ALSA_SEQ - int chn; - if (!ok()) return; - uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; - sysex(gm_reset, sizeof(gm_reset)); - for (chn=0;chn<16;chn++) - { - chnmute[chn]=0; - if (chn!=9) chnPatchChange(chn,0); - chnPressure(chn,64); - chnPitchBender(chn, 0x00, 0x40); - chnController(chn, CTL_MAIN_VOLUME,110*volumepercentage); - chnController(chn, CTL_EXT_EFF_DEPTH, 0); - chnController(chn, CTL_CHORUS_DEPTH, 0); - chnController(chn, 0x4a, 127); - } -#endif -} - -#ifdef HAVE_ALSA_SEQ -void AlsaOut::eventInit(snd_seq_event_t *ev) -{ - snd_seq_ev_clear(ev); - snd_seq_real_time_t tmp; - tmp.tv_sec=(time)/1000; - tmp.tv_nsec=(time%1000)*1000000; -// printf("time : %d %d %d\n",(int)time,(int)tmp.tv_sec, (int)tmp.tv_nsec); - if (!di->src) { fprintf(stderr,"AlsaOut::eventInit : no source\n"); return; } - ev->source = *di->src; - if (!di->tgt) { fprintf(stderr,"AlsaOut::eventInit : no target\n"); return; } - ev->dest = *di->tgt; - - snd_seq_ev_schedule_real(ev, di->queue, 0, &tmp); -} - -void AlsaOut::eventSend(snd_seq_event_t *ev) -{ - /*int err = */ snd_seq_event_output(di->handle, ev); -/* if (err < 0) - return; -*/ -//#ifndef SND_SEQ_IOCTL_GET_CLIENT_POOL - /* - * If this is not defined then block mode writes will not be - * working correctly. Therefore loop until all events are flushed - * out. - */ -/* err = 0; - do { - err = snd_seq_flush_output(di->handle); - if (err > 0) - usleep(2000); - } while (err > 0); - -#endif - - return ; -*/ -} - -void AlsaOut::timerEventSend(int type) -{ - snd_seq_event_t ev; - - ev.queue = di->queue; - ev.dest.client = SND_SEQ_CLIENT_SYSTEM; - ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; - - ev.data.queue.queue = di->queue; - - ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL; - ev.time.time.tv_sec = 0; - ev.time.time.tv_nsec = 0; - - ev.type = type; - - snd_seq_event_output(di->handle, &ev); - snd_seq_flush_output(di->handle); -} - -#endif // HAVE_ALSA_SEQ - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::noteOn (uchar , uchar , uchar ) -{ -#else -void AlsaOut::noteOn (uchar chn, uchar note, uchar vel) -{ - if (vel==0) - { - noteOff(chn,note,vel); - } - else - { - eventInit(di->ev); - snd_seq_ev_set_noteon(di->ev,map->channel(chn), map->key(chn,chnpatch[chn],note), vel); - eventSend(di->ev); - } -#endif -#ifdef MIDIOUTDEBUG - printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::noteOff (uchar , uchar , uchar ) -{ -#else -void AlsaOut::noteOff (uchar chn, uchar note, uchar vel) -{ - eventInit(di->ev); - snd_seq_ev_set_noteoff(di->ev,map->channel(chn), map->key(chn,chnpatch[chn],note), vel); - eventSend(di->ev); -#endif -#ifdef MIDIOUTDEBUG - printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::keyPressure (uchar , uchar , uchar ) -{ -#else -void AlsaOut::keyPressure (uchar chn, uchar note, uchar vel) -{ - eventInit(di->ev); - snd_seq_ev_set_keypress(di->ev,map->channel(chn), map->key(chn,chnpatch[chn],note), vel); - eventSend(di->ev); -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::chnPatchChange (uchar , uchar ) -{ -#else -void AlsaOut::chnPatchChange (uchar chn, uchar patch) -{ -#ifdef MIDIOUTDEBUG - printfdebug("PATCHCHANGE [%d->%d] %d -> %d\n", - chn,map->channel(chn),patch,map->patch(chn,patch)); -#endif - eventInit(di->ev); - snd_seq_ev_set_pgmchange(di->ev,map->channel(chn), map->patch(chn,patch)); - eventSend(di->ev); - chnpatch[chn]=patch; -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::chnPressure (uchar , uchar ) -{ -#else -void AlsaOut::chnPressure (uchar chn, uchar vel) -{ - eventInit(di->ev); - snd_seq_ev_set_chanpress(di->ev,map->channel(chn), vel); - eventSend(di->ev); - - chnpressure[chn]=vel; -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::chnPitchBender(uchar ,uchar , uchar ) -{ -#else -void AlsaOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) -{ - map->pitchBender(chn,lsb,msb); - chnbender[chn]=((short)msb<<7) | (lsb & 0x7F); - chnbender[chn]=chnbender[chn]-0x2000; - - eventInit(di->ev); - snd_seq_ev_set_pitchbend(di->ev,map->channel(chn), chnbender[chn]); - eventSend(di->ev); -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::chnController (uchar , uchar , uchar ) -{ -#else -void AlsaOut::chnController (uchar chn, uchar ctl, uchar v) -{ - map->controller(chn,ctl,v); - if ((ctl==11)||(ctl==7)) - { - v=(v*volumepercentage)/100; - if (v>127) v=127; - } - - eventInit(di->ev); - snd_seq_ev_set_controller(di->ev,map->channel(chn), ctl, v); - eventSend(di->ev); - - chncontroller[chn][ctl]=v; -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::sysex(uchar *, ulong ) -{ -#else -void AlsaOut::sysex(uchar *data, ulong size) -{ - eventInit(di->ev); - snd_seq_ev_set_sysex(di->ev, size, data); - eventSend(di->ev); -#endif - -#ifdef MIDIOUTDEBUG - printfdebug("sysex\n"); -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::channelSilence (uchar ) -{ -#else -void AlsaOut::channelSilence (uchar chn) -{ - uchar i; - for ( i=0; i<127; i++) - { - noteOff(chn,i,0); - } -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::channelMute(uchar , int ) -{ -#else -void AlsaOut::channelMute(uchar chn, int a) -{ - if (a==1) - { - chnmute[chn]=a; - channelSilence(chn); - } - else if (a==0) - { - chnmute[chn]=a; - } - /* else ignore the call to this procedure */ -#endif -} - -void AlsaOut::seqbuf_dump (void) -{ - printf("You shouldn't be here.\n"); -} - -void AlsaOut::seqbuf_clean(void) -{ - printf("You shouldn't be here neither.\n"); -} - -void AlsaOut::wait(double ticks) -{ -// SEQ_WAIT_TIME(((int)(ticks/convertrate))); - time=static_cast(ticks); - -#ifdef MIDIOUTDEBUG - printfdebug("Wait >\t ticks: %g\n",ticks); -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::tmrSetTempo(int ) -{ -#else -void AlsaOut::tmrSetTempo(int v) -{ - eventInit(di->ev); - di->ev->type = SND_SEQ_EVENT_TEMPO; - snd_seq_ev_set_direct(di->ev); - di->ev->data.queue.queue = di->queue; - di->ev->data.queue.param.value = v; - di->ev->dest.client = SND_SEQ_CLIENT_SYSTEM; - di->ev->dest.port = SND_SEQ_PORT_SYSTEM_TIMER; - snd_seq_event_output_direct(di->handle, di->ev); -#ifdef MIDIOUTDEBUG - printfdebug("SETTEMPO >\t tempo: %d\n",v); -#endif -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::sync(int ) -{ -#else -void AlsaOut::sync(int i) -{ - if (i==1) - { - snd_seq_flush_output(di->handle); - } - - if (di->timerStarted && di->src) - { - eventInit(di->ev); - di->ev->dest = *di->src; - eventSend(di->ev); - snd_seq_flush_output(di->handle); - snd_seq_event_input(di->handle,&di->ev); - } - -#endif -} - -#ifndef HAVE_ALSA_SEQ -void AlsaOut::tmrStart(int ) -{ -#else -void AlsaOut::tmrStart(int tpcn) -{ - int ret; - di->timerStarted=true; - di->tPCN=tpcn; - -#ifdef HAVE_LIBASOUND2 - snd_seq_queue_tempo_t *queuetempo; - snd_seq_queue_tempo_alloca(&queuetempo); - snd_seq_queue_tempo_set_ppq(queuetempo, tpcn); - snd_seq_queue_tempo_set_tempo(queuetempo, 60*1000000/120); - ret = snd_seq_set_queue_tempo(di->handle, di->queue, queuetempo); -#else - snd_seq_queue_tempo_t queuetempo; - memset(&queuetempo, 0, sizeof(queuetempo)); - queuetempo.queue = di->queue; - queuetempo.ppq = tpcn; - queuetempo.tempo = 60*1000000/120; - ret = snd_seq_set_queue_tempo(di->handle, di->queue, &queuetempo); -#endif - - timerEventSend(SND_SEQ_EVENT_START); - snd_seq_start_queue(di->handle,di->queue,NULL); -#endif -} - -void AlsaOut::tmrStop(void) -{ -#ifdef HAVE_ALSA_SEQ - di->timerStarted=false; - timerEventSend(SND_SEQ_EVENT_STOP); -#endif -} - -void AlsaOut::tmrContinue(void) -{ -} - -const char * AlsaOut::deviceName(void) const -{ -#ifdef HAVE_ALSA_SEQ - return di->tgtname; -#else - return 0L; -#endif -} diff --git a/libtdemid/alsaout.cpp b/libtdemid/alsaout.cpp new file mode 100644 index 000000000..2e1b769f4 --- /dev/null +++ b/libtdemid/alsaout.cpp @@ -0,0 +1,571 @@ +/************************************************************************** + + alsaout.cpp - class AlsaOut which represents an alsa client/port pair + This file is part of LibKMid 0.9.5 + Copyright (C) 2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "alsaout.h" +#include +#include +#include +#include "sndcard.h" +#include +#include +#include +#include +#include "midispec.h" + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_ALSA_ASOUNDLIB_H +# include +#elif defined(HAVE_SYS_ASOUNDLIB_H) +# include +#endif + +#ifdef HAVE_LIBASOUND2 +# define HAVE_ALSA_SEQ 1 +# define snd_seq_flush_output(x) snd_seq_drain_output(x) +#elif defined(HAVE_LIBASOUND) +# define HAVE_ALSA_SEQ 1 +# include +#endif + + +SEQ_USE_EXTBUF(); + +class AlsaOut::AlsaOutPrivate +{ +public: +#ifdef HAVE_ALSA_SEQ + AlsaOutPrivate(int _client, int _port, const char *cname,const char *pname) + { + handle=0L; + src=tgt=0L; + queue=0; + tPCN=1; + tgtclient=_client; + tgtport=_port; + tgtname=new char[strlen(cname)+strlen(pname)+3]; + strcpy(tgtname, cname); + strcat(tgtname, " "); + strcat(tgtname, pname); + ev=new snd_seq_event_t; + timerStarted=false; + } +#else + AlsaOutPrivate(int, int, const char *,const char *) + { + } +#endif + + ~AlsaOutPrivate() + { +#ifdef HAVE_ALSA_SEQ + delete ev; + delete tgtname; +#endif + } + +#ifdef HAVE_ALSA_SEQ + snd_seq_t *handle; + int client; + int queue; + snd_seq_addr_t *src; + snd_seq_addr_t *tgt; + + snd_seq_event_t *ev; + int tPCN; + + int tgtclient; + int tgtport; + char *tgtname; + + bool timerStarted; + +#endif +}; + +AlsaOut::AlsaOut(int d,int _client, int _port, const char *cname,const char *pname) : MidiOut (d) +{ + di = new AlsaOutPrivate( _client, _port, cname, pname); + seqfd = 0; + devicetype=KMID_ALSA; + device= d; + + volumepercentage=100; +#ifdef HAVE_ALSA_SEQ +// printf("%d %d %d (%s)\n",device, di->tgtclient, di->tgtport, di->tgtname); +#endif + + _ok=1; +} + +AlsaOut::~AlsaOut() +{ + closeDev(); + delete di; +} + +void AlsaOut::openDev (int) +{ +#ifndef HAVE_ALSA_SEQ + return; +#else + _ok=1; +#ifdef HAVE_LIBASOUND2 + if (snd_seq_open(&di->handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) + fprintf(stderr, "Couldn't open sequencer: %s", snd_strerror(errno)); +#else + if (snd_seq_open(&di->handle, SND_SEQ_OPEN) < 0) + fprintf(stderr, "Couldn't open sequencer: %s", snd_strerror(errno)); +#endif + + di->queue = snd_seq_alloc_queue(di->handle); + if (di->queue < 0) {fprintf(stderr, "Couldn't allocate queue"); return; }; + di->client = snd_seq_client_id(di->handle); + if (di->client < 0) {fprintf(stderr, "Couldn't get client id"); return; }; + di->tgt = new snd_seq_addr_t; + di->tgt->client=di->tgtclient; + di->tgt->port=di->tgtport; + + di->src = new snd_seq_addr_t; + di->src->client = di->client; + int port = snd_seq_create_simple_port(di->handle, NULL, + SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE + | SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC); + if ( port < 0 ) + { + delete di->src; + delete di->tgt; + di->src=0; + di->tgt=0; + _ok=0; + time=0; + snd_seq_free_queue(di->handle, di->queue); + snd_seq_close(di->handle); + fprintf(stderr, "Cannot connect to %d:%d\n",di->tgtclient,di->tgtport); + return; + } + di->src->port = port; + + + int r=snd_seq_connect_to(di->handle, di->src->port, di->tgt->client, di->tgt->port); + if (r < 0) { _ok=0; fprintf(stderr, "Cannot connect to %d:%d\n",di->tgtclient,di->tgtport); } + time=0; +#endif +} + +void AlsaOut::closeDev (void) +{ + if (!ok()) return; +#ifdef HAVE_ALSA_SEQ + if (di->handle) + { + if (di->src) + { + snd_seq_delete_simple_port(di->handle,di->src->port); + delete di->src; + di->src=0; + } + if (di->tgt) + { + delete di->tgt; + di->tgt=0; + } + if (di->queue) + { + snd_seq_free_queue(di->handle, di->queue); + snd_seq_close(di->handle); + } + di->handle=0; + } + +#endif +} + +void AlsaOut::initDev (void) +{ +#ifdef HAVE_ALSA_SEQ + int chn; + if (!ok()) return; + uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; + sysex(gm_reset, sizeof(gm_reset)); + for (chn=0;chn<16;chn++) + { + chnmute[chn]=0; + if (chn!=9) chnPatchChange(chn,0); + chnPressure(chn,64); + chnPitchBender(chn, 0x00, 0x40); + chnController(chn, CTL_MAIN_VOLUME,110*volumepercentage); + chnController(chn, CTL_EXT_EFF_DEPTH, 0); + chnController(chn, CTL_CHORUS_DEPTH, 0); + chnController(chn, 0x4a, 127); + } +#endif +} + +#ifdef HAVE_ALSA_SEQ +void AlsaOut::eventInit(snd_seq_event_t *ev) +{ + snd_seq_ev_clear(ev); + snd_seq_real_time_t tmp; + tmp.tv_sec=(time)/1000; + tmp.tv_nsec=(time%1000)*1000000; +// printf("time : %d %d %d\n",(int)time,(int)tmp.tv_sec, (int)tmp.tv_nsec); + if (!di->src) { fprintf(stderr,"AlsaOut::eventInit : no source\n"); return; } + ev->source = *di->src; + if (!di->tgt) { fprintf(stderr,"AlsaOut::eventInit : no target\n"); return; } + ev->dest = *di->tgt; + + snd_seq_ev_schedule_real(ev, di->queue, 0, &tmp); +} + +void AlsaOut::eventSend(snd_seq_event_t *ev) +{ + /*int err = */ snd_seq_event_output(di->handle, ev); +/* if (err < 0) + return; +*/ +//#ifndef SND_SEQ_IOCTL_GET_CLIENT_POOL + /* + * If this is not defined then block mode writes will not be + * working correctly. Therefore loop until all events are flushed + * out. + */ +/* err = 0; + do { + err = snd_seq_flush_output(di->handle); + if (err > 0) + usleep(2000); + } while (err > 0); + +#endif + + return ; +*/ +} + +void AlsaOut::timerEventSend(int type) +{ + snd_seq_event_t ev; + + ev.queue = di->queue; + ev.dest.client = SND_SEQ_CLIENT_SYSTEM; + ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; + + ev.data.queue.queue = di->queue; + + ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL; + ev.time.time.tv_sec = 0; + ev.time.time.tv_nsec = 0; + + ev.type = type; + + snd_seq_event_output(di->handle, &ev); + snd_seq_flush_output(di->handle); +} + +#endif // HAVE_ALSA_SEQ + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::noteOn (uchar , uchar , uchar ) +{ +#else +void AlsaOut::noteOn (uchar chn, uchar note, uchar vel) +{ + if (vel==0) + { + noteOff(chn,note,vel); + } + else + { + eventInit(di->ev); + snd_seq_ev_set_noteon(di->ev,map->channel(chn), map->key(chn,chnpatch[chn],note), vel); + eventSend(di->ev); + } +#endif +#ifdef MIDIOUTDEBUG + printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::noteOff (uchar , uchar , uchar ) +{ +#else +void AlsaOut::noteOff (uchar chn, uchar note, uchar vel) +{ + eventInit(di->ev); + snd_seq_ev_set_noteoff(di->ev,map->channel(chn), map->key(chn,chnpatch[chn],note), vel); + eventSend(di->ev); +#endif +#ifdef MIDIOUTDEBUG + printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::keyPressure (uchar , uchar , uchar ) +{ +#else +void AlsaOut::keyPressure (uchar chn, uchar note, uchar vel) +{ + eventInit(di->ev); + snd_seq_ev_set_keypress(di->ev,map->channel(chn), map->key(chn,chnpatch[chn],note), vel); + eventSend(di->ev); +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::chnPatchChange (uchar , uchar ) +{ +#else +void AlsaOut::chnPatchChange (uchar chn, uchar patch) +{ +#ifdef MIDIOUTDEBUG + printfdebug("PATCHCHANGE [%d->%d] %d -> %d\n", + chn,map->channel(chn),patch,map->patch(chn,patch)); +#endif + eventInit(di->ev); + snd_seq_ev_set_pgmchange(di->ev,map->channel(chn), map->patch(chn,patch)); + eventSend(di->ev); + chnpatch[chn]=patch; +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::chnPressure (uchar , uchar ) +{ +#else +void AlsaOut::chnPressure (uchar chn, uchar vel) +{ + eventInit(di->ev); + snd_seq_ev_set_chanpress(di->ev,map->channel(chn), vel); + eventSend(di->ev); + + chnpressure[chn]=vel; +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::chnPitchBender(uchar ,uchar , uchar ) +{ +#else +void AlsaOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) +{ + map->pitchBender(chn,lsb,msb); + chnbender[chn]=((short)msb<<7) | (lsb & 0x7F); + chnbender[chn]=chnbender[chn]-0x2000; + + eventInit(di->ev); + snd_seq_ev_set_pitchbend(di->ev,map->channel(chn), chnbender[chn]); + eventSend(di->ev); +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::chnController (uchar , uchar , uchar ) +{ +#else +void AlsaOut::chnController (uchar chn, uchar ctl, uchar v) +{ + map->controller(chn,ctl,v); + if ((ctl==11)||(ctl==7)) + { + v=(v*volumepercentage)/100; + if (v>127) v=127; + } + + eventInit(di->ev); + snd_seq_ev_set_controller(di->ev,map->channel(chn), ctl, v); + eventSend(di->ev); + + chncontroller[chn][ctl]=v; +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::sysex(uchar *, ulong ) +{ +#else +void AlsaOut::sysex(uchar *data, ulong size) +{ + eventInit(di->ev); + snd_seq_ev_set_sysex(di->ev, size, data); + eventSend(di->ev); +#endif + +#ifdef MIDIOUTDEBUG + printfdebug("sysex\n"); +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::channelSilence (uchar ) +{ +#else +void AlsaOut::channelSilence (uchar chn) +{ + uchar i; + for ( i=0; i<127; i++) + { + noteOff(chn,i,0); + } +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::channelMute(uchar , int ) +{ +#else +void AlsaOut::channelMute(uchar chn, int a) +{ + if (a==1) + { + chnmute[chn]=a; + channelSilence(chn); + } + else if (a==0) + { + chnmute[chn]=a; + } + /* else ignore the call to this procedure */ +#endif +} + +void AlsaOut::seqbuf_dump (void) +{ + printf("You shouldn't be here.\n"); +} + +void AlsaOut::seqbuf_clean(void) +{ + printf("You shouldn't be here neither.\n"); +} + +void AlsaOut::wait(double ticks) +{ +// SEQ_WAIT_TIME(((int)(ticks/convertrate))); + time=static_cast(ticks); + +#ifdef MIDIOUTDEBUG + printfdebug("Wait >\t ticks: %g\n",ticks); +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::tmrSetTempo(int ) +{ +#else +void AlsaOut::tmrSetTempo(int v) +{ + eventInit(di->ev); + di->ev->type = SND_SEQ_EVENT_TEMPO; + snd_seq_ev_set_direct(di->ev); + di->ev->data.queue.queue = di->queue; + di->ev->data.queue.param.value = v; + di->ev->dest.client = SND_SEQ_CLIENT_SYSTEM; + di->ev->dest.port = SND_SEQ_PORT_SYSTEM_TIMER; + snd_seq_event_output_direct(di->handle, di->ev); +#ifdef MIDIOUTDEBUG + printfdebug("SETTEMPO >\t tempo: %d\n",v); +#endif +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::sync(int ) +{ +#else +void AlsaOut::sync(int i) +{ + if (i==1) + { + snd_seq_flush_output(di->handle); + } + + if (di->timerStarted && di->src) + { + eventInit(di->ev); + di->ev->dest = *di->src; + eventSend(di->ev); + snd_seq_flush_output(di->handle); + snd_seq_event_input(di->handle,&di->ev); + } + +#endif +} + +#ifndef HAVE_ALSA_SEQ +void AlsaOut::tmrStart(int ) +{ +#else +void AlsaOut::tmrStart(int tpcn) +{ + int ret; + di->timerStarted=true; + di->tPCN=tpcn; + +#ifdef HAVE_LIBASOUND2 + snd_seq_queue_tempo_t *queuetempo; + snd_seq_queue_tempo_alloca(&queuetempo); + snd_seq_queue_tempo_set_ppq(queuetempo, tpcn); + snd_seq_queue_tempo_set_tempo(queuetempo, 60*1000000/120); + ret = snd_seq_set_queue_tempo(di->handle, di->queue, queuetempo); +#else + snd_seq_queue_tempo_t queuetempo; + memset(&queuetempo, 0, sizeof(queuetempo)); + queuetempo.queue = di->queue; + queuetempo.ppq = tpcn; + queuetempo.tempo = 60*1000000/120; + ret = snd_seq_set_queue_tempo(di->handle, di->queue, &queuetempo); +#endif + + timerEventSend(SND_SEQ_EVENT_START); + snd_seq_start_queue(di->handle,di->queue,NULL); +#endif +} + +void AlsaOut::tmrStop(void) +{ +#ifdef HAVE_ALSA_SEQ + di->timerStarted=false; + timerEventSend(SND_SEQ_EVENT_STOP); +#endif +} + +void AlsaOut::tmrContinue(void) +{ +} + +const char * AlsaOut::deviceName(void) const +{ +#ifdef HAVE_ALSA_SEQ + return di->tgtname; +#else + return 0L; +#endif +} diff --git a/libtdemid/alsaout.h b/libtdemid/alsaout.h index 016ca29c6..4dace44ce 100644 --- a/libtdemid/alsaout.h +++ b/libtdemid/alsaout.h @@ -1,4 +1,4 @@ -/* alsaout.cc - class AlsaOut which represents an alsa client/port pair +/* alsaout.cpp - class AlsaOut which represents an alsa client/port pair This file is part of LibKMid 0.9.5 Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html diff --git a/libtdemid/dattypes.cc b/libtdemid/dattypes.cc deleted file mode 100644 index 218591fa4..000000000 --- a/libtdemid/dattypes.cc +++ /dev/null @@ -1,110 +0,0 @@ -/************************************************************************** - - dattypes.cc - Some always useful definitions and functions - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "dattypes.h" -#include - -ushort readShort(FILE *fh) -{ - uchar c1; - uchar c2; - - fread(&c1,1,1,fh); - fread(&c2,1,1,fh); - return (c1<<8)|c2; -} - -ulong readLong(FILE *fh) -{ - uchar c1; - uchar c2; - uchar c3; - uchar c4; - ulong l; - - fread(&c1,1,1,fh); - fread(&c2,1,1,fh); - fread(&c3,1,1,fh); - fread(&c4,1,1,fh); - l=((c1<<24)|(c2<<16)|(c3<<8)|c4); - return l; -} - -#ifdef DEBUG - -void printfdebug(const char *format, int a, int b, int c) -{ - char *s=(char *)format; - int i=0; - while (*s!=0) - { - if (*s=='%') i++; - s++; - } - switch (i) - { - case (1) : fprintf(stderr,format,a); break; - case (2) : fprintf(stderr,format,a,b); break; - case (3) : fprintf(stderr,format,a,b,c); break; - default : fprintf(stderr,format); break; - } - -} - -void printfdebug(const char *format, int a, long b) -{ - fprintf(stderr,format,a,b); -} - -void printfdebug(const char *format, double a, double b, double c) -{ - char *s=(char *)format; - int i=0; - while (*s!=0) - { - if (*s=='%') i++; - s++; - } - switch (i) - { - case (1) : fprintf(stderr,format,a); break; - case (2) : fprintf(stderr,format,a,b); break; - case (3) : fprintf(stderr,format,a,b,c); break; - default : fprintf(stderr,format); break; - } - -} -#else - -void printfdebug(const char *, int , int , int ) -{ -} -void printfdebug(const char *, int , long ) -{ -} -void printfdebug(const char *, double , double , double ) -{ -} -#endif diff --git a/libtdemid/dattypes.cpp b/libtdemid/dattypes.cpp new file mode 100644 index 000000000..7ae0aba52 --- /dev/null +++ b/libtdemid/dattypes.cpp @@ -0,0 +1,110 @@ +/************************************************************************** + + dattypes.cpp - Some always useful definitions and functions + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "dattypes.h" +#include + +ushort readShort(FILE *fh) +{ + uchar c1; + uchar c2; + + fread(&c1,1,1,fh); + fread(&c2,1,1,fh); + return (c1<<8)|c2; +} + +ulong readLong(FILE *fh) +{ + uchar c1; + uchar c2; + uchar c3; + uchar c4; + ulong l; + + fread(&c1,1,1,fh); + fread(&c2,1,1,fh); + fread(&c3,1,1,fh); + fread(&c4,1,1,fh); + l=((c1<<24)|(c2<<16)|(c3<<8)|c4); + return l; +} + +#ifdef DEBUG + +void printfdebug(const char *format, int a, int b, int c) +{ + char *s=(char *)format; + int i=0; + while (*s!=0) + { + if (*s=='%') i++; + s++; + } + switch (i) + { + case (1) : fprintf(stderr,format,a); break; + case (2) : fprintf(stderr,format,a,b); break; + case (3) : fprintf(stderr,format,a,b,c); break; + default : fprintf(stderr,format); break; + } + +} + +void printfdebug(const char *format, int a, long b) +{ + fprintf(stderr,format,a,b); +} + +void printfdebug(const char *format, double a, double b, double c) +{ + char *s=(char *)format; + int i=0; + while (*s!=0) + { + if (*s=='%') i++; + s++; + } + switch (i) + { + case (1) : fprintf(stderr,format,a); break; + case (2) : fprintf(stderr,format,a,b); break; + case (3) : fprintf(stderr,format,a,b,c); break; + default : fprintf(stderr,format); break; + } + +} +#else + +void printfdebug(const char *, int , int , int ) +{ +} +void printfdebug(const char *, int , long ) +{ +} +void printfdebug(const char *, double , double , double ) +{ +} +#endif diff --git a/libtdemid/deviceman.cc b/libtdemid/deviceman.cc deleted file mode 100644 index 82f973d3f..000000000 --- a/libtdemid/deviceman.cc +++ /dev/null @@ -1,828 +0,0 @@ -/************************************************************************** - - deviceman.cc - The device manager, that hides the use of midiOut - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - $Id$ - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "deviceman.h" -#include "midiout.h" -#include -#include -#include -#include -#include -#include "sndcard.h" -#include "synthout.h" -#include "fmout.h" -#include "gusout.h" -#include "alsaout.h" -#include "midimapper.h" -#include "midispec.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_STAT_H -#include -#endif - -#ifdef HAVE_ALSA_ASOUNDLIB_H -# define HAVE_ALSA_SUPPORT -# include -#elif defined(HAVE_SYS_ASOUNDLIB_H) -# define HAVE_ALSA_SUPPORT -# include -#else -#ifdef HAVE_LIBASOUND2 -# define HAVE_ALSA_SUPPORT -# include -# include -#elif defined(HAVE_LIBASOUND) -# define HAVE_ALSA_SUPPORT -# include -#endif -#endif - -#if 1 -#include -#include -#include -#endif - -//#define DEVICEMANDEBUG -//#define GENERAL_DEBUG_MESSAGES - -SEQ_DEFINEBUF (4096); - -#define CONTROLTIMER - -#ifdef GENERAL_DEBUG_MESSAGES -void DEBUGPRINTF(const char *format) -{ - printf(format); -} - -void DEBUGPRINTF(const char *format,int i) -{ - printf(format,i); -} - -void DEBUGPRINTF(const char *format,const char *s) -{ - printf(format,s); -} - -#else - -void DEBUGPRINTF(const char *) { } -void DEBUGPRINTF(const char *,int ) { } -void DEBUGPRINTF(const char *,const char * ) { } - -#endif - - -DeviceManager::DeviceManager(int def) -{ -#if 1 - if (def==-1) - { - TDEInstance *tmp_instance=0L; - if (!TDEGlobal::_instance) tmp_instance=new TDEInstance("nonKDEapp"); - TDEConfig *config = new TDEConfig("kcmmidirc", true); - - config->setGroup("Configuration"); - default_dev=config->readNumEntry("midiDevice",0); - if ( default_dev < 0 ) - default_dev=0; - TQString mapurl(config->readPathEntry("mapFilename")); - if ((config->readBoolEntry("useMidiMapper", false))&&(!mapurl.isEmpty())) - { - mapper_tmp = new MidiMapper( mapurl.mid(mapurl.find(":")+1 ).local8Bit() ); - } - else - mapper_tmp = 0L; - - delete config; - delete tmp_instance; - } - else -#endif - { - default_dev = def; - mapper_tmp = 0L; - } - - initialized=0; - _ok=1; - alsa=false; - device = 0L; - m_rate=0; - convertrate=10; - seqfd=-1; - timerstarted=0; - n_midi=0; - n_synths=0; - n_total=0; - midiinfo=0L; - synthinfo=0L; - for (int i=0;i<16;i++) chn2dev[i]=default_dev; -} - -DeviceManager::~DeviceManager(void) -{ - closeDev(); - if (device) - { - for (int i=0;i=n_total) default_dev=0; - DEBUGPRINTF("check : %d\n",r); - return r; - } - return 0; -} - -void DeviceManager::checkAlsa(void) -{ -#ifdef HAVE_SYS_STAT_H - struct stat buf; - stat("/proc/asound", &buf); - if ((stat("/proc/asound", &buf) == 0 ) && (S_ISDIR(buf.st_mode))) - alsa=true; - else - alsa=false; -#else -#warning "ALSA won't be found at runtime" - alsa=false; -#endif -} - -int DeviceManager::initManager(void) -{ - checkAlsa(); - - if (!alsa) // We are using OSS - { -#ifdef HAVE_OSS_SUPPORT - n_synths=0; - n_midi=0; - n_total=0; - - seqfd = open("/dev/sequencer", O_WRONLY | O_NONBLOCK, 0); - if (seqfd==-1) - { - fprintf(stderr,"ERROR: Couldn't open /dev/sequencer to get some information\n"); - _ok=0; - return -1; - } - ioctl(seqfd,SNDCTL_SEQ_NRSYNTHS,&n_synths); - ioctl(seqfd,SNDCTL_SEQ_NRMIDIS,&n_midi); - n_total=n_midi+n_synths; - - - if (n_midi==0) - { - fprintf(stderr,"ERROR: There's no midi port\n"); - /* This could be a problem if the user don't have a synth neither, - but not having any of both things is unusual */ - // _ok=0; - // return 1; - } - - device=new MidiOut*[n_total]; - midiinfo=new midi_info[n_midi]; - synthinfo=new synth_info[n_synths]; - - int i; - for (i=0;iopenDev(seqfd); -// DEBUGPRINTF("%s ",device[i]->deviceName()); - } -// DEBUGPRINTF("\n"); - for (int i=0;iok()) _ok=0; - if (_ok==0) - { - for (int i=0;icloseDev(); -// DEBUGPRINTF("DeviceMan :: ERROR : Closing devices\n"); - return; - } - -// DEBUGPRINTF("Devices opened\n"); -} - -void DeviceManager::closeDev(void) -{ - if (alsa) - { - if (device) - for (int i=0;icloseDev(); - - return; - } - -#ifdef HAVE_OSS_SUPPORT - if (seqfd==-1) return; - tmrStop(); - if (device) - for (int i=0;icloseDev(); - /* - DEBUGPRINTF("Closing devices : "); - if (device!=NULL) for (int i=0;iinitDev(); - DEBUGPRINTF("%s ",device[i]->deviceName()); - - // device[i]->closeDev(); - }; - DEBUGPRINTF("\n"); - */ - close(seqfd); - seqfd=-1; -#endif -} - -void DeviceManager::initDev(void) -{ - if (device!=0L) - { -// DEBUGPRINTF("Initializing devices :"); - for (int i=0;iinitDev(); - DEBUGPRINTF("%s ",device[i]->deviceName()); - } - DEBUGPRINTF("\n"); - } -} - -void DeviceManager::noteOn ( uchar chn, uchar note, uchar vel ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->noteOn(chn,note,vel); -} -void DeviceManager::noteOff ( uchar chn, uchar note, uchar vel ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->noteOff(chn,note,vel); -} -void DeviceManager::keyPressure ( uchar chn, uchar note, uchar vel ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->keyPressure(chn,note,vel); -} -void DeviceManager::chnPatchChange ( uchar chn, uchar patch ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->chnPatchChange(chn,patch); -} -void DeviceManager::chnPressure ( uchar chn, uchar vel ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->chnPressure(chn,vel); -} -void DeviceManager::chnPitchBender ( uchar chn, uchar lsb, uchar msb ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->chnPitchBender(chn,lsb,msb); -} -void DeviceManager::chnController ( uchar chn, uchar ctl , uchar v ) -{ - MidiOut *midi=chntodev(chn); - if (midi) midi->chnController(chn,ctl,v); -} -void DeviceManager::sysEx ( uchar *data,ulong size) -{ - for (int i=0;isysex(data,size); -} - -void DeviceManager::wait (double ticks) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->wait(ticks); return; }; -#endif - -#ifdef HAVE_OSS_SUPPORT - unsigned long int t=(unsigned long int)(ticks/convertrate); - if (lastwaittime==t) return; - lastwaittime=t; - SEQ_WAIT_TIME(t); - SEQ_DUMPBUF(); -#endif -} - -//void DeviceManager::tmrSetTempo(int v) -void DeviceManager::tmrSetTempo(int v) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->tmrSetTempo(v); return; } -#endif - -#ifdef HAVE_OSS_SUPPORT - SEQ_SET_TEMPO(v); - SEQ_DUMPBUF(); -#endif -} - -void DeviceManager::tmrStart(long int -#ifdef HAVE_ALSA_SUPPORT -tpcn /*name the argument only if it is used*/ -#endif -) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->tmrStart(tpcn); return; } -#endif - -#ifdef HAVE_OSS_SUPPORT -#ifdef CONTROLTIMER - if (!timerstarted) - { - SEQ_START_TIMER(); - SEQ_DUMPBUF(); - timerstarted=1; - } - lastwaittime=0; -#else - SEQ_START_TIMER(); - SEQ_DUMPBUF(); -#endif -#endif -} - -void DeviceManager::tmrStop(void) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->tmrStop(); return; } -#endif - -#ifdef HAVE_OSS_SUPPORT -#ifdef CONTROLTIMER - if (timerstarted) - { - SEQ_STOP_TIMER(); - SEQ_DUMPBUF(); - timerstarted=0; - } -#else - SEQ_STOP_TIMER(); - SEQ_DUMPBUF(); -#endif -#endif -} - -void DeviceManager::tmrContinue(void) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->tmrContinue(); return; } -#endif - -#ifdef HAVE_OSS_SUPPORT -#ifdef CONTROLTIMER - if (timerstarted) - { - SEQ_CONTINUE_TIMER(); - SEQ_DUMPBUF(); - } -#else - SEQ_CONTINUE_TIMER(); - SEQ_DUMPBUF(); -#endif -#endif -} - -void DeviceManager::sync(bool f) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->sync(f); return ; }; -#endif - -#ifdef HAVE_OSS_SUPPORT -#ifdef DEVICEMANDEBUG - printf("Sync %d\n",f); -#endif - if (f) - { - seqbuf_clean(); - /* If you have any problem, try removing the next 2 lines, - I though they would be useful here but the may have side effects */ - ioctl(seqfd,SNDCTL_SEQ_RESET); - ioctl(seqfd,SNDCTL_SEQ_PANIC); - } - else - { - seqbuf_dump(); - ioctl(seqfd, SNDCTL_SEQ_SYNC); - }; -#endif -} - -void DeviceManager::seqbuf_dump (void) -{ - if (!alsa) - { -#ifdef HAVE_OSS_SUPPORT - if (_seqbufptr) - { - int r=0; - unsigned char *sb=_seqbuf; - int w=_seqbufptr; - r=write (seqfd, _seqbuf, _seqbufptr); -#ifdef DEVICEMANDEBUG - printf("%d == %d\n",r,w); - printf("%d\n",(errno==EAGAIN)? 1 : 0); -#endif - while (((r == -1)&&(errno==EAGAIN))||(r != w)) - { - if ((r==-1)&&(errno==EAGAIN)) - { - usleep(1); - } - else if ((r>0)&&(r!=w)) - { - w-=r; - sb+=r; - } - r=write (seqfd, sb, w); -#ifdef DEVICEMANDEBUG - printf("%d == %d\n",r,w); - printf("%d\n",(errno==EAGAIN)? 1 : 0); -#endif - } - } - /* - * if (_seqbufptr) - * if (write (seqfd, _seqbuf, _seqbufptr) == -1) - * { - * printf("Error writing to /dev/sequencer in deviceManager::seqbuf_dump\n"); - * perror ("write /dev/sequencer in seqbuf_dump\n"); - * exit (-1); - * } - */ - _seqbufptr = 0; -#endif - } -} - -void DeviceManager::seqbuf_clean(void) -{ -#ifdef HAVE_ALSA_SUPPORT - if (alsa) { ((AlsaOut *)device[default_dev])->seqbuf_clean(); return ; } -#endif -#ifdef HAVE_OSS_SUPPORT - _seqbufptr=0; -#endif -} - - -const char *DeviceManager::name(int i) -{ -#ifdef HAVE_OSS_SUPPORT - if (checkInit()<0) {_ok = 0; return NULL;} - - if (alsa) - { - if (ideviceName(); - } - else - { - if (i=n_total) return; - default_dev=i; - for (int i=0;i<16;i++) chn2dev[i]=default_dev; -} - -const char *DeviceManager::midiMapFilename(void) -{ - if (device==0L) return ""; - if (default_dev>=n_total) return ""; - return (device[default_dev]!=NULL) ? - device[default_dev]->midiMapFilename() : ""; -} - -void DeviceManager::setMidiMap(MidiMapper *map) -{ - if (map==NULL) return; - mapper_tmp=map; - if (default_dev>=n_total) {default_dev=0;return;}; - if ((device==0L)||(device[default_dev]==NULL)) - return; - device[default_dev]->setMidiMapper(map); -} - -int DeviceManager::setPatchesToUse(int *patchesused) -{ - if (checkInit()<0) return -1; - if ((device==0L)||(device[default_dev]==NULL)) - return 0; - - if ((device[default_dev]->deviceType())==KMID_GUS) - { - GUSOut *gus=(GUSOut *)device[default_dev]; - gus->setPatchesToUse(patchesused); - } - return 0; -} - -void DeviceManager::setVolumePercentage(int v) -{ - if (device!=0L) - { - for (int i=0;isetVolumePercentage(v); - } - } -} - -void DeviceManager::setDeviceNumberForChannel(int chn, int dev) -{ - chn2dev[chn]=dev; -} - -void DeviceManager::allNotesOff(void) -{ - for (int i=0;iallNotesOff(); -} diff --git a/libtdemid/deviceman.cpp b/libtdemid/deviceman.cpp new file mode 100644 index 000000000..18bb9fcc2 --- /dev/null +++ b/libtdemid/deviceman.cpp @@ -0,0 +1,828 @@ +/************************************************************************** + + deviceman.cpp - The device manager, that hides the use of midiOut + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + $Id$ + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "deviceman.h" +#include "midiout.h" +#include +#include +#include +#include +#include +#include "sndcard.h" +#include "synthout.h" +#include "fmout.h" +#include "gusout.h" +#include "alsaout.h" +#include "midimapper.h" +#include "midispec.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_ALSA_ASOUNDLIB_H +# define HAVE_ALSA_SUPPORT +# include +#elif defined(HAVE_SYS_ASOUNDLIB_H) +# define HAVE_ALSA_SUPPORT +# include +#else +#ifdef HAVE_LIBASOUND2 +# define HAVE_ALSA_SUPPORT +# include +# include +#elif defined(HAVE_LIBASOUND) +# define HAVE_ALSA_SUPPORT +# include +#endif +#endif + +#if 1 +#include +#include +#include +#endif + +//#define DEVICEMANDEBUG +//#define GENERAL_DEBUG_MESSAGES + +SEQ_DEFINEBUF (4096); + +#define CONTROLTIMER + +#ifdef GENERAL_DEBUG_MESSAGES +void DEBUGPRINTF(const char *format) +{ + printf(format); +} + +void DEBUGPRINTF(const char *format,int i) +{ + printf(format,i); +} + +void DEBUGPRINTF(const char *format,const char *s) +{ + printf(format,s); +} + +#else + +void DEBUGPRINTF(const char *) { } +void DEBUGPRINTF(const char *,int ) { } +void DEBUGPRINTF(const char *,const char * ) { } + +#endif + + +DeviceManager::DeviceManager(int def) +{ +#if 1 + if (def==-1) + { + TDEInstance *tmp_instance=0L; + if (!TDEGlobal::_instance) tmp_instance=new TDEInstance("nonKDEapp"); + TDEConfig *config = new TDEConfig("kcmmidirc", true); + + config->setGroup("Configuration"); + default_dev=config->readNumEntry("midiDevice",0); + if ( default_dev < 0 ) + default_dev=0; + TQString mapurl(config->readPathEntry("mapFilename")); + if ((config->readBoolEntry("useMidiMapper", false))&&(!mapurl.isEmpty())) + { + mapper_tmp = new MidiMapper( mapurl.mid(mapurl.find(":")+1 ).local8Bit() ); + } + else + mapper_tmp = 0L; + + delete config; + delete tmp_instance; + } + else +#endif + { + default_dev = def; + mapper_tmp = 0L; + } + + initialized=0; + _ok=1; + alsa=false; + device = 0L; + m_rate=0; + convertrate=10; + seqfd=-1; + timerstarted=0; + n_midi=0; + n_synths=0; + n_total=0; + midiinfo=0L; + synthinfo=0L; + for (int i=0;i<16;i++) chn2dev[i]=default_dev; +} + +DeviceManager::~DeviceManager(void) +{ + closeDev(); + if (device) + { + for (int i=0;i=n_total) default_dev=0; + DEBUGPRINTF("check : %d\n",r); + return r; + } + return 0; +} + +void DeviceManager::checkAlsa(void) +{ +#ifdef HAVE_SYS_STAT_H + struct stat buf; + stat("/proc/asound", &buf); + if ((stat("/proc/asound", &buf) == 0 ) && (S_ISDIR(buf.st_mode))) + alsa=true; + else + alsa=false; +#else +#warning "ALSA won't be found at runtime" + alsa=false; +#endif +} + +int DeviceManager::initManager(void) +{ + checkAlsa(); + + if (!alsa) // We are using OSS + { +#ifdef HAVE_OSS_SUPPORT + n_synths=0; + n_midi=0; + n_total=0; + + seqfd = open("/dev/sequencer", O_WRONLY | O_NONBLOCK, 0); + if (seqfd==-1) + { + fprintf(stderr,"ERROR: Couldn't open /dev/sequencer to get some information\n"); + _ok=0; + return -1; + } + ioctl(seqfd,SNDCTL_SEQ_NRSYNTHS,&n_synths); + ioctl(seqfd,SNDCTL_SEQ_NRMIDIS,&n_midi); + n_total=n_midi+n_synths; + + + if (n_midi==0) + { + fprintf(stderr,"ERROR: There's no midi port\n"); + /* This could be a problem if the user don't have a synth neither, + but not having any of both things is unusual */ + // _ok=0; + // return 1; + } + + device=new MidiOut*[n_total]; + midiinfo=new midi_info[n_midi]; + synthinfo=new synth_info[n_synths]; + + int i; + for (i=0;iopenDev(seqfd); +// DEBUGPRINTF("%s ",device[i]->deviceName()); + } +// DEBUGPRINTF("\n"); + for (int i=0;iok()) _ok=0; + if (_ok==0) + { + for (int i=0;icloseDev(); +// DEBUGPRINTF("DeviceMan :: ERROR : Closing devices\n"); + return; + } + +// DEBUGPRINTF("Devices opened\n"); +} + +void DeviceManager::closeDev(void) +{ + if (alsa) + { + if (device) + for (int i=0;icloseDev(); + + return; + } + +#ifdef HAVE_OSS_SUPPORT + if (seqfd==-1) return; + tmrStop(); + if (device) + for (int i=0;icloseDev(); + /* + DEBUGPRINTF("Closing devices : "); + if (device!=NULL) for (int i=0;iinitDev(); + DEBUGPRINTF("%s ",device[i]->deviceName()); + + // device[i]->closeDev(); + }; + DEBUGPRINTF("\n"); + */ + close(seqfd); + seqfd=-1; +#endif +} + +void DeviceManager::initDev(void) +{ + if (device!=0L) + { +// DEBUGPRINTF("Initializing devices :"); + for (int i=0;iinitDev(); + DEBUGPRINTF("%s ",device[i]->deviceName()); + } + DEBUGPRINTF("\n"); + } +} + +void DeviceManager::noteOn ( uchar chn, uchar note, uchar vel ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->noteOn(chn,note,vel); +} +void DeviceManager::noteOff ( uchar chn, uchar note, uchar vel ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->noteOff(chn,note,vel); +} +void DeviceManager::keyPressure ( uchar chn, uchar note, uchar vel ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->keyPressure(chn,note,vel); +} +void DeviceManager::chnPatchChange ( uchar chn, uchar patch ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->chnPatchChange(chn,patch); +} +void DeviceManager::chnPressure ( uchar chn, uchar vel ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->chnPressure(chn,vel); +} +void DeviceManager::chnPitchBender ( uchar chn, uchar lsb, uchar msb ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->chnPitchBender(chn,lsb,msb); +} +void DeviceManager::chnController ( uchar chn, uchar ctl , uchar v ) +{ + MidiOut *midi=chntodev(chn); + if (midi) midi->chnController(chn,ctl,v); +} +void DeviceManager::sysEx ( uchar *data,ulong size) +{ + for (int i=0;isysex(data,size); +} + +void DeviceManager::wait (double ticks) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->wait(ticks); return; }; +#endif + +#ifdef HAVE_OSS_SUPPORT + unsigned long int t=(unsigned long int)(ticks/convertrate); + if (lastwaittime==t) return; + lastwaittime=t; + SEQ_WAIT_TIME(t); + SEQ_DUMPBUF(); +#endif +} + +//void DeviceManager::tmrSetTempo(int v) +void DeviceManager::tmrSetTempo(int v) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->tmrSetTempo(v); return; } +#endif + +#ifdef HAVE_OSS_SUPPORT + SEQ_SET_TEMPO(v); + SEQ_DUMPBUF(); +#endif +} + +void DeviceManager::tmrStart(long int +#ifdef HAVE_ALSA_SUPPORT +tpcn /*name the argument only if it is used*/ +#endif +) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->tmrStart(tpcn); return; } +#endif + +#ifdef HAVE_OSS_SUPPORT +#ifdef CONTROLTIMER + if (!timerstarted) + { + SEQ_START_TIMER(); + SEQ_DUMPBUF(); + timerstarted=1; + } + lastwaittime=0; +#else + SEQ_START_TIMER(); + SEQ_DUMPBUF(); +#endif +#endif +} + +void DeviceManager::tmrStop(void) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->tmrStop(); return; } +#endif + +#ifdef HAVE_OSS_SUPPORT +#ifdef CONTROLTIMER + if (timerstarted) + { + SEQ_STOP_TIMER(); + SEQ_DUMPBUF(); + timerstarted=0; + } +#else + SEQ_STOP_TIMER(); + SEQ_DUMPBUF(); +#endif +#endif +} + +void DeviceManager::tmrContinue(void) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->tmrContinue(); return; } +#endif + +#ifdef HAVE_OSS_SUPPORT +#ifdef CONTROLTIMER + if (timerstarted) + { + SEQ_CONTINUE_TIMER(); + SEQ_DUMPBUF(); + } +#else + SEQ_CONTINUE_TIMER(); + SEQ_DUMPBUF(); +#endif +#endif +} + +void DeviceManager::sync(bool f) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->sync(f); return ; }; +#endif + +#ifdef HAVE_OSS_SUPPORT +#ifdef DEVICEMANDEBUG + printf("Sync %d\n",f); +#endif + if (f) + { + seqbuf_clean(); + /* If you have any problem, try removing the next 2 lines, + I though they would be useful here but the may have side effects */ + ioctl(seqfd,SNDCTL_SEQ_RESET); + ioctl(seqfd,SNDCTL_SEQ_PANIC); + } + else + { + seqbuf_dump(); + ioctl(seqfd, SNDCTL_SEQ_SYNC); + }; +#endif +} + +void DeviceManager::seqbuf_dump (void) +{ + if (!alsa) + { +#ifdef HAVE_OSS_SUPPORT + if (_seqbufptr) + { + int r=0; + unsigned char *sb=_seqbuf; + int w=_seqbufptr; + r=write (seqfd, _seqbuf, _seqbufptr); +#ifdef DEVICEMANDEBUG + printf("%d == %d\n",r,w); + printf("%d\n",(errno==EAGAIN)? 1 : 0); +#endif + while (((r == -1)&&(errno==EAGAIN))||(r != w)) + { + if ((r==-1)&&(errno==EAGAIN)) + { + usleep(1); + } + else if ((r>0)&&(r!=w)) + { + w-=r; + sb+=r; + } + r=write (seqfd, sb, w); +#ifdef DEVICEMANDEBUG + printf("%d == %d\n",r,w); + printf("%d\n",(errno==EAGAIN)? 1 : 0); +#endif + } + } + /* + * if (_seqbufptr) + * if (write (seqfd, _seqbuf, _seqbufptr) == -1) + * { + * printf("Error writing to /dev/sequencer in deviceManager::seqbuf_dump\n"); + * perror ("write /dev/sequencer in seqbuf_dump\n"); + * exit (-1); + * } + */ + _seqbufptr = 0; +#endif + } +} + +void DeviceManager::seqbuf_clean(void) +{ +#ifdef HAVE_ALSA_SUPPORT + if (alsa) { ((AlsaOut *)device[default_dev])->seqbuf_clean(); return ; } +#endif +#ifdef HAVE_OSS_SUPPORT + _seqbufptr=0; +#endif +} + + +const char *DeviceManager::name(int i) +{ +#ifdef HAVE_OSS_SUPPORT + if (checkInit()<0) {_ok = 0; return NULL;} + + if (alsa) + { + if (ideviceName(); + } + else + { + if (i=n_total) return; + default_dev=i; + for (int i=0;i<16;i++) chn2dev[i]=default_dev; +} + +const char *DeviceManager::midiMapFilename(void) +{ + if (device==0L) return ""; + if (default_dev>=n_total) return ""; + return (device[default_dev]!=NULL) ? + device[default_dev]->midiMapFilename() : ""; +} + +void DeviceManager::setMidiMap(MidiMapper *map) +{ + if (map==NULL) return; + mapper_tmp=map; + if (default_dev>=n_total) {default_dev=0;return;}; + if ((device==0L)||(device[default_dev]==NULL)) + return; + device[default_dev]->setMidiMapper(map); +} + +int DeviceManager::setPatchesToUse(int *patchesused) +{ + if (checkInit()<0) return -1; + if ((device==0L)||(device[default_dev]==NULL)) + return 0; + + if ((device[default_dev]->deviceType())==KMID_GUS) + { + GUSOut *gus=(GUSOut *)device[default_dev]; + gus->setPatchesToUse(patchesused); + } + return 0; +} + +void DeviceManager::setVolumePercentage(int v) +{ + if (device!=0L) + { + for (int i=0;isetVolumePercentage(v); + } + } +} + +void DeviceManager::setDeviceNumberForChannel(int chn, int dev) +{ + chn2dev[chn]=dev; +} + +void DeviceManager::allNotesOff(void) +{ + for (int i=0;iallNotesOff(); +} diff --git a/libtdemid/fmout.cc b/libtdemid/fmout.cc deleted file mode 100644 index 72b3198c9..000000000 --- a/libtdemid/fmout.cc +++ /dev/null @@ -1,354 +0,0 @@ -/************************************************************************** - - fmout.cc - class fmOut which handles the /dev/sequencer device - for fm synths - This file is part of LibKMid 0.9.5 - Copyright (C) 1998,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "fmout.h" -#include -#include -#include -#include "sndcard.h" -#include -#include -#include -#include -#include -#include -#include "midispec.h" -#ifdef HAVE_CONFIG_H -#include -#endif - -SEQ_USE_EXTBUF(); - -FMOut::FMOut( int d, int total ) -{ - seqfd = -1; - devicetype = KMID_FM; - device = d; - _ok = 1; - // Put opl=3 for opl/3 (better quality/ 6 voices) - // or opl=2 for fm output (less quality/ 18 voices, which is better imho) : - opl = 2; - // But be aware that opl=3 is not intended to be fully supported by now - - nvoices = total; - vm = new VoiceManager (nvoices); -} - -FMOut::~FMOut() -{ - closeDev(); - delete vm; - if (deleteFMPatchesDirectory) - { - free((char *)FMPatchesDirectory); - deleteFMPatchesDirectory = 0; - FMPatchesDirectory="/etc"; - } -} - -void FMOut::openDev (int sqfd) -{ -#ifdef HAVE_OSS_SUPPORT - _ok=1; - seqfd = sqfd; - //vm->clearLists(); - if ( seqfd == -1 ) - { - printfdebug("ERROR: Could not open /dev/sequencer\n"); - return; - } - - loadFMPatches(); -#endif - -} - -void FMOut::closeDev (void) -{ - if (!ok()) return; - vm->clearLists(); - //if (seqfd>=0) close(seqfd); - seqfd = -1; -} - -void FMOut::initDev (void) -{ -#ifdef HAVE_OSS_SUPPORT - int chn; - if (!ok()) return; - uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; - sysex(gm_reset, sizeof(gm_reset)); - for (chn=0;chn<16;chn++) - { - chnmute[chn]=0; - chnPatchChange(chn,0); - chnPressure(chn,127); - chnPitchBender(chn, 0x00, 0x40); - chnController(chn, CTL_MAIN_VOLUME,127); - chnController(chn, CTL_EXT_EFF_DEPTH, 0); - chnController(chn, CTL_CHORUS_DEPTH, 0); - chnController(chn, 0x4a, 127); - } - - if (opl==3) ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &device); - SEQ_VOLUME_MODE(device,VOL_METHOD_LINEAR); - - for (int i = 0; i < nvoices; i++) - { - SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR); - SEQ_STOP_NOTE(device, i, vm->note(i), 64); - } -#endif -} - -void FMOut::loadFMPatches(void) -{ -#ifdef HAVE_OSS_SUPPORT - char patchesfile[strlen(FMPatchesDirectory)+7+1]; - char drumsfile[strlen(FMPatchesDirectory)+9+1]; - int size; - struct sbi_instrument instr; - char tmp[60]; - int i,j; - for ( i=0; i<256; i++ ) - patchloaded[i] = 0; - int stereoeffect=rand()%3; - FILE *fh; - int datasize; - - if (opl==3) - { - snprintf(patchesfile, sizeof(patchesfile), "%s/std.o3",FMPatchesDirectory); - size=60; - } - else - { - snprintf(patchesfile, sizeof(patchesfile), "%s/std.sb",FMPatchesDirectory); - size=52; - } - fh=fopen(patchesfile,"rb"); - if (fh==NULL) return; - - for (i=0;i<128;i++) - { - fread(tmp,size,1,fh); - patchloaded[i]=1; - instr.key = ((strncmp(tmp, "4OP", 3) == 0))? OPL3_PATCH : FM_PATCH; - datasize = (strncmp(tmp, "4OP", 3) == 0)? 22 : 11; - instr.device=device; - instr.channel = i; - // Let's get some stereo effect ... - tmp[46] = (tmp[46] & 0xcf) | ((++stereoeffect)<<4); - stereoeffect=stereoeffect%3; - for (j=0; j<22; j++) - instr.operators[j] = tmp[j+36]; - SEQ_WRPATCH(&instr,sizeof(instr)); - } - fclose(fh); - - if (opl==3) - { - snprintf(drumsfile, sizeof(drumsfile), "%s/drums.o3",FMPatchesDirectory); - } - else - { - snprintf(drumsfile, sizeof(drumsfile), "%s/drums.sb",FMPatchesDirectory); - } - - fh=fopen(drumsfile,"rb"); - if (fh==NULL) return; - - for (i=128;i<175;i++) - { - fread(tmp,size,1,fh); - patchloaded[i]=1; - instr.key = (strncmp(tmp, "4OP", 3) == 0)? OPL3_PATCH : FM_PATCH; - datasize = (strncmp(tmp, "4OP", 3) == 0)? 22 : 11; - instr.device=device; - instr.channel = i; - // Let's get some stereo effect ... - tmp[46] = (tmp[46] & 0xcf) | ((++stereoeffect)<<4); - stereoeffect=stereoeffect%3; - for (j=0; j<22; j++) - instr.operators[j] = tmp[j+36]; - SEQ_WRPATCH(&instr,sizeof(instr)); - } - fclose(fh); - -#ifdef FMOUTDEBUG - printfdebug("Patches loaded\n"); -#endif -#endif -} - -int FMOut::patch(int p) -{ - if (patchloaded[p]==1) return p; -#ifdef FMOUTDEBUG - printfdebug("Not loaded %d!\n",p); -#endif - p=0; - while ((p<256)&&(patchloaded[p]==0)) p++; - return p; -} - -void FMOut::noteOn (uchar chn, uchar note, uchar vel) -{ - if (vel==0) - { - noteOff(chn,note,vel); - } - else - { - if (chn==PERCUSSION_CHANNEL) - { - if (patchloaded[note+128]==0) return; - else - if (patchloaded[chnpatch[chn]]==0) return; - } - int v=vm->allocateVoice(chn,note); - int p; - if (chn==PERCUSSION_CHANNEL) - SEQ_SET_PATCH(device,v ,p=patch(note+128)) - else - SEQ_SET_PATCH(device,v ,p=map->patch(chn,chnpatch[chn])); - SEQ_BENDER(device, v, chnbender[chn]); - - SEQ_START_NOTE(device, v, note, vel); - // SEQ_CONTROL(device, v, CTL_MAIN_VOLUME, chncontroller[chn][CTL_MAIN_VOLUME]); - - SEQ_CHN_PRESSURE(device, v , chnpressure[chn]); - } - -#ifdef FMOUTDEBUG - printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void FMOut::noteOff (uchar chn, uchar note, uchar vel) -{ - int i; - vm->initSearch(); - while ((i=vm->search(chn,note))!=-1) - { - SEQ_STOP_NOTE(device, i, note, vel); - vm->deallocateVoice(i); - } - -#ifdef FMOUTDEBUG - printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void FMOut::keyPressure (uchar chn, uchar note, uchar vel) -{ - int i; - vm->initSearch(); - while ((i=vm->search(chn,note))!=-1) - SEQ_KEY_PRESSURE(device, i, note,vel); -} - -void FMOut::chnPatchChange (uchar chn, uchar patch) -{ - if (chn==PERCUSSION_CHANNEL) return; - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_SET_PATCH(device,i,map->patch(chn,patch)); - - chnpatch[chn]=patch; -} - -void FMOut::chnPressure (uchar chn, uchar vel) -{ - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_CHN_PRESSURE(device, i , vel); - - chnpressure[chn]=vel; -} - -void FMOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) -{ - chnbender[chn]=((int)msb<<7) | (lsb & 0x7F); - - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_BENDER(device, i, chnbender[chn]); - -} - -void FMOut::chnController (uchar chn, uchar ctl, uchar v) -{ - if ((ctl==11)||(ctl==7)) - { - v=(v*volumepercentage)/100; - if (v>127) v=127; - } - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_CONTROL(device, i, ctl, v); - - chncontroller[chn][ctl]=v; -} - -void FMOut::sysex(uchar *, ulong ) -{ - -} - -void FMOut::setFMPatchesDirectory(const char *dir) -{ - if ((dir==NULL)||(dir[0]==0)) return; - if (deleteFMPatchesDirectory) - free((char *)FMPatchesDirectory); - - FMPatchesDirectory = strdup(dir); - - deleteFMPatchesDirectory=1; -} - -void FMOut::setVolumePercentage ( int i ) -{ -#ifdef HAVE_OSS_SUPPORT - int fd=open("/dev/mixer0",O_RDWR,0); - if (fd==-1) return; - int a=i*255/100; - if (a>255) a=255; - a=(a<<8) | a; - if (ioctl(fd,MIXER_WRITE(SOUND_MIXER_SYNTH),&a) == -1) - printfdebug("ERROR writing to mixer\n"); - close(fd); -#endif - volumepercentage=i; -} - - -const char *FMOut::FMPatchesDirectory = "/etc"; -int FMOut::deleteFMPatchesDirectory = 0; diff --git a/libtdemid/fmout.cpp b/libtdemid/fmout.cpp new file mode 100644 index 000000000..eb069e51c --- /dev/null +++ b/libtdemid/fmout.cpp @@ -0,0 +1,354 @@ +/************************************************************************** + + fmout.cpp - class fmOut which handles the /dev/sequencer device + for fm synths + This file is part of LibKMid 0.9.5 + Copyright (C) 1998,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "fmout.h" +#include +#include +#include +#include "sndcard.h" +#include +#include +#include +#include +#include +#include +#include "midispec.h" +#ifdef HAVE_CONFIG_H +#include +#endif + +SEQ_USE_EXTBUF(); + +FMOut::FMOut( int d, int total ) +{ + seqfd = -1; + devicetype = KMID_FM; + device = d; + _ok = 1; + // Put opl=3 for opl/3 (better quality/ 6 voices) + // or opl=2 for fm output (less quality/ 18 voices, which is better imho) : + opl = 2; + // But be aware that opl=3 is not intended to be fully supported by now + + nvoices = total; + vm = new VoiceManager (nvoices); +} + +FMOut::~FMOut() +{ + closeDev(); + delete vm; + if (deleteFMPatchesDirectory) + { + free((char *)FMPatchesDirectory); + deleteFMPatchesDirectory = 0; + FMPatchesDirectory="/etc"; + } +} + +void FMOut::openDev (int sqfd) +{ +#ifdef HAVE_OSS_SUPPORT + _ok=1; + seqfd = sqfd; + //vm->clearLists(); + if ( seqfd == -1 ) + { + printfdebug("ERROR: Could not open /dev/sequencer\n"); + return; + } + + loadFMPatches(); +#endif + +} + +void FMOut::closeDev (void) +{ + if (!ok()) return; + vm->clearLists(); + //if (seqfd>=0) close(seqfd); + seqfd = -1; +} + +void FMOut::initDev (void) +{ +#ifdef HAVE_OSS_SUPPORT + int chn; + if (!ok()) return; + uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; + sysex(gm_reset, sizeof(gm_reset)); + for (chn=0;chn<16;chn++) + { + chnmute[chn]=0; + chnPatchChange(chn,0); + chnPressure(chn,127); + chnPitchBender(chn, 0x00, 0x40); + chnController(chn, CTL_MAIN_VOLUME,127); + chnController(chn, CTL_EXT_EFF_DEPTH, 0); + chnController(chn, CTL_CHORUS_DEPTH, 0); + chnController(chn, 0x4a, 127); + } + + if (opl==3) ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &device); + SEQ_VOLUME_MODE(device,VOL_METHOD_LINEAR); + + for (int i = 0; i < nvoices; i++) + { + SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR); + SEQ_STOP_NOTE(device, i, vm->note(i), 64); + } +#endif +} + +void FMOut::loadFMPatches(void) +{ +#ifdef HAVE_OSS_SUPPORT + char patchesfile[strlen(FMPatchesDirectory)+7+1]; + char drumsfile[strlen(FMPatchesDirectory)+9+1]; + int size; + struct sbi_instrument instr; + char tmp[60]; + int i,j; + for ( i=0; i<256; i++ ) + patchloaded[i] = 0; + int stereoeffect=rand()%3; + FILE *fh; + int datasize; + + if (opl==3) + { + snprintf(patchesfile, sizeof(patchesfile), "%s/std.o3",FMPatchesDirectory); + size=60; + } + else + { + snprintf(patchesfile, sizeof(patchesfile), "%s/std.sb",FMPatchesDirectory); + size=52; + } + fh=fopen(patchesfile,"rb"); + if (fh==NULL) return; + + for (i=0;i<128;i++) + { + fread(tmp,size,1,fh); + patchloaded[i]=1; + instr.key = ((strncmp(tmp, "4OP", 3) == 0))? OPL3_PATCH : FM_PATCH; + datasize = (strncmp(tmp, "4OP", 3) == 0)? 22 : 11; + instr.device=device; + instr.channel = i; + // Let's get some stereo effect ... + tmp[46] = (tmp[46] & 0xcf) | ((++stereoeffect)<<4); + stereoeffect=stereoeffect%3; + for (j=0; j<22; j++) + instr.operators[j] = tmp[j+36]; + SEQ_WRPATCH(&instr,sizeof(instr)); + } + fclose(fh); + + if (opl==3) + { + snprintf(drumsfile, sizeof(drumsfile), "%s/drums.o3",FMPatchesDirectory); + } + else + { + snprintf(drumsfile, sizeof(drumsfile), "%s/drums.sb",FMPatchesDirectory); + } + + fh=fopen(drumsfile,"rb"); + if (fh==NULL) return; + + for (i=128;i<175;i++) + { + fread(tmp,size,1,fh); + patchloaded[i]=1; + instr.key = (strncmp(tmp, "4OP", 3) == 0)? OPL3_PATCH : FM_PATCH; + datasize = (strncmp(tmp, "4OP", 3) == 0)? 22 : 11; + instr.device=device; + instr.channel = i; + // Let's get some stereo effect ... + tmp[46] = (tmp[46] & 0xcf) | ((++stereoeffect)<<4); + stereoeffect=stereoeffect%3; + for (j=0; j<22; j++) + instr.operators[j] = tmp[j+36]; + SEQ_WRPATCH(&instr,sizeof(instr)); + } + fclose(fh); + +#ifdef FMOUTDEBUG + printfdebug("Patches loaded\n"); +#endif +#endif +} + +int FMOut::patch(int p) +{ + if (patchloaded[p]==1) return p; +#ifdef FMOUTDEBUG + printfdebug("Not loaded %d!\n",p); +#endif + p=0; + while ((p<256)&&(patchloaded[p]==0)) p++; + return p; +} + +void FMOut::noteOn (uchar chn, uchar note, uchar vel) +{ + if (vel==0) + { + noteOff(chn,note,vel); + } + else + { + if (chn==PERCUSSION_CHANNEL) + { + if (patchloaded[note+128]==0) return; + else + if (patchloaded[chnpatch[chn]]==0) return; + } + int v=vm->allocateVoice(chn,note); + int p; + if (chn==PERCUSSION_CHANNEL) + SEQ_SET_PATCH(device,v ,p=patch(note+128)) + else + SEQ_SET_PATCH(device,v ,p=map->patch(chn,chnpatch[chn])); + SEQ_BENDER(device, v, chnbender[chn]); + + SEQ_START_NOTE(device, v, note, vel); + // SEQ_CONTROL(device, v, CTL_MAIN_VOLUME, chncontroller[chn][CTL_MAIN_VOLUME]); + + SEQ_CHN_PRESSURE(device, v , chnpressure[chn]); + } + +#ifdef FMOUTDEBUG + printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void FMOut::noteOff (uchar chn, uchar note, uchar vel) +{ + int i; + vm->initSearch(); + while ((i=vm->search(chn,note))!=-1) + { + SEQ_STOP_NOTE(device, i, note, vel); + vm->deallocateVoice(i); + } + +#ifdef FMOUTDEBUG + printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void FMOut::keyPressure (uchar chn, uchar note, uchar vel) +{ + int i; + vm->initSearch(); + while ((i=vm->search(chn,note))!=-1) + SEQ_KEY_PRESSURE(device, i, note,vel); +} + +void FMOut::chnPatchChange (uchar chn, uchar patch) +{ + if (chn==PERCUSSION_CHANNEL) return; + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_SET_PATCH(device,i,map->patch(chn,patch)); + + chnpatch[chn]=patch; +} + +void FMOut::chnPressure (uchar chn, uchar vel) +{ + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_CHN_PRESSURE(device, i , vel); + + chnpressure[chn]=vel; +} + +void FMOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) +{ + chnbender[chn]=((int)msb<<7) | (lsb & 0x7F); + + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_BENDER(device, i, chnbender[chn]); + +} + +void FMOut::chnController (uchar chn, uchar ctl, uchar v) +{ + if ((ctl==11)||(ctl==7)) + { + v=(v*volumepercentage)/100; + if (v>127) v=127; + } + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_CONTROL(device, i, ctl, v); + + chncontroller[chn][ctl]=v; +} + +void FMOut::sysex(uchar *, ulong ) +{ + +} + +void FMOut::setFMPatchesDirectory(const char *dir) +{ + if ((dir==NULL)||(dir[0]==0)) return; + if (deleteFMPatchesDirectory) + free((char *)FMPatchesDirectory); + + FMPatchesDirectory = strdup(dir); + + deleteFMPatchesDirectory=1; +} + +void FMOut::setVolumePercentage ( int i ) +{ +#ifdef HAVE_OSS_SUPPORT + int fd=open("/dev/mixer0",O_RDWR,0); + if (fd==-1) return; + int a=i*255/100; + if (a>255) a=255; + a=(a<<8) | a; + if (ioctl(fd,MIXER_WRITE(SOUND_MIXER_SYNTH),&a) == -1) + printfdebug("ERROR writing to mixer\n"); + close(fd); +#endif + volumepercentage=i; +} + + +const char *FMOut::FMPatchesDirectory = "/etc"; +int FMOut::deleteFMPatchesDirectory = 0; diff --git a/libtdemid/gusout.cc b/libtdemid/gusout.cc deleted file mode 100644 index 69aae3927..000000000 --- a/libtdemid/gusout.cc +++ /dev/null @@ -1,691 +0,0 @@ -/************************************************************************** - - gusout.cc - class GUSOut which implements support for Gravis - Ultrasound cards through a /dev/sequencer device - This file is part of LibKMid 0.9.5 - Copyright (C) 1998,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "gusout.h" -#include "sndcard.h" -#include "midispec.h" -#include "gusvoices.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_CONFIG_H -#include -#endif - -SEQ_USE_EXTBUF(); - -#ifdef HAVE_OSS_SUPPORT -struct pat_header -{ - char magic[12]; - char version[10]; - char description[60]; - unsigned char instruments; - char voices; - char channels; - unsigned short nr_waveforms; - unsigned short master_volume; - unsigned long data_size; -}; -struct sample_header -{ - char name[7]; - unsigned char fractions; - long len; - long loop_start; - long loop_end; - unsigned short base_freq; - long low_note; - long high_note; - long base_note; - short detune; - unsigned char panning; - - unsigned char envelope_rate[6]; - unsigned char envelope_offset[6]; - - unsigned char tremolo_sweep; - unsigned char tremolo_rate; - unsigned char tremolo_depth; - - unsigned char vibrato_sweep; - unsigned char vibrato_rate; - unsigned char vibrato_depth; - - char modes; - - short scale_frequency; - unsigned short scale_factor; -}; - -int get_dint(unsigned char *p) -{ - unsigned int v=0; - - for (int i=0;i<4;i++) - { - v |= (p[i] << (i*8)); - } - return (int)v; -} - -unsigned short get_word(unsigned char *p) -{ - unsigned short v=0; - - for (int i=0;i<2;i++) - v |= (*p++ << (i*8)); - return (short)v; -} - -#endif - -GUSOut::GUSOut(int d,int total) -{ - seqfd = -1; - devicetype=KMID_GUS; - device= d; - _ok=1; - - use8bit=0; - nvoices=total; - vm=new VoiceManager(nvoices); -} - -GUSOut::~GUSOut() -{ - closeDev(); - - delete vm; - if (delete_GUS_patches_directory) - { - free((char *)GUS_patches_directory); - delete_GUS_patches_directory = 0; - GUS_patches_directory="/etc"; - } -} - -void GUSOut::openDev (int sqfd) -{ - _ok=1; - seqfd = sqfd; - //vm->clearLists(); - if (seqfd==-1) - { - printfdebug("ERROR: Could not open /dev/sequencer\n"); - return; - } - -#ifdef HAVE_OSS_SUPPORT - - //seqbuf_clean(); - //ioctl(seqfd,SNDCTL_SEQ_RESET); - //ioctl(seqfd,SNDCTL_SEQ_PANIC); - - if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &device)==-1) - { - printfdebug("Error reseting gus samples. Please report\n"); - }; - use8bit=0; - totalmemory = device; - ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &totalmemory); - freememory = device; - ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory); - -#endif - - -} - -void GUSOut::closeDev (void) -{ - if (!ok()) return; - vm->clearLists(); - //if (seqfd>=0) - // close(seqfd); - seqfd=-1; -} - -void GUSOut::initDev (void) -{ -#ifdef HAVE_OSS_SUPPORT - int chn; - if (!ok()) return; - uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; - sysex(gm_reset, sizeof(gm_reset)); - for (chn=0;chn<16;chn++) - { - chnmute[chn]=0; - chnPatchChange(chn,0); - // chnPressure(chn,127); - chnPitchBender(chn, 0x00, 0x40); - chnController(chn, CTL_MAIN_VOLUME,127); - chnController(chn, CTL_EXT_EFF_DEPTH, 0); - chnController(chn, CTL_CHORUS_DEPTH, 0); - chnController(chn, 0x4a, 127); - } - - - for (int i = 0; i < nvoices; i++) - { - SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR); - SEQ_STOP_NOTE(device, i, vm->note(i), 64); - } - -#endif -} - - -int GUSOut::patch(int p) -{ - if (patchloaded[p]==1) return p; - printfdebug("Not loaded %d!\n",p); - p=0; - while ((p<256)&&(patchloaded[p]==0)) p++; - return p; -} - -void GUSOut::noteOn (uchar chn, uchar note, uchar vel) -{ - if (vel==0) - { - noteOff(chn,note,vel); - } - else - { - if (chn==PERCUSSION_CHANNEL) - { - if (patchloaded[note+128]==0) return; - else - if (patchloaded[chnpatch[chn]]==0) return; - }; - int v=vm->allocateVoice(chn,note); - int p; - if (chn==PERCUSSION_CHANNEL) - SEQ_SET_PATCH(device,v ,p=patch(note+128)) - else - SEQ_SET_PATCH(device,v ,p=map->patch(chn,chnpatch[chn])); - SEQ_BENDER(device, v, chnbender[chn]); - - SEQ_START_NOTE(device, v, note, vel); - // SEQ_CONTROL(device, v, CTL_MAIN_VOLUME, chncontroller[chn][CTL_MAIN_VOLUME]); - SEQ_CHN_PRESSURE(device, v , chnpressure[chn]); - } - - printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -} - -void GUSOut::noteOff (uchar chn, uchar note, uchar vel) -{ - int i; - vm->initSearch(); - while ((i=vm->search(chn,note))!=-1) - { - SEQ_STOP_NOTE(device, i, note, vel); - vm->deallocateVoice(i); - } - -#ifdef GUSOUTDEBUG - printf("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void GUSOut::keyPressure (uchar chn, uchar note, uchar vel) -{ - int i; - vm->initSearch(); - while ((i=vm->search(chn,note))!=-1) - SEQ_KEY_PRESSURE(device, i, note,vel); -} - -void GUSOut::chnPatchChange (uchar chn, uchar patch) -{ - if (chn==PERCUSSION_CHANNEL) return; - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_SET_PATCH(device,i,map->patch(chn,patch)); - chnpatch[chn]=patch; - -} - -void GUSOut::chnPressure (uchar /*chn*/, uchar /*vel*/) -{ - /* int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_CHN_PRESSURE(device, i , vel); - chnpressure[chn]=vel; - */ -} - -void GUSOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) -{ - chnbender[chn]=((int)msb<<7) | (lsb & 0x7F); - - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_BENDER(device, i, chnbender[chn]); -} - -void GUSOut::chnController (uchar chn, uchar ctl, uchar v) -{ - if ((ctl==11)||(ctl==7)) - { - v=(v*volumepercentage)/100; - if (v>127) v=127; - }; - - int i; - vm->initSearch(); - while ((i=vm->search(chn))!=-1) - SEQ_CONTROL(device, i, ctl, v); - - chncontroller[chn][ctl]=v; -} - -void GUSOut::sysex(uchar *, ulong ) -{ - -} - -void GUSOut::setGUSPatchesDirectory(const char *dir) -{ - if ((dir==NULL)||(dir[0]==0)) return; - if (delete_GUS_patches_directory) - free((char *)GUS_patches_directory); - - GUS_patches_directory = strdup(dir); - delete_GUS_patches_directory=1; -} - -const char *GUSOut::patchName(int pgm) -{ - return GUS_voice_names[pgm]; -} - - -int GUSOut::loadPatch(int pgm) -{ -#ifdef HAVE_OSS_SUPPORT - struct pat_header header; - struct sample_header sample; - if (patchloaded[pgm]==1) - { -#ifdef GUSOUTDEBUG - printf("Trying to reload a patch. This should never happen, please report.\n"); -#endif - return 0; - } - if ((patchName(pgm)==NULL)||((patchName(pgm))[0]==0)) - { -#ifdef GUSOUTDEBUG - printf("Couldn't guess patch name for patch number %d\n",pgm); -#endif - return -1; - } - char *s=new char[strlen(GUS_patches_directory)+strlen(patchName(pgm))+10]; - if (s==NULL) return -1; - sprintf(s,"%s/%s.pat",GUS_patches_directory,patchName(pgm)); -#ifdef GUSOUTDEBUG - printf("Loading patch : %s\n",s); -#endif - struct patch_info *patch=NULL; - struct stat info; - if (stat(s, &info)==-1) - { -#ifdef GUSOUTDEBUG - printf("File %s doesn't exist\n",s); -#endif - return -1; - } - - FILE *fh=fopen(s,"rb"); - if (fh==NULL) - { -#ifdef GUSOUTDEBUG - printf("Couldn't open patch %s\n",s); -#endif - return -1; - } - - unsigned char tmp[256]; - if (fread(tmp,1,0xef,fh)!=0xef) - { - fclose(fh); -#ifdef GUSOUTDEBUG - printf("Short file ! \n"); -#endif - return -1; - } - memcpy ((char *) &header, tmp, sizeof (header)); - - if (strncmp(header.magic,"GF1PATCH110",12)!=0) - { -#ifdef GUSOUTDEBUG - printf("File %s is corrupted or it isn't a patch file\n",s); -#endif - return -1; - } - if (strncmp(header.version,"ID#000002",10)!=0) - { -#ifdef GUSOUTDEBUG - printf("File %s's version is not supported\n",s); -#endif - return -1; - } - unsigned short nWaves= *(unsigned short *)&tmp[85]; -#ifdef GUSOUTDEBUG - unsigned short masterVolume= *(unsigned short *)&tmp[87]; - printf("nWaves: %d\n",nWaves); - printf("masterVolume : %d\n",masterVolume); -#endif - - unsigned short i; - int offset=0xef; - for (i=0;ikey = GUS_PATCH; - patch->device_no = device; - patch->instr_no = pgm; - patch->mode = sample.modes | WAVE_TREMOLO | WAVE_VIBRATO | WAVE_SCALE; - patch->len = sample.len; - patch->loop_start = sample.loop_start; - patch->loop_end = sample.loop_end; - patch->base_note = sample.base_note; - patch->high_note = sample.high_note; - patch->low_note = sample.low_note; - patch->base_freq = sample.base_freq; - patch->detuning = sample.detune; - patch->panning = (sample.panning - 7) * 16; - - memcpy (patch->env_rate, sample.envelope_rate, 6); - memcpy (patch->env_offset, sample.envelope_offset, 6); - - patch->tremolo_sweep = sample.tremolo_sweep; - patch->tremolo_rate = sample.tremolo_rate; - patch->tremolo_depth = sample.tremolo_depth; - - patch->vibrato_sweep = sample.vibrato_sweep; - patch->vibrato_rate = sample.vibrato_rate; - patch->vibrato_depth = sample.vibrato_depth; - - patch->scale_frequency = sample.scale_frequency; - patch->scale_factor = sample.scale_factor; - - patch->volume = header.master_volume; - - if (fseek (fh, offset, 0) == -1) - { - fclose(fh); - return -1; - } - - if ((long)fread (patch->data, 1,sample.len,fh) != sample.len) - { -#ifdef GUSOUTDEBUG - printf ("Short file\n"); -#endif - return -1; - } - - SEQ_WRPATCH (patch, sizeof (*patch) + sample.len); - - offset = offset + sample.len; - - } - patchloaded[pgm]=1; - - fclose(fh); - free(patch); // Shouldn't this 'free' be within the 'for' loop ? - delete s; - freememory = device; - ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory); -#endif - return 0; -} - - -void GUSOut::setPatchesToUse(int *patchesused) -{ -#ifdef HAVE_OSS_SUPPORT - int k; - for (k=0;k<256;k++) patchloaded[k]=0; - - int patchesordered[256]; //This holds the pgm used ordered by a method which - // put first the patches more oftenly used, and then the least - // In example, if a song only uses a piano and a splash cymbal, - // This is set to : 0,188,-1,-1,-1,-1 ... - patchesLoadingOrder(patchesused,patchesordered); - - // If above line doesn't work, perhaps you could try this ? : - // for (int j=0;j<256;j++) patchesordered[j]=patchesused[j]; -#ifdef GUSOUTDEBUG - printf("Patches used : \n"); - for (k=0;k<256;k++) - { - if (patchesused[k]!=-1) printf("%d,",patchesused[k]); - } - printf("\n Patches used, sorted :\n"); - for (k=0;k<256;k++) - { - if (patchesordered[k]!=-1) printf("%d,",patchesordered[k]); - } -#endif - - int i=0; - while (patchesordered[i]!=-1) - { -#ifdef GUSOUTDEBUG - printf("Load Patch : %d\n",patchesordered[i]); -#endif - loadPatch(patchesordered[i]); - i++; - } -#endif -} - -int compare_decreasing(const void *a,const void *b) -{ - struct instr_gm - { - int used; - int pgm; - }; - instr_gm *ai=(instr_gm *)a; - instr_gm *bi=(instr_gm *)b; - return ai->usedused; -} - - -void GUSOut::patchesLoadingOrder(int *patchesused,int *patchesordered) -{ - struct instr_gm - { - int used; - int pgm; - }; - - instr_gm tempmelody[128]; - instr_gm tempdrums[128]; - int i,j; - for (i=0,j=128;i<128;i++,j++) - { - tempmelody[i].used=patchesused[i]; - tempmelody[i].pgm=i; - tempdrums[i].used=patchesused[j]; - tempdrums[i].pgm=j; - } - /* SORT */ // Decreasing order (first most used patch, then less used patch) - qsort(&tempmelody[0],128,sizeof(instr_gm),compare_decreasing); - qsort(&tempdrums[0],128,sizeof(instr_gm),compare_decreasing); - - /* Once they are sorted, the result is put on patchesordered in the following - * way : If tempmelody is : M0 M1 M2 M3 ... M127 and tempdrums is : - * D0 D1 D2 D3 ... D127, the result is : - * M0 D0 M1 M2 D1 M3 M4 D2 M5 M6 D3 ... - * P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 ... - */ - -#ifdef GUSOUTDEBUG - for (int k=0;k<128;k++) - { - printf("%d - %d\n",tempmelody[k].used,tempmelody[k].pgm); - } - for (int k=0;k<128;k++) - { - printf("%d : %d\n",tempdrums[k].used,tempdrums[k].pgm); - } -#endif - - i=0; - int totalmelody=0; - while ((i<128)&&(tempmelody[i].used!=0)) - { - totalmelody++; - i++; - } - i=0; - int totaldrums=0; - while ((i<128)&&(tempdrums[i].used!=0)) - { - totaldrums++; - i++; - } -#ifdef GUSOUTDEBUG - printf("Totalmelody : %d,totaldrums : %d\n",totalmelody,totaldrums); -#endif - int tgt=0; - - int tm=totalmelody; - int td=totaldrums; - int cm,cd; - cm=cd=0; - if ((tm!=0)&&(td!=0)) - { - patchesordered[0]=tempmelody[0].pgm; - patchesordered[1]=tempdrums[0].pgm; - tm--;td--; - cm++;cd++; - tgt+=2; - while ((tm>0)&&(td>0)) - { - if (((tgt-1)%3)==0) - { - patchesordered[tgt]=tempdrums[cd].pgm; - cd++; - td--; - } - else - { - patchesordered[tgt]=tempmelody[cm].pgm; - cm++; - tm--; - } - tgt++; - } - } - while (tm>0) - { - patchesordered[tgt]=tempmelody[cm].pgm; - tgt++; - cm++; - tm--; - } - while (td>0) - { - patchesordered[tgt]=tempdrums[cd].pgm; - tgt++; - cd++; - td--; - } - - // Now we put as not used (-1) the rest of the array - while (tgt<256) - { - patchesordered[tgt]=-1; - tgt++; - } -} - -//char *GUSOut::GUS_patches_directory="/mnt/dosc/gravis/patches"; -const char *GUSOut::GUS_patches_directory="/usr/share/ultrasnd"; - -int GUSOut::delete_GUS_patches_directory = 0; -/* No, this doesn't delete any file :-) it's just for internal use */ diff --git a/libtdemid/gusout.cpp b/libtdemid/gusout.cpp new file mode 100644 index 000000000..96c9fb915 --- /dev/null +++ b/libtdemid/gusout.cpp @@ -0,0 +1,691 @@ +/************************************************************************** + + gusout.cpp - class GUSOut which implements support for Gravis + Ultrasound cards through a /dev/sequencer device + This file is part of LibKMid 0.9.5 + Copyright (C) 1998,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "gusout.h" +#include "sndcard.h" +#include "midispec.h" +#include "gusvoices.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_CONFIG_H +#include +#endif + +SEQ_USE_EXTBUF(); + +#ifdef HAVE_OSS_SUPPORT +struct pat_header +{ + char magic[12]; + char version[10]; + char description[60]; + unsigned char instruments; + char voices; + char channels; + unsigned short nr_waveforms; + unsigned short master_volume; + unsigned long data_size; +}; +struct sample_header +{ + char name[7]; + unsigned char fractions; + long len; + long loop_start; + long loop_end; + unsigned short base_freq; + long low_note; + long high_note; + long base_note; + short detune; + unsigned char panning; + + unsigned char envelope_rate[6]; + unsigned char envelope_offset[6]; + + unsigned char tremolo_sweep; + unsigned char tremolo_rate; + unsigned char tremolo_depth; + + unsigned char vibrato_sweep; + unsigned char vibrato_rate; + unsigned char vibrato_depth; + + char modes; + + short scale_frequency; + unsigned short scale_factor; +}; + +int get_dint(unsigned char *p) +{ + unsigned int v=0; + + for (int i=0;i<4;i++) + { + v |= (p[i] << (i*8)); + } + return (int)v; +} + +unsigned short get_word(unsigned char *p) +{ + unsigned short v=0; + + for (int i=0;i<2;i++) + v |= (*p++ << (i*8)); + return (short)v; +} + +#endif + +GUSOut::GUSOut(int d,int total) +{ + seqfd = -1; + devicetype=KMID_GUS; + device= d; + _ok=1; + + use8bit=0; + nvoices=total; + vm=new VoiceManager(nvoices); +} + +GUSOut::~GUSOut() +{ + closeDev(); + + delete vm; + if (delete_GUS_patches_directory) + { + free((char *)GUS_patches_directory); + delete_GUS_patches_directory = 0; + GUS_patches_directory="/etc"; + } +} + +void GUSOut::openDev (int sqfd) +{ + _ok=1; + seqfd = sqfd; + //vm->clearLists(); + if (seqfd==-1) + { + printfdebug("ERROR: Could not open /dev/sequencer\n"); + return; + } + +#ifdef HAVE_OSS_SUPPORT + + //seqbuf_clean(); + //ioctl(seqfd,SNDCTL_SEQ_RESET); + //ioctl(seqfd,SNDCTL_SEQ_PANIC); + + if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &device)==-1) + { + printfdebug("Error reseting gus samples. Please report\n"); + }; + use8bit=0; + totalmemory = device; + ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &totalmemory); + freememory = device; + ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory); + +#endif + + +} + +void GUSOut::closeDev (void) +{ + if (!ok()) return; + vm->clearLists(); + //if (seqfd>=0) + // close(seqfd); + seqfd=-1; +} + +void GUSOut::initDev (void) +{ +#ifdef HAVE_OSS_SUPPORT + int chn; + if (!ok()) return; + uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; + sysex(gm_reset, sizeof(gm_reset)); + for (chn=0;chn<16;chn++) + { + chnmute[chn]=0; + chnPatchChange(chn,0); + // chnPressure(chn,127); + chnPitchBender(chn, 0x00, 0x40); + chnController(chn, CTL_MAIN_VOLUME,127); + chnController(chn, CTL_EXT_EFF_DEPTH, 0); + chnController(chn, CTL_CHORUS_DEPTH, 0); + chnController(chn, 0x4a, 127); + } + + + for (int i = 0; i < nvoices; i++) + { + SEQ_CONTROL(device, i, SEQ_VOLMODE, VOL_METHOD_LINEAR); + SEQ_STOP_NOTE(device, i, vm->note(i), 64); + } + +#endif +} + + +int GUSOut::patch(int p) +{ + if (patchloaded[p]==1) return p; + printfdebug("Not loaded %d!\n",p); + p=0; + while ((p<256)&&(patchloaded[p]==0)) p++; + return p; +} + +void GUSOut::noteOn (uchar chn, uchar note, uchar vel) +{ + if (vel==0) + { + noteOff(chn,note,vel); + } + else + { + if (chn==PERCUSSION_CHANNEL) + { + if (patchloaded[note+128]==0) return; + else + if (patchloaded[chnpatch[chn]]==0) return; + }; + int v=vm->allocateVoice(chn,note); + int p; + if (chn==PERCUSSION_CHANNEL) + SEQ_SET_PATCH(device,v ,p=patch(note+128)) + else + SEQ_SET_PATCH(device,v ,p=map->patch(chn,chnpatch[chn])); + SEQ_BENDER(device, v, chnbender[chn]); + + SEQ_START_NOTE(device, v, note, vel); + // SEQ_CONTROL(device, v, CTL_MAIN_VOLUME, chncontroller[chn][CTL_MAIN_VOLUME]); + SEQ_CHN_PRESSURE(device, v , chnpressure[chn]); + } + + printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +} + +void GUSOut::noteOff (uchar chn, uchar note, uchar vel) +{ + int i; + vm->initSearch(); + while ((i=vm->search(chn,note))!=-1) + { + SEQ_STOP_NOTE(device, i, note, vel); + vm->deallocateVoice(i); + } + +#ifdef GUSOUTDEBUG + printf("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void GUSOut::keyPressure (uchar chn, uchar note, uchar vel) +{ + int i; + vm->initSearch(); + while ((i=vm->search(chn,note))!=-1) + SEQ_KEY_PRESSURE(device, i, note,vel); +} + +void GUSOut::chnPatchChange (uchar chn, uchar patch) +{ + if (chn==PERCUSSION_CHANNEL) return; + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_SET_PATCH(device,i,map->patch(chn,patch)); + chnpatch[chn]=patch; + +} + +void GUSOut::chnPressure (uchar /*chn*/, uchar /*vel*/) +{ + /* int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_CHN_PRESSURE(device, i , vel); + chnpressure[chn]=vel; + */ +} + +void GUSOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) +{ + chnbender[chn]=((int)msb<<7) | (lsb & 0x7F); + + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_BENDER(device, i, chnbender[chn]); +} + +void GUSOut::chnController (uchar chn, uchar ctl, uchar v) +{ + if ((ctl==11)||(ctl==7)) + { + v=(v*volumepercentage)/100; + if (v>127) v=127; + }; + + int i; + vm->initSearch(); + while ((i=vm->search(chn))!=-1) + SEQ_CONTROL(device, i, ctl, v); + + chncontroller[chn][ctl]=v; +} + +void GUSOut::sysex(uchar *, ulong ) +{ + +} + +void GUSOut::setGUSPatchesDirectory(const char *dir) +{ + if ((dir==NULL)||(dir[0]==0)) return; + if (delete_GUS_patches_directory) + free((char *)GUS_patches_directory); + + GUS_patches_directory = strdup(dir); + delete_GUS_patches_directory=1; +} + +const char *GUSOut::patchName(int pgm) +{ + return GUS_voice_names[pgm]; +} + + +int GUSOut::loadPatch(int pgm) +{ +#ifdef HAVE_OSS_SUPPORT + struct pat_header header; + struct sample_header sample; + if (patchloaded[pgm]==1) + { +#ifdef GUSOUTDEBUG + printf("Trying to reload a patch. This should never happen, please report.\n"); +#endif + return 0; + } + if ((patchName(pgm)==NULL)||((patchName(pgm))[0]==0)) + { +#ifdef GUSOUTDEBUG + printf("Couldn't guess patch name for patch number %d\n",pgm); +#endif + return -1; + } + char *s=new char[strlen(GUS_patches_directory)+strlen(patchName(pgm))+10]; + if (s==NULL) return -1; + sprintf(s,"%s/%s.pat",GUS_patches_directory,patchName(pgm)); +#ifdef GUSOUTDEBUG + printf("Loading patch : %s\n",s); +#endif + struct patch_info *patch=NULL; + struct stat info; + if (stat(s, &info)==-1) + { +#ifdef GUSOUTDEBUG + printf("File %s doesn't exist\n",s); +#endif + return -1; + } + + FILE *fh=fopen(s,"rb"); + if (fh==NULL) + { +#ifdef GUSOUTDEBUG + printf("Couldn't open patch %s\n",s); +#endif + return -1; + } + + unsigned char tmp[256]; + if (fread(tmp,1,0xef,fh)!=0xef) + { + fclose(fh); +#ifdef GUSOUTDEBUG + printf("Short file ! \n"); +#endif + return -1; + } + memcpy ((char *) &header, tmp, sizeof (header)); + + if (strncmp(header.magic,"GF1PATCH110",12)!=0) + { +#ifdef GUSOUTDEBUG + printf("File %s is corrupted or it isn't a patch file\n",s); +#endif + return -1; + } + if (strncmp(header.version,"ID#000002",10)!=0) + { +#ifdef GUSOUTDEBUG + printf("File %s's version is not supported\n",s); +#endif + return -1; + } + unsigned short nWaves= *(unsigned short *)&tmp[85]; +#ifdef GUSOUTDEBUG + unsigned short masterVolume= *(unsigned short *)&tmp[87]; + printf("nWaves: %d\n",nWaves); + printf("masterVolume : %d\n",masterVolume); +#endif + + unsigned short i; + int offset=0xef; + for (i=0;ikey = GUS_PATCH; + patch->device_no = device; + patch->instr_no = pgm; + patch->mode = sample.modes | WAVE_TREMOLO | WAVE_VIBRATO | WAVE_SCALE; + patch->len = sample.len; + patch->loop_start = sample.loop_start; + patch->loop_end = sample.loop_end; + patch->base_note = sample.base_note; + patch->high_note = sample.high_note; + patch->low_note = sample.low_note; + patch->base_freq = sample.base_freq; + patch->detuning = sample.detune; + patch->panning = (sample.panning - 7) * 16; + + memcpy (patch->env_rate, sample.envelope_rate, 6); + memcpy (patch->env_offset, sample.envelope_offset, 6); + + patch->tremolo_sweep = sample.tremolo_sweep; + patch->tremolo_rate = sample.tremolo_rate; + patch->tremolo_depth = sample.tremolo_depth; + + patch->vibrato_sweep = sample.vibrato_sweep; + patch->vibrato_rate = sample.vibrato_rate; + patch->vibrato_depth = sample.vibrato_depth; + + patch->scale_frequency = sample.scale_frequency; + patch->scale_factor = sample.scale_factor; + + patch->volume = header.master_volume; + + if (fseek (fh, offset, 0) == -1) + { + fclose(fh); + return -1; + } + + if ((long)fread (patch->data, 1,sample.len,fh) != sample.len) + { +#ifdef GUSOUTDEBUG + printf ("Short file\n"); +#endif + return -1; + } + + SEQ_WRPATCH (patch, sizeof (*patch) + sample.len); + + offset = offset + sample.len; + + } + patchloaded[pgm]=1; + + fclose(fh); + free(patch); // Shouldn't this 'free' be within the 'for' loop ? + delete s; + freememory = device; + ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &freememory); +#endif + return 0; +} + + +void GUSOut::setPatchesToUse(int *patchesused) +{ +#ifdef HAVE_OSS_SUPPORT + int k; + for (k=0;k<256;k++) patchloaded[k]=0; + + int patchesordered[256]; //This holds the pgm used ordered by a method which + // put first the patches more oftenly used, and then the least + // In example, if a song only uses a piano and a splash cymbal, + // This is set to : 0,188,-1,-1,-1,-1 ... + patchesLoadingOrder(patchesused,patchesordered); + + // If above line doesn't work, perhaps you could try this ? : + // for (int j=0;j<256;j++) patchesordered[j]=patchesused[j]; +#ifdef GUSOUTDEBUG + printf("Patches used : \n"); + for (k=0;k<256;k++) + { + if (patchesused[k]!=-1) printf("%d,",patchesused[k]); + } + printf("\n Patches used, sorted :\n"); + for (k=0;k<256;k++) + { + if (patchesordered[k]!=-1) printf("%d,",patchesordered[k]); + } +#endif + + int i=0; + while (patchesordered[i]!=-1) + { +#ifdef GUSOUTDEBUG + printf("Load Patch : %d\n",patchesordered[i]); +#endif + loadPatch(patchesordered[i]); + i++; + } +#endif +} + +int compare_decreasing(const void *a,const void *b) +{ + struct instr_gm + { + int used; + int pgm; + }; + instr_gm *ai=(instr_gm *)a; + instr_gm *bi=(instr_gm *)b; + return ai->usedused; +} + + +void GUSOut::patchesLoadingOrder(int *patchesused,int *patchesordered) +{ + struct instr_gm + { + int used; + int pgm; + }; + + instr_gm tempmelody[128]; + instr_gm tempdrums[128]; + int i,j; + for (i=0,j=128;i<128;i++,j++) + { + tempmelody[i].used=patchesused[i]; + tempmelody[i].pgm=i; + tempdrums[i].used=patchesused[j]; + tempdrums[i].pgm=j; + } + /* SORT */ // Decreasing order (first most used patch, then less used patch) + qsort(&tempmelody[0],128,sizeof(instr_gm),compare_decreasing); + qsort(&tempdrums[0],128,sizeof(instr_gm),compare_decreasing); + + /* Once they are sorted, the result is put on patchesordered in the following + * way : If tempmelody is : M0 M1 M2 M3 ... M127 and tempdrums is : + * D0 D1 D2 D3 ... D127, the result is : + * M0 D0 M1 M2 D1 M3 M4 D2 M5 M6 D3 ... + * P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 ... + */ + +#ifdef GUSOUTDEBUG + for (int k=0;k<128;k++) + { + printf("%d - %d\n",tempmelody[k].used,tempmelody[k].pgm); + } + for (int k=0;k<128;k++) + { + printf("%d : %d\n",tempdrums[k].used,tempdrums[k].pgm); + } +#endif + + i=0; + int totalmelody=0; + while ((i<128)&&(tempmelody[i].used!=0)) + { + totalmelody++; + i++; + } + i=0; + int totaldrums=0; + while ((i<128)&&(tempdrums[i].used!=0)) + { + totaldrums++; + i++; + } +#ifdef GUSOUTDEBUG + printf("Totalmelody : %d,totaldrums : %d\n",totalmelody,totaldrums); +#endif + int tgt=0; + + int tm=totalmelody; + int td=totaldrums; + int cm,cd; + cm=cd=0; + if ((tm!=0)&&(td!=0)) + { + patchesordered[0]=tempmelody[0].pgm; + patchesordered[1]=tempdrums[0].pgm; + tm--;td--; + cm++;cd++; + tgt+=2; + while ((tm>0)&&(td>0)) + { + if (((tgt-1)%3)==0) + { + patchesordered[tgt]=tempdrums[cd].pgm; + cd++; + td--; + } + else + { + patchesordered[tgt]=tempmelody[cm].pgm; + cm++; + tm--; + } + tgt++; + } + } + while (tm>0) + { + patchesordered[tgt]=tempmelody[cm].pgm; + tgt++; + cm++; + tm--; + } + while (td>0) + { + patchesordered[tgt]=tempdrums[cd].pgm; + tgt++; + cd++; + td--; + } + + // Now we put as not used (-1) the rest of the array + while (tgt<256) + { + patchesordered[tgt]=-1; + tgt++; + } +} + +//char *GUSOut::GUS_patches_directory="/mnt/dosc/gravis/patches"; +const char *GUSOut::GUS_patches_directory="/usr/share/ultrasnd"; + +int GUSOut::delete_GUS_patches_directory = 0; +/* No, this doesn't delete any file :-) it's just for internal use */ diff --git a/libtdemid/libtdemid.cc b/libtdemid/libtdemid.cc deleted file mode 100644 index 04a0dac0d..000000000 --- a/libtdemid/libtdemid.cc +++ /dev/null @@ -1,263 +0,0 @@ -/************************************************************************** - - libtdemid.cc - class KMidSimpleAPI that makes it easy to use libtdemid - and a C wrapper. - This file is part of LibKMid 0.9.5 - Copyright (C) 2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ - -#include "libtdemid.h" -#include -#include -#include -#include -#include -#include - -#include "deviceman.h" -#include "player.h" -#include "midimapper.h" - -struct kMidData kMid; - -int KMidSimpleAPI::kMidInit(void) -{ - kMid.midi = new DeviceManager(); - if ( kMid.midi == 0L ) return 1; - kMid.midi->initManager(); - if (!kMid.midi->ok()) return 1; - - kMid.pctlsmID=shmget(getpid(),sizeof(PlayerController),0600 | IPC_CREAT); - if (kMid.pctlsmID==-1) return 1; - kMid.pctl=(PlayerController *)shmat(kMid.pctlsmID,NULL,0); - if (kMid.pctl==NULL) return 1; - - kMid.player=new MidiPlayer(kMid.midi,kMid.pctl); - if ( kMid.player == 0L ) - { - delete kMid.midi; - return 1; - } - - kMid.player->setParseSong(false); - - kMid.pctl->message=0; - kMid.pctl->gm=1; - kMid.pctl->error=0; - kMid.pctl->ratioTempo=1.0; - kMid.pctl->tempo=500000; - kMid.pctl->volumepercentage=100; - for (int i=0;i<16;i++) - { - kMid.pctl->forcepgm[i]=0; - kMid.pctl->pgm[i]=0; - } - - return 0; -} - -int KMidSimpleAPI::kMidLoad(const char *filename) -{ - if (kMidDevices()==0) return 0; - return kMid.player->loadSong(filename); -} - -int KMidSimpleAPI::kMidPlay(int loop) -{ - if (kMidDevices()==0) return 4; - if (!kMid.player->isSongLoaded()) return 1; - if (kMid.pctl->playing==1) return 2; - if (kMid.midi->checkInit()==-1) return 3; - kMid.pctl->message=0; - kMid.pctl->playing=0; - kMid.pctl->finished=0; - kMid.pctl->error=0; - kMid.pctl->SPEVplayed=0; - kMid.pctl->SPEVprocessed=0; - kMid.pctl->millisecsPlayed=0; - if ((kMid.pid=fork())==0) - { - if (loop) - { - while (1) - { - kMid.player->play(); - if (kMid.pctl->error) return 5; - kMid.pctl->message=0; - kMid.pctl->playing=0; - kMid.pctl->finished=0; - kMid.pctl->error=0; - kMid.pctl->SPEVplayed=0; - kMid.pctl->SPEVprocessed=0; - kMid.pctl->millisecsPlayed=0; - } - - } else { - kMid.player->play(); - if (kMid.pctl->error) return 5; - } - _exit(0); - } else return 4; - return 0; -} - -int KMidSimpleAPI::kMidStop(void) -{ - if (kMidDevices()==0) return 4; - if (kMid.pctl->playing==0) return 1; - if (kMid.pid!=0) - { - kill(kMid.pid,SIGTERM); - waitpid(kMid.pid, NULL, 0); - kMid.pid=0; - } else return 2; - - kMid.pctl->playing=0; - return 0; -} - -void KMidSimpleAPI::kMidDestruct(void) -{ - delete kMid.midi; - kMid.midi=0L; - delete kMid.player; - kMid.player=0L; - delete kMid.map; - shmdt((char *)kMid.pctl); - shmctl(kMid.pctlsmID, IPC_RMID, 0L); -} - -int KMidSimpleAPI::kMidIsPlaying(void) -{ - return kMid.pctl->playing; -} - -int KMidSimpleAPI::kMidDevices(void) -{ - return kMid.midi->midiPorts()+kMid.midi->synthDevices(); -} - -const char * KMidSimpleAPI::kMidName(int i) -{ - return kMid.midi->name(i); -} - -const char * KMidSimpleAPI::kMidType(int i) -{ - return kMid.midi->type(i); -} - -void KMidSimpleAPI::kMidSetDevice(int i) -{ - kMid.midi->setDefaultDevice(i); -} - -void KMidSimpleAPI::kMidSetMidiMapper(const char *mapfilename) -{ - if (kMidDevices()==0) return; - kMid.map=new MidiMapper(mapfilename); - if ((kMid.map->ok() == 0L)||(!kMid.map->ok())) return; - kMid.midi->setMidiMap(kMid.map); -} - -const char *KMidSimpleAPI::kMidVersion(void) -{ - return "0.9.5"; -} - -const char *KMidSimpleAPI::kMidCopyright(void) -{ - return "LibKMid 0.9.5 (C)1997-2000 Antonio Larrosa Jimenez .Malaga(es)"; -} - -/* * * * * * - - Under this line (------) there's only a C wrapper for the KMidSimpleAPI class - -* * * * * */ - - -int kMidInit(void) -{ - return KMidSimpleAPI::kMidInit(); -} - -int kMidLoad(const char *filename) -{ - return KMidSimpleAPI::kMidLoad(filename); -} - -int kMidPlay(void) -{ - return KMidSimpleAPI::kMidPlay(); -} - -int kMidStop(void) -{ - return KMidSimpleAPI::kMidStop(); -} - -void kMidDestruct(void) -{ - KMidSimpleAPI::kMidDestruct(); -} - -int kMidIsPlaying(void) -{ - return KMidSimpleAPI::kMidIsPlaying(); -} - -int kMidDevices(void) -{ - return KMidSimpleAPI::kMidDevices(); -} - -const char *kMidName(int i) -{ - return KMidSimpleAPI::kMidName(i); -} - -const char *kMidType(int i) -{ - return KMidSimpleAPI::kMidType(i); -} - -void kMidSetDevice(int i) -{ - KMidSimpleAPI::kMidSetDevice(i); -} - -void kMidSetMidiMapper(const char *mapfilename) -{ - KMidSimpleAPI::kMidSetMidiMapper(mapfilename); -} - -const char *kMidVersion(void) -{ - return KMidSimpleAPI::kMidVersion(); -} - -const char *kMidCopyright(void) -{ - return KMidSimpleAPI::kMidCopyright(); -} - diff --git a/libtdemid/libtdemid.cpp b/libtdemid/libtdemid.cpp new file mode 100644 index 000000000..fcc75d3e5 --- /dev/null +++ b/libtdemid/libtdemid.cpp @@ -0,0 +1,263 @@ +/************************************************************************** + + libtdemid.cpp - class KMidSimpleAPI that makes it easy to use libtdemid + and a C wrapper. + This file is part of LibKMid 0.9.5 + Copyright (C) 2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ + +#include "libtdemid.h" +#include +#include +#include +#include +#include +#include + +#include "deviceman.h" +#include "player.h" +#include "midimapper.h" + +struct kMidData kMid; + +int KMidSimpleAPI::kMidInit(void) +{ + kMid.midi = new DeviceManager(); + if ( kMid.midi == 0L ) return 1; + kMid.midi->initManager(); + if (!kMid.midi->ok()) return 1; + + kMid.pctlsmID=shmget(getpid(),sizeof(PlayerController),0600 | IPC_CREAT); + if (kMid.pctlsmID==-1) return 1; + kMid.pctl=(PlayerController *)shmat(kMid.pctlsmID,NULL,0); + if (kMid.pctl==NULL) return 1; + + kMid.player=new MidiPlayer(kMid.midi,kMid.pctl); + if ( kMid.player == 0L ) + { + delete kMid.midi; + return 1; + } + + kMid.player->setParseSong(false); + + kMid.pctl->message=0; + kMid.pctl->gm=1; + kMid.pctl->error=0; + kMid.pctl->ratioTempo=1.0; + kMid.pctl->tempo=500000; + kMid.pctl->volumepercentage=100; + for (int i=0;i<16;i++) + { + kMid.pctl->forcepgm[i]=0; + kMid.pctl->pgm[i]=0; + } + + return 0; +} + +int KMidSimpleAPI::kMidLoad(const char *filename) +{ + if (kMidDevices()==0) return 0; + return kMid.player->loadSong(filename); +} + +int KMidSimpleAPI::kMidPlay(int loop) +{ + if (kMidDevices()==0) return 4; + if (!kMid.player->isSongLoaded()) return 1; + if (kMid.pctl->playing==1) return 2; + if (kMid.midi->checkInit()==-1) return 3; + kMid.pctl->message=0; + kMid.pctl->playing=0; + kMid.pctl->finished=0; + kMid.pctl->error=0; + kMid.pctl->SPEVplayed=0; + kMid.pctl->SPEVprocessed=0; + kMid.pctl->millisecsPlayed=0; + if ((kMid.pid=fork())==0) + { + if (loop) + { + while (1) + { + kMid.player->play(); + if (kMid.pctl->error) return 5; + kMid.pctl->message=0; + kMid.pctl->playing=0; + kMid.pctl->finished=0; + kMid.pctl->error=0; + kMid.pctl->SPEVplayed=0; + kMid.pctl->SPEVprocessed=0; + kMid.pctl->millisecsPlayed=0; + } + + } else { + kMid.player->play(); + if (kMid.pctl->error) return 5; + } + _exit(0); + } else return 4; + return 0; +} + +int KMidSimpleAPI::kMidStop(void) +{ + if (kMidDevices()==0) return 4; + if (kMid.pctl->playing==0) return 1; + if (kMid.pid!=0) + { + kill(kMid.pid,SIGTERM); + waitpid(kMid.pid, NULL, 0); + kMid.pid=0; + } else return 2; + + kMid.pctl->playing=0; + return 0; +} + +void KMidSimpleAPI::kMidDestruct(void) +{ + delete kMid.midi; + kMid.midi=0L; + delete kMid.player; + kMid.player=0L; + delete kMid.map; + shmdt((char *)kMid.pctl); + shmctl(kMid.pctlsmID, IPC_RMID, 0L); +} + +int KMidSimpleAPI::kMidIsPlaying(void) +{ + return kMid.pctl->playing; +} + +int KMidSimpleAPI::kMidDevices(void) +{ + return kMid.midi->midiPorts()+kMid.midi->synthDevices(); +} + +const char * KMidSimpleAPI::kMidName(int i) +{ + return kMid.midi->name(i); +} + +const char * KMidSimpleAPI::kMidType(int i) +{ + return kMid.midi->type(i); +} + +void KMidSimpleAPI::kMidSetDevice(int i) +{ + kMid.midi->setDefaultDevice(i); +} + +void KMidSimpleAPI::kMidSetMidiMapper(const char *mapfilename) +{ + if (kMidDevices()==0) return; + kMid.map=new MidiMapper(mapfilename); + if ((kMid.map->ok() == 0L)||(!kMid.map->ok())) return; + kMid.midi->setMidiMap(kMid.map); +} + +const char *KMidSimpleAPI::kMidVersion(void) +{ + return "0.9.5"; +} + +const char *KMidSimpleAPI::kMidCopyright(void) +{ + return "LibKMid 0.9.5 (C)1997-2000 Antonio Larrosa Jimenez .Malaga(es)"; +} + +/* * * * * * + + Under this line (------) there's only a C wrapper for the KMidSimpleAPI class + +* * * * * */ + + +int kMidInit(void) +{ + return KMidSimpleAPI::kMidInit(); +} + +int kMidLoad(const char *filename) +{ + return KMidSimpleAPI::kMidLoad(filename); +} + +int kMidPlay(void) +{ + return KMidSimpleAPI::kMidPlay(); +} + +int kMidStop(void) +{ + return KMidSimpleAPI::kMidStop(); +} + +void kMidDestruct(void) +{ + KMidSimpleAPI::kMidDestruct(); +} + +int kMidIsPlaying(void) +{ + return KMidSimpleAPI::kMidIsPlaying(); +} + +int kMidDevices(void) +{ + return KMidSimpleAPI::kMidDevices(); +} + +const char *kMidName(int i) +{ + return KMidSimpleAPI::kMidName(i); +} + +const char *kMidType(int i) +{ + return KMidSimpleAPI::kMidType(i); +} + +void kMidSetDevice(int i) +{ + KMidSimpleAPI::kMidSetDevice(i); +} + +void kMidSetMidiMapper(const char *mapfilename) +{ + KMidSimpleAPI::kMidSetMidiMapper(mapfilename); +} + +const char *kMidVersion(void) +{ + return KMidSimpleAPI::kMidVersion(); +} + +const char *kMidCopyright(void) +{ + return KMidSimpleAPI::kMidCopyright(); +} + diff --git a/libtdemid/midfile.cc b/libtdemid/midfile.cc deleted file mode 100644 index f8222b3f8..000000000 --- a/libtdemid/midfile.cc +++ /dev/null @@ -1,460 +0,0 @@ -/************************************************************************** - - midfile.cc - function which reads a midi file,and creates the track classes - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "midfile.h" -#include -#include -#include -#include -#include "sndcard.h" -#include "midispec.h" -#include "mt32togm.h" -#include "sys/stat.h" -#include - -#include -#include - -int fsearch(FILE *fh,const char *text,long *ptr); - -/* This function gives the metronome tempo, from a tempo data as found in - a midi file */ -double tempoToMetronomeTempo(ulong x) -{ - return 60/((double)x/1000000); -} - -double metronomeTempoToTempo(ulong x) -{ - return ((double)60*x)/1000000; -} - -int uncompressFile(const char *gzname, char *tmpname) - // Returns 0 if OK, 1 if error (tmpname not set) -{ - TQString cmd("gzip -dc " + TDEProcess::quote(gzname)); - FILE *infile = popen( TQFile::encodeName(cmd).data(), "r"); - if (infile==NULL) { - fprintf(stderr,"ERROR : popen failed : %s\n",TQFile::encodeName(cmd).data()); - return 1; - } - strcpy(tmpname, "/tmp/KMid.XXXXXXXXXX"); - int fd = mkstemp(tmpname); - if (fd == -1) - { - pclose(infile); - return 1; - } - FILE *outfile= fdopen(fd,"wb"); - if (outfile==NULL) - { - pclose(infile); - return 1; - } - int n=getc(infile); - if (n==EOF) - { - pclose(infile); - fclose(outfile); - unlink(tmpname); - return 1; - } - fputc(n,outfile); - int buf[BUFSIZ]; - n = fread(buf, 1, BUFSIZ, infile); - while (n>0) - { - fwrite(buf, 1, n, outfile); - n = fread(buf, 1, BUFSIZ, infile); - } - - pclose(infile); - - //if (pclose(infile) != 0) fprintf(stderr,"Error : pclose failed\n"); - // Is it right for pclose to always fail ? - - fclose(outfile); - return 0; -} - -MidiTrack **readMidiFile( const char *name, MidiFileInfo *info, int &ok) -{ - ok=1; - MidiTrack **tracks; - - struct stat buf; - if (stat(name,&buf) || !S_ISREG(buf.st_mode)) - { - fprintf(stderr,"ERROR: %s is not a regular file\n",name); - ok=-6; - return NULL; - } - - FILE *fh=fopen(name,"rb"); - if (fh==NULL) - { - fprintf(stderr,"ERROR: Can't open file %s\n",name); - ok=-1; - return NULL; - } - char text[4]; - text[0] = 0; - fread(text,1,4,fh); - if ((strncmp(text,"MThd",4)!=0)&&(strcmp(&name[strlen(name)-3],".gz")==0)) - { - fclose(fh); - char tempname[200]; - fprintf(stderr,"Trying to open zipped midi file...\n"); - if (uncompressFile(name,tempname)!=0) - { - fprintf(stderr,"ERROR: %s is not a (zipped) midi file\n",name); - ok=-2; - return NULL; - } - fh=fopen(tempname,"rb"); - fread(text,1,4,fh); - unlink(tempname); - } - - if (strncmp(text,"MThd",4)!=0) - { - fseek(fh,0,SEEK_SET); - long pos; - if (fsearch(fh,"MThd",&pos)==0) - { - fclose(fh); - fprintf(stderr,"ERROR: %s is not a midi file.\n",name); - ok=-2; - return NULL; - } - fseek(fh,pos,SEEK_SET); - fread(text,1,4,fh); - } - long header_size=readLong(fh); - info->format=readShort(fh); - info->ntracks=readShort(fh); - info->ticksPerCuarterNote=readShort(fh); - if (info->ticksPerCuarterNote<0) - { - fprintf(stderr,"ERROR: Ticks per cuarter note is negative !\n"); - fprintf(stderr,"Please report this error to : larrosa@kde.org\n"); - fclose(fh); - ok=-3; - return NULL; - } - if (header_size>6) fseek(fh,header_size-6,SEEK_CUR); - tracks=new MidiTrack*[info->ntracks]; - if (tracks==NULL) - { - fprintf(stderr,"ERROR: Not enough memory\n"); - fclose(fh); - ok=-4; - return NULL; - } - int i=0; - while (intracks) - { - fread(text,1,4,fh); - if (strncmp(text,"MTrk",4)!=0) - { - fprintf(stderr,"ERROR: Not a well built midi file\n"); - fprintf(stderr,"%s",text); - fclose(fh); - ok=-5; - return NULL; - } - tracks[i]=new MidiTrack(fh,info->ticksPerCuarterNote,i); - if (tracks[i]==NULL) - { - fprintf(stderr,"ERROR: Not enough memory"); - fclose(fh); - ok=-4; - return NULL; - } - i++; - } - - fclose(fh); - - return tracks; - -} - -void parseInfoData(MidiFileInfo *info,MidiTrack **tracks,float ratioTempo) -{ - - info->ticksTotal=0; - info->millisecsTotal=0.0; - info->ticksPlayed=0; - int i; - for (i=0;i<256;i++) - { - info->patchesUsed[i]=0; - } - - int parsing=1; - int trk,minTrk; - ulong tempo=(ulong)(500000 * ratioTempo); - -#ifdef MIDFILEDEBUG - printf("Parsing 1 ...\n"); -#endif - - int pgminchannel[16]; - for (i=0;i<16;i++) - { - pgminchannel[i]=0; - } - - int j; - for (i=0;intracks;i++) - { - tracks[i]->init(); - tracks[i]->changeTempo(tempo); - } - double prevms=0; - double minTime=0; - double maxTime; - MidiEvent *ev=new MidiEvent; - while (parsing) - { - prevms=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 2 * 60000L; - minTime=maxTime; - while (trkntracks) - { - if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); - } - trk++; - } - if ((minTime==maxTime)) - { - parsing=0; -#ifdef MIDFILEDEBUG - printf("END of parsing\n"); -#endif - } - else - { - trk=0; - while (trkntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - } - trk=minTrk; - tracks[trk]->readEvent(ev); - - switch (ev->command) - { - case (MIDI_NOTEON) : - if (ev->chn!=PERCUSSION_CHANNEL) - info->patchesUsed[pgminchannel[ev->chn]]++; - else - info->patchesUsed[ev->note+128]++; - break; - case (MIDI_PGM_CHANGE) : - pgminchannel[ev->chn]=(ev->patch); - break; - case (MIDI_SYSTEM_PREFIX) : - if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) - { - tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ratioTempo); - for (j=0;jntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - } - break; - } - } - - delete ev; - info->millisecsTotal=prevms; - - for (i=0;intracks;i++) - { - tracks[i]->init(); - } - -#ifdef MIDFILEDEBUG - printf("info.ticksTotal = %ld \n",info->ticksTotal); - printf("info.ticksPlayed= %ld \n",info->ticksPlayed); - printf("info.millisecsTotal = %g \n",info->millisecsTotal); - printf("info.TicksPerCN = %d \n",info->ticksPerCuarterNote); -#endif - -} - - -void parsePatchesUsed(MidiTrack **tracks,MidiFileInfo *info,int gm) -{ - int i; - for (i=0;i<256;i++) - { - info->patchesUsed[i]=0; - } - int parsing=1; - int trk,minTrk; - ulong tempo=500000; - -#ifdef MIDFILEDEBUG - printf("Parsing for patches ...\n"); -#endif - - int j; - for (i=0;intracks;i++) - { - tracks[i]->init(); - } - double prevms=0; - double minTime=0; - double maxTime; - ulong tmp; - MidiEvent *ev=new MidiEvent; - int pgminchannel[16]; - for (i=0;i<16;i++) - { - pgminchannel[i]=0; - } - - while (parsing) - { - prevms=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 2 * 60000L; - minTime=maxTime; - while (trkntracks) - { - if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); - } - trk++; - } - if ((minTime==maxTime)) - { - parsing=0; -#ifdef MIDFILEDEBUG - printf("END of parsing for patches\n"); -#endif - } - else - { - trk=0; - while (trkntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - } - trk=minTrk; - tracks[trk]->readEvent(ev); - switch (ev->command) - { - case (MIDI_NOTEON) : - if (ev->chn!=PERCUSSION_CHANNEL) - info->patchesUsed[pgminchannel[ev->chn]]++; - else - info->patchesUsed[ev->note+128]++; - break; - case (MIDI_PGM_CHANGE) : - pgminchannel[ev->chn]=(gm==1)?(ev->patch):(MT32toGM[ev->patch]); - break; - case (MIDI_SYSTEM_PREFIX) : - if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) - { - if (tempoToMetronomeTempo(tmp=((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])))>=8) - { - tempo=tmp; - // printf("setTempo %ld\n",tempo); - for (j=0;jntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - } - } - break; - } - } - - delete ev; - - for (i=0;intracks;i++) - { - tracks[i]->init(); - } - -} - -int fsearch(FILE *fh,const char *text,long *ptr) - // Search for "text" through the fh file and then returns : - // text MUST BE smaller than 256 characters - // 0 if not was found - // 1 if it was found and in ptr (if !=NULL) the position where text begins. -{ - if ((text==NULL)||(text[0]==0)) return 0; - char buf[1024]; - char tmp[256]; - long pos; - int l=strlen(text); - int i,k,r; - while (!feof(fh)) - { - pos=ftell(fh); - k=fread(buf,1,1024,fh); - i=0; - while (i=l) - r=strncmp(text,&buf[i],l); - else - { - fseek(fh,pos+i,SEEK_SET); - if (fread(tmp,1,l,fh)<(uint)l) return 0; - fseek(fh,pos+k,SEEK_SET); - r=strncmp(text,tmp,l); - } - if (r==0) - { - if (ptr!=NULL) *ptr=pos+i; - return 1; - } - } - i++; - } - } - return 0; -} diff --git a/libtdemid/midfile.cpp b/libtdemid/midfile.cpp new file mode 100644 index 000000000..bfeb056f0 --- /dev/null +++ b/libtdemid/midfile.cpp @@ -0,0 +1,460 @@ +/************************************************************************** + + midfile.cpp - function which reads a midi file,and creates the track classes + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "midfile.h" +#include +#include +#include +#include +#include "sndcard.h" +#include "midispec.h" +#include "mt32togm.h" +#include "sys/stat.h" +#include + +#include +#include + +int fsearch(FILE *fh,const char *text,long *ptr); + +/* This function gives the metronome tempo, from a tempo data as found in + a midi file */ +double tempoToMetronomeTempo(ulong x) +{ + return 60/((double)x/1000000); +} + +double metronomeTempoToTempo(ulong x) +{ + return ((double)60*x)/1000000; +} + +int uncompressFile(const char *gzname, char *tmpname) + // Returns 0 if OK, 1 if error (tmpname not set) +{ + TQString cmd("gzip -dc " + TDEProcess::quote(gzname)); + FILE *infile = popen( TQFile::encodeName(cmd).data(), "r"); + if (infile==NULL) { + fprintf(stderr,"ERROR : popen failed : %s\n",TQFile::encodeName(cmd).data()); + return 1; + } + strcpy(tmpname, "/tmp/KMid.XXXXXXXXXX"); + int fd = mkstemp(tmpname); + if (fd == -1) + { + pclose(infile); + return 1; + } + FILE *outfile= fdopen(fd,"wb"); + if (outfile==NULL) + { + pclose(infile); + return 1; + } + int n=getc(infile); + if (n==EOF) + { + pclose(infile); + fclose(outfile); + unlink(tmpname); + return 1; + } + fputc(n,outfile); + int buf[BUFSIZ]; + n = fread(buf, 1, BUFSIZ, infile); + while (n>0) + { + fwrite(buf, 1, n, outfile); + n = fread(buf, 1, BUFSIZ, infile); + } + + pclose(infile); + + //if (pclose(infile) != 0) fprintf(stderr,"Error : pclose failed\n"); + // Is it right for pclose to always fail ? + + fclose(outfile); + return 0; +} + +MidiTrack **readMidiFile( const char *name, MidiFileInfo *info, int &ok) +{ + ok=1; + MidiTrack **tracks; + + struct stat buf; + if (stat(name,&buf) || !S_ISREG(buf.st_mode)) + { + fprintf(stderr,"ERROR: %s is not a regular file\n",name); + ok=-6; + return NULL; + } + + FILE *fh=fopen(name,"rb"); + if (fh==NULL) + { + fprintf(stderr,"ERROR: Can't open file %s\n",name); + ok=-1; + return NULL; + } + char text[4]; + text[0] = 0; + fread(text,1,4,fh); + if ((strncmp(text,"MThd",4)!=0)&&(strcmp(&name[strlen(name)-3],".gz")==0)) + { + fclose(fh); + char tempname[200]; + fprintf(stderr,"Trying to open zipped midi file...\n"); + if (uncompressFile(name,tempname)!=0) + { + fprintf(stderr,"ERROR: %s is not a (zipped) midi file\n",name); + ok=-2; + return NULL; + } + fh=fopen(tempname,"rb"); + fread(text,1,4,fh); + unlink(tempname); + } + + if (strncmp(text,"MThd",4)!=0) + { + fseek(fh,0,SEEK_SET); + long pos; + if (fsearch(fh,"MThd",&pos)==0) + { + fclose(fh); + fprintf(stderr,"ERROR: %s is not a midi file.\n",name); + ok=-2; + return NULL; + } + fseek(fh,pos,SEEK_SET); + fread(text,1,4,fh); + } + long header_size=readLong(fh); + info->format=readShort(fh); + info->ntracks=readShort(fh); + info->ticksPerCuarterNote=readShort(fh); + if (info->ticksPerCuarterNote<0) + { + fprintf(stderr,"ERROR: Ticks per cuarter note is negative !\n"); + fprintf(stderr,"Please report this error to : larrosa@kde.org\n"); + fclose(fh); + ok=-3; + return NULL; + } + if (header_size>6) fseek(fh,header_size-6,SEEK_CUR); + tracks=new MidiTrack*[info->ntracks]; + if (tracks==NULL) + { + fprintf(stderr,"ERROR: Not enough memory\n"); + fclose(fh); + ok=-4; + return NULL; + } + int i=0; + while (intracks) + { + fread(text,1,4,fh); + if (strncmp(text,"MTrk",4)!=0) + { + fprintf(stderr,"ERROR: Not a well built midi file\n"); + fprintf(stderr,"%s",text); + fclose(fh); + ok=-5; + return NULL; + } + tracks[i]=new MidiTrack(fh,info->ticksPerCuarterNote,i); + if (tracks[i]==NULL) + { + fprintf(stderr,"ERROR: Not enough memory"); + fclose(fh); + ok=-4; + return NULL; + } + i++; + } + + fclose(fh); + + return tracks; + +} + +void parseInfoData(MidiFileInfo *info,MidiTrack **tracks,float ratioTempo) +{ + + info->ticksTotal=0; + info->millisecsTotal=0.0; + info->ticksPlayed=0; + int i; + for (i=0;i<256;i++) + { + info->patchesUsed[i]=0; + } + + int parsing=1; + int trk,minTrk; + ulong tempo=(ulong)(500000 * ratioTempo); + +#ifdef MIDFILEDEBUG + printf("Parsing 1 ...\n"); +#endif + + int pgminchannel[16]; + for (i=0;i<16;i++) + { + pgminchannel[i]=0; + } + + int j; + for (i=0;intracks;i++) + { + tracks[i]->init(); + tracks[i]->changeTempo(tempo); + } + double prevms=0; + double minTime=0; + double maxTime; + MidiEvent *ev=new MidiEvent; + while (parsing) + { + prevms=minTime; + trk=0; + minTrk=0; + maxTime=minTime + 2 * 60000L; + minTime=maxTime; + while (trkntracks) + { + if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); + } + trk++; + } + if ((minTime==maxTime)) + { + parsing=0; +#ifdef MIDFILEDEBUG + printf("END of parsing\n"); +#endif + } + else + { + trk=0; + while (trkntracks) + { + tracks[trk]->currentMs(minTime); + trk++; + } + } + trk=minTrk; + tracks[trk]->readEvent(ev); + + switch (ev->command) + { + case (MIDI_NOTEON) : + if (ev->chn!=PERCUSSION_CHANNEL) + info->patchesUsed[pgminchannel[ev->chn]]++; + else + info->patchesUsed[ev->note+128]++; + break; + case (MIDI_PGM_CHANGE) : + pgminchannel[ev->chn]=(ev->patch); + break; + case (MIDI_SYSTEM_PREFIX) : + if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) + { + tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ratioTempo); + for (j=0;jntracks;j++) + { + tracks[j]->changeTempo(tempo); + } + } + break; + } + } + + delete ev; + info->millisecsTotal=prevms; + + for (i=0;intracks;i++) + { + tracks[i]->init(); + } + +#ifdef MIDFILEDEBUG + printf("info.ticksTotal = %ld \n",info->ticksTotal); + printf("info.ticksPlayed= %ld \n",info->ticksPlayed); + printf("info.millisecsTotal = %g \n",info->millisecsTotal); + printf("info.TicksPerCN = %d \n",info->ticksPerCuarterNote); +#endif + +} + + +void parsePatchesUsed(MidiTrack **tracks,MidiFileInfo *info,int gm) +{ + int i; + for (i=0;i<256;i++) + { + info->patchesUsed[i]=0; + } + int parsing=1; + int trk,minTrk; + ulong tempo=500000; + +#ifdef MIDFILEDEBUG + printf("Parsing for patches ...\n"); +#endif + + int j; + for (i=0;intracks;i++) + { + tracks[i]->init(); + } + double prevms=0; + double minTime=0; + double maxTime; + ulong tmp; + MidiEvent *ev=new MidiEvent; + int pgminchannel[16]; + for (i=0;i<16;i++) + { + pgminchannel[i]=0; + } + + while (parsing) + { + prevms=minTime; + trk=0; + minTrk=0; + maxTime=minTime + 2 * 60000L; + minTime=maxTime; + while (trkntracks) + { + if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); + } + trk++; + } + if ((minTime==maxTime)) + { + parsing=0; +#ifdef MIDFILEDEBUG + printf("END of parsing for patches\n"); +#endif + } + else + { + trk=0; + while (trkntracks) + { + tracks[trk]->currentMs(minTime); + trk++; + } + } + trk=minTrk; + tracks[trk]->readEvent(ev); + switch (ev->command) + { + case (MIDI_NOTEON) : + if (ev->chn!=PERCUSSION_CHANNEL) + info->patchesUsed[pgminchannel[ev->chn]]++; + else + info->patchesUsed[ev->note+128]++; + break; + case (MIDI_PGM_CHANGE) : + pgminchannel[ev->chn]=(gm==1)?(ev->patch):(MT32toGM[ev->patch]); + break; + case (MIDI_SYSTEM_PREFIX) : + if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) + { + if (tempoToMetronomeTempo(tmp=((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])))>=8) + { + tempo=tmp; + // printf("setTempo %ld\n",tempo); + for (j=0;jntracks;j++) + { + tracks[j]->changeTempo(tempo); + } + } + } + break; + } + } + + delete ev; + + for (i=0;intracks;i++) + { + tracks[i]->init(); + } + +} + +int fsearch(FILE *fh,const char *text,long *ptr) + // Search for "text" through the fh file and then returns : + // text MUST BE smaller than 256 characters + // 0 if not was found + // 1 if it was found and in ptr (if !=NULL) the position where text begins. +{ + if ((text==NULL)||(text[0]==0)) return 0; + char buf[1024]; + char tmp[256]; + long pos; + int l=strlen(text); + int i,k,r; + while (!feof(fh)) + { + pos=ftell(fh); + k=fread(buf,1,1024,fh); + i=0; + while (i=l) + r=strncmp(text,&buf[i],l); + else + { + fseek(fh,pos+i,SEEK_SET); + if (fread(tmp,1,l,fh)<(uint)l) return 0; + fseek(fh,pos+k,SEEK_SET); + r=strncmp(text,tmp,l); + } + if (r==0) + { + if (ptr!=NULL) *ptr=pos+i; + return 1; + } + } + i++; + } + } + return 0; +} diff --git a/libtdemid/midimapper.cc b/libtdemid/midimapper.cc deleted file mode 100644 index 837728410..000000000 --- a/libtdemid/midimapper.cc +++ /dev/null @@ -1,456 +0,0 @@ -/************************************************************************** - - midimapper.cc - The midi mapper object - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "midimapper.h" -#include -#include -#include -#ifdef HAVE_CONFIG_H -#include -#endif - -MidiMapper::MidiMapper(const char *name) -{ - _ok=1; - keymaps=NULL; - _filename=NULL; - mapPitchBender=0; - mapExpressionToVolumeEvents=0; - if ((name==NULL)||(name[0]==0)) - { - deallocateMaps(); - int i; - for (i=0;i<16;i++) - { - channelmap[i]=i; - channelPatchForced[i]=-1; - } - for (i=0;i<128;i++) patchmap[i]=i; - } - else - loadFile(name); -} - -MidiMapper::~MidiMapper() -{ - if (_filename) free(_filename); - deallocateMaps(); -} - -void MidiMapper::deallocateMaps(void) -{ - int i; - for (i=0;i<16;i++) channelKeymap[i]=NULL; - for (i=0;i<128;i++) patchKeymap[i]=NULL; - Keymap *km; - while (keymaps!=NULL) - { - km=keymaps->next; - delete keymaps; - keymaps=km; - } -} - -void MidiMapper::getValue(char *s,char *v) -{ - char *c=s; - while ((*c!=0)&&(*c!='=')) c++; - if (*c==0) v[0]=0; - else - { - c++; - while (*c!=0) - { - *v=*c; - c++;v++; - } - *v=0; - } -} - -void MidiMapper::removeSpaces(char *s) -{ - char *a=s; - while ((*a!=0)&&(*a==' ')) a++; - if (*a==0) {*s=0;return;}; - while (*a!=0) - { - while ((*a!=0)&&(*a!=' ')&&(*a!=10)&&(*a!=13)) - { - *s=*a; - s++; - a++; - } - while ((*a!=0)&&((*a==' ')||(*a==10)||(*a==13))) a++; - *s=' ';s++; - if (*a==0) {*s=0;return;}; - } - *s=0; - -} - -int MidiMapper::countWords(char *s) -{ - int c=0; - while (*s!=0) - { - if (*s==' ') c++; - s++; - } - return c; -} - -void MidiMapper::getWord(char *t,char *s,int w) -{ - int i=0; - *t=0; - while ((*s!=0)&&(iname, name, KM_NAME_SIZE); - km->name[KM_NAME_SIZE - 1] = 0; - - int i; - if (use_same_note==1) - { - for (i=0;i<128;i++) - km->key[i]=note; - } - else - { - for (i=0;i<128;i++) - km->key[i]=i; - } - addKeymap(km); - return km; -} - -void MidiMapper::addKeymap(Keymap *newkm) -{ - Keymap *km=keymaps; - if (keymaps==NULL) - { - keymaps=newkm; - newkm->next=NULL; - return; - } - while (km->next!=NULL) km=km->next; - km->next=newkm; - newkm->next=NULL; - return; -} - -MidiMapper::Keymap *MidiMapper::keymap(char *n) -{ - Keymap *km=keymaps; - while ((km!=NULL)&&(strcmp(km->name,n)!=0)) km=km->next; - return km; -} - -void MidiMapper::readOptions(FILE *fh) -{ -#ifdef MIDIMAPPERDEBUG - printf("Loading Options ... \n"); -#endif - char s[101]; - char v[101]; - char t[101]; - int fin=0; - mapPitchBender=0; - while (!fin) - { - s[0]=0; - while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); - if (strncmp(s,"PitchBenderRatio",16)==0) - { - getValue(s,v); - removeSpaces(v); - getWord(t,v,0); - mapPitchBender=1; - pitchBenderRatio=atoi(t); - } - else if (strncmp(s,"MapExpressionToVolumeEvents",27)==0) mapExpressionToVolumeEvents=1; - else if (strncmp(s,"END",3)==0) - { - fin=1; - } - else - { - printf("ERROR: Invalid option in OPTIONS section of map file : (%s)\n",s); - _ok=0; - return; - } - } -} - -void MidiMapper::readPatchmap(FILE *fh) -{ - char s[101]; - char v[101]; - char t[101]; - char name[256]; /* Longer than t and 'AllKeysTo' */ - int i=0; - int j,w; -#ifdef MIDIMAPPERDEBUG - printf("Loading Patch map ... \n"); -#endif - while (i<128) - { - s[0]=0; - while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); - getValue(s,v); - removeSpaces(v); - w=countWords(v); - j=0; - patchKeymap[i]=NULL; - patchmap[i]=i; - while (j=w) - { - printf("ERROR: Invalid option in PATCHMAP section of map file\n"); - _ok=0; - return; - } - getWord(t,v,j); - sprintf(name,"AllKeysTo%s",t); - patchKeymap[i]=createKeymap(name,1,atoi(t)); - } - else - { - patchmap[i]=atoi(t); - } - j++; - } - i++; - } - s[0]=0; - while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); - if (strncmp(s,"END",3)!=0) - { - printf("ERROR: End of section not found in map file\n"); - _ok=0; - return; - } -} - -void MidiMapper::readKeymap(FILE *fh,char *first_line) -{ - char s[101]; - char v[101]; -#ifdef MIDIMAPPERDEBUG - printf("Loading Key map ... %s",first_line); -#endif - removeSpaces(first_line); - getWord(v,first_line,2); - Keymap *km=new Keymap; - strncpy(km->name, v, KM_NAME_SIZE); - km->name[KM_NAME_SIZE - 1] = 0; - - int i=0; - while (i<128) - { - s[0]=0; - while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); - getValue(s,v); - removeSpaces(v); - km->key[i]=atoi(v); - i++; - } - s[0]=0; - while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); - if (strncmp(s,"END",3)!=0) - { - printf("ERROR: End of section not found in map file\n"); - _ok=0; - return; - } - addKeymap(km); -} - -void MidiMapper::readChannelmap(FILE *fh) -{ - char s[101]; - char v[101]; - char t[101]; - int i=0; - int w,j; -#ifdef MIDIMAPPERDEBUG - printf("Loading Channel map ... \n"); -#endif - while (i<16) - { - s[0]=0; - while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); - getValue(s,v); - removeSpaces(v); - w=countWords(v); - j=0; - channelKeymap[i]=NULL; - channelPatchForced[i]=-1; - channelmap[i]=i; - while (j=w) - { - printf("ERROR: Invalid option in CHANNELMAP section of map file\n"); - _ok=0; - return; - } - getWord(t,v,j); - channelKeymap[i]=keymap(t); - } - else if (strcmp(t,"ForcePatch")==0) - { - j++; - if (j>=w) - { - printf("ERROR: Invalid option in CHANNELMAP section of map file\n"); - _ok=0; - return; - } - getWord(t,v,j); - channelPatchForced[i]=atoi(t); - } - else - { - channelmap[i]=atoi(t); - } - j++; - } - i++; - } - s[0]=0; - while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); - if (strncmp(s,"END",3)!=0) - { - printf("END of section not found in map file\n"); - _ok=0; - return; - } - -} - -const char *MidiMapper::filename(void) -{ - return (_filename)? _filename : ""; -} - -uchar MidiMapper::key(uchar chn,uchar pgm, uchar note) -{ - uchar notemapped=note; - if (patchKeymap[pgm]!=NULL) notemapped=patchKeymap[pgm]->key[note]; - if (channelKeymap[chn]!=NULL) notemapped=channelKeymap[chn]->key[note]; - return notemapped; -} - -uchar MidiMapper::patch(uchar chn,uchar pgm) -{ - return (channelPatchForced[chn] == -1) ? - patchmap[pgm] : (uchar)channelPatchForced[chn] ; -} - -void MidiMapper::pitchBender(uchar ,uchar &lsb,uchar &msb) -{ - if (mapPitchBender) - { - short pbs=((short)msb<<7) | (lsb & 0x7F); - pbs=pbs-0x2000; - short pbs2=(((long)pbs*pitchBenderRatio)/4096); -#ifdef MIDIMAPPERDEBUG - printf("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2); -#endif - pbs2=pbs2+0x2000; - lsb=pbs2 & 0x7F; - msb=(pbs2 >> 7)&0x7F; - } -} - -void MidiMapper::controller(uchar ,uchar &ctl, uchar &) -{ - if ((mapExpressionToVolumeEvents)&&(ctl==11)) ctl=7; -} diff --git a/libtdemid/midimapper.cpp b/libtdemid/midimapper.cpp new file mode 100644 index 000000000..157ef864f --- /dev/null +++ b/libtdemid/midimapper.cpp @@ -0,0 +1,456 @@ +/************************************************************************** + + midimapper.cpp - The midi mapper object + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "midimapper.h" +#include +#include +#include +#ifdef HAVE_CONFIG_H +#include +#endif + +MidiMapper::MidiMapper(const char *name) +{ + _ok=1; + keymaps=NULL; + _filename=NULL; + mapPitchBender=0; + mapExpressionToVolumeEvents=0; + if ((name==NULL)||(name[0]==0)) + { + deallocateMaps(); + int i; + for (i=0;i<16;i++) + { + channelmap[i]=i; + channelPatchForced[i]=-1; + } + for (i=0;i<128;i++) patchmap[i]=i; + } + else + loadFile(name); +} + +MidiMapper::~MidiMapper() +{ + if (_filename) free(_filename); + deallocateMaps(); +} + +void MidiMapper::deallocateMaps(void) +{ + int i; + for (i=0;i<16;i++) channelKeymap[i]=NULL; + for (i=0;i<128;i++) patchKeymap[i]=NULL; + Keymap *km; + while (keymaps!=NULL) + { + km=keymaps->next; + delete keymaps; + keymaps=km; + } +} + +void MidiMapper::getValue(char *s,char *v) +{ + char *c=s; + while ((*c!=0)&&(*c!='=')) c++; + if (*c==0) v[0]=0; + else + { + c++; + while (*c!=0) + { + *v=*c; + c++;v++; + } + *v=0; + } +} + +void MidiMapper::removeSpaces(char *s) +{ + char *a=s; + while ((*a!=0)&&(*a==' ')) a++; + if (*a==0) {*s=0;return;}; + while (*a!=0) + { + while ((*a!=0)&&(*a!=' ')&&(*a!=10)&&(*a!=13)) + { + *s=*a; + s++; + a++; + } + while ((*a!=0)&&((*a==' ')||(*a==10)||(*a==13))) a++; + *s=' ';s++; + if (*a==0) {*s=0;return;}; + } + *s=0; + +} + +int MidiMapper::countWords(char *s) +{ + int c=0; + while (*s!=0) + { + if (*s==' ') c++; + s++; + } + return c; +} + +void MidiMapper::getWord(char *t,char *s,int w) +{ + int i=0; + *t=0; + while ((*s!=0)&&(iname, name, KM_NAME_SIZE); + km->name[KM_NAME_SIZE - 1] = 0; + + int i; + if (use_same_note==1) + { + for (i=0;i<128;i++) + km->key[i]=note; + } + else + { + for (i=0;i<128;i++) + km->key[i]=i; + } + addKeymap(km); + return km; +} + +void MidiMapper::addKeymap(Keymap *newkm) +{ + Keymap *km=keymaps; + if (keymaps==NULL) + { + keymaps=newkm; + newkm->next=NULL; + return; + } + while (km->next!=NULL) km=km->next; + km->next=newkm; + newkm->next=NULL; + return; +} + +MidiMapper::Keymap *MidiMapper::keymap(char *n) +{ + Keymap *km=keymaps; + while ((km!=NULL)&&(strcmp(km->name,n)!=0)) km=km->next; + return km; +} + +void MidiMapper::readOptions(FILE *fh) +{ +#ifdef MIDIMAPPERDEBUG + printf("Loading Options ... \n"); +#endif + char s[101]; + char v[101]; + char t[101]; + int fin=0; + mapPitchBender=0; + while (!fin) + { + s[0]=0; + while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); + if (strncmp(s,"PitchBenderRatio",16)==0) + { + getValue(s,v); + removeSpaces(v); + getWord(t,v,0); + mapPitchBender=1; + pitchBenderRatio=atoi(t); + } + else if (strncmp(s,"MapExpressionToVolumeEvents",27)==0) mapExpressionToVolumeEvents=1; + else if (strncmp(s,"END",3)==0) + { + fin=1; + } + else + { + printf("ERROR: Invalid option in OPTIONS section of map file : (%s)\n",s); + _ok=0; + return; + } + } +} + +void MidiMapper::readPatchmap(FILE *fh) +{ + char s[101]; + char v[101]; + char t[101]; + char name[256]; /* Longer than t and 'AllKeysTo' */ + int i=0; + int j,w; +#ifdef MIDIMAPPERDEBUG + printf("Loading Patch map ... \n"); +#endif + while (i<128) + { + s[0]=0; + while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); + getValue(s,v); + removeSpaces(v); + w=countWords(v); + j=0; + patchKeymap[i]=NULL; + patchmap[i]=i; + while (j=w) + { + printf("ERROR: Invalid option in PATCHMAP section of map file\n"); + _ok=0; + return; + } + getWord(t,v,j); + sprintf(name,"AllKeysTo%s",t); + patchKeymap[i]=createKeymap(name,1,atoi(t)); + } + else + { + patchmap[i]=atoi(t); + } + j++; + } + i++; + } + s[0]=0; + while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); + if (strncmp(s,"END",3)!=0) + { + printf("ERROR: End of section not found in map file\n"); + _ok=0; + return; + } +} + +void MidiMapper::readKeymap(FILE *fh,char *first_line) +{ + char s[101]; + char v[101]; +#ifdef MIDIMAPPERDEBUG + printf("Loading Key map ... %s",first_line); +#endif + removeSpaces(first_line); + getWord(v,first_line,2); + Keymap *km=new Keymap; + strncpy(km->name, v, KM_NAME_SIZE); + km->name[KM_NAME_SIZE - 1] = 0; + + int i=0; + while (i<128) + { + s[0]=0; + while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); + getValue(s,v); + removeSpaces(v); + km->key[i]=atoi(v); + i++; + } + s[0]=0; + while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); + if (strncmp(s,"END",3)!=0) + { + printf("ERROR: End of section not found in map file\n"); + _ok=0; + return; + } + addKeymap(km); +} + +void MidiMapper::readChannelmap(FILE *fh) +{ + char s[101]; + char v[101]; + char t[101]; + int i=0; + int w,j; +#ifdef MIDIMAPPERDEBUG + printf("Loading Channel map ... \n"); +#endif + while (i<16) + { + s[0]=0; + while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh); + getValue(s,v); + removeSpaces(v); + w=countWords(v); + j=0; + channelKeymap[i]=NULL; + channelPatchForced[i]=-1; + channelmap[i]=i; + while (j=w) + { + printf("ERROR: Invalid option in CHANNELMAP section of map file\n"); + _ok=0; + return; + } + getWord(t,v,j); + channelKeymap[i]=keymap(t); + } + else if (strcmp(t,"ForcePatch")==0) + { + j++; + if (j>=w) + { + printf("ERROR: Invalid option in CHANNELMAP section of map file\n"); + _ok=0; + return; + } + getWord(t,v,j); + channelPatchForced[i]=atoi(t); + } + else + { + channelmap[i]=atoi(t); + } + j++; + } + i++; + } + s[0]=0; + while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh); + if (strncmp(s,"END",3)!=0) + { + printf("END of section not found in map file\n"); + _ok=0; + return; + } + +} + +const char *MidiMapper::filename(void) +{ + return (_filename)? _filename : ""; +} + +uchar MidiMapper::key(uchar chn,uchar pgm, uchar note) +{ + uchar notemapped=note; + if (patchKeymap[pgm]!=NULL) notemapped=patchKeymap[pgm]->key[note]; + if (channelKeymap[chn]!=NULL) notemapped=channelKeymap[chn]->key[note]; + return notemapped; +} + +uchar MidiMapper::patch(uchar chn,uchar pgm) +{ + return (channelPatchForced[chn] == -1) ? + patchmap[pgm] : (uchar)channelPatchForced[chn] ; +} + +void MidiMapper::pitchBender(uchar ,uchar &lsb,uchar &msb) +{ + if (mapPitchBender) + { + short pbs=((short)msb<<7) | (lsb & 0x7F); + pbs=pbs-0x2000; + short pbs2=(((long)pbs*pitchBenderRatio)/4096); +#ifdef MIDIMAPPERDEBUG + printf("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2); +#endif + pbs2=pbs2+0x2000; + lsb=pbs2 & 0x7F; + msb=(pbs2 >> 7)&0x7F; + } +} + +void MidiMapper::controller(uchar ,uchar &ctl, uchar &) +{ + if ((mapExpressionToVolumeEvents)&&(ctl==11)) ctl=7; +} diff --git a/libtdemid/midiout.cc b/libtdemid/midiout.cc deleted file mode 100644 index 24a209cce..000000000 --- a/libtdemid/midiout.cc +++ /dev/null @@ -1,301 +0,0 @@ -/************************************************************************** - - midiout.cc - class midiOut which handles external midi devices - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "midiout.h" -#include -#include -#include -#include "sndcard.h" -#include -#include -#include -#include -#include "midispec.h" -#include "alsaout.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -SEQ_USE_EXTBUF(); - -MidiOut::MidiOut(int d) -{ - seqfd = -1; - devicetype=KMID_EXTERNAL_MIDI; - device= d; - volumepercentage=100; - map=new MidiMapper(NULL); - if (map==NULL) { printfdebug("ERROR : midiOut : Map is NULL\n"); return; }; - _ok=1; -} - -MidiOut::~MidiOut() -{ - delete map; - closeDev(); -} - -void MidiOut::openDev (int sqfd) -{ -#ifdef HAVE_OSS_SUPPORT - _ok=1; - seqfd=sqfd; - if (seqfd==-1) - { - printfdebug("ERROR: Could not open /dev/sequencer\n"); - _ok=0; - return; - } -#endif -} - -void MidiOut::closeDev (void) -{ - if (!ok()) return; -// if (deviceType()!=KMID_ALSA) allNotesOff(); - SEQ_STOP_TIMER(); - SEQ_DUMPBUF(); - seqfd=-1; -} - -void MidiOut::initDev (void) -{ -#ifdef HAVE_OSS_SUPPORT - int chn; - if (!ok()) return; - uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; - sysex(gm_reset, sizeof(gm_reset)); - for (chn=0;chn<16;chn++) - { - chnmute[chn]=0; - chnPatchChange(chn,0); - chnPressure(chn,127); - chnPitchBender(chn, 0x00, 0x40); - chnController(chn, CTL_MAIN_VOLUME,110*volumepercentage); - chnController(chn, CTL_EXT_EFF_DEPTH, 0); - chnController(chn, CTL_CHORUS_DEPTH, 0); - chnController(chn, 0x4a, 127); - } -#endif -} - -void MidiOut::setMidiMapper(MidiMapper *_map) -{ - delete map; - map=_map; -} - -void MidiOut::noteOn (uchar chn, uchar note, uchar vel) -{ - if (vel==0) - { - noteOff(chn,note,vel); - } - else - { - SEQ_MIDIOUT(device, MIDI_NOTEON + map->channel(chn)); - SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note)); - SEQ_MIDIOUT(device, vel); - } -#ifdef MIDIOUTDEBUG - printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void MidiOut::noteOff (uchar chn, uchar note, uchar vel) -{ - SEQ_MIDIOUT(device, MIDI_NOTEOFF + map->channel(chn)); - SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note)); - SEQ_MIDIOUT(device, vel); -#ifdef MIDIOUTDEBUG - printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void MidiOut::keyPressure (uchar chn, uchar note, uchar vel) -{ - SEQ_MIDIOUT(device, MIDI_KEY_PRESSURE + map->channel(chn)); - SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note)); - SEQ_MIDIOUT(device, vel); -} - -void MidiOut::chnPatchChange (uchar chn, uchar patch) -{ -#ifdef MIDIOUTDEBUG - printfdebug("PATCHCHANGE [%d->%d] %d -> %d\n", - chn,map->channel(chn),patch,map->patch(chn,patch)); -#endif - SEQ_MIDIOUT(device, MIDI_PGM_CHANGE + map->channel(chn)); - SEQ_MIDIOUT(device, map->patch(chn,patch)); - chnpatch[chn]=patch; -} - -void MidiOut::chnPressure (uchar chn, uchar vel) -{ - SEQ_MIDIOUT(device, MIDI_CHN_PRESSURE + map->channel(chn)); - SEQ_MIDIOUT(device, vel); - - chnpressure[chn]=vel; -} - -void MidiOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) -{ - SEQ_MIDIOUT(device, MIDI_PITCH_BEND + map->channel(chn)); - /* -#ifdef AT_HOME - short pbs=((short)msb<<7) | (lsb & 0x7F); - pbs=pbs-0x2000; - short pbs2=(((long)pbs*672)/4096); - printfdebug("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2); - pbs2=pbs2+0x2000; - lsb=pbs2 & 0x7F; - msb=(pbs2 >> 7)&0x7F; -#endif - */ - map->pitchBender(chn,lsb,msb); - SEQ_MIDIOUT(device, lsb); - SEQ_MIDIOUT(device, msb); - chnbender[chn]=(msb << 8) | (lsb & 0xFF); -} - -void MidiOut::chnController (uchar chn, uchar ctl, uchar v) -{ - SEQ_MIDIOUT(device, MIDI_CTL_CHANGE + map->channel(chn)); -#ifdef AT_HOME - if (ctl==11) ctl=7; -#endif - map->controller(chn,ctl,v); - if ((ctl==11)||(ctl==7)) - { - v=(v*volumepercentage)/100; - if (v>127) v=127; - } - - SEQ_MIDIOUT(device, ctl); - SEQ_MIDIOUT(device, v); - - chncontroller[chn][ctl]=v; -} - -void MidiOut::sysex(uchar *data, ulong size) -{ - ulong i=0; - SEQ_MIDIOUT(device, MIDI_SYSTEM_PREFIX); - while (ifilename() : ""; -} - -const char * MidiOut::deviceName(void) const -{ - switch (deviceType()) - { - case (KMID_EXTERNAL_MIDI) : return "External Midi"; - case (KMID_SYNTH) : return "Synth"; - case (KMID_FM) : return "FM"; - case (KMID_GUS) : return "GUS"; - case (KMID_AWE) : return "AWE"; - case (KMID_ALSA) : return reinterpret_cast(this)->deviceName(); - } - return "Unknown"; -} - -void MidiOut::sync(int i) -{ - if (deviceType()==KMID_ALSA) { // XXX : sync should be virtual after next bic - reinterpret_cast(this)->sync(i); - return; - } - SEQ_DUMPBUF(); -} diff --git a/libtdemid/midiout.cpp b/libtdemid/midiout.cpp new file mode 100644 index 000000000..c4949b03c --- /dev/null +++ b/libtdemid/midiout.cpp @@ -0,0 +1,301 @@ +/************************************************************************** + + midiout.cpp - class midiOut which handles external midi devices + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "midiout.h" +#include +#include +#include +#include "sndcard.h" +#include +#include +#include +#include +#include "midispec.h" +#include "alsaout.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +SEQ_USE_EXTBUF(); + +MidiOut::MidiOut(int d) +{ + seqfd = -1; + devicetype=KMID_EXTERNAL_MIDI; + device= d; + volumepercentage=100; + map=new MidiMapper(NULL); + if (map==NULL) { printfdebug("ERROR : midiOut : Map is NULL\n"); return; }; + _ok=1; +} + +MidiOut::~MidiOut() +{ + delete map; + closeDev(); +} + +void MidiOut::openDev (int sqfd) +{ +#ifdef HAVE_OSS_SUPPORT + _ok=1; + seqfd=sqfd; + if (seqfd==-1) + { + printfdebug("ERROR: Could not open /dev/sequencer\n"); + _ok=0; + return; + } +#endif +} + +void MidiOut::closeDev (void) +{ + if (!ok()) return; +// if (deviceType()!=KMID_ALSA) allNotesOff(); + SEQ_STOP_TIMER(); + SEQ_DUMPBUF(); + seqfd=-1; +} + +void MidiOut::initDev (void) +{ +#ifdef HAVE_OSS_SUPPORT + int chn; + if (!ok()) return; + uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; + sysex(gm_reset, sizeof(gm_reset)); + for (chn=0;chn<16;chn++) + { + chnmute[chn]=0; + chnPatchChange(chn,0); + chnPressure(chn,127); + chnPitchBender(chn, 0x00, 0x40); + chnController(chn, CTL_MAIN_VOLUME,110*volumepercentage); + chnController(chn, CTL_EXT_EFF_DEPTH, 0); + chnController(chn, CTL_CHORUS_DEPTH, 0); + chnController(chn, 0x4a, 127); + } +#endif +} + +void MidiOut::setMidiMapper(MidiMapper *_map) +{ + delete map; + map=_map; +} + +void MidiOut::noteOn (uchar chn, uchar note, uchar vel) +{ + if (vel==0) + { + noteOff(chn,note,vel); + } + else + { + SEQ_MIDIOUT(device, MIDI_NOTEON + map->channel(chn)); + SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note)); + SEQ_MIDIOUT(device, vel); + } +#ifdef MIDIOUTDEBUG + printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void MidiOut::noteOff (uchar chn, uchar note, uchar vel) +{ + SEQ_MIDIOUT(device, MIDI_NOTEOFF + map->channel(chn)); + SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note)); + SEQ_MIDIOUT(device, vel); +#ifdef MIDIOUTDEBUG + printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void MidiOut::keyPressure (uchar chn, uchar note, uchar vel) +{ + SEQ_MIDIOUT(device, MIDI_KEY_PRESSURE + map->channel(chn)); + SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note)); + SEQ_MIDIOUT(device, vel); +} + +void MidiOut::chnPatchChange (uchar chn, uchar patch) +{ +#ifdef MIDIOUTDEBUG + printfdebug("PATCHCHANGE [%d->%d] %d -> %d\n", + chn,map->channel(chn),patch,map->patch(chn,patch)); +#endif + SEQ_MIDIOUT(device, MIDI_PGM_CHANGE + map->channel(chn)); + SEQ_MIDIOUT(device, map->patch(chn,patch)); + chnpatch[chn]=patch; +} + +void MidiOut::chnPressure (uchar chn, uchar vel) +{ + SEQ_MIDIOUT(device, MIDI_CHN_PRESSURE + map->channel(chn)); + SEQ_MIDIOUT(device, vel); + + chnpressure[chn]=vel; +} + +void MidiOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) +{ + SEQ_MIDIOUT(device, MIDI_PITCH_BEND + map->channel(chn)); + /* +#ifdef AT_HOME + short pbs=((short)msb<<7) | (lsb & 0x7F); + pbs=pbs-0x2000; + short pbs2=(((long)pbs*672)/4096); + printfdebug("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2); + pbs2=pbs2+0x2000; + lsb=pbs2 & 0x7F; + msb=(pbs2 >> 7)&0x7F; +#endif + */ + map->pitchBender(chn,lsb,msb); + SEQ_MIDIOUT(device, lsb); + SEQ_MIDIOUT(device, msb); + chnbender[chn]=(msb << 8) | (lsb & 0xFF); +} + +void MidiOut::chnController (uchar chn, uchar ctl, uchar v) +{ + SEQ_MIDIOUT(device, MIDI_CTL_CHANGE + map->channel(chn)); +#ifdef AT_HOME + if (ctl==11) ctl=7; +#endif + map->controller(chn,ctl,v); + if ((ctl==11)||(ctl==7)) + { + v=(v*volumepercentage)/100; + if (v>127) v=127; + } + + SEQ_MIDIOUT(device, ctl); + SEQ_MIDIOUT(device, v); + + chncontroller[chn][ctl]=v; +} + +void MidiOut::sysex(uchar *data, ulong size) +{ + ulong i=0; + SEQ_MIDIOUT(device, MIDI_SYSTEM_PREFIX); + while (ifilename() : ""; +} + +const char * MidiOut::deviceName(void) const +{ + switch (deviceType()) + { + case (KMID_EXTERNAL_MIDI) : return "External Midi"; + case (KMID_SYNTH) : return "Synth"; + case (KMID_FM) : return "FM"; + case (KMID_GUS) : return "GUS"; + case (KMID_AWE) : return "AWE"; + case (KMID_ALSA) : return reinterpret_cast(this)->deviceName(); + } + return "Unknown"; +} + +void MidiOut::sync(int i) +{ + if (deviceType()==KMID_ALSA) { // XXX : sync should be virtual after next bic + reinterpret_cast(this)->sync(i); + return; + } + SEQ_DUMPBUF(); +} diff --git a/libtdemid/midistat.cc b/libtdemid/midistat.cc deleted file mode 100644 index 6a6c94b0c..000000000 --- a/libtdemid/midistat.cc +++ /dev/null @@ -1,115 +0,0 @@ -/************************************************************************** - - midistat.cc - class MidiStatus, change it internally and then send it. - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "midistat.h" -#include "deviceman.h" -#include "sndcard.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -extern int MT32toGM[128]; - -MidiStatus::MidiStatus() -{ - int i; - tempo=1000000; - for (int chn=0;chn<16;chn++) - { - chn_patch[chn]=0; - chn_bender[chn]=0x4000; - chn_pressure[chn]=127; - for (i=0;i<256;i++) - chn_controller[chn][i]=0; - chn_controller[chn][CTL_MAIN_VOLUME]=127; - chn_controller[chn][11]=127; - chn_controller[chn][0x4a]=127; - chn_lastisvolumeev[chn]=1; - } -} - -MidiStatus::~MidiStatus() -{ -} - -// void noteOn ( uchar chn, uchar note, uchar vel ); -// void noteOff ( uchar chn, uchar note, uchar vel ); - -void MidiStatus::chnPatchChange ( uchar chn, uchar patch ) -{ - chn_patch[chn]=patch; -} - -void MidiStatus::chnPressure ( uchar chn, uchar vel ) -{ - chn_pressure[chn]=vel; -} - -void MidiStatus::chnPitchBender ( uchar chn, uchar lsb, uchar msb ) -{ - chn_bender[chn]=((int)msb<<8|lsb); -} - -void MidiStatus::chnController ( uchar chn, uchar ctl , uchar v ) -{ - if (ctl==7) chn_lastisvolumeev[chn]=1; - else if (ctl==11) chn_lastisvolumeev[chn]=0; - - chn_controller[chn][ctl]=v; -} - -void MidiStatus::tmrSetTempo(int v) -{ - tempo=v; -} - -void MidiStatus::sendData(DeviceManager *midi,int gm) -{ - for (int chn=0;chn<16;chn++) - { -#ifdef MIDISTATDEBUG - printf("Restoring channel %d\n",chn); -#endif - midi->chnPatchChange(chn, - (gm==1)?(chn_patch[chn]):(MT32toGM[chn_patch[chn]])); - midi->chnPitchBender(chn,chn_bender[chn]&0xFF,chn_bender[chn]>>8); - midi->chnPressure(chn,chn_pressure[chn]); - if (chn_lastisvolumeev[chn]) - { - midi->chnController(chn,11,chn_controller[chn][11]); - midi->chnController(chn,CTL_MAIN_VOLUME,chn_controller[chn][CTL_MAIN_VOLUME]); - } else { - midi->chnController(chn,CTL_MAIN_VOLUME,chn_controller[chn][CTL_MAIN_VOLUME]); - midi->chnController(chn,11,chn_controller[chn][11]); - } - /* - for (int i=0;i<256;i++) - midi->chnController(chn,i,chn_controller[chn][i]); - */ - } - midi->tmrSetTempo(tempo); - midi->sync(); -} diff --git a/libtdemid/midistat.cpp b/libtdemid/midistat.cpp new file mode 100644 index 000000000..7bd02c95a --- /dev/null +++ b/libtdemid/midistat.cpp @@ -0,0 +1,115 @@ +/************************************************************************** + + midistat.cpp - class MidiStatus, change it internally and then send it. + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "midistat.h" +#include "deviceman.h" +#include "sndcard.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +extern int MT32toGM[128]; + +MidiStatus::MidiStatus() +{ + int i; + tempo=1000000; + for (int chn=0;chn<16;chn++) + { + chn_patch[chn]=0; + chn_bender[chn]=0x4000; + chn_pressure[chn]=127; + for (i=0;i<256;i++) + chn_controller[chn][i]=0; + chn_controller[chn][CTL_MAIN_VOLUME]=127; + chn_controller[chn][11]=127; + chn_controller[chn][0x4a]=127; + chn_lastisvolumeev[chn]=1; + } +} + +MidiStatus::~MidiStatus() +{ +} + +// void noteOn ( uchar chn, uchar note, uchar vel ); +// void noteOff ( uchar chn, uchar note, uchar vel ); + +void MidiStatus::chnPatchChange ( uchar chn, uchar patch ) +{ + chn_patch[chn]=patch; +} + +void MidiStatus::chnPressure ( uchar chn, uchar vel ) +{ + chn_pressure[chn]=vel; +} + +void MidiStatus::chnPitchBender ( uchar chn, uchar lsb, uchar msb ) +{ + chn_bender[chn]=((int)msb<<8|lsb); +} + +void MidiStatus::chnController ( uchar chn, uchar ctl , uchar v ) +{ + if (ctl==7) chn_lastisvolumeev[chn]=1; + else if (ctl==11) chn_lastisvolumeev[chn]=0; + + chn_controller[chn][ctl]=v; +} + +void MidiStatus::tmrSetTempo(int v) +{ + tempo=v; +} + +void MidiStatus::sendData(DeviceManager *midi,int gm) +{ + for (int chn=0;chn<16;chn++) + { +#ifdef MIDISTATDEBUG + printf("Restoring channel %d\n",chn); +#endif + midi->chnPatchChange(chn, + (gm==1)?(chn_patch[chn]):(MT32toGM[chn_patch[chn]])); + midi->chnPitchBender(chn,chn_bender[chn]&0xFF,chn_bender[chn]>>8); + midi->chnPressure(chn,chn_pressure[chn]); + if (chn_lastisvolumeev[chn]) + { + midi->chnController(chn,11,chn_controller[chn][11]); + midi->chnController(chn,CTL_MAIN_VOLUME,chn_controller[chn][CTL_MAIN_VOLUME]); + } else { + midi->chnController(chn,CTL_MAIN_VOLUME,chn_controller[chn][CTL_MAIN_VOLUME]); + midi->chnController(chn,11,chn_controller[chn][11]); + } + /* + for (int i=0;i<256;i++) + midi->chnController(chn,i,chn_controller[chn][i]); + */ + } + midi->tmrSetTempo(tempo); + midi->sync(); +} diff --git a/libtdemid/mt32togm.cc b/libtdemid/mt32togm.cc deleted file mode 100644 index a59eb959c..000000000 --- a/libtdemid/mt32togm.cc +++ /dev/null @@ -1,18 +0,0 @@ -#include "mt32togm.h" - -int MT32toGM[128] = -{ - 0, 1, 2, 4, 4, 5, 5, 3, 16, 16, - 16, 16, 19, 19, 19, 21, 6, 6, 6, 7, - 7, 7, 8, 8, 62, 57, 63, 58, 38, 38, - 39, 39, 88, 33, 52, 35, 97, 100, 38, 39, - 14, 102, 68, 103, 44, 92, 46, 80, 48, 49, - 51, 45, 40, 40, 42, 42, 43, 46, 46, 24, - 25, 28, 27, 104, 32, 32, 34, 33, 36, 37, - 39, 35, 79, 73, 76, 72, 74, 75, 64, 65, - 66, 67, 71, 71, 69, 70, 60, 22, 56, 59, - 57, 63, 60, 60, 58, 61, 61, 11, 11, 99, - 100, 9, 14, 13, 12, 107, 106, 77, 78, 78, - 76, 111, 47, 117, 127, 115, 118, 116, 118, 126, - 121, 121, 55, 124, 120, 125, 126, 127 -}; diff --git a/libtdemid/mt32togm.cpp b/libtdemid/mt32togm.cpp new file mode 100644 index 000000000..a59eb959c --- /dev/null +++ b/libtdemid/mt32togm.cpp @@ -0,0 +1,18 @@ +#include "mt32togm.h" + +int MT32toGM[128] = +{ + 0, 1, 2, 4, 4, 5, 5, 3, 16, 16, + 16, 16, 19, 19, 19, 21, 6, 6, 6, 7, + 7, 7, 8, 8, 62, 57, 63, 58, 38, 38, + 39, 39, 88, 33, 52, 35, 97, 100, 38, 39, + 14, 102, 68, 103, 44, 92, 46, 80, 48, 49, + 51, 45, 40, 40, 42, 42, 43, 46, 46, 24, + 25, 28, 27, 104, 32, 32, 34, 33, 36, 37, + 39, 35, 79, 73, 76, 72, 74, 75, 64, 65, + 66, 67, 71, 71, 69, 70, 60, 22, 56, 59, + 57, 63, 60, 60, 58, 61, 61, 11, 11, 99, + 100, 9, 14, 13, 12, 107, 106, 77, 78, 78, + 76, 111, 47, 117, 127, 115, 118, 116, 118, 126, + 121, 121, 55, 124, 120, 125, 126, 127 +}; diff --git a/libtdemid/notearray.cc b/libtdemid/notearray.cc deleted file mode 100644 index 9899fd837..000000000 --- a/libtdemid/notearray.cc +++ /dev/null @@ -1,122 +0,0 @@ -/************************************************************************** - - notearray.cc - NoteArray class, which holds an array of notes - This file is part of LibKMid 0.9.5 - Copyright (C) 1998,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ - -#include "notearray.h" -#include - -NoteArray::NoteArray(void) -{ - totalAllocated=50; - data=new noteCmd[totalAllocated]; - lastAdded=0L; -} - -NoteArray::~NoteArray() -{ - delete data; - totalAllocated=0; -} - -NoteArray::noteCmd *NoteArray::pointerTo(ulong pos) -{ - if (pos=totalAllocated) - { - noteCmd *tmp=new noteCmd[totalAllocated*2]; - memcpy(tmp,data,sizeof(noteCmd)*totalAllocated); - delete data; - data=tmp; - totalAllocated*=2; - } - return &data[pos]; -} - -void NoteArray::at(ulong pos, ulong ms,int chn,int cmd,int note) -{ - noteCmd *tmp=pointerTo(pos); - tmp->ms=ms; - tmp->chn=chn; - tmp->cmd=cmd; - tmp->note=note; -} - -void NoteArray::at(ulong pos, noteCmd s) -{ - noteCmd *tmp=pointerTo(pos); - tmp->ms=s.ms; - tmp->chn=s.chn; - tmp->cmd=s.cmd; - tmp->note=s.note; -} - -NoteArray::noteCmd NoteArray::at(int pos) -{ - return *pointerTo(pos); -} - -void NoteArray::add(ulong ms,int chn,int cmd,int note) -{ - if (lastAdded==NULL) - { - lastAdded=data; - last=0; - } - else - { - last++; - if (last==totalAllocated) lastAdded=pointerTo(totalAllocated); - else lastAdded++; - } - lastAdded->ms=ms; - lastAdded->chn=chn; - lastAdded->cmd=cmd; - lastAdded->note=note; -} - -void NoteArray::next(void) -{ - if (it==lastAdded) {it=NULL;return;}; - it++; -} - -void NoteArray::moveIteratorTo(ulong ms,int *pgm) -{ - noteCmd *ncmd; - iteratorBegin(); - ncmd=get(); - int pgm2[16]; - for (int j=0;j<16;j++) pgm2[j]=0; - while ((ncmd!=NULL)&&(ncmd->mscmd==2) pgm2[ncmd->chn]=ncmd->note; - next(); - ncmd=get(); - } - if (pgm!=NULL) - { - for (int i=0;i<16;i++) pgm[i]=pgm2[i]; - } -} diff --git a/libtdemid/notearray.cpp b/libtdemid/notearray.cpp new file mode 100644 index 000000000..d08a5b074 --- /dev/null +++ b/libtdemid/notearray.cpp @@ -0,0 +1,122 @@ +/************************************************************************** + + notearray.cpp - NoteArray class, which holds an array of notes + This file is part of LibKMid 0.9.5 + Copyright (C) 1998,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ + +#include "notearray.h" +#include + +NoteArray::NoteArray(void) +{ + totalAllocated=50; + data=new noteCmd[totalAllocated]; + lastAdded=0L; +} + +NoteArray::~NoteArray() +{ + delete data; + totalAllocated=0; +} + +NoteArray::noteCmd *NoteArray::pointerTo(ulong pos) +{ + if (pos=totalAllocated) + { + noteCmd *tmp=new noteCmd[totalAllocated*2]; + memcpy(tmp,data,sizeof(noteCmd)*totalAllocated); + delete data; + data=tmp; + totalAllocated*=2; + } + return &data[pos]; +} + +void NoteArray::at(ulong pos, ulong ms,int chn,int cmd,int note) +{ + noteCmd *tmp=pointerTo(pos); + tmp->ms=ms; + tmp->chn=chn; + tmp->cmd=cmd; + tmp->note=note; +} + +void NoteArray::at(ulong pos, noteCmd s) +{ + noteCmd *tmp=pointerTo(pos); + tmp->ms=s.ms; + tmp->chn=s.chn; + tmp->cmd=s.cmd; + tmp->note=s.note; +} + +NoteArray::noteCmd NoteArray::at(int pos) +{ + return *pointerTo(pos); +} + +void NoteArray::add(ulong ms,int chn,int cmd,int note) +{ + if (lastAdded==NULL) + { + lastAdded=data; + last=0; + } + else + { + last++; + if (last==totalAllocated) lastAdded=pointerTo(totalAllocated); + else lastAdded++; + } + lastAdded->ms=ms; + lastAdded->chn=chn; + lastAdded->cmd=cmd; + lastAdded->note=note; +} + +void NoteArray::next(void) +{ + if (it==lastAdded) {it=NULL;return;}; + it++; +} + +void NoteArray::moveIteratorTo(ulong ms,int *pgm) +{ + noteCmd *ncmd; + iteratorBegin(); + ncmd=get(); + int pgm2[16]; + for (int j=0;j<16;j++) pgm2[j]=0; + while ((ncmd!=NULL)&&(ncmd->mscmd==2) pgm2[ncmd->chn]=ncmd->note; + next(); + ncmd=get(); + } + if (pgm!=NULL) + { + for (int i=0;i<16;i++) pgm[i]=pgm2[i]; + } +} diff --git a/libtdemid/player.cc b/libtdemid/player.cc deleted file mode 100644 index ff7093496..000000000 --- a/libtdemid/player.cc +++ /dev/null @@ -1,959 +0,0 @@ -/************************************************************************** - - player.cc - class MidiPlayer. Plays a set of tracks - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - $Id$ - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "player.h" -#include "sndcard.h" -#include "midispec.h" -#include -#include -#include -#include "midistat.h" -#include "mt32togm.h" - -//#define PLAYERDEBUG -//#define GENERAL_DEBUG_MESSAGES - -#define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote) - -#define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote)/((double)60000L)) - -#define REMOVEDUPSTRINGS - -MidiPlayer::MidiPlayer(DeviceManager *midi_,PlayerController *pctl) -{ - midi=midi_; - info=NULL; - tracks=NULL; - songLoaded=0; - ctl=pctl; - spev=NULL; - na=NULL; - parsesong=true; - generatebeats=false; -} - -MidiPlayer::~MidiPlayer() -{ - removeSpecialEvents(); - removeSong(); -} - -void MidiPlayer::removeSong(void) -{ - if ((songLoaded)&&(tracks!=NULL)) - { -#ifdef PLAYERDEBUG - printf("Removing song from memory\n"); -#endif - int i=0; - while (intracks) - { - if (tracks[i]!=NULL) delete tracks[i]; - i++; - } - delete tracks; - tracks=NULL; - if (info!=NULL) - { - delete info; - info=NULL; - } - } - songLoaded=0; -} - -int MidiPlayer::loadSong(const char *filename) -{ - removeSong(); -#ifdef PLAYERDEBUG - printf("Loading Song : %s\n",filename); -#endif - info=new MidiFileInfo; - int ok; - tracks=readMidiFile(filename,info,ok); - if (ok<0) return ok; - if (tracks==NULL) return -4; - - parseInfoData(info,tracks,ctl->ratioTempo); - - if (parsesong) - { - parseSpecialEvents(); - if (generatebeats) generateBeats(); - } - - songLoaded=1; - return 0; -} - -void MidiPlayer::insertBeat(SpecialEvent *ev,ulong ms,int num,int den) -{ - SpecialEvent *beat=new SpecialEvent; - beat->next=ev->next; - ev->next=beat; - beat->id=1; - beat->type=7; - beat->absmilliseconds=ms; - beat->num=num; - beat->den=den; -} - - -void MidiPlayer::generateBeats(void) -{ -#ifdef PLAYERDEBUG - printf("player::Generating Beats...\n"); -#endif - - if (spev==NULL) return; - SpecialEvent *ev=spev; - SpecialEvent *nextev=ev->next; - ulong tempo=(ulong)(500000 * ctl->ratioTempo); - int i=1; - int num=4; - int den=4; - // ulong beatstep=((double)tempo*4/(den*1000)); - // ulong beatstep=T2MS(info->ticksPerCuarterNote*(4/den)); - double ticksleft=(((double)info->ticksPerCuarterNote*4)/den); - - double beatstep=T2MS(ticksleft); - double nextbeatms=0; - double lastbeatms=0; - double measurems=0; - - while (nextev!=NULL) - { - switch (ev->type) - { - case (0): // End of list - { - };break; - case (1): // Text - case (2): // Lyrics - { - };break; - case (3): // Change Tempo - { - lastbeatms=ev->absmilliseconds; - ticksleft=MS2T(nextbeatms-lastbeatms); - tempo=ev->tempo; - nextbeatms=lastbeatms+T2MS(ticksleft); - // printf("Change at %lu to %d\n",ev->absmilliseconds,ev->tempo); - // beatstep=((double)tempo*4/(den*1000)); - beatstep=T2MS(((static_cast(info->ticksPerCuarterNote)*4)/den)); - };break; - case (6): // Change number of beats per measure - { - num=ev->num; - i=1; - den=ev->den; - // printf("Change at %lu to %d/%d\n",ev->absmilliseconds,num,den); - // beatstep=((double)tempo*4/(den*1000)); - // beatstep=T2MS(info->ticksPerCuarterNote*(4/den)); - beatstep=T2MS((((double)info->ticksPerCuarterNote*4)/den)); - nextbeatms=ev->absmilliseconds; - };break; - }; - if (nextev->absmilliseconds>nextbeatms) - { - //printf("Adding %d,%d\n",num,tot); - //printf("beat at %g , %d/%d\n",nextbeatms,i,num); - //printf(" %ld %d\n",nextev->absmilliseconds,nextev->type); - if (i == 1) { - measurems=nextbeatms; - } - insertBeat(ev, static_cast(nextbeatms), i++, num); - if (i > num) { - i=1; - } - lastbeatms=nextbeatms; - nextbeatms+=beatstep; - // nextbeatms=measurems+beatstep*i; - - ticksleft = ( (static_cast(info->ticksPerCuarterNote)*4) / den); - - } - - ev=ev->next; - nextev=ev->next; - } - - /* ev==NULL doesn't indicate the end of the song, so continue generating beats */ - - if (ev!=NULL) - { - if (ev->type==0) - { - ev=spev; - /* Looking if ev->next is NULL is not needed because - we are sure that a ev->type == 0 exists, we just have - to assure that the first spev is not the only one */ - if (ev->next!=NULL) - while (ev->next->type!=0) ev=ev->next; - } - while (nextbeatmsmillisecsTotal) - { - // printf("beat2 at %g , %d/%d\n",nextbeatms,i,num); - if (i==1) measurems=nextbeatms; - insertBeat(ev, static_cast(nextbeatms), i++, num); - if (i>num) i=1; - nextbeatms+=beatstep; - ev=ev->next; - } - } - - /* Regenerate IDs */ - - ev=spev; - i=1; - while (ev!=NULL) - { - ev->id=i++; - ev=ev->next; - } - - -#ifdef PLAYERDEBUG - printf("player::Beats Generated\n"); -#endif - -} - -void MidiPlayer::removeSpecialEvents(void) -{ - SpecialEvent * ev=spev; - while (spev!=NULL) - { - ev=spev->next; - delete spev; - spev=ev; - } - delete na; - na=0; -} - -void MidiPlayer::parseSpecialEvents(void) -{ -#ifdef PLAYERDEBUG - printf("player::Parsing...\n"); -#endif - removeSpecialEvents(); - spev=new SpecialEvent; - if (spev==NULL) return; - SpecialEvent *pspev=spev; - pspev->type=0; - pspev->ticks=0; - if (na) delete na; - na=new NoteArray(); - if (!na) { delete spev; spev=0L; return; }; - int trk; - int minTrk; - double minTime=0; - double maxTime; - ulong tempo=(ulong)(500000 * (ctl->ratioTempo)); - ulong firsttempo=0; - for (int i=0;intracks;i++) - { - tracks[i]->init(); - tracks[i]->changeTempo(tempo); - } - MidiEvent *ev=new MidiEvent; - //ulong mspass; - double prevms=0; - int spev_id=1; - int j; - int parsing=1; -#ifdef REMOVEDUPSTRINGS - char lasttext[1024]; - ulong lasttexttime=0; - lasttext[0]=0; - int lasttexttype=0; -#endif - while (parsing) - { - prevms=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 2 * 60000L; - minTime=maxTime; - parsing=0; - while (trkntracks) - { - if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); - parsing=1; - } - trk++; - } - // if ((minTime==maxTime)) - if (parsing==0) - { - // parsing=0; -#ifdef PLAYERDEBUG - printf("END of parsing\n"); -#endif - } - else - { - // mspass=(ulong)(minTime-prevms); - trk=0; - while (trkntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - } - trk=minTrk; - tracks[trk]->readEvent(ev); - switch (ev->command) - { - case (MIDI_NOTEON) : - if (ev->vel==0) na->add((ulong)minTime,ev->chn,0, ev->note); - else na->add((ulong)minTime,ev->chn,1,ev->note); - break; - case (MIDI_NOTEOFF) : - na->add((ulong)minTime,ev->chn,0, ev->note); - break; - case (MIDI_PGM_CHANGE) : - na->add((ulong)minTime,ev->chn, 2,ev->patch); - break; - case (MIDI_SYSTEM_PREFIX) : - { - if ((ev->command|ev->chn)==META_EVENT) - { - switch (ev->d1) - { - case (1) : - case (5) : - { - if (pspev!=NULL) - { - pspev->absmilliseconds=(ulong)minTime; - pspev->type=ev->d1; - pspev->id=spev_id++; -#ifdef PLAYERDEBUG - printf("ev->length %ld\n",ev->length); - -#endif - strncpy(pspev->text,(char *)ev->data, - (ev->length>= sizeof(lasttext))? sizeof(lasttext)-1 : (ev->length) ); - pspev->text[(ev->length>= sizeof(lasttext))? sizeof(lasttext)-1:(ev->length)]=0; -#ifdef PLAYERDEBUG - printf("(%s)(%s)\n",pspev->text,lasttext); -#endif -#ifdef REMOVEDUPSTRINGS - if ((strcmp(pspev->text,lasttext)!=0)||(pspev->absmilliseconds!=lasttexttime)||(pspev->type!=lasttexttype)) - { - lasttexttime=pspev->absmilliseconds; - lasttexttype=pspev->type; - strncpy(lasttext, pspev->text, 1024); - lasttext[sizeof(lasttext)-1] = 0; -#endif - pspev->next=new SpecialEvent; -#ifdef PLAYERDEBUG - if (pspev->next==NULL) printf("pspev->next=NULL\n"); -#endif - pspev=pspev->next; -#ifdef REMOVEDUPSTRINGS - } -#endif - } - } - break; - case (ME_SET_TEMPO) : - { - if (pspev!=NULL) - { - pspev->absmilliseconds=(ulong)minTime; - pspev->type=3; - pspev->id=spev_id++; - tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ctl->ratioTempo); - pspev->tempo=tempo; - if (firsttempo==0) firsttempo=tempo; - for (j=0;jntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - pspev->next=new SpecialEvent; - pspev=pspev->next; - } - } - break; - case (ME_TIME_SIGNATURE) : - { - if (pspev!=NULL) - { - pspev->absmilliseconds=(ulong)minTime; - pspev->type=6; - pspev->id=spev_id++; - pspev->num=ev->d2; - pspev->den=ev->d3; - pspev->next=new SpecialEvent; - pspev=pspev->next; - } - } - break; - } - } - } - break; - } - } - - delete ev; - pspev->type=0; - pspev->absmilliseconds=(ulong)prevms; - pspev->next=NULL; - if (firsttempo==0) firsttempo=tempo; - ctl->tempo=firsttempo; - - //writeSPEV(); - for (int i=0;intracks;i++) - { - tracks[i]->init(); - } -} - -/* -NoteArray *MidiPlayer::parseNotes(void) -{ -#ifdef PLAYERDEBUG - printf("player::Parsing Notes...\n"); -#endif - NoteArray *na=new NoteArray(); - int trk; - int minTrk; - double minTime=0; - double maxTime; - for (int i=0;intracks;i++) - { - tracks[i]->init(); - }; - ulong tempo=1000000; - ulong tmp; - Midi_event *ev=new Midi_event; - //ulong mspass; - double prevms=0; - int j; - int parsing=1; - while (parsing) - { - prevms=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 2 * 60000L; - minTime=maxTime; - while (trkntracks) - { - if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); - }; - trk++; - }; - if ((minTime==maxTime)) - { - parsing=0; -#ifdef PLAYERDEBUG - printf("END of parsing\n"); -#endif - } - else - { - // mspass=(ulong)(minTime-prevms); - trk=0; - while (trkntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - }; - }; - trk=minTrk; - tracks[trk]->readEvent(ev); - if (ev->command==MIDI_NOTEON) - { - if (ev->vel==0) {printf("note off at %g\n",minTime);na->add((ulong)minTime,ev->chn,0, ev->note);} - else {printf("note on at %g\n",minTime);na->add((ulong)minTime,ev->chn,1,ev->note);} - } - else - if (ev->command==MIDI_NOTEOFF) na->add((ulong)minTime,ev->chn,0, ev->note); - if (ev->command==MIDI_PGM_CHANGE) na->add((ulong)minTime,ev->chn, 2,ev->patch); - if (ev->command==MIDI_SYSTEM_PREFIX) - { - if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) - { - tempo=(ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]); - for (j=0;jntracks;j++) - { - tracks[j]->changeTempo(tempo); - }; - }; - }; - - }; - - delete ev; - for (int i=0;intracks;i++) - { - tracks[i]->init(); - }; - return na; -}; -*/ - -void MidiPlayer::play(bool calloutput,void output(void)) -{ -#ifdef PLAYERDEBUG - printf("Playing...\n"); -#endif - - if (midi->midiPorts()+midi->synthDevices()==0) - { - fprintf(stderr,"Player :: There are no midi ports !\n"); - ctl->error=1; - return; - } - - midi->openDev(); - if (midi->ok()==0) - { - fprintf(stderr,"Player :: Couldn't play !\n"); - ctl->error=1; - return; - } - midi->setVolumePercentage(ctl->volumepercentage); - midi->initDev(); - // parsePatchesUsed(tracks,info,ctl->gm); - midi->setPatchesToUse(info->patchesUsed); - - int trk; - int minTrk; - double minTime=0; - double maxTime; - int i; - ulong tempo=(ulong)(500000 * ctl->ratioTempo); - for (i=0;intracks;i++) - { - tracks[i]->init(); - tracks[i]->changeTempo(tempo); - } - - midi->tmrStart(info->ticksPerCuarterNote); - MidiEvent *ev=new MidiEvent; - ctl->ev=ev; - ctl->ticksTotal=info->ticksTotal; - ctl->ticksPlayed=0; - //ctl->millisecsPlayed=0; - ulong ticksplayed=0; - double absTimeAtChangeTempo=0; - double absTime=0; - double diffTime=0; - MidiStatus *midistat; - //ulong mspass; - double prevms=0; - int j; - int halt=0; - ctl->tempo=tempo; - ctl->num=4; - ctl->den=4; - int playing; - ctl->paused=0; - if ((ctl->message!=0)&&(ctl->message & PLAYER_SETPOS)) - { - ctl->moving=1; - ctl->message&=~PLAYER_SETPOS; - midi->sync(1); - midi->tmrStop(); - midi->closeDev(); - midistat = new MidiStatus(); - setPos(ctl->gotomsec,midistat); - minTime=ctl->gotomsec; - prevms=(ulong)minTime; - midi->openDev(); - midi->tmrStart(info->ticksPerCuarterNote); - diffTime=ctl->gotomsec; - midistat->sendData(midi,ctl->gm); - delete midistat; - midi->setPatchesToUse(info->patchesUsed); - ctl->moving=0; - } else - for (i=0;i<16;i++) - { - if (ctl->forcepgm[i]) - { - midi->chnPatchChange(i, ctl->pgm[i]); - } - } - - timeval begintv; - gettimeofday(&begintv, NULL); - ctl->beginmillisec=begintv.tv_sec*1000+begintv.tv_usec/1000; - ctl->OK=1; - ctl->playing=playing=1; - - while (playing) - { - /* - if (ctl->message!=0) - { - if (ctl->message & PLAYER_DOPAUSE) - { - diffTime=minTime; - ctl->message&=~PLAYER_DOPAUSE; - midi->sync(1); - midi->tmrStop(); - ctl->paused=1; - midi->closeDev(); - while ((ctl->paused)&&(!(ctl->message&PLAYER_DOSTOP)) - &&(!(ctl->message&PLAYER_HALT))) sleep(1); - midi->openDev(); - midi->tmrStart(); - ctl->OK=1; - printf("Continue playing ... \n"); - }; - if (ctl->message & PLAYER_DOSTOP) - { - ctl->message&=~PLAYER_DOSTOP; - playing=0; - }; - if (ctl->message & PLAYER_HALT) - { - ctl->message&=~PLAYER_HALT; - playing=0; - halt=1; - }; - if (ctl->message & PLAYER_SETPOS) - { - ctl->moving=1; - ctl->message&=~PLAYER_SETPOS; - midi->sync(1); - midi->tmrStop(); - midi->closeDev(); - midistat = new midiStat(); - SetPos(ctl->gotomsec,midistat); - minTime=ctl->gotomsec; - prevms=(ulong)minTime; - midi->openDev(); - midi->tmrStart(); - diffTime=ctl->gotomsec; - ctl->moving=0; - midistat->sendData(midi,ctl->gm); - delete midistat; - ctl->OK=1; - while (ctl->OK==1) ; - ctl->moving=0; - }; - }; - */ - prevms=minTime; - // ctl->millisecsPlayed=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 120000L /* milliseconds */; - minTime=maxTime; - playing=0; - while (trkntracks) - { - if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); - playing=1; - } - trk++; - } -#ifdef PLAYERDEBUG - printf("minTime %g\n",minTime); -#endif - // if ((minTime==maxTime)/* || (minTicks> 60000L)*/) - if (playing==0) - { - // playing=0; -#ifdef PLAYERDEBUG - printf("END of playing\n"); -#endif - } - else - { - // mspass=(ulong)(minTime-prevms); - trk=0; - while (trkntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - midi->wait(minTime-diffTime); - } - trk=minTrk; - tracks[trk]->readEvent(ev); - switch (ev->command) - { - case (MIDI_NOTEON) : - midi->noteOn(ev->chn, ev->note, ev->vel);break; - case (MIDI_NOTEOFF): - midi->noteOff(ev->chn, ev->note, ev->vel);break; - case (MIDI_KEY_PRESSURE) : - midi->keyPressure(ev->chn, ev->note,ev->vel);break; - case (MIDI_PGM_CHANGE) : - if (!ctl->forcepgm[ev->chn]) - midi->chnPatchChange(ev->chn, (ctl->gm==1)?(ev->patch):(MT32toGM[ev->patch]));break; - case (MIDI_CHN_PRESSURE) : - midi->chnPressure(ev->chn, ev->vel);break; - case (MIDI_PITCH_BEND) : - midi->chnPitchBender(ev->chn, ev->d1,ev->d2);break; - case (MIDI_CTL_CHANGE) : - midi->chnController(ev->chn, ev->ctl,ev->d1);break; - case (MIDI_SYSTEM_PREFIX) : - if ((ev->command|ev->chn)==META_EVENT) - { - if ((ev->d1==5)||(ev->d1==1)) - { - ctl->SPEVplayed++; - } - if (ev->d1==ME_SET_TEMPO) - { - absTimeAtChangeTempo=absTime; - ticksplayed=0; - ctl->SPEVplayed++; - tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo); -#ifdef PLAYERDEBUG - printf("Tempo : %ld %g (ratio : %g)\n",tempo,tempoToMetronomeTempo(tempo),ctl->ratioTempo); -#endif - midi->tmrSetTempo((int)tempoToMetronomeTempo(tempo)); - ctl->tempo=tempo; - for (j=0;jntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - } - if (ev->d1==ME_TIME_SIGNATURE) - { - ctl->num=ev->d2; - ctl->den=ev->d3; - ctl->SPEVplayed++; - } - } - break; - } - if (calloutput) - { - midi->sync(); - output(); - } - - } - ctl->ev=NULL; - delete ev; -#ifdef PLAYERDEBUG - printf("Syncronizing ...\n"); -#endif - if (halt) - midi->sync(1); - else - midi->sync(); -#ifdef PLAYERDEBUG - printf("Closing device ...\n"); -#endif - midi->allNotesOff(); - midi->closeDev(); - ctl->playing=0; -#ifdef PLAYERDEBUG - printf("Bye...\n"); -#endif - ctl->OK=1; - ctl->finished=1; -} - - -void MidiPlayer::setPos(ulong gotomsec,MidiStatus *midistat) -{ - int trk,minTrk; - ulong tempo=(ulong)(500000 * ctl->ratioTempo); - double minTime=0,maxTime,prevms=0; - int i,j,likeplaying=1; - - MidiEvent *ev=new MidiEvent; - ctl->SPEVplayed=0; - for (i=0;intracks;i++) - { - tracks[i]->init(); - tracks[i]->changeTempo(tempo); - } - - for (i=0;i<16;i++) - { - if (ctl->forcepgm[i]) midistat->chnPatchChange(i, ctl->pgm[i]); - } - - while (likeplaying) - { - trk=0; - minTrk=0; - maxTime=minTime + 120000L; /*milliseconds (2 minutes)*/ - minTime=maxTime; - while (trkntracks) - { - if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); - } - trk++; - } - if (minTime==maxTime) - { - likeplaying=0; -#ifdef GENERAL_DEBUG_MESSAGES - printf("END of likeplaying\n"); -#endif - } - else - { - if (minTime>=gotomsec) - { - prevms=gotomsec; - likeplaying=0; -#ifdef GENERAL_DEBUG_MESSAGES - printf("Position reached !! \n"); -#endif - minTime=gotomsec; - } - else - { - prevms=minTime; - } - trk=0; - while (trkntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - } - - if (likeplaying) - { - trk=minTrk; - tracks[trk]->readEvent(ev); - switch (ev->command) - { - /* case (MIDI_NOTEON) : - midistat->noteOn(ev->chn, ev->note, ev->vel);break; - case (MIDI_NOTEOFF): - midistat->noteOff(ev->chn, ev->note, ev->vel);break; - case (MIDI_KEY_PRESSURE) : - midistat->keyPressure(ev->chn, ev->note,ev->vel);break; - */ - case (MIDI_PGM_CHANGE) : - if (!ctl->forcepgm[ev->chn]) midistat->chnPatchChange(ev->chn, ev->patch);break; - case (MIDI_CHN_PRESSURE) : - midistat->chnPressure(ev->chn, ev->vel);break; - case (MIDI_PITCH_BEND) : - midistat->chnPitchBender(ev->chn, ev->d1,ev->d2);break; - case (MIDI_CTL_CHANGE) : - midistat->chnController(ev->chn, ev->ctl,ev->d1);break; - case (MIDI_SYSTEM_PREFIX) : - if ((ev->command|ev->chn)==META_EVENT) - { - if ((ev->d1==5)||(ev->d1==1)) - { - ctl->SPEVplayed++; - } - if (ev->d1==ME_SET_TEMPO) - { - ctl->SPEVplayed++; - tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo); - - midistat->tmrSetTempo((int)tempoToMetronomeTempo(tempo)); - for (j=0;jntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - } - if (ev->d1==ME_TIME_SIGNATURE) - { - ctl->num=ev->d2; - ctl->den=ev->d3; - ctl->SPEVplayed++; - } - } - break; - } - } - } - delete ev; - ctl->tempo=tempo; -} - - -void MidiPlayer::debugSpecialEvents(void) -{ - SpecialEvent *pspev=spev; - printf("**************************************\n"); - while ((pspev!=NULL)&&(pspev->type!=0)) - { - printf("t:%d ticks:%d diff:%ld abs:%ld s:%s tempo:%ld\n",pspev->type,pspev->ticks,pspev->diffmilliseconds,pspev->absmilliseconds,pspev->text,pspev->tempo); - pspev=pspev->next; - } - -} - -void MidiPlayer::setParseSong(bool b) -{ - parsesong=b; -} - -void MidiPlayer::setGenerateBeats(bool b) -{ - generatebeats=b; -} - -void MidiPlayer::setTempoRatio(double ratio) -{ - if (songLoaded) - { - ctl->ratioTempo=ratio; - parseInfoData(info,tracks,ctl->ratioTempo); - if (parsesong) - { - parseSpecialEvents(); - if (generatebeats) generateBeats(); - - } - } - else - { - ctl->tempo=(ulong)((ctl->tempo*ctl->ratioTempo)/ratio); - ctl->ratioTempo=ratio; - } - -} - -#undef T2MS -#undef MS2T diff --git a/libtdemid/player.cpp b/libtdemid/player.cpp new file mode 100644 index 000000000..1596d46f4 --- /dev/null +++ b/libtdemid/player.cpp @@ -0,0 +1,959 @@ +/************************************************************************** + + player.cpp - class MidiPlayer. Plays a set of tracks + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + $Id$ + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ +#include "player.h" +#include "sndcard.h" +#include "midispec.h" +#include +#include +#include +#include "midistat.h" +#include "mt32togm.h" + +//#define PLAYERDEBUG +//#define GENERAL_DEBUG_MESSAGES + +#define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote) + +#define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote)/((double)60000L)) + +#define REMOVEDUPSTRINGS + +MidiPlayer::MidiPlayer(DeviceManager *midi_,PlayerController *pctl) +{ + midi=midi_; + info=NULL; + tracks=NULL; + songLoaded=0; + ctl=pctl; + spev=NULL; + na=NULL; + parsesong=true; + generatebeats=false; +} + +MidiPlayer::~MidiPlayer() +{ + removeSpecialEvents(); + removeSong(); +} + +void MidiPlayer::removeSong(void) +{ + if ((songLoaded)&&(tracks!=NULL)) + { +#ifdef PLAYERDEBUG + printf("Removing song from memory\n"); +#endif + int i=0; + while (intracks) + { + if (tracks[i]!=NULL) delete tracks[i]; + i++; + } + delete tracks; + tracks=NULL; + if (info!=NULL) + { + delete info; + info=NULL; + } + } + songLoaded=0; +} + +int MidiPlayer::loadSong(const char *filename) +{ + removeSong(); +#ifdef PLAYERDEBUG + printf("Loading Song : %s\n",filename); +#endif + info=new MidiFileInfo; + int ok; + tracks=readMidiFile(filename,info,ok); + if (ok<0) return ok; + if (tracks==NULL) return -4; + + parseInfoData(info,tracks,ctl->ratioTempo); + + if (parsesong) + { + parseSpecialEvents(); + if (generatebeats) generateBeats(); + } + + songLoaded=1; + return 0; +} + +void MidiPlayer::insertBeat(SpecialEvent *ev,ulong ms,int num,int den) +{ + SpecialEvent *beat=new SpecialEvent; + beat->next=ev->next; + ev->next=beat; + beat->id=1; + beat->type=7; + beat->absmilliseconds=ms; + beat->num=num; + beat->den=den; +} + + +void MidiPlayer::generateBeats(void) +{ +#ifdef PLAYERDEBUG + printf("player::Generating Beats...\n"); +#endif + + if (spev==NULL) return; + SpecialEvent *ev=spev; + SpecialEvent *nextev=ev->next; + ulong tempo=(ulong)(500000 * ctl->ratioTempo); + int i=1; + int num=4; + int den=4; + // ulong beatstep=((double)tempo*4/(den*1000)); + // ulong beatstep=T2MS(info->ticksPerCuarterNote*(4/den)); + double ticksleft=(((double)info->ticksPerCuarterNote*4)/den); + + double beatstep=T2MS(ticksleft); + double nextbeatms=0; + double lastbeatms=0; + double measurems=0; + + while (nextev!=NULL) + { + switch (ev->type) + { + case (0): // End of list + { + };break; + case (1): // Text + case (2): // Lyrics + { + };break; + case (3): // Change Tempo + { + lastbeatms=ev->absmilliseconds; + ticksleft=MS2T(nextbeatms-lastbeatms); + tempo=ev->tempo; + nextbeatms=lastbeatms+T2MS(ticksleft); + // printf("Change at %lu to %d\n",ev->absmilliseconds,ev->tempo); + // beatstep=((double)tempo*4/(den*1000)); + beatstep=T2MS(((static_cast(info->ticksPerCuarterNote)*4)/den)); + };break; + case (6): // Change number of beats per measure + { + num=ev->num; + i=1; + den=ev->den; + // printf("Change at %lu to %d/%d\n",ev->absmilliseconds,num,den); + // beatstep=((double)tempo*4/(den*1000)); + // beatstep=T2MS(info->ticksPerCuarterNote*(4/den)); + beatstep=T2MS((((double)info->ticksPerCuarterNote*4)/den)); + nextbeatms=ev->absmilliseconds; + };break; + }; + if (nextev->absmilliseconds>nextbeatms) + { + //printf("Adding %d,%d\n",num,tot); + //printf("beat at %g , %d/%d\n",nextbeatms,i,num); + //printf(" %ld %d\n",nextev->absmilliseconds,nextev->type); + if (i == 1) { + measurems=nextbeatms; + } + insertBeat(ev, static_cast(nextbeatms), i++, num); + if (i > num) { + i=1; + } + lastbeatms=nextbeatms; + nextbeatms+=beatstep; + // nextbeatms=measurems+beatstep*i; + + ticksleft = ( (static_cast(info->ticksPerCuarterNote)*4) / den); + + } + + ev=ev->next; + nextev=ev->next; + } + + /* ev==NULL doesn't indicate the end of the song, so continue generating beats */ + + if (ev!=NULL) + { + if (ev->type==0) + { + ev=spev; + /* Looking if ev->next is NULL is not needed because + we are sure that a ev->type == 0 exists, we just have + to assure that the first spev is not the only one */ + if (ev->next!=NULL) + while (ev->next->type!=0) ev=ev->next; + } + while (nextbeatmsmillisecsTotal) + { + // printf("beat2 at %g , %d/%d\n",nextbeatms,i,num); + if (i==1) measurems=nextbeatms; + insertBeat(ev, static_cast(nextbeatms), i++, num); + if (i>num) i=1; + nextbeatms+=beatstep; + ev=ev->next; + } + } + + /* Regenerate IDs */ + + ev=spev; + i=1; + while (ev!=NULL) + { + ev->id=i++; + ev=ev->next; + } + + +#ifdef PLAYERDEBUG + printf("player::Beats Generated\n"); +#endif + +} + +void MidiPlayer::removeSpecialEvents(void) +{ + SpecialEvent * ev=spev; + while (spev!=NULL) + { + ev=spev->next; + delete spev; + spev=ev; + } + delete na; + na=0; +} + +void MidiPlayer::parseSpecialEvents(void) +{ +#ifdef PLAYERDEBUG + printf("player::Parsing...\n"); +#endif + removeSpecialEvents(); + spev=new SpecialEvent; + if (spev==NULL) return; + SpecialEvent *pspev=spev; + pspev->type=0; + pspev->ticks=0; + if (na) delete na; + na=new NoteArray(); + if (!na) { delete spev; spev=0L; return; }; + int trk; + int minTrk; + double minTime=0; + double maxTime; + ulong tempo=(ulong)(500000 * (ctl->ratioTempo)); + ulong firsttempo=0; + for (int i=0;intracks;i++) + { + tracks[i]->init(); + tracks[i]->changeTempo(tempo); + } + MidiEvent *ev=new MidiEvent; + //ulong mspass; + double prevms=0; + int spev_id=1; + int j; + int parsing=1; +#ifdef REMOVEDUPSTRINGS + char lasttext[1024]; + ulong lasttexttime=0; + lasttext[0]=0; + int lasttexttype=0; +#endif + while (parsing) + { + prevms=minTime; + trk=0; + minTrk=0; + maxTime=minTime + 2 * 60000L; + minTime=maxTime; + parsing=0; + while (trkntracks) + { + if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); + parsing=1; + } + trk++; + } + // if ((minTime==maxTime)) + if (parsing==0) + { + // parsing=0; +#ifdef PLAYERDEBUG + printf("END of parsing\n"); +#endif + } + else + { + // mspass=(ulong)(minTime-prevms); + trk=0; + while (trkntracks) + { + tracks[trk]->currentMs(minTime); + trk++; + } + } + trk=minTrk; + tracks[trk]->readEvent(ev); + switch (ev->command) + { + case (MIDI_NOTEON) : + if (ev->vel==0) na->add((ulong)minTime,ev->chn,0, ev->note); + else na->add((ulong)minTime,ev->chn,1,ev->note); + break; + case (MIDI_NOTEOFF) : + na->add((ulong)minTime,ev->chn,0, ev->note); + break; + case (MIDI_PGM_CHANGE) : + na->add((ulong)minTime,ev->chn, 2,ev->patch); + break; + case (MIDI_SYSTEM_PREFIX) : + { + if ((ev->command|ev->chn)==META_EVENT) + { + switch (ev->d1) + { + case (1) : + case (5) : + { + if (pspev!=NULL) + { + pspev->absmilliseconds=(ulong)minTime; + pspev->type=ev->d1; + pspev->id=spev_id++; +#ifdef PLAYERDEBUG + printf("ev->length %ld\n",ev->length); + +#endif + strncpy(pspev->text,(char *)ev->data, + (ev->length>= sizeof(lasttext))? sizeof(lasttext)-1 : (ev->length) ); + pspev->text[(ev->length>= sizeof(lasttext))? sizeof(lasttext)-1:(ev->length)]=0; +#ifdef PLAYERDEBUG + printf("(%s)(%s)\n",pspev->text,lasttext); +#endif +#ifdef REMOVEDUPSTRINGS + if ((strcmp(pspev->text,lasttext)!=0)||(pspev->absmilliseconds!=lasttexttime)||(pspev->type!=lasttexttype)) + { + lasttexttime=pspev->absmilliseconds; + lasttexttype=pspev->type; + strncpy(lasttext, pspev->text, 1024); + lasttext[sizeof(lasttext)-1] = 0; +#endif + pspev->next=new SpecialEvent; +#ifdef PLAYERDEBUG + if (pspev->next==NULL) printf("pspev->next=NULL\n"); +#endif + pspev=pspev->next; +#ifdef REMOVEDUPSTRINGS + } +#endif + } + } + break; + case (ME_SET_TEMPO) : + { + if (pspev!=NULL) + { + pspev->absmilliseconds=(ulong)minTime; + pspev->type=3; + pspev->id=spev_id++; + tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ctl->ratioTempo); + pspev->tempo=tempo; + if (firsttempo==0) firsttempo=tempo; + for (j=0;jntracks;j++) + { + tracks[j]->changeTempo(tempo); + } + pspev->next=new SpecialEvent; + pspev=pspev->next; + } + } + break; + case (ME_TIME_SIGNATURE) : + { + if (pspev!=NULL) + { + pspev->absmilliseconds=(ulong)minTime; + pspev->type=6; + pspev->id=spev_id++; + pspev->num=ev->d2; + pspev->den=ev->d3; + pspev->next=new SpecialEvent; + pspev=pspev->next; + } + } + break; + } + } + } + break; + } + } + + delete ev; + pspev->type=0; + pspev->absmilliseconds=(ulong)prevms; + pspev->next=NULL; + if (firsttempo==0) firsttempo=tempo; + ctl->tempo=firsttempo; + + //writeSPEV(); + for (int i=0;intracks;i++) + { + tracks[i]->init(); + } +} + +/* +NoteArray *MidiPlayer::parseNotes(void) +{ +#ifdef PLAYERDEBUG + printf("player::Parsing Notes...\n"); +#endif + NoteArray *na=new NoteArray(); + int trk; + int minTrk; + double minTime=0; + double maxTime; + for (int i=0;intracks;i++) + { + tracks[i]->init(); + }; + ulong tempo=1000000; + ulong tmp; + Midi_event *ev=new Midi_event; + //ulong mspass; + double prevms=0; + int j; + int parsing=1; + while (parsing) + { + prevms=minTime; + trk=0; + minTrk=0; + maxTime=minTime + 2 * 60000L; + minTime=maxTime; + while (trkntracks) + { + if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); + }; + trk++; + }; + if ((minTime==maxTime)) + { + parsing=0; +#ifdef PLAYERDEBUG + printf("END of parsing\n"); +#endif + } + else + { + // mspass=(ulong)(minTime-prevms); + trk=0; + while (trkntracks) + { + tracks[trk]->currentMs(minTime); + trk++; + }; + }; + trk=minTrk; + tracks[trk]->readEvent(ev); + if (ev->command==MIDI_NOTEON) + { + if (ev->vel==0) {printf("note off at %g\n",minTime);na->add((ulong)minTime,ev->chn,0, ev->note);} + else {printf("note on at %g\n",minTime);na->add((ulong)minTime,ev->chn,1,ev->note);} + } + else + if (ev->command==MIDI_NOTEOFF) na->add((ulong)minTime,ev->chn,0, ev->note); + if (ev->command==MIDI_PGM_CHANGE) na->add((ulong)minTime,ev->chn, 2,ev->patch); + if (ev->command==MIDI_SYSTEM_PREFIX) + { + if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) + { + tempo=(ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]); + for (j=0;jntracks;j++) + { + tracks[j]->changeTempo(tempo); + }; + }; + }; + + }; + + delete ev; + for (int i=0;intracks;i++) + { + tracks[i]->init(); + }; + return na; +}; +*/ + +void MidiPlayer::play(bool calloutput,void output(void)) +{ +#ifdef PLAYERDEBUG + printf("Playing...\n"); +#endif + + if (midi->midiPorts()+midi->synthDevices()==0) + { + fprintf(stderr,"Player :: There are no midi ports !\n"); + ctl->error=1; + return; + } + + midi->openDev(); + if (midi->ok()==0) + { + fprintf(stderr,"Player :: Couldn't play !\n"); + ctl->error=1; + return; + } + midi->setVolumePercentage(ctl->volumepercentage); + midi->initDev(); + // parsePatchesUsed(tracks,info,ctl->gm); + midi->setPatchesToUse(info->patchesUsed); + + int trk; + int minTrk; + double minTime=0; + double maxTime; + int i; + ulong tempo=(ulong)(500000 * ctl->ratioTempo); + for (i=0;intracks;i++) + { + tracks[i]->init(); + tracks[i]->changeTempo(tempo); + } + + midi->tmrStart(info->ticksPerCuarterNote); + MidiEvent *ev=new MidiEvent; + ctl->ev=ev; + ctl->ticksTotal=info->ticksTotal; + ctl->ticksPlayed=0; + //ctl->millisecsPlayed=0; + ulong ticksplayed=0; + double absTimeAtChangeTempo=0; + double absTime=0; + double diffTime=0; + MidiStatus *midistat; + //ulong mspass; + double prevms=0; + int j; + int halt=0; + ctl->tempo=tempo; + ctl->num=4; + ctl->den=4; + int playing; + ctl->paused=0; + if ((ctl->message!=0)&&(ctl->message & PLAYER_SETPOS)) + { + ctl->moving=1; + ctl->message&=~PLAYER_SETPOS; + midi->sync(1); + midi->tmrStop(); + midi->closeDev(); + midistat = new MidiStatus(); + setPos(ctl->gotomsec,midistat); + minTime=ctl->gotomsec; + prevms=(ulong)minTime; + midi->openDev(); + midi->tmrStart(info->ticksPerCuarterNote); + diffTime=ctl->gotomsec; + midistat->sendData(midi,ctl->gm); + delete midistat; + midi->setPatchesToUse(info->patchesUsed); + ctl->moving=0; + } else + for (i=0;i<16;i++) + { + if (ctl->forcepgm[i]) + { + midi->chnPatchChange(i, ctl->pgm[i]); + } + } + + timeval begintv; + gettimeofday(&begintv, NULL); + ctl->beginmillisec=begintv.tv_sec*1000+begintv.tv_usec/1000; + ctl->OK=1; + ctl->playing=playing=1; + + while (playing) + { + /* + if (ctl->message!=0) + { + if (ctl->message & PLAYER_DOPAUSE) + { + diffTime=minTime; + ctl->message&=~PLAYER_DOPAUSE; + midi->sync(1); + midi->tmrStop(); + ctl->paused=1; + midi->closeDev(); + while ((ctl->paused)&&(!(ctl->message&PLAYER_DOSTOP)) + &&(!(ctl->message&PLAYER_HALT))) sleep(1); + midi->openDev(); + midi->tmrStart(); + ctl->OK=1; + printf("Continue playing ... \n"); + }; + if (ctl->message & PLAYER_DOSTOP) + { + ctl->message&=~PLAYER_DOSTOP; + playing=0; + }; + if (ctl->message & PLAYER_HALT) + { + ctl->message&=~PLAYER_HALT; + playing=0; + halt=1; + }; + if (ctl->message & PLAYER_SETPOS) + { + ctl->moving=1; + ctl->message&=~PLAYER_SETPOS; + midi->sync(1); + midi->tmrStop(); + midi->closeDev(); + midistat = new midiStat(); + SetPos(ctl->gotomsec,midistat); + minTime=ctl->gotomsec; + prevms=(ulong)minTime; + midi->openDev(); + midi->tmrStart(); + diffTime=ctl->gotomsec; + ctl->moving=0; + midistat->sendData(midi,ctl->gm); + delete midistat; + ctl->OK=1; + while (ctl->OK==1) ; + ctl->moving=0; + }; + }; + */ + prevms=minTime; + // ctl->millisecsPlayed=minTime; + trk=0; + minTrk=0; + maxTime=minTime + 120000L /* milliseconds */; + minTime=maxTime; + playing=0; + while (trkntracks) + { + if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); + playing=1; + } + trk++; + } +#ifdef PLAYERDEBUG + printf("minTime %g\n",minTime); +#endif + // if ((minTime==maxTime)/* || (minTicks> 60000L)*/) + if (playing==0) + { + // playing=0; +#ifdef PLAYERDEBUG + printf("END of playing\n"); +#endif + } + else + { + // mspass=(ulong)(minTime-prevms); + trk=0; + while (trkntracks) + { + tracks[trk]->currentMs(minTime); + trk++; + } + midi->wait(minTime-diffTime); + } + trk=minTrk; + tracks[trk]->readEvent(ev); + switch (ev->command) + { + case (MIDI_NOTEON) : + midi->noteOn(ev->chn, ev->note, ev->vel);break; + case (MIDI_NOTEOFF): + midi->noteOff(ev->chn, ev->note, ev->vel);break; + case (MIDI_KEY_PRESSURE) : + midi->keyPressure(ev->chn, ev->note,ev->vel);break; + case (MIDI_PGM_CHANGE) : + if (!ctl->forcepgm[ev->chn]) + midi->chnPatchChange(ev->chn, (ctl->gm==1)?(ev->patch):(MT32toGM[ev->patch]));break; + case (MIDI_CHN_PRESSURE) : + midi->chnPressure(ev->chn, ev->vel);break; + case (MIDI_PITCH_BEND) : + midi->chnPitchBender(ev->chn, ev->d1,ev->d2);break; + case (MIDI_CTL_CHANGE) : + midi->chnController(ev->chn, ev->ctl,ev->d1);break; + case (MIDI_SYSTEM_PREFIX) : + if ((ev->command|ev->chn)==META_EVENT) + { + if ((ev->d1==5)||(ev->d1==1)) + { + ctl->SPEVplayed++; + } + if (ev->d1==ME_SET_TEMPO) + { + absTimeAtChangeTempo=absTime; + ticksplayed=0; + ctl->SPEVplayed++; + tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo); +#ifdef PLAYERDEBUG + printf("Tempo : %ld %g (ratio : %g)\n",tempo,tempoToMetronomeTempo(tempo),ctl->ratioTempo); +#endif + midi->tmrSetTempo((int)tempoToMetronomeTempo(tempo)); + ctl->tempo=tempo; + for (j=0;jntracks;j++) + { + tracks[j]->changeTempo(tempo); + } + } + if (ev->d1==ME_TIME_SIGNATURE) + { + ctl->num=ev->d2; + ctl->den=ev->d3; + ctl->SPEVplayed++; + } + } + break; + } + if (calloutput) + { + midi->sync(); + output(); + } + + } + ctl->ev=NULL; + delete ev; +#ifdef PLAYERDEBUG + printf("Syncronizing ...\n"); +#endif + if (halt) + midi->sync(1); + else + midi->sync(); +#ifdef PLAYERDEBUG + printf("Closing device ...\n"); +#endif + midi->allNotesOff(); + midi->closeDev(); + ctl->playing=0; +#ifdef PLAYERDEBUG + printf("Bye...\n"); +#endif + ctl->OK=1; + ctl->finished=1; +} + + +void MidiPlayer::setPos(ulong gotomsec,MidiStatus *midistat) +{ + int trk,minTrk; + ulong tempo=(ulong)(500000 * ctl->ratioTempo); + double minTime=0,maxTime,prevms=0; + int i,j,likeplaying=1; + + MidiEvent *ev=new MidiEvent; + ctl->SPEVplayed=0; + for (i=0;intracks;i++) + { + tracks[i]->init(); + tracks[i]->changeTempo(tempo); + } + + for (i=0;i<16;i++) + { + if (ctl->forcepgm[i]) midistat->chnPatchChange(i, ctl->pgm[i]); + } + + while (likeplaying) + { + trk=0; + minTrk=0; + maxTime=minTime + 120000L; /*milliseconds (2 minutes)*/ + minTime=maxTime; + while (trkntracks) + { + if (tracks[trk]->absMsOfNextEvent()absMsOfNextEvent(); + } + trk++; + } + if (minTime==maxTime) + { + likeplaying=0; +#ifdef GENERAL_DEBUG_MESSAGES + printf("END of likeplaying\n"); +#endif + } + else + { + if (minTime>=gotomsec) + { + prevms=gotomsec; + likeplaying=0; +#ifdef GENERAL_DEBUG_MESSAGES + printf("Position reached !! \n"); +#endif + minTime=gotomsec; + } + else + { + prevms=minTime; + } + trk=0; + while (trkntracks) + { + tracks[trk]->currentMs(minTime); + trk++; + } + } + + if (likeplaying) + { + trk=minTrk; + tracks[trk]->readEvent(ev); + switch (ev->command) + { + /* case (MIDI_NOTEON) : + midistat->noteOn(ev->chn, ev->note, ev->vel);break; + case (MIDI_NOTEOFF): + midistat->noteOff(ev->chn, ev->note, ev->vel);break; + case (MIDI_KEY_PRESSURE) : + midistat->keyPressure(ev->chn, ev->note,ev->vel);break; + */ + case (MIDI_PGM_CHANGE) : + if (!ctl->forcepgm[ev->chn]) midistat->chnPatchChange(ev->chn, ev->patch);break; + case (MIDI_CHN_PRESSURE) : + midistat->chnPressure(ev->chn, ev->vel);break; + case (MIDI_PITCH_BEND) : + midistat->chnPitchBender(ev->chn, ev->d1,ev->d2);break; + case (MIDI_CTL_CHANGE) : + midistat->chnController(ev->chn, ev->ctl,ev->d1);break; + case (MIDI_SYSTEM_PREFIX) : + if ((ev->command|ev->chn)==META_EVENT) + { + if ((ev->d1==5)||(ev->d1==1)) + { + ctl->SPEVplayed++; + } + if (ev->d1==ME_SET_TEMPO) + { + ctl->SPEVplayed++; + tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo); + + midistat->tmrSetTempo((int)tempoToMetronomeTempo(tempo)); + for (j=0;jntracks;j++) + { + tracks[j]->changeTempo(tempo); + } + } + if (ev->d1==ME_TIME_SIGNATURE) + { + ctl->num=ev->d2; + ctl->den=ev->d3; + ctl->SPEVplayed++; + } + } + break; + } + } + } + delete ev; + ctl->tempo=tempo; +} + + +void MidiPlayer::debugSpecialEvents(void) +{ + SpecialEvent *pspev=spev; + printf("**************************************\n"); + while ((pspev!=NULL)&&(pspev->type!=0)) + { + printf("t:%d ticks:%d diff:%ld abs:%ld s:%s tempo:%ld\n",pspev->type,pspev->ticks,pspev->diffmilliseconds,pspev->absmilliseconds,pspev->text,pspev->tempo); + pspev=pspev->next; + } + +} + +void MidiPlayer::setParseSong(bool b) +{ + parsesong=b; +} + +void MidiPlayer::setGenerateBeats(bool b) +{ + generatebeats=b; +} + +void MidiPlayer::setTempoRatio(double ratio) +{ + if (songLoaded) + { + ctl->ratioTempo=ratio; + parseInfoData(info,tracks,ctl->ratioTempo); + if (parsesong) + { + parseSpecialEvents(); + if (generatebeats) generateBeats(); + + } + } + else + { + ctl->tempo=(ulong)((ctl->tempo*ctl->ratioTempo)/ratio); + ctl->ratioTempo=ratio; + } + +} + +#undef T2MS +#undef MS2T diff --git a/libtdemid/synthout.cc b/libtdemid/synthout.cc deleted file mode 100644 index 6d7ef47a1..000000000 --- a/libtdemid/synthout.cc +++ /dev/null @@ -1,211 +0,0 @@ -/************************************************************************** - - synthout.cc - class synthOut which handles the /dev/sequencer device - for synths (as AWE32) - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98 Antonio Larrosa Jimenez and P.J.Leonard - 1999,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ -#include "synthout.h" -#include -#include -#include -#include "sndcard.h" -#include -#include -#include -#include -#include "awe_sup.h" -#include "midispec.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -SEQ_USE_EXTBUF(); - -SynthOut::SynthOut(int d) -{ - seqfd = -1; - devicetype=KMID_SYNTH; - device= d; - _ok=1; -} - -SynthOut::~SynthOut() -{ - closeDev(); -} - -void SynthOut::openDev (int sqfd) -{ - _ok=1; - seqfd = sqfd; - if (seqfd==-1) - { - printfdebug("ERROR: Could not open /dev/sequencer\n"); - return; - } -#ifdef HAVE_OSS_SUPPORT - /* - int i=1; - ioctl(seqfd,SNDCTL_SEQ_THRESHOLD,i); - printfdebug("Threshold : %d\n",i); - */ -#ifdef SYNTHOUTDEBUG - printfdebug("Number of synth devices : %d\n",ndevs); - printfdebug("Number of midi ports : %d\n",nmidiports); - printfdebug("Rate : %d\n",m_rate); -#endif - -#ifdef HAVE_AWE32 - - struct synth_info info; - - // Should really collect the possible devices and let the user choose ? - - info.device = device; - - if (ioctl (seqfd, SNDCTL_SYNTH_INFO, &info) == -1) - printfdebug(" ioctl SNDCTL_SYNTH_INFO FAILED \n"); - - if (info.synth_type == SYNTH_TYPE_SAMPLE - && info.synth_subtype == SAMPLE_TYPE_AWE32) - { - - // Enable layered patches .... - AWE_SET_CHANNEL_MODE(device,1); -#ifdef SYNTHOUTDEBUG - printfdebug(" Found AWE32 dev=%d \n",device); -#endif - } -#endif // HAVE_AWE32 -#endif // HAVE_OSS_SUPPORT - -} - -void SynthOut::closeDev (void) -{ - if (!ok()) return; - //if (seqfd>=0) close(seqfd); - seqfd=-1; -} - -void SynthOut::initDev (void) -{ -#ifdef HAVE_OSS_SUPPORT - int chn; - if (!ok()) return; - uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; - sysex(gm_reset, sizeof(gm_reset)); - for (chn=0;chn<16;chn++) - { - chnmute[chn]=0; - chnPatchChange(chn,0); - chnPressure(chn,127); - chnPitchBender(chn, 0x00, 0x40); - chnController(chn, CTL_MAIN_VOLUME,127); - chnController(chn, CTL_EXT_EFF_DEPTH, 0); - chnController(chn, CTL_CHORUS_DEPTH, 0); - chnController(chn, 0x4a, 127); - } -#endif -} - -void SynthOut::noteOn (uchar chn, uchar note, uchar vel) -{ - if (vel==0) - { - noteOff(chn,note,vel); - } - else - { - SEQ_START_NOTE(device, map->channel(chn), - map->key(chn,chnpatch[chn],note), - vel); - } -#ifdef SYNTHOUTDEBUG - printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void SynthOut::noteOff (uchar chn, uchar note, uchar) -{ - SEQ_STOP_NOTE(device, map->channel(chn), - map->key(chn,chnpatch[chn],note), 0); -#ifdef SYNTHOUTDEBUG - printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); -#endif -} - -void SynthOut::keyPressure (uchar chn, uchar note, uchar vel) -{ - SEQ_KEY_PRESSURE(device, map->channel(chn), map->key(chn,chnpatch[chn],note),vel); -} - -void SynthOut::chnPatchChange (uchar chn, uchar patch) -{ - SEQ_SET_PATCH(device,map->channel(chn),map->patch(chn,patch)); - chnpatch[chn]=patch; -} - -void SynthOut::chnPressure (uchar chn, uchar vel) -{ - SEQ_CHN_PRESSURE(device, map->channel(chn) , vel); - chnpressure[chn]=vel; -} - -void SynthOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) -{ - chnbender[chn]=((int)msb<<7) | (lsb & 0x7F); - SEQ_BENDER(device, map->channel(chn), chnbender[chn]); -} - -void SynthOut::chnController (uchar chn, uchar ctl, uchar v) -{ - if ((ctl==11)||(ctl==7)) - { - v=(v*volumepercentage)/100; - if (v>127) v=127; - } - - SEQ_CONTROL(device, map->channel(chn), ctl, v); - chncontroller[chn][ctl]=v; -} - -void SynthOut::sysex(uchar *, ulong ) -{ - // AWE32 doesn't respond to sysex (AFAIK) -/* -#ifndef HAVE_AWE32 - ulong i=0; - SEQ_MIDIOUT(device, MIDI_SYSTEM_PREFIX); - while (i + +***************************************************************************/ +#include "synthout.h" +#include +#include +#include +#include "sndcard.h" +#include +#include +#include +#include +#include "awe_sup.h" +#include "midispec.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +SEQ_USE_EXTBUF(); + +SynthOut::SynthOut(int d) +{ + seqfd = -1; + devicetype=KMID_SYNTH; + device= d; + _ok=1; +} + +SynthOut::~SynthOut() +{ + closeDev(); +} + +void SynthOut::openDev (int sqfd) +{ + _ok=1; + seqfd = sqfd; + if (seqfd==-1) + { + printfdebug("ERROR: Could not open /dev/sequencer\n"); + return; + } +#ifdef HAVE_OSS_SUPPORT + /* + int i=1; + ioctl(seqfd,SNDCTL_SEQ_THRESHOLD,i); + printfdebug("Threshold : %d\n",i); + */ +#ifdef SYNTHOUTDEBUG + printfdebug("Number of synth devices : %d\n",ndevs); + printfdebug("Number of midi ports : %d\n",nmidiports); + printfdebug("Rate : %d\n",m_rate); +#endif + +#ifdef HAVE_AWE32 + + struct synth_info info; + + // Should really collect the possible devices and let the user choose ? + + info.device = device; + + if (ioctl (seqfd, SNDCTL_SYNTH_INFO, &info) == -1) + printfdebug(" ioctl SNDCTL_SYNTH_INFO FAILED \n"); + + if (info.synth_type == SYNTH_TYPE_SAMPLE + && info.synth_subtype == SAMPLE_TYPE_AWE32) + { + + // Enable layered patches .... + AWE_SET_CHANNEL_MODE(device,1); +#ifdef SYNTHOUTDEBUG + printfdebug(" Found AWE32 dev=%d \n",device); +#endif + } +#endif // HAVE_AWE32 +#endif // HAVE_OSS_SUPPORT + +} + +void SynthOut::closeDev (void) +{ + if (!ok()) return; + //if (seqfd>=0) close(seqfd); + seqfd=-1; +} + +void SynthOut::initDev (void) +{ +#ifdef HAVE_OSS_SUPPORT + int chn; + if (!ok()) return; + uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7}; + sysex(gm_reset, sizeof(gm_reset)); + for (chn=0;chn<16;chn++) + { + chnmute[chn]=0; + chnPatchChange(chn,0); + chnPressure(chn,127); + chnPitchBender(chn, 0x00, 0x40); + chnController(chn, CTL_MAIN_VOLUME,127); + chnController(chn, CTL_EXT_EFF_DEPTH, 0); + chnController(chn, CTL_CHORUS_DEPTH, 0); + chnController(chn, 0x4a, 127); + } +#endif +} + +void SynthOut::noteOn (uchar chn, uchar note, uchar vel) +{ + if (vel==0) + { + noteOff(chn,note,vel); + } + else + { + SEQ_START_NOTE(device, map->channel(chn), + map->key(chn,chnpatch[chn],note), + vel); + } +#ifdef SYNTHOUTDEBUG + printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void SynthOut::noteOff (uchar chn, uchar note, uchar) +{ + SEQ_STOP_NOTE(device, map->channel(chn), + map->key(chn,chnpatch[chn],note), 0); +#ifdef SYNTHOUTDEBUG + printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel); +#endif +} + +void SynthOut::keyPressure (uchar chn, uchar note, uchar vel) +{ + SEQ_KEY_PRESSURE(device, map->channel(chn), map->key(chn,chnpatch[chn],note),vel); +} + +void SynthOut::chnPatchChange (uchar chn, uchar patch) +{ + SEQ_SET_PATCH(device,map->channel(chn),map->patch(chn,patch)); + chnpatch[chn]=patch; +} + +void SynthOut::chnPressure (uchar chn, uchar vel) +{ + SEQ_CHN_PRESSURE(device, map->channel(chn) , vel); + chnpressure[chn]=vel; +} + +void SynthOut::chnPitchBender(uchar chn,uchar lsb, uchar msb) +{ + chnbender[chn]=((int)msb<<7) | (lsb & 0x7F); + SEQ_BENDER(device, map->channel(chn), chnbender[chn]); +} + +void SynthOut::chnController (uchar chn, uchar ctl, uchar v) +{ + if ((ctl==11)||(ctl==7)) + { + v=(v*volumepercentage)/100; + if (v>127) v=127; + } + + SEQ_CONTROL(device, map->channel(chn), ctl, v); + chncontroller[chn][ctl]=v; +} + +void SynthOut::sysex(uchar *, ulong ) +{ + // AWE32 doesn't respond to sysex (AFAIK) +/* +#ifndef HAVE_AWE32 + ulong i=0; + SEQ_MIDIOUT(device, MIDI_SYSTEM_PREFIX); + while (i -#include -#include - -int main (int , char **) -{ - printf("Libtdemid test2 . (C) 2000 Antonio Larrosa Jimenez . Malaga (Spain)\n"); - printf("Using libtdemid from a simple C++ application\n"); - - KMidSimpleAPI::kMidInit(); - KMidSimpleAPI::kMidLoad("Kathzy.mid"); - KMidSimpleAPI::kMidPlay(); - - for (int i=0;i<30;i++) - { - printf("%d/30 seconds\n",i+1); - sleep(1); - }; - - KMidSimpleAPI::kMidStop(); - KMidSimpleAPI::kMidDestruct(); - - return 0; -}; - diff --git a/libtdemid/tests/apitest.cpp b/libtdemid/tests/apitest.cpp new file mode 100644 index 000000000..7f370331e --- /dev/null +++ b/libtdemid/tests/apitest.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +int main (int , char **) +{ + printf("Libtdemid test2 . (C) 2000 Antonio Larrosa Jimenez . Malaga (Spain)\n"); + printf("Using libtdemid from a simple C++ application\n"); + + KMidSimpleAPI::kMidInit(); + KMidSimpleAPI::kMidLoad("Kathzy.mid"); + KMidSimpleAPI::kMidPlay(); + + for (int i=0;i<30;i++) + { + printf("%d/30 seconds\n",i+1); + sleep(1); + }; + + KMidSimpleAPI::kMidStop(); + KMidSimpleAPI::kMidDestruct(); + + return 0; +}; + diff --git a/libtdemid/tests/notesoff.cc b/libtdemid/tests/notesoff.cc deleted file mode 100644 index 15e00bd6c..000000000 --- a/libtdemid/tests/notesoff.cc +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -int main (int , char **) -{ - printf("Libtdemid Notes Off . (C) 2000 Antonio Larrosa Jimenez . Malaga (Spain)\n"); - printf("Using libtdemid from a simple C++ application\n"); - - KMidSimpleAPI::kMidInit(); - - kMid.midi->checkInit(); - kMid.midi->openDev(); - kMid.midi->initDev(); - - kMid.midi->allNotesOff(); - kMid.midi->closeDev(); - - KMidSimpleAPI::kMidDestruct(); - - return 0; -}; - diff --git a/libtdemid/tests/notesoff.cpp b/libtdemid/tests/notesoff.cpp new file mode 100644 index 000000000..15e00bd6c --- /dev/null +++ b/libtdemid/tests/notesoff.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +int main (int , char **) +{ + printf("Libtdemid Notes Off . (C) 2000 Antonio Larrosa Jimenez . Malaga (Spain)\n"); + printf("Using libtdemid from a simple C++ application\n"); + + KMidSimpleAPI::kMidInit(); + + kMid.midi->checkInit(); + kMid.midi->openDev(); + kMid.midi->initDev(); + + kMid.midi->allNotesOff(); + kMid.midi->closeDev(); + + KMidSimpleAPI::kMidDestruct(); + + return 0; +}; + diff --git a/libtdemid/track.cc b/libtdemid/track.cc deleted file mode 100644 index c7c858919..000000000 --- a/libtdemid/track.cc +++ /dev/null @@ -1,566 +0,0 @@ -/************************************************************************** - - track.cc - class track, which has a midi file track and its events - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ - -#include "track.h" -#include -#include "sndcard.h" -#include "midispec.h" -#include "midfile.h" - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)tPCN) - -#define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)tPCN)/((double)60000L)) - -#define PEDANTIC_TRACK -#define CHANGETEMPO_ONLY_IN_TRACK0 -//#define TRACKDEBUG -//#define TRACKDEBUG2 - -MidiTrack::MidiTrack(FILE *file,int tpcn,int Id) -{ - id=Id; - tPCN=tpcn; - currentpos=0; - size=0; - data=0L; - tempo=1000000; - if (feof(file)) - { - clear(); - return; - }; - size=readLong(file); -#ifdef TRACKDEBUG - printf("Track %d : Size %ld\n",id,size); -#endif - data=new uchar[size]; - if (data==NULL) - { - perror("track: Not enough memory ?"); - exit(-1); - } - ulong rsize=0; - if ((rsize=fread(data,1,size,file))!=size) - { - fprintf(stderr,"track (%d): File is corrupt : Couldn't load track (%ld!=%ld) !!\n", id, rsize, size); - size=rsize; - }; - /* - ptrdata=data; - current_ticks=0; - delta_ticks=readVariableLengthValue(); - wait_ticks=delta_ticks; - endoftrack=0; - */ - init(); -} - -MidiTrack::~MidiTrack() -{ - delete data; - endoftrack=1; - currentpos=0; - size=0; -} - -int MidiTrack::power2to(int i) -{ - return 1<=size) - { - endoftrack=1; - fprintf(stderr, "track (%d) : EndofTrack found by accident !\n",id); - delta_ticks = wait_ticks = ~0; - time_at_next_event=10000 * 60000L; - return 0; - } - else -#endif - { - dticks=(dticks << 7) | (*ptrdata) & 0x7F; - ptrdata++;currentpos++; - } - - } - dticks=((dticks << 7) | (*ptrdata) & 0x7F); - ptrdata++;currentpos++; - -#ifdef PEDANTIC_TRACK - - if (currentpos>=size) - { - endoftrack=1; - fprintf(stderr,"track (%d): EndofTrack found by accident 2 !\n",id); - dticks=0; - delta_ticks = wait_ticks = ~0; - time_at_next_event=10000 * 60000L; - return 0; - } -#endif -#ifdef TRACKDEBUG - printfdebug("track(%d): DTICKS : %ld\n",id,dticks); - usleep(10); -#endif - return dticks; -} - -int MidiTrack::ticksPassed (ulong ticks) -{ - if (endoftrack==1) return 0; - if (ticks>wait_ticks) - { - printfdebug("track (%d): ERROR : TICKS PASSED > WAIT TICKS\n", id); - return 1; - } - wait_ticks-=ticks; - return 0; -} - -int MidiTrack::msPassed (ulong ms) -{ - if (endoftrack==1) return 0; - current_time+=ms; - //fprintf(stderr, "old + %ld = CURR %g ", ms,current_time); - if ( current_time>time_at_next_event ) - { - fprintf(stderr, "track (%d): ERROR : MS PASSED > WAIT MS\n", id); - return 1; - } -#ifdef TRACKDEBUG - if (current_time==time_at_next_event) printfdebug("track(%d): _OK_",id); -#endif - return 0; -} - -int MidiTrack::currentMs(double ms) -{ - if (endoftrack==1) return 0; - current_time=ms; - //printfdebug("CURR %g",current_time); -#ifdef PEDANTIC_TRACK - if (current_time>time_at_next_event) - { - fprintf(stderr,"track(%d): ERROR : MS PASSED > WAIT MS\n", id); - exit(-1); - return 1; - } -#endif - return 0; -} - -void MidiTrack::readEvent(MidiEvent *ev) -{ - int i,j; - if (endoftrack==1) - { - ev->command=0; - return; - } - /* - printfdebug("...... %d\n",id); - printfdebug("current : %g , tane : %g\n",current_time,time_at_next_event); - printfdebug("......\n"); - */ - int skip_event=0; - current_time=time_at_next_event; - if (((*ptrdata)&0x80)!=0) - { - ev->command=(*ptrdata); - ptrdata++;currentpos++; - lastcommand=ev->command; - } - else - { - ev->command=lastcommand; - } - -#ifdef PEDANTIC_TRACK - if (currentpos>=size) - { - endoftrack=1; - delta_ticks = wait_ticks = ~0; - time_at_next_event=10000 * 60000L; - ev->command=MIDI_SYSTEM_PREFIX; - ev->chn=0xF; - ev->d1=ME_END_OF_TRACK; - fprintf(stderr, "track (%d): EndofTrack found by accident 3\n",id); - return; - } -#endif - - ev->chn=ev->command & 0xF; - ev->command=ev->command & 0xF0; - switch (ev->command) - { - case (MIDI_NOTEON) : - ev->note = *ptrdata;ptrdata++;currentpos++; - ev->vel = *ptrdata;ptrdata++;currentpos++; - if (ev->vel==0) - note[ev->chn][ev->note]=FALSE; - else - note[ev->chn][ev->note]=TRUE; - -#ifdef TRACKDEBUG2 - if (ev->chn==6) { - if (ev->vel==0) printfdebug("Note Onf\n"); - else printfdebug("Note On\n"); - }; -#endif - break; - case (MIDI_NOTEOFF) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug("Note Off\n"); -#endif - ev->note = *ptrdata;ptrdata++;currentpos++; - ev->vel = *ptrdata;ptrdata++;currentpos++; - note[ev->chn][ev->note]=FALSE; - - break; - case (MIDI_KEY_PRESSURE) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug ("Key press\n"); -#endif - ev->note = *ptrdata;ptrdata++;currentpos++; - ev->vel = *ptrdata;ptrdata++;currentpos++; - break; - case (MIDI_PGM_CHANGE) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug ("Pgm\n"); -#endif - ev->patch = *ptrdata;ptrdata++;currentpos++; - break; - case (MIDI_CHN_PRESSURE) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug ("Chn press\n"); -#endif - ev->vel = *ptrdata;ptrdata++;currentpos++; - break; - case (MIDI_PITCH_BEND) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug ("Pitch\n"); -#endif - ev->d1 = *ptrdata;ptrdata++;currentpos++; - ev->d2 = *ptrdata;ptrdata++;currentpos++; - break; - case (MIDI_CTL_CHANGE) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug (stderr, "Ctl\n"); -#endif - ev->ctl = *ptrdata;ptrdata++; currentpos++; - ev->d1 = *ptrdata;ptrdata++;currentpos++; - /* - switch (ev->ctl) - { - case (96) : printfdebug("RPN Increment\n");break; - case (97) : printfdebug("RPN Decrement\n");break; - case (98) : printfdebug("nRPN 98 %d\n",ev->d1);break; - case (99) : printfdebug("nRPN 99 %d\n",ev->d1);break; - case (100) : printfdebug("RPN 100 %d\n",ev->d1);break; - case (101) : printfdebug("RPN 101 %d\n",ev->d1);break; - }; - */ - break; - - case (MIDI_SYSTEM_PREFIX) : -#ifdef TRACKDEBUG2 - if (ev->chn==6) printfdebug ("Sys Prefix\n"); -#endif - switch ((ev->command|ev->chn)) - { - case (0xF0) : - case (0xF7) : - ev->length=readVariableLengthValue(); -#ifdef PEDANTIC_TRACK - if (endoftrack) - { - ev->command=MIDI_SYSTEM_PREFIX; - ev->chn=0xF; - ev->d1=ME_END_OF_TRACK; - } - else -#endif - { - ev->data=ptrdata; - ptrdata+=ev->length;currentpos+=ev->length; - } - break; - case (0xFE): - case (0xF8): - // printfdebug("Active sensing\n"); - break; - case (META_EVENT) : - ev->d1=*ptrdata;ptrdata++;currentpos++; - switch (ev->d1) - { - case (ME_END_OF_TRACK) : - i=0; - j=0; - while ((i<16)&&(note[i][j]==FALSE)) - { - j++; - if (j==128) { j=0; i++; }; - } - if (i<16) // that is, if there is any key still pressed - { - ptrdata--;currentpos--; - ev->chn=i; - ev->command=MIDI_NOTEOFF; - ev->note = j; - ev->vel = 0; - note[ev->chn][ev->note]=FALSE; - fprintf(stderr,"Note Off(simulated)\n"); - return; - } - else - { - endoftrack=1; - delta_ticks = wait_ticks = ~0; - time_at_next_event=10000 * 60000L; -#ifdef TRACKDEBUG - printfdebug("EndofTrack %d event\n",id); -#endif - } - break; - case (ME_SET_TEMPO): - ev->length=readVariableLengthValue(); -#ifdef PEDANTIC_TRACK - if (endoftrack) - { - ev->command=MIDI_SYSTEM_PREFIX; - ev->chn=0xF; - ev->d1=ME_END_OF_TRACK; - } - else -#endif - { - ev->data=ptrdata; - ptrdata+=ev->length;currentpos+=ev->length; - // tempo=((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])); - // ticks_from_previous_tempochange=0; - // time_at_previous_tempochange=current_time; -#ifdef TRACKDEBUG - printfdebug("Track %d : Set Tempo : %ld\n",id,tempo); -#endif -#ifdef CHANGETEMPO_ONLY_IN_TRACK0 - if (id!=0) skip_event=1; -#endif - } - break; - case (ME_TIME_SIGNATURE) : - ev->length=*ptrdata;ptrdata++;currentpos++; - ev->d2=*ptrdata;ptrdata++;currentpos++; - ev->d3=power2to(*ptrdata);ptrdata++;currentpos++; - ev->d4=*ptrdata;ptrdata++;currentpos++; - ev->d5=*ptrdata;ptrdata++;currentpos++; -#ifdef TRACKDEBUG - printfdebug("TIME SIGNATURE :\n"); - printfdebug("%d\n",ev->d2); - printfdebug("---- %d metronome , %d number of 32nd notes per quarter note\n",ev->d4,ev->d5); - printfdebug("%d\n",ev->d3); -#endif - break; - case (ME_TRACK_SEQ_NUMBER) : - case (ME_TEXT) : - case (ME_COPYRIGHT) : - case (ME_SEQ_OR_TRACK_NAME) : - case (ME_TRACK_INSTR_NAME) : - case (ME_LYRIC) : - case (ME_MARKER) : - case (ME_CUE_POINT) : - case (ME_CHANNEL_PREFIX) : - case (ME_MIDI_PORT) : - case (ME_SMPTE_OFFSET) : - case (ME_KEY_SIGNATURE) : - ev->length=readVariableLengthValue(); -#ifdef PEDANTIC_TRACK - if (endoftrack) - { - ev->command=MIDI_SYSTEM_PREFIX; - ev->chn=0xF; - ev->d1=ME_END_OF_TRACK; - } - else -#endif - { - ev->data=ptrdata; - ptrdata+=ev->length;currentpos+=ev->length; - } - break; - default: -#ifdef GENERAL_DEBUG_MESSAGES - fprintf(stderr,"track (%d) : Default handler for meta event " \ - "0x%x\n", id, ev->d1); -#endif - ev->length=readVariableLengthValue(); -#ifdef PEDANTIC_TRACK - if (endoftrack) - { - ev->command=MIDI_SYSTEM_PREFIX; - ev->chn=0xF; - ev->d1=ME_END_OF_TRACK; - } - else -#endif - { - ev->data=ptrdata; - ptrdata+=ev->length;currentpos+=ev->length; - } - break; - } - break; - default : - fprintf(stderr,"track (%d): Default handler for system event 0x%x\n", - id, (ev->command|ev->chn)); - break; - } - break; - default : - fprintf(stderr,"track (%d): Default handler for event 0x%x\n", - id, (ev->command|ev->chn)); - break; - } -#ifdef PEDANTIC_TRACK - if (currentpos>=size) - { - endoftrack=1; - delta_ticks = wait_ticks = ~0; - time_at_next_event=10000 * 60000L; - printfdebug("track (%d): EndofTrack reached\n",id); - } -#endif - if (endoftrack==0) - { - current_ticks+=delta_ticks; - delta_ticks=readVariableLengthValue(); -#ifdef PEDANTIC_TRACK - if (endoftrack) - { - ev->command=MIDI_SYSTEM_PREFIX; - ev->chn=0xF; - ev->d1=ME_END_OF_TRACK; - return; - } -#endif - ticks_from_previous_tempochange+=delta_ticks; - - time_at_next_event=T2MS(ticks_from_previous_tempochange)+time_at_previous_tempochange; - /* - printf("tane2 : %g, ticks : %g, delta_ticks %ld, tempo : %ld\n", - time_at_next_event,ticks_from_previous_tempochange,delta_ticks,tempo); - printf("timeatprevtc %g , curr %g\n",time_at_previous_tempochange,current_time); - */ - wait_ticks=delta_ticks; - - } - if (skip_event) readEvent(ev); -} - - -void MidiTrack::clear(void) -{ - endoftrack=1; - ptrdata=data; - current_ticks=0; - currentpos=0; - - for (int i=0;i<16;i++) - for (int j=0;j<128;j++) - note[i][j]=FALSE; - - delta_ticks = wait_ticks = ~0; - time_at_previous_tempochange=0; - current_time=0; - ticks_from_previous_tempochange=0; - tempo=1000000; - time_at_next_event=10000 * 60000L; - -} - - -void MidiTrack::init(void) -{ - if (data==0L) { clear(); return; }; - endoftrack=0; - ptrdata=data; - current_ticks=0; - currentpos=0; - - for (int i=0;i<16;i++) - for (int j=0;j<128;j++) - note[i][j]=FALSE; - - delta_ticks=readVariableLengthValue(); - if (endoftrack) return; - wait_ticks=delta_ticks; - - - time_at_previous_tempochange=0; - current_time=0; - ticks_from_previous_tempochange=wait_ticks; - tempo=1000000; - time_at_next_event=T2MS(delta_ticks); - //printf("tane1 : %g\n",time_at_next_event); -} - -void MidiTrack::changeTempo(ulong t) -{ - if (endoftrack==1) return; - if (tempo==t) return; - double ticks; - time_at_previous_tempochange=current_time; - ticks=MS2T(time_at_next_event-current_time); - tempo=t; - time_at_next_event=T2MS(ticks)+current_time; - ticks_from_previous_tempochange=ticks; - -} - -/* -double MidiTrack::absMsOfNextEvent (void) -{ - //printf("%d : %g\n",id,time_at_next_event); - return time_at_next_event; -} -*/ - -#undef T2MS -#undef MS2T diff --git a/libtdemid/track.cpp b/libtdemid/track.cpp new file mode 100644 index 000000000..44375b637 --- /dev/null +++ b/libtdemid/track.cpp @@ -0,0 +1,566 @@ +/************************************************************************** + + track.cpp - class track, which has a midi file track and its events + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ + +#include "track.h" +#include +#include "sndcard.h" +#include "midispec.h" +#include "midfile.h" + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)tPCN) + +#define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)tPCN)/((double)60000L)) + +#define PEDANTIC_TRACK +#define CHANGETEMPO_ONLY_IN_TRACK0 +//#define TRACKDEBUG +//#define TRACKDEBUG2 + +MidiTrack::MidiTrack(FILE *file,int tpcn,int Id) +{ + id=Id; + tPCN=tpcn; + currentpos=0; + size=0; + data=0L; + tempo=1000000; + if (feof(file)) + { + clear(); + return; + }; + size=readLong(file); +#ifdef TRACKDEBUG + printf("Track %d : Size %ld\n",id,size); +#endif + data=new uchar[size]; + if (data==NULL) + { + perror("track: Not enough memory ?"); + exit(-1); + } + ulong rsize=0; + if ((rsize=fread(data,1,size,file))!=size) + { + fprintf(stderr,"track (%d): File is corrupt : Couldn't load track (%ld!=%ld) !!\n", id, rsize, size); + size=rsize; + }; + /* + ptrdata=data; + current_ticks=0; + delta_ticks=readVariableLengthValue(); + wait_ticks=delta_ticks; + endoftrack=0; + */ + init(); +} + +MidiTrack::~MidiTrack() +{ + delete data; + endoftrack=1; + currentpos=0; + size=0; +} + +int MidiTrack::power2to(int i) +{ + return 1<=size) + { + endoftrack=1; + fprintf(stderr, "track (%d) : EndofTrack found by accident !\n",id); + delta_ticks = wait_ticks = ~0; + time_at_next_event=10000 * 60000L; + return 0; + } + else +#endif + { + dticks=(dticks << 7) | (*ptrdata) & 0x7F; + ptrdata++;currentpos++; + } + + } + dticks=((dticks << 7) | (*ptrdata) & 0x7F); + ptrdata++;currentpos++; + +#ifdef PEDANTIC_TRACK + + if (currentpos>=size) + { + endoftrack=1; + fprintf(stderr,"track (%d): EndofTrack found by accident 2 !\n",id); + dticks=0; + delta_ticks = wait_ticks = ~0; + time_at_next_event=10000 * 60000L; + return 0; + } +#endif +#ifdef TRACKDEBUG + printfdebug("track(%d): DTICKS : %ld\n",id,dticks); + usleep(10); +#endif + return dticks; +} + +int MidiTrack::ticksPassed (ulong ticks) +{ + if (endoftrack==1) return 0; + if (ticks>wait_ticks) + { + printfdebug("track (%d): ERROR : TICKS PASSED > WAIT TICKS\n", id); + return 1; + } + wait_ticks-=ticks; + return 0; +} + +int MidiTrack::msPassed (ulong ms) +{ + if (endoftrack==1) return 0; + current_time+=ms; + //fprintf(stderr, "old + %ld = CURR %g ", ms,current_time); + if ( current_time>time_at_next_event ) + { + fprintf(stderr, "track (%d): ERROR : MS PASSED > WAIT MS\n", id); + return 1; + } +#ifdef TRACKDEBUG + if (current_time==time_at_next_event) printfdebug("track(%d): _OK_",id); +#endif + return 0; +} + +int MidiTrack::currentMs(double ms) +{ + if (endoftrack==1) return 0; + current_time=ms; + //printfdebug("CURR %g",current_time); +#ifdef PEDANTIC_TRACK + if (current_time>time_at_next_event) + { + fprintf(stderr,"track(%d): ERROR : MS PASSED > WAIT MS\n", id); + exit(-1); + return 1; + } +#endif + return 0; +} + +void MidiTrack::readEvent(MidiEvent *ev) +{ + int i,j; + if (endoftrack==1) + { + ev->command=0; + return; + } + /* + printfdebug("...... %d\n",id); + printfdebug("current : %g , tane : %g\n",current_time,time_at_next_event); + printfdebug("......\n"); + */ + int skip_event=0; + current_time=time_at_next_event; + if (((*ptrdata)&0x80)!=0) + { + ev->command=(*ptrdata); + ptrdata++;currentpos++; + lastcommand=ev->command; + } + else + { + ev->command=lastcommand; + } + +#ifdef PEDANTIC_TRACK + if (currentpos>=size) + { + endoftrack=1; + delta_ticks = wait_ticks = ~0; + time_at_next_event=10000 * 60000L; + ev->command=MIDI_SYSTEM_PREFIX; + ev->chn=0xF; + ev->d1=ME_END_OF_TRACK; + fprintf(stderr, "track (%d): EndofTrack found by accident 3\n",id); + return; + } +#endif + + ev->chn=ev->command & 0xF; + ev->command=ev->command & 0xF0; + switch (ev->command) + { + case (MIDI_NOTEON) : + ev->note = *ptrdata;ptrdata++;currentpos++; + ev->vel = *ptrdata;ptrdata++;currentpos++; + if (ev->vel==0) + note[ev->chn][ev->note]=FALSE; + else + note[ev->chn][ev->note]=TRUE; + +#ifdef TRACKDEBUG2 + if (ev->chn==6) { + if (ev->vel==0) printfdebug("Note Onf\n"); + else printfdebug("Note On\n"); + }; +#endif + break; + case (MIDI_NOTEOFF) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug("Note Off\n"); +#endif + ev->note = *ptrdata;ptrdata++;currentpos++; + ev->vel = *ptrdata;ptrdata++;currentpos++; + note[ev->chn][ev->note]=FALSE; + + break; + case (MIDI_KEY_PRESSURE) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug ("Key press\n"); +#endif + ev->note = *ptrdata;ptrdata++;currentpos++; + ev->vel = *ptrdata;ptrdata++;currentpos++; + break; + case (MIDI_PGM_CHANGE) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug ("Pgm\n"); +#endif + ev->patch = *ptrdata;ptrdata++;currentpos++; + break; + case (MIDI_CHN_PRESSURE) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug ("Chn press\n"); +#endif + ev->vel = *ptrdata;ptrdata++;currentpos++; + break; + case (MIDI_PITCH_BEND) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug ("Pitch\n"); +#endif + ev->d1 = *ptrdata;ptrdata++;currentpos++; + ev->d2 = *ptrdata;ptrdata++;currentpos++; + break; + case (MIDI_CTL_CHANGE) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug (stderr, "Ctl\n"); +#endif + ev->ctl = *ptrdata;ptrdata++; currentpos++; + ev->d1 = *ptrdata;ptrdata++;currentpos++; + /* + switch (ev->ctl) + { + case (96) : printfdebug("RPN Increment\n");break; + case (97) : printfdebug("RPN Decrement\n");break; + case (98) : printfdebug("nRPN 98 %d\n",ev->d1);break; + case (99) : printfdebug("nRPN 99 %d\n",ev->d1);break; + case (100) : printfdebug("RPN 100 %d\n",ev->d1);break; + case (101) : printfdebug("RPN 101 %d\n",ev->d1);break; + }; + */ + break; + + case (MIDI_SYSTEM_PREFIX) : +#ifdef TRACKDEBUG2 + if (ev->chn==6) printfdebug ("Sys Prefix\n"); +#endif + switch ((ev->command|ev->chn)) + { + case (0xF0) : + case (0xF7) : + ev->length=readVariableLengthValue(); +#ifdef PEDANTIC_TRACK + if (endoftrack) + { + ev->command=MIDI_SYSTEM_PREFIX; + ev->chn=0xF; + ev->d1=ME_END_OF_TRACK; + } + else +#endif + { + ev->data=ptrdata; + ptrdata+=ev->length;currentpos+=ev->length; + } + break; + case (0xFE): + case (0xF8): + // printfdebug("Active sensing\n"); + break; + case (META_EVENT) : + ev->d1=*ptrdata;ptrdata++;currentpos++; + switch (ev->d1) + { + case (ME_END_OF_TRACK) : + i=0; + j=0; + while ((i<16)&&(note[i][j]==FALSE)) + { + j++; + if (j==128) { j=0; i++; }; + } + if (i<16) // that is, if there is any key still pressed + { + ptrdata--;currentpos--; + ev->chn=i; + ev->command=MIDI_NOTEOFF; + ev->note = j; + ev->vel = 0; + note[ev->chn][ev->note]=FALSE; + fprintf(stderr,"Note Off(simulated)\n"); + return; + } + else + { + endoftrack=1; + delta_ticks = wait_ticks = ~0; + time_at_next_event=10000 * 60000L; +#ifdef TRACKDEBUG + printfdebug("EndofTrack %d event\n",id); +#endif + } + break; + case (ME_SET_TEMPO): + ev->length=readVariableLengthValue(); +#ifdef PEDANTIC_TRACK + if (endoftrack) + { + ev->command=MIDI_SYSTEM_PREFIX; + ev->chn=0xF; + ev->d1=ME_END_OF_TRACK; + } + else +#endif + { + ev->data=ptrdata; + ptrdata+=ev->length;currentpos+=ev->length; + // tempo=((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])); + // ticks_from_previous_tempochange=0; + // time_at_previous_tempochange=current_time; +#ifdef TRACKDEBUG + printfdebug("Track %d : Set Tempo : %ld\n",id,tempo); +#endif +#ifdef CHANGETEMPO_ONLY_IN_TRACK0 + if (id!=0) skip_event=1; +#endif + } + break; + case (ME_TIME_SIGNATURE) : + ev->length=*ptrdata;ptrdata++;currentpos++; + ev->d2=*ptrdata;ptrdata++;currentpos++; + ev->d3=power2to(*ptrdata);ptrdata++;currentpos++; + ev->d4=*ptrdata;ptrdata++;currentpos++; + ev->d5=*ptrdata;ptrdata++;currentpos++; +#ifdef TRACKDEBUG + printfdebug("TIME SIGNATURE :\n"); + printfdebug("%d\n",ev->d2); + printfdebug("---- %d metronome , %d number of 32nd notes per quarter note\n",ev->d4,ev->d5); + printfdebug("%d\n",ev->d3); +#endif + break; + case (ME_TRACK_SEQ_NUMBER) : + case (ME_TEXT) : + case (ME_COPYRIGHT) : + case (ME_SEQ_OR_TRACK_NAME) : + case (ME_TRACK_INSTR_NAME) : + case (ME_LYRIC) : + case (ME_MARKER) : + case (ME_CUE_POINT) : + case (ME_CHANNEL_PREFIX) : + case (ME_MIDI_PORT) : + case (ME_SMPTE_OFFSET) : + case (ME_KEY_SIGNATURE) : + ev->length=readVariableLengthValue(); +#ifdef PEDANTIC_TRACK + if (endoftrack) + { + ev->command=MIDI_SYSTEM_PREFIX; + ev->chn=0xF; + ev->d1=ME_END_OF_TRACK; + } + else +#endif + { + ev->data=ptrdata; + ptrdata+=ev->length;currentpos+=ev->length; + } + break; + default: +#ifdef GENERAL_DEBUG_MESSAGES + fprintf(stderr,"track (%d) : Default handler for meta event " \ + "0x%x\n", id, ev->d1); +#endif + ev->length=readVariableLengthValue(); +#ifdef PEDANTIC_TRACK + if (endoftrack) + { + ev->command=MIDI_SYSTEM_PREFIX; + ev->chn=0xF; + ev->d1=ME_END_OF_TRACK; + } + else +#endif + { + ev->data=ptrdata; + ptrdata+=ev->length;currentpos+=ev->length; + } + break; + } + break; + default : + fprintf(stderr,"track (%d): Default handler for system event 0x%x\n", + id, (ev->command|ev->chn)); + break; + } + break; + default : + fprintf(stderr,"track (%d): Default handler for event 0x%x\n", + id, (ev->command|ev->chn)); + break; + } +#ifdef PEDANTIC_TRACK + if (currentpos>=size) + { + endoftrack=1; + delta_ticks = wait_ticks = ~0; + time_at_next_event=10000 * 60000L; + printfdebug("track (%d): EndofTrack reached\n",id); + } +#endif + if (endoftrack==0) + { + current_ticks+=delta_ticks; + delta_ticks=readVariableLengthValue(); +#ifdef PEDANTIC_TRACK + if (endoftrack) + { + ev->command=MIDI_SYSTEM_PREFIX; + ev->chn=0xF; + ev->d1=ME_END_OF_TRACK; + return; + } +#endif + ticks_from_previous_tempochange+=delta_ticks; + + time_at_next_event=T2MS(ticks_from_previous_tempochange)+time_at_previous_tempochange; + /* + printf("tane2 : %g, ticks : %g, delta_ticks %ld, tempo : %ld\n", + time_at_next_event,ticks_from_previous_tempochange,delta_ticks,tempo); + printf("timeatprevtc %g , curr %g\n",time_at_previous_tempochange,current_time); + */ + wait_ticks=delta_ticks; + + } + if (skip_event) readEvent(ev); +} + + +void MidiTrack::clear(void) +{ + endoftrack=1; + ptrdata=data; + current_ticks=0; + currentpos=0; + + for (int i=0;i<16;i++) + for (int j=0;j<128;j++) + note[i][j]=FALSE; + + delta_ticks = wait_ticks = ~0; + time_at_previous_tempochange=0; + current_time=0; + ticks_from_previous_tempochange=0; + tempo=1000000; + time_at_next_event=10000 * 60000L; + +} + + +void MidiTrack::init(void) +{ + if (data==0L) { clear(); return; }; + endoftrack=0; + ptrdata=data; + current_ticks=0; + currentpos=0; + + for (int i=0;i<16;i++) + for (int j=0;j<128;j++) + note[i][j]=FALSE; + + delta_ticks=readVariableLengthValue(); + if (endoftrack) return; + wait_ticks=delta_ticks; + + + time_at_previous_tempochange=0; + current_time=0; + ticks_from_previous_tempochange=wait_ticks; + tempo=1000000; + time_at_next_event=T2MS(delta_ticks); + //printf("tane1 : %g\n",time_at_next_event); +} + +void MidiTrack::changeTempo(ulong t) +{ + if (endoftrack==1) return; + if (tempo==t) return; + double ticks; + time_at_previous_tempochange=current_time; + ticks=MS2T(time_at_next_event-current_time); + tempo=t; + time_at_next_event=T2MS(ticks)+current_time; + ticks_from_previous_tempochange=ticks; + +} + +/* +double MidiTrack::absMsOfNextEvent (void) +{ + //printf("%d : %g\n",id,time_at_next_event); + return time_at_next_event; +} +*/ + +#undef T2MS +#undef MS2T diff --git a/libtdemid/voiceman.cc b/libtdemid/voiceman.cc deleted file mode 100644 index 867ee6024..000000000 --- a/libtdemid/voiceman.cc +++ /dev/null @@ -1,279 +0,0 @@ -/************************************************************************** - - voiceman.cc - The VoiceManager class handles a set of voices for synths - This file is part of LibKMid 0.9.5 - Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez - LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Antonio Larrosa - -***************************************************************************/ - -#include "voiceman.h" -#include -#ifdef HAVE_CONFIG_H -#include -#endif - -VoiceManager::VoiceManager(int totalvoices) -{ - nvoices=totalvoices; - - FirstVoice=new voice; - FirstVoice->id=0; - FirstVoice->channel=0; - FirstVoice->note=0; - FirstVoice->used=0; - FirstVoice->prev=NULL; - - voice *ptrb=FirstVoice; - voice *ptr=NULL; - int i; - for (i=1;inext=ptr; - ptr->id=i; - ptr->channel=0; - ptr->note=0; - ptr->used=0; - ptr->prev=ptrb; - ptrb=ptr; - } - LastVoice=ptr; - LastVoice->next=NULL; - LastnotusedVoice=LastVoice; - - VoiceList=new voice *[nvoices]; - ptr=FirstVoice; - for (i=0;inext; - } - searcher_aid=new voice; -} - -VoiceManager::~VoiceManager() -{ - voice *ptr=FirstVoice; - voice *ptr2; - while (ptr!=NULL) - { - ptr2=ptr->next; - delete ptr; - ptr=ptr2; - } - FirstVoice=NULL; - LastVoice=NULL; - LastnotusedVoice=NULL; - - delete [] VoiceList; - VoiceList=NULL; - - delete searcher_aid; -} - -void VoiceManager::clearLists(void) -{ -#ifdef VOICEMANDEBUG - printf("voicemanager::cleanLists\n"); -#endif - voice *ptr=FirstVoice; - voice *ptr2=FirstVoice; - while (ptr!=NULL) - { - ptr->used=0; - ptr2=ptr; - ptr=ptr->next; - } - LastVoice=ptr2; - LastnotusedVoice=ptr2; - -} - -int VoiceManager::allocateVoice(int chn,int key) -{ - // First, we take the allocated voice out of the first place of the list - if ((LastnotusedVoice!=NULL)&&(LastnotusedVoice->id==FirstVoice->id)) - { -#ifdef VOICEMANDEBUG - printf("Used last voice !\n"); -#endif - LastnotusedVoice=NULL; - } - voice *newvoice=FirstVoice; - FirstVoice=FirstVoice->next; - FirstVoice->prev=NULL; - -#ifdef VOICEMANDEBUG - printf("Allocating id :%d\n",newvoice->id); -#endif - // then we put the allocated voice at the end of the list - LastVoice->next=newvoice; - newvoice->prev=LastVoice; - LastVoice=newvoice; - LastVoice->next=NULL; - - newvoice->channel=chn; - newvoice->note=key; - -#ifdef VOICEMANDEBUG - if (newvoice->used==1) - { - printf("Replacing voice : %d\n",newvoice->id); - } -#endif - newvoice->used=1; - - //dispStat(); - return newvoice->id; -} - -void VoiceManager::deallocateVoice(int id) -{ - voice *delvoice=VoiceList[id]; -#ifdef VOICEMANDEBUG - printf("Deallocating id :%d\n",id); -#endif - if (delvoice->id==LastVoice->id) - { - LastVoice=delvoice->prev; - LastVoice->next=NULL; - - if (LastnotusedVoice==NULL) - { - delvoice->next=FirstVoice; - FirstVoice->prev=delvoice; - FirstVoice=delvoice; - FirstVoice->prev=NULL; - LastnotusedVoice=FirstVoice; - } - else - { - if (LastnotusedVoice->next==NULL) - { - LastnotusedVoice->next=delvoice; - delvoice->prev=LastnotusedVoice; - delvoice->next=NULL; - LastnotusedVoice=delvoice; - LastVoice=delvoice; - } - else - { - delvoice->next=LastnotusedVoice->next; - delvoice->next->prev=delvoice; - delvoice->prev=LastnotusedVoice; - LastnotusedVoice->next=delvoice; - LastnotusedVoice=delvoice; - } - } - } - else - { - if (delvoice->prev!=NULL) - { - delvoice->prev->next=delvoice->next; - delvoice->next->prev=delvoice->prev; - if (LastnotusedVoice==NULL) - { - delvoice->next=FirstVoice; - FirstVoice->prev=delvoice; - FirstVoice=delvoice; - FirstVoice->prev=NULL; - LastnotusedVoice=FirstVoice; } - else - { - if (LastnotusedVoice->next==NULL) - { - LastnotusedVoice->next=delvoice; - delvoice->prev=LastnotusedVoice; - delvoice->next=NULL; - LastnotusedVoice=delvoice; - LastVoice=delvoice; - } - else - { - delvoice->next=LastnotusedVoice->next; - delvoice->next->prev=delvoice; - delvoice->prev=LastnotusedVoice; - LastnotusedVoice->next=delvoice; - LastnotusedVoice=delvoice; - } - } - } - } - delvoice->used=0; - - // dispStat(); -} - -void VoiceManager::initSearch(void) -{ - searcher=searcher_aid; - searcher_aid->prev=LastVoice; -} - -int VoiceManager::search(int chn) -{ - if (searcher==NULL) return -1; - searcher=searcher->prev; - - while (searcher!=NULL) - { - if (searcher->used==0) return -1; - if (searcher->channel==chn) - { - return searcher->id; - } - searcher=searcher->prev; - } - return -1; -} - -int VoiceManager::search(int chn,int note) -{ - if (searcher==NULL) return -1; - searcher=searcher->prev; - while ((searcher!=NULL)) - { - if (searcher->used==0) return -1; - if ((searcher->channel==chn)&&(searcher->note==note)) - { - return searcher->id; - } - searcher=searcher->prev; - } - return -1; -} - -/* -void VoiceManager::dispStat(void) -{ -#ifdef VOICEMANDEBUG - printf("Stats\n"); - voice *ptr=FirstVoice; - while (ptr!=NULL) - { - printf("Voice %d is %s\n",ptr->id,(ptr->used==0)?("off"):("on")); - ptr=ptr->next; - } - if (LastnotusedVoice!=NULL) printf("LnuV = %d\n",LastnotusedVoice->id); -#endif -} -*/ diff --git a/libtdemid/voiceman.cpp b/libtdemid/voiceman.cpp new file mode 100644 index 000000000..fddf68f0e --- /dev/null +++ b/libtdemid/voiceman.cpp @@ -0,0 +1,279 @@ +/************************************************************************** + + voiceman.cpp - The VoiceManager class handles a set of voices for synths + This file is part of LibKMid 0.9.5 + Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez + LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libtdemid.html + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Antonio Larrosa + +***************************************************************************/ + +#include "voiceman.h" +#include +#ifdef HAVE_CONFIG_H +#include +#endif + +VoiceManager::VoiceManager(int totalvoices) +{ + nvoices=totalvoices; + + FirstVoice=new voice; + FirstVoice->id=0; + FirstVoice->channel=0; + FirstVoice->note=0; + FirstVoice->used=0; + FirstVoice->prev=NULL; + + voice *ptrb=FirstVoice; + voice *ptr=NULL; + int i; + for (i=1;inext=ptr; + ptr->id=i; + ptr->channel=0; + ptr->note=0; + ptr->used=0; + ptr->prev=ptrb; + ptrb=ptr; + } + LastVoice=ptr; + LastVoice->next=NULL; + LastnotusedVoice=LastVoice; + + VoiceList=new voice *[nvoices]; + ptr=FirstVoice; + for (i=0;inext; + } + searcher_aid=new voice; +} + +VoiceManager::~VoiceManager() +{ + voice *ptr=FirstVoice; + voice *ptr2; + while (ptr!=NULL) + { + ptr2=ptr->next; + delete ptr; + ptr=ptr2; + } + FirstVoice=NULL; + LastVoice=NULL; + LastnotusedVoice=NULL; + + delete [] VoiceList; + VoiceList=NULL; + + delete searcher_aid; +} + +void VoiceManager::clearLists(void) +{ +#ifdef VOICEMANDEBUG + printf("voicemanager::cleanLists\n"); +#endif + voice *ptr=FirstVoice; + voice *ptr2=FirstVoice; + while (ptr!=NULL) + { + ptr->used=0; + ptr2=ptr; + ptr=ptr->next; + } + LastVoice=ptr2; + LastnotusedVoice=ptr2; + +} + +int VoiceManager::allocateVoice(int chn,int key) +{ + // First, we take the allocated voice out of the first place of the list + if ((LastnotusedVoice!=NULL)&&(LastnotusedVoice->id==FirstVoice->id)) + { +#ifdef VOICEMANDEBUG + printf("Used last voice !\n"); +#endif + LastnotusedVoice=NULL; + } + voice *newvoice=FirstVoice; + FirstVoice=FirstVoice->next; + FirstVoice->prev=NULL; + +#ifdef VOICEMANDEBUG + printf("Allocating id :%d\n",newvoice->id); +#endif + // then we put the allocated voice at the end of the list + LastVoice->next=newvoice; + newvoice->prev=LastVoice; + LastVoice=newvoice; + LastVoice->next=NULL; + + newvoice->channel=chn; + newvoice->note=key; + +#ifdef VOICEMANDEBUG + if (newvoice->used==1) + { + printf("Replacing voice : %d\n",newvoice->id); + } +#endif + newvoice->used=1; + + //dispStat(); + return newvoice->id; +} + +void VoiceManager::deallocateVoice(int id) +{ + voice *delvoice=VoiceList[id]; +#ifdef VOICEMANDEBUG + printf("Deallocating id :%d\n",id); +#endif + if (delvoice->id==LastVoice->id) + { + LastVoice=delvoice->prev; + LastVoice->next=NULL; + + if (LastnotusedVoice==NULL) + { + delvoice->next=FirstVoice; + FirstVoice->prev=delvoice; + FirstVoice=delvoice; + FirstVoice->prev=NULL; + LastnotusedVoice=FirstVoice; + } + else + { + if (LastnotusedVoice->next==NULL) + { + LastnotusedVoice->next=delvoice; + delvoice->prev=LastnotusedVoice; + delvoice->next=NULL; + LastnotusedVoice=delvoice; + LastVoice=delvoice; + } + else + { + delvoice->next=LastnotusedVoice->next; + delvoice->next->prev=delvoice; + delvoice->prev=LastnotusedVoice; + LastnotusedVoice->next=delvoice; + LastnotusedVoice=delvoice; + } + } + } + else + { + if (delvoice->prev!=NULL) + { + delvoice->prev->next=delvoice->next; + delvoice->next->prev=delvoice->prev; + if (LastnotusedVoice==NULL) + { + delvoice->next=FirstVoice; + FirstVoice->prev=delvoice; + FirstVoice=delvoice; + FirstVoice->prev=NULL; + LastnotusedVoice=FirstVoice; } + else + { + if (LastnotusedVoice->next==NULL) + { + LastnotusedVoice->next=delvoice; + delvoice->prev=LastnotusedVoice; + delvoice->next=NULL; + LastnotusedVoice=delvoice; + LastVoice=delvoice; + } + else + { + delvoice->next=LastnotusedVoice->next; + delvoice->next->prev=delvoice; + delvoice->prev=LastnotusedVoice; + LastnotusedVoice->next=delvoice; + LastnotusedVoice=delvoice; + } + } + } + } + delvoice->used=0; + + // dispStat(); +} + +void VoiceManager::initSearch(void) +{ + searcher=searcher_aid; + searcher_aid->prev=LastVoice; +} + +int VoiceManager::search(int chn) +{ + if (searcher==NULL) return -1; + searcher=searcher->prev; + + while (searcher!=NULL) + { + if (searcher->used==0) return -1; + if (searcher->channel==chn) + { + return searcher->id; + } + searcher=searcher->prev; + } + return -1; +} + +int VoiceManager::search(int chn,int note) +{ + if (searcher==NULL) return -1; + searcher=searcher->prev; + while ((searcher!=NULL)) + { + if (searcher->used==0) return -1; + if ((searcher->channel==chn)&&(searcher->note==note)) + { + return searcher->id; + } + searcher=searcher->prev; + } + return -1; +} + +/* +void VoiceManager::dispStat(void) +{ +#ifdef VOICEMANDEBUG + printf("Stats\n"); + voice *ptr=FirstVoice; + while (ptr!=NULL) + { + printf("Voice %d is %s\n",ptr->id,(ptr->used==0)?("off"):("on")); + ptr=ptr->next; + } + if (LastnotusedVoice!=NULL) printf("LnuV = %d\n",LastnotusedVoice->id); +#endif +} +*/ diff --git a/tdecert/CMakeLists.txt b/tdecert/CMakeLists.txt index 75f354c99..3c616fde9 100644 --- a/tdecert/CMakeLists.txt +++ b/tdecert/CMakeLists.txt @@ -44,7 +44,7 @@ install( FILES tdecertpart.rc DESTINATION ${DATA_INSTALL_DIR}/tdecertpart ) set( target libtdecertpart ) set( ${target}_SRCS - tdecertpart.cc + tdecertpart.cpp ) tde_add_kpart( ${target} AUTOMOC diff --git a/tdecert/Makefile.am b/tdecert/Makefile.am index a98232be6..ebd06ce23 100644 --- a/tdecert/Makefile.am +++ b/tdecert/Makefile.am @@ -2,7 +2,7 @@ INCLUDES= -I$(top_srcdir)/tdeio/kssl -I$(top_builddir)/tdeio/kssl -I$(top_srcdir kde_module_LTLIBRARIES = libtdecertpart.la -libtdecertpart_la_SOURCES = tdecertpart.cc +libtdecertpart_la_SOURCES = tdecertpart.cpp libtdecertpart_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) libtdecertpart_la_LIBADD = $(LIB_TDEPARTS) $(LIB_TQT) $(LIB_TDEUI) $(LIB_TDEFILE) $(LIB_TDECORE) diff --git a/tdecert/tdecertpart.cc b/tdecert/tdecertpart.cc deleted file mode 100644 index 02afc9b75..000000000 --- a/tdecert/tdecertpart.cc +++ /dev/null @@ -1,876 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001-2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include "tdecertpart.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -K_EXPORT_COMPONENT_FACTORY( libtdecertpart, KParts::GenericFactory ) - - -KX509Item::KX509Item(TDEListViewItem *parent, KSSLCertificate *x) : - TDEListViewItem(parent, 0L) -{ - setup(x); -} - -KX509Item::KX509Item(TDEListView *parent, KSSLCertificate *x) : - TDEListViewItem(parent) -{ - setup(x); -} - -void KX509Item::setup(KSSLCertificate *x) { - cert = x; - if (x) { - KSSLX509Map xm(x->getSubject()); - TQString OU = "OU"; - TQString CN = "CN"; - OU = xm.getValue(OU); - CN = xm.getValue(CN); - OU.replace(TQRegExp("\n.*"), ""); - CN.replace(TQRegExp("\n.*"), ""); - - if (OU.length() > 0) { - _prettyName = OU; - } - - if (CN.length() > 0) { - if (_prettyName.length() > 0) { - _prettyName += " - "; - } - _prettyName += CN; - } - setText(0, _prettyName); - } else { - setText(0, i18n("Invalid certificate!")); - } -} - - -KX509Item::~KX509Item() -{ - delete cert; -} - - -KPKCS12Item::KPKCS12Item(TDEListViewItem *parent, KSSLPKCS12 *x) : - TDEListViewItem(parent, 0L) -{ - cert = x; - if (x) { - KSSLX509Map xm(x->getCertificate()->getSubject()); - TQString CN = "CN"; - CN = xm.getValue(CN); - CN.replace(TQRegExp("\n.*"), ""); - _prettyName = CN; - setText(0, _prettyName); - } else { - setText(0, i18n("Invalid certificate!")); - } -} - - -KPKCS12Item::~KPKCS12Item() -{ - delete cert; -} - - -class KCertPartPrivate { - public: - KParts::BrowserExtension *browserExtension; -}; - - -KCertPart::KCertPart(TQWidget *parentWidget, const char *widgetName, - TQObject *parent, const char *name, - const TQStringList & /*args*/ ) - : KParts::ReadWritePart(parent, name) { -TDEInstance *instance = new TDEInstance("KCertPart"); -TQGridLayout *grid; -setInstance(instance); - - -_signers = new KSSLSigners; -// This is a bit confusing now. Here's how it works: -// We create a _frame and split it left/right -// Then we add the ListView to the left and create -// a new frame on the right. We set the main widget -// on the right. - -_p12 = NULL; -_ca = NULL; -_silentImport = false; -d = new KCertPartPrivate; -d->browserExtension = new KParts::BrowserExtension(this); - -_frame = new TQFrame(parentWidget, widgetName); -setWidget(_frame); - -_baseGrid = new TQGridLayout(_frame, 15, 9, KDialog::marginHint(), - KDialog::spacingHint()); - -_sideList = new TDEListView(_frame); -_sideList->setRootIsDecorated(true); -_sideList->addColumn(i18n("Certificates")); -_parentCA = new TDEListViewItem(_sideList, i18n("Signers")); -_parentCA->setExpandable(true); -_sideList->setOpen(_parentCA, true); -_parentP12 = new TDEListViewItem(_sideList, i18n("Client")); -_parentP12->setExpandable(true); -_sideList->setOpen(_parentP12, true); - -_baseGrid->addMultiCellWidget(_sideList, 0, 13, 0, 1); - -_importAll = new TQPushButton(i18n("Import &All"), _frame); -_baseGrid->addMultiCellWidget(_importAll, 14, 14, 0, 1); -connect(_importAll, TQT_SIGNAL(clicked()), TQT_SLOT(slotImportAll())); - - - -//------------------------------------------------------------------------ -// The PKCS widget -//------------------------------------------------------------------------ -_pkcsFrame = new TQFrame(_frame); - -grid = new TQGridLayout(_pkcsFrame, 13, 6, KDialog::marginHint(), - KDialog::spacingHint() ); -grid->addMultiCellWidget(new TQLabel(i18n("TDE Secure Certificate Import"), _pkcsFrame), 0, 0, 0, 5); -grid->addWidget(new TQLabel(i18n("Chain:"), _pkcsFrame), 1, 0); -_p12_chain = new KComboBox(_pkcsFrame); -grid->addMultiCellWidget(_p12_chain, 1, 1, 1, 4); -connect(_p12_chain, TQT_SIGNAL(activated(int)), TQT_SLOT(slotChain(int))); - -grid->addWidget(new TQLabel(i18n("Subject:"), _pkcsFrame), 2, 0); -grid->addWidget(new TQLabel(i18n("Issued by:"), _pkcsFrame), 2, 3); -_p12_subject = KSSLInfoDlg::certInfoWidget(_pkcsFrame, TQString("")); -_p12_issuer = KSSLInfoDlg::certInfoWidget(_pkcsFrame, TQString("")); -grid->addMultiCellWidget(_p12_subject, 3, 6, 0, 2); -grid->addMultiCellWidget(_p12_issuer, 3, 6, 3, 5); - -grid->addWidget(new TQLabel(i18n("File:"), _pkcsFrame), 7, 0); -_p12_filenameLabel = new TQLabel("", _pkcsFrame); -grid->addWidget(_p12_filenameLabel, 7, 1); -grid->addWidget(new TQLabel(i18n("File format:"), _pkcsFrame), 7, 3); -grid->addWidget(new TQLabel("PKCS#12", _pkcsFrame), 7, 4); - - -// -// Make the first tab -// -_tabs = new TQTabWidget(_pkcsFrame); -grid->addMultiCellWidget(_tabs, 8, 12, 0, 5); - -TQFrame *tab = new TQFrame(_pkcsFrame); -TQGridLayout *tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), - KDialog::spacingHint() ); -tabGrid->addWidget(new TQLabel(i18n("State:"), tab), 0, 0); -_p12_certState = new TQLabel("", tab); -tabGrid->addMultiCellWidget(_p12_certState, 0, 0, 1, 4); - -tabGrid->addWidget(new TQLabel(i18n("Valid from:"), tab), 1, 0); -_p12_validFrom = new TQLabel("", tab); -tabGrid->addMultiCellWidget(_p12_validFrom, 1, 1, 1, 4); - -tabGrid->addWidget(new TQLabel(i18n("Valid until:"), tab), 2, 0); -_p12_validUntil = new TQLabel("", tab); -tabGrid->addMultiCellWidget(_p12_validUntil, 2, 2, 1, 4); - -tabGrid->addWidget(new TQLabel(i18n("Serial number:"), tab), 3, 0); -_p12_serialNum = new TQLabel("", tab); -tabGrid->addWidget(_p12_serialNum, 3, 1); -_tabs->addTab(tab, i18n("State")); - - -// -// Make the second tab -// -tab = new TQFrame(_pkcsFrame); -tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), - KDialog::spacingHint() ); -tabGrid->addWidget(new TQLabel(i18n("MD5 digest:"), tab), 0, 0); -_p12_digest = new TQLabel(tab); -tabGrid->addMultiCellWidget(_p12_digest, 0, 0, 1, 4); -tabGrid->addWidget(new TQLabel(i18n("Signature:"), tab), 1, 0); -_p12_sig = new TQMultiLineEdit(tab); -tabGrid->addMultiCellWidget(_p12_sig, 1, 3, 1, 4); -_p12_sig->setReadOnly(true); - -_tabs->addTab(tab, i18n("Signature")); - - -// -// Make the third tab -// -tab = new TQFrame(_pkcsFrame); -tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), - KDialog::spacingHint() ); -tabGrid->addWidget(new TQLabel(i18n("Public key:"), tab), 0, 0); -_p12_pubkey = new TQMultiLineEdit(tab); -tabGrid->addMultiCellWidget(_p12_pubkey, 0, 3, 1, 4); -_p12_pubkey->setReadOnly(true); - - -_tabs->addTab(tab, i18n("Public Key")); - -_pkcsFrame->hide(); - -//------------------------------------------------------------------------ -// The X509 widget -//------------------------------------------------------------------------ -// Note: this is almost identical to the above, but I duplicate it for -// the simple reason that the above has potential to display much -// more information, and this one has potential to display different -// information. -_x509Frame = new TQFrame(_frame); - -grid = new TQGridLayout(_x509Frame, 12, 6, KDialog::marginHint(), - KDialog::spacingHint() ); -grid->addMultiCellWidget(new TQLabel(i18n("TDE Secure Certificate Import"), _x509Frame), 0, 0, 0, 5); - -grid->addWidget(new TQLabel(i18n("Subject:"), _x509Frame), 1, 0); -grid->addWidget(new TQLabel(i18n("Issued by:"), _x509Frame), 1, 3); -_ca_subject = KSSLInfoDlg::certInfoWidget(_x509Frame, TQString("")); -_ca_issuer = KSSLInfoDlg::certInfoWidget(_x509Frame, TQString("")); -grid->addMultiCellWidget(_ca_subject, 2, 5, 0, 2); -grid->addMultiCellWidget(_ca_issuer, 2, 5, 3, 5); - -grid->addWidget(new TQLabel(i18n("File:"), _x509Frame), 6, 0); -_ca_filenameLabel = new TQLabel("", _x509Frame); -grid->addWidget(_ca_filenameLabel, 6, 1); -grid->addWidget(new TQLabel(i18n("File format:"), _x509Frame), 6, 3); -grid->addWidget(new TQLabel("PEM or DER Encoded X.509", _x509Frame), 6, 4); - - -// -// Make the first tab -// -_tabs = new TQTabWidget(_x509Frame); -grid->addMultiCellWidget(_tabs, 7, 11, 0, 5); - -tab = new TQFrame(_x509Frame); -tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), - KDialog::spacingHint() ); -tabGrid->addWidget(new TQLabel(i18n("State:"), tab), 0, 0); -_ca_certState = new TQLabel("", tab); -tabGrid->addMultiCellWidget(_ca_certState, 0, 0, 1, 4); - -tabGrid->addWidget(new TQLabel(i18n("Valid from:"), tab), 1, 0); -_ca_validFrom = new TQLabel("", tab); -tabGrid->addMultiCellWidget(_ca_validFrom, 1, 1, 1, 4); - -tabGrid->addWidget(new TQLabel(i18n("Valid until:"), tab), 2, 0); -_ca_validUntil = new TQLabel("", tab); -tabGrid->addMultiCellWidget(_ca_validUntil, 2, 2, 1, 4); - -tabGrid->addWidget(new TQLabel(i18n("Serial number:"), tab), 3, 0); -_ca_serialNum = new TQLabel("", tab); -tabGrid->addWidget(_ca_serialNum, 3, 1); -_tabs->addTab(tab, i18n("State")); - - -// -// Make the second tab -// -tab = new TQFrame(_x509Frame); -tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), - KDialog::spacingHint() ); -tabGrid->addWidget(new TQLabel(i18n("MD5 digest:"), tab), 0, 0); -_ca_digest = new TQLabel(tab); -tabGrid->addMultiCellWidget(_ca_digest, 0, 0, 1, 4); -tabGrid->addWidget(new TQLabel(i18n("Signature:"), tab), 1, 0); -_ca_sig = new TQMultiLineEdit(tab); -tabGrid->addMultiCellWidget(_ca_sig, 1, 3, 1, 4); -_ca_sig->setReadOnly(true); - -_tabs->addTab(tab, i18n("Signature")); - - -// -// Make the third tab -// -tab = new TQFrame(_x509Frame); -tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), - KDialog::spacingHint() ); -tabGrid->addWidget(new TQLabel(i18n("Public key:"), tab), 0, 0); -_ca_pubkey = new TQMultiLineEdit(tab); -tabGrid->addMultiCellWidget(_ca_pubkey, 0, 3, 1, 4); -_ca_pubkey->setReadOnly(true); - - -_tabs->addTab(tab, i18n("Public Key")); - -_x509Frame->hide(); - - - - -//------------------------------------------------------------------------ -// The blank widget -//------------------------------------------------------------------------ -_blankFrame = new TQFrame(_frame); -grid = new TQGridLayout(_blankFrame, 1, 1, KDialog::marginHint(), - KDialog::spacingHint() ); -grid->addMultiCellWidget(new TQLabel(i18n("TDE Secure Certificate Import"), _blankFrame), 0, 0, 0, 0); -_blankFrame->show(); - - - -// -// Finish it off -// -_baseGrid->addMultiCellWidget(new KSeparator(KSeparator::HLine, _frame), 13, 13, 2, 8); -_launch = new TQPushButton(i18n("&Crypto Manager..."), _frame); -_import = new TQPushButton(i18n("&Import"), _frame); -_save = new TQPushButton(i18n("&Save..."), _frame); -_done = new TQPushButton(i18n("&Done"), _frame); -_baseGrid->addMultiCellWidget(_launch, 14, 14, 4, 5); -_baseGrid->addWidget(_import, 14, 6); -_baseGrid->addWidget(_save, 14, 7); -_baseGrid->addWidget(_done, 14, 8); -connect(_launch, TQT_SIGNAL(clicked()), TQT_SLOT(slotLaunch())); -connect(_import, TQT_SIGNAL(clicked()), TQT_SLOT(slotImport())); -connect(_save, TQT_SIGNAL(clicked()), TQT_SLOT(slotSave())); -connect(_done, TQT_SIGNAL(clicked()), TQT_SLOT(slotDone())); -_import->setEnabled(false); -_save->setEnabled(false); - - - -_baseGrid->addMultiCellWidget(_pkcsFrame, 0, 12, 2, 8); -_baseGrid->addMultiCellWidget(_x509Frame, 0, 12, 2, 8); -_baseGrid->addMultiCellWidget(_blankFrame, 0, 12, 2, 8); - -connect(_sideList, TQT_SIGNAL(selectionChanged(TQListViewItem*)), - this, TQT_SLOT(slotSelectionChanged(TQListViewItem*))); -setReadWrite(true); -} - - -KCertPart::~KCertPart() { - delete _signers; - delete d->browserExtension; - delete d; -} - - -void KCertPart::setReadWrite(bool rw) { - if (!rw) { - _import->setEnabled(false); - _save->setEnabled(false); - } - KParts::ReadWritePart::setReadWrite(rw); -} - - -bool KCertPart::saveFile() { -if (_p12) { - TQString certFile = KFileDialog::getSaveFileName(TQString::null, "application/x-pkcs12"); - if (certFile.isEmpty()) - return false; - - if (!_p12->toFile(certFile)) { - KMessageBox::sorry(_frame, i18n("Save failed."), i18n("Certificate Import")); - return false; - } - - return true; -} else if (_ca) { - TQString certFile = KFileDialog::getSaveFileName(TQString::null, "application/x-x509-ca-cert"); - if (certFile.isEmpty()) - return false; - - TQByteArray enc; - if (certFile.endsWith("der") || certFile.endsWith("crt")) { - enc = _ca->toDer(); - } else if (certFile.endsWith("netscape")) { - enc = _ca->toNetscape(); - } else { - enc = _ca->toPem(); - } - - TQFile of(certFile); - - if (!of.open(IO_WriteOnly) || (unsigned)of.writeBlock(enc) != enc.size()) { - KMessageBox::sorry(_frame, i18n("Save failed."), i18n("Certificate Import")); - return false; - } - - of.flush(); - - return true; -} else { - return false; -} -} - - -bool KCertPart::openFile() { -#ifndef HAVE_SSL - KMessageBox::sorry(_frame, i18n("You do not seem to have compiled TDE with SSL support."), i18n("Certificate Import")); - return false; -#else - -if (TQFileInfo(m_file).size() == 0) { - KMessageBox::sorry(_frame, i18n("Certificate file is empty."), i18n("Certificate Import")); - return false; -} - -TQString whatType = d->browserExtension->urlArgs().serviceType; -//whatType = KMimeType::findByURL(m_url,0,true)->name(); -if (whatType.isEmpty()) - whatType = KServiceTypeFactory::self()->findFromPattern(m_file)->name(); - -/* - TQString blah = "file: " + m_file - + "\nurl: " + m_url.url() - + "\nserviceType: " + d->browserExtension->urlArgs().serviceType - + "\nfactory: " + KServiceTypeFactory::self()->findFromPattern(m_file)->name() - + "\nmimeType: " + KMimeType::findByURL(m_url)->name(); - KMessageBox::information(_frame, blah, "ssl"); - */ - - -emit completed(); - -///////////////////////////////////////////////////////////////////////////// -// x-pkcs12 loading -///////////////////////////////////////////////////////////////////////////// -if (whatType == "application/x-pkcs12") { - TQString pass; - _p12 = KSSLPKCS12::loadCertFile(m_file); - - while (!_p12) { - // try prompting for a password. - int rc = KPasswordDialog::getPassword(pass, i18n("Certificate Password")); - if (rc != KPasswordDialog::Accepted) break; - - _p12 = KSSLPKCS12::loadCertFile(m_file, pass); - - if (!_p12) { - rc = KMessageBox::warningContinueCancel(_frame, i18n("The certificate file could not be loaded. Try a different password?"), i18n("Certificate Import"),i18n("Try Different")); - if (rc == KMessageBox::Continue) continue; - break; - } - } - - if (!_p12) return false; - - new KPKCS12Item(_parentP12, _p12); - _p12 = NULL; - return true; - ///////////////////////////////////////////////////////////////////////////// - // x-509-ca-cert loading - ///////////////////////////////////////////////////////////////////////////// -} else if (whatType == "application/x-x509-ca-cert" || - whatType == "application/binary-certificate") { - FILE *fp; - bool isPEM = false; - - _ca_filenameLabel->setText(m_file); - - ///////////// UGLY HACK TO GET AROUND OPENSSL PROBLEMS /////////// - if (whatType == "application/x-x509-ca-cert") { - // Check if it is PEM or not - TQFile qf(m_file); - qf.open(IO_ReadOnly); - TQByteArray theFile = qf.readAll(); - qf.close(); - - const char *signature = "-----BEGIN CERTIFICATE-----"; - theFile[(uint)(qf.size()-1)] = 0; - isPEM = (TQCString(theFile.data()).find(signature) >= 0); - } - - fp = fopen(m_file.local8Bit(), "r"); - if (!fp) { - KMessageBox::sorry(_frame, i18n("This file cannot be opened."), i18n("Certificate Import")); - return false; - } - - /* - kdDebug() << "Reading in a file in " - << (isPEM ? "PEM" : "DER") - << " format." << endl; - */ - - if (!isPEM) { - X509 *dx = KOSSL::self()->X509_d2i_fp(fp, NULL); - - if (dx) { - KSSLCertificate *xc = KSSLCertificate::fromX509(dx); - if (xc) { - if (xc->x509V3Extensions().certTypeCA()) - new KX509Item(_parentCA, xc); - else - new KX509Item(_sideList, xc); - fclose(fp); - return true; - } - KOSSL::self()->X509_free(dx); - } - return false; - } - - STACK_OF(X509_INFO) *sx5i = KOSSL::self()->PEM_X509_INFO_read(fp, NULL, KSSLPemCallback, NULL); - - if (!sx5i) { - KMessageBox::sorry(_frame, i18n("This file cannot be opened."), i18n("Certificate Import")); - fclose(fp); - return false; - } - - _ca_filenameLabel->setText(m_file); - for (int i = 0; i < KOSSL::self()->OPENSSL_sk_num(sx5i); i++) { - X509_INFO* x5i = reinterpret_cast(KOSSL::self()->OPENSSL_sk_value(sx5i, i)); - if (x5i->x_pkey && x5i->x509) { // a personal cert (like PKCS12) - KSSLCertificate *xc = KSSLCertificate::fromX509(x5i->x509); - new KX509Item(_sideList, xc); - } else if (x5i->x509) { // something else - maybe a CA file - KSSLCertificate *xc = KSSLCertificate::fromX509(x5i->x509); - if (xc->x509V3Extensions().certTypeCA()) - new KX509Item(_parentCA, xc); - else new KX509Item(_sideList, xc); - } else if (x5i->crl) { // a crl - kdDebug() << "Found a CRL..." << endl; - } - } - - KOSSL::self()->OPENSSL_sk_free(sx5i); - - fclose(fp); - return true; - ///////////////////////////////////////////////////////////////////////////// - // Dunno how to load this - ///////////////////////////////////////////////////////////////////////////// -} else { - TQString emsg = i18n("I do not know how to handle this type of file.") + "\n" + whatType; - KMessageBox::sorry(_frame, emsg, i18n("Certificate Import")); - return false; -} -#endif -} - - -void KCertPart::displayPKCS12() { - KSSLCertificate *xc = _p12->getCertificate(); - _p12_filenameLabel->setText(m_file); - displayPKCS12Cert(xc); - _p12_certState->setText(KSSLCertificate::verifyText(_p12->validate())); - - // Set the chain if it's there - if (xc->chain().depth() > 1) { - TQPtrList cl = xc->chain().getChain(); - int cnt = 0; - _p12_chain->setEnabled(true); - _p12_chain->clear(); - _p12_chain->insertItem(i18n("0 - Site Certificate")); - for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { - KSSLX509Map map(c->getSubject()); - _p12_chain->insertItem(TQString::number(++cnt)+" - "+map.getValue("CN")); - } - _p12_chain->setCurrentItem(0); - } else { - _p12_chain->clear(); - _p12_chain->setEnabled(false); - } -} - - -void KCertPart::displayCACert(KSSLCertificate *c) { - // We have the file, lets work with it. - _ca_subject->setValues(c->getSubject()); - _ca_issuer->setValues(c->getIssuer()); - - // Set the valid period - TQPalette cspl = _ca_validFrom->palette(); - if (TQDateTime::currentDateTime(Qt::UTC) < c->getQDTNotBefore()) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } else { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } - _ca_validFrom->setPalette(cspl); - _ca_validFrom->setText(c->getNotBefore()); - - cspl = _ca_validUntil->palette(); - if (TQDateTime::currentDateTime(Qt::UTC) > c->getQDTNotAfter()) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } else { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } - _ca_validUntil->setPalette(cspl); - _ca_validUntil->setText(c->getNotAfter()); - - _ca_serialNum->setText(c->getSerialNumber()); - cspl = _ca_certState->palette(); - if (!c->isValid()) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } else { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } - _ca_certState->setPalette(cspl); - _ca_certState->setText(KSSLCertificate::verifyText(c->validate())); - - _ca_pubkey->setText(c->getPublicKeyText()); - _ca_digest->setText(c->getMD5DigestText()); - _ca_sig->setText(c->getSignatureText()); -} - - - -void KCertPart::displayPKCS12Cert(KSSLCertificate *c) { - // We have the file, lets work with it. - _p12_subject->setValues(c->getSubject()); - _p12_issuer->setValues(c->getIssuer()); - - // Set the valid period - TQPalette cspl = _p12_validFrom->palette(); - if (TQDateTime::currentDateTime(Qt::UTC) < c->getQDTNotBefore()) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } else { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } - _p12_validFrom->setPalette(cspl); - _p12_validFrom->setText(c->getNotBefore()); - - cspl = _p12_validUntil->palette(); - if (TQDateTime::currentDateTime(Qt::UTC) > c->getQDTNotAfter()) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } else { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } - _p12_validUntil->setPalette(cspl); - _p12_validUntil->setText(c->getNotAfter()); - - _p12_serialNum->setText(c->getSerialNumber()); - cspl = _p12_certState->palette(); - if (!c->isValid()) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } else { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } - _p12_certState->setPalette(cspl); - _p12_certState->setText(KSSLCertificate::verifyText(c->validate())); - - _p12_pubkey->setText(c->getPublicKeyText()); - _p12_digest->setText(c->getMD5DigestText()); - _p12_sig->setText(c->getSignatureText()); -} - - - -void KCertPart::slotChain(int c) { - if (c == 0) { - displayPKCS12Cert(_p12->getCertificate()); - _p12_certState->setText(KSSLCertificate::verifyText(_p12->validate())); - } else { - displayPKCS12Cert(_p12->getCertificate()->chain().getChain().at(c-1)); - } -} - - -void KCertPart::slotImport() { - if (_p12) { - KSimpleConfig cfg("ksslcertificates", false); - - if (cfg.hasGroup(_p12->getCertificate()->getSubject())) { - TQString msg = _curName + "\n" + i18n("A certificate with that name already exists. Are you sure that you wish to replace it?"); - int rc= KMessageBox::warningContinueCancel(_frame, msg, i18n("Certificate Import"),i18n("Replace")); - if (rc == KMessageBox::Cancel) { - return; - } - } - - cfg.setGroup(_p12->getCertificate()->getSubject()); - cfg.writeEntry("PKCS12Base64", _p12->toString()); - cfg.writeEntry("Password", ""); - cfg.sync(); - if (!_silentImport) - KMessageBox::information(_frame, i18n("Certificate has been successfully imported into TDE.\nYou can manage your certificate settings from the Trinity Control Center."), i18n("Certificate Import")); - } else if (_ca) { - TDEConfig cfg("ksslcalist", true, false); - if (cfg.hasGroup(_ca->getSubject())) { - TQString msg = _curName + "\n" + i18n("A certificate with that name already exists. Are you sure that you wish to replace it?"); - int rc= KMessageBox::warningContinueCancel(_frame, msg, i18n("Certificate Import"),i18n("Replace")); - if (rc == KMessageBox::Cancel) { - return; - } - } - _signers->addCA(_ca->toString(), - _ca->x509V3Extensions().certTypeSSLCA(), - _ca->x509V3Extensions().certTypeEmailCA(), - _ca->x509V3Extensions().certTypeCodeCA()); - if (!_silentImport) - _signers->regenerate(); - - if (!_silentImport) - KMessageBox::information(_frame, i18n("Certificate has been successfully imported into TDE.\nYou can manage your certificate settings from the Trinity Control Center."), i18n("Certificate Import")); - } -} - - -void KCertPart::slotSave() { - saveFile(); -} - - -void KCertPart::slotDone() { - KParts::BrowserInterface *iface = d->browserExtension->browserInterface(); - iface->callMethod("goHistory(int)", -1); -} - - -void KCertPart::slotLaunch() { -KShellProcess p; -p << "tdecmshell" << "crypto"; -p.start(TDEProcess::DontCare); -} - - -void KCertPart::slotSelectionChanged(TQListViewItem *x) { - KX509Item *x5i = dynamic_cast(x); - KPKCS12Item *p12i = dynamic_cast(x); - _p12 = NULL; - _ca = NULL; - if (x && x->parent() == _parentCA) { - if (!x5i) { - return; - } - x5i->cert->revalidate(); - _blankFrame->hide(); - _pkcsFrame->hide(); - _x509Frame->show(); - _ca = x5i->cert; - _import->setEnabled(true); - _save->setEnabled(true); - _curName = x5i->_prettyName; - displayCACert(_ca); - } else if (x && x->parent() == NULL && x->rtti() == 1) { - if (!x5i) { - return; - } - x5i->cert->revalidate(); - _blankFrame->hide(); - _pkcsFrame->hide(); - _x509Frame->show(); - _ca = x5i->cert; - _import->setEnabled(false); - _save->setEnabled(false); - _curName = x5i->_prettyName; - displayCACert(_ca); - } else if (x && x->parent() == _parentP12) { - if (!p12i) { - return; - } - p12i->cert->revalidate(); - _blankFrame->hide(); - _x509Frame->hide(); - _pkcsFrame->show(); - _p12 = p12i->cert; - _import->setEnabled(true); - _save->setEnabled(true); - _curName = p12i->_prettyName; - displayPKCS12(); - } else { - _pkcsFrame->hide(); - _x509Frame->hide(); - _blankFrame->show(); - _import->setEnabled(false); - _save->setEnabled(false); - _curName = ""; - } -} - - -void KCertPart::slotImportAll() { -KSSLPKCS12 *p12Save = _p12; -KSSLCertificate *caSave = _ca; -TQString curNameSave = _curName; - -_p12 = NULL; -_ca = NULL; -_silentImport = true; - -for (KPKCS12Item *t = dynamic_cast(_parentP12->firstChild()); - t; - t = dynamic_cast(t->nextSibling())) { - if (t) { - _p12 = t->cert; - _curName = t->_prettyName; - } - slotImport(); -} -_p12 = NULL; - -for (KX509Item *t = dynamic_cast(_parentCA->firstChild()); - t; - t = dynamic_cast(t->nextSibling())) { - if (t) { - _ca = t->cert; - _curName = t->_prettyName; - } - slotImport(); -} -_ca = NULL; - -_signers->regenerate(); -_silentImport = false; -_p12 = p12Save; -_ca = caSave; -_curName = curNameSave; -KMessageBox::information(_frame, i18n("Certificates have been successfully imported into TDE.\nYou can manage your certificate settings from the Trinity Control Center."), i18n("Certificate Import")); -} - - -TDEAboutData *KCertPart::createAboutData() -{ - return new TDEAboutData("KCertPart", I18N_NOOP("TDE Certificate Part"), "1.0"); -} - -#include "tdecertpart.moc" - diff --git a/tdecert/tdecertpart.cpp b/tdecert/tdecertpart.cpp new file mode 100644 index 000000000..02afc9b75 --- /dev/null +++ b/tdecert/tdecertpart.cpp @@ -0,0 +1,876 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001-2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include "tdecertpart.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +K_EXPORT_COMPONENT_FACTORY( libtdecertpart, KParts::GenericFactory ) + + +KX509Item::KX509Item(TDEListViewItem *parent, KSSLCertificate *x) : + TDEListViewItem(parent, 0L) +{ + setup(x); +} + +KX509Item::KX509Item(TDEListView *parent, KSSLCertificate *x) : + TDEListViewItem(parent) +{ + setup(x); +} + +void KX509Item::setup(KSSLCertificate *x) { + cert = x; + if (x) { + KSSLX509Map xm(x->getSubject()); + TQString OU = "OU"; + TQString CN = "CN"; + OU = xm.getValue(OU); + CN = xm.getValue(CN); + OU.replace(TQRegExp("\n.*"), ""); + CN.replace(TQRegExp("\n.*"), ""); + + if (OU.length() > 0) { + _prettyName = OU; + } + + if (CN.length() > 0) { + if (_prettyName.length() > 0) { + _prettyName += " - "; + } + _prettyName += CN; + } + setText(0, _prettyName); + } else { + setText(0, i18n("Invalid certificate!")); + } +} + + +KX509Item::~KX509Item() +{ + delete cert; +} + + +KPKCS12Item::KPKCS12Item(TDEListViewItem *parent, KSSLPKCS12 *x) : + TDEListViewItem(parent, 0L) +{ + cert = x; + if (x) { + KSSLX509Map xm(x->getCertificate()->getSubject()); + TQString CN = "CN"; + CN = xm.getValue(CN); + CN.replace(TQRegExp("\n.*"), ""); + _prettyName = CN; + setText(0, _prettyName); + } else { + setText(0, i18n("Invalid certificate!")); + } +} + + +KPKCS12Item::~KPKCS12Item() +{ + delete cert; +} + + +class KCertPartPrivate { + public: + KParts::BrowserExtension *browserExtension; +}; + + +KCertPart::KCertPart(TQWidget *parentWidget, const char *widgetName, + TQObject *parent, const char *name, + const TQStringList & /*args*/ ) + : KParts::ReadWritePart(parent, name) { +TDEInstance *instance = new TDEInstance("KCertPart"); +TQGridLayout *grid; +setInstance(instance); + + +_signers = new KSSLSigners; +// This is a bit confusing now. Here's how it works: +// We create a _frame and split it left/right +// Then we add the ListView to the left and create +// a new frame on the right. We set the main widget +// on the right. + +_p12 = NULL; +_ca = NULL; +_silentImport = false; +d = new KCertPartPrivate; +d->browserExtension = new KParts::BrowserExtension(this); + +_frame = new TQFrame(parentWidget, widgetName); +setWidget(_frame); + +_baseGrid = new TQGridLayout(_frame, 15, 9, KDialog::marginHint(), + KDialog::spacingHint()); + +_sideList = new TDEListView(_frame); +_sideList->setRootIsDecorated(true); +_sideList->addColumn(i18n("Certificates")); +_parentCA = new TDEListViewItem(_sideList, i18n("Signers")); +_parentCA->setExpandable(true); +_sideList->setOpen(_parentCA, true); +_parentP12 = new TDEListViewItem(_sideList, i18n("Client")); +_parentP12->setExpandable(true); +_sideList->setOpen(_parentP12, true); + +_baseGrid->addMultiCellWidget(_sideList, 0, 13, 0, 1); + +_importAll = new TQPushButton(i18n("Import &All"), _frame); +_baseGrid->addMultiCellWidget(_importAll, 14, 14, 0, 1); +connect(_importAll, TQT_SIGNAL(clicked()), TQT_SLOT(slotImportAll())); + + + +//------------------------------------------------------------------------ +// The PKCS widget +//------------------------------------------------------------------------ +_pkcsFrame = new TQFrame(_frame); + +grid = new TQGridLayout(_pkcsFrame, 13, 6, KDialog::marginHint(), + KDialog::spacingHint() ); +grid->addMultiCellWidget(new TQLabel(i18n("TDE Secure Certificate Import"), _pkcsFrame), 0, 0, 0, 5); +grid->addWidget(new TQLabel(i18n("Chain:"), _pkcsFrame), 1, 0); +_p12_chain = new KComboBox(_pkcsFrame); +grid->addMultiCellWidget(_p12_chain, 1, 1, 1, 4); +connect(_p12_chain, TQT_SIGNAL(activated(int)), TQT_SLOT(slotChain(int))); + +grid->addWidget(new TQLabel(i18n("Subject:"), _pkcsFrame), 2, 0); +grid->addWidget(new TQLabel(i18n("Issued by:"), _pkcsFrame), 2, 3); +_p12_subject = KSSLInfoDlg::certInfoWidget(_pkcsFrame, TQString("")); +_p12_issuer = KSSLInfoDlg::certInfoWidget(_pkcsFrame, TQString("")); +grid->addMultiCellWidget(_p12_subject, 3, 6, 0, 2); +grid->addMultiCellWidget(_p12_issuer, 3, 6, 3, 5); + +grid->addWidget(new TQLabel(i18n("File:"), _pkcsFrame), 7, 0); +_p12_filenameLabel = new TQLabel("", _pkcsFrame); +grid->addWidget(_p12_filenameLabel, 7, 1); +grid->addWidget(new TQLabel(i18n("File format:"), _pkcsFrame), 7, 3); +grid->addWidget(new TQLabel("PKCS#12", _pkcsFrame), 7, 4); + + +// +// Make the first tab +// +_tabs = new TQTabWidget(_pkcsFrame); +grid->addMultiCellWidget(_tabs, 8, 12, 0, 5); + +TQFrame *tab = new TQFrame(_pkcsFrame); +TQGridLayout *tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), + KDialog::spacingHint() ); +tabGrid->addWidget(new TQLabel(i18n("State:"), tab), 0, 0); +_p12_certState = new TQLabel("", tab); +tabGrid->addMultiCellWidget(_p12_certState, 0, 0, 1, 4); + +tabGrid->addWidget(new TQLabel(i18n("Valid from:"), tab), 1, 0); +_p12_validFrom = new TQLabel("", tab); +tabGrid->addMultiCellWidget(_p12_validFrom, 1, 1, 1, 4); + +tabGrid->addWidget(new TQLabel(i18n("Valid until:"), tab), 2, 0); +_p12_validUntil = new TQLabel("", tab); +tabGrid->addMultiCellWidget(_p12_validUntil, 2, 2, 1, 4); + +tabGrid->addWidget(new TQLabel(i18n("Serial number:"), tab), 3, 0); +_p12_serialNum = new TQLabel("", tab); +tabGrid->addWidget(_p12_serialNum, 3, 1); +_tabs->addTab(tab, i18n("State")); + + +// +// Make the second tab +// +tab = new TQFrame(_pkcsFrame); +tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), + KDialog::spacingHint() ); +tabGrid->addWidget(new TQLabel(i18n("MD5 digest:"), tab), 0, 0); +_p12_digest = new TQLabel(tab); +tabGrid->addMultiCellWidget(_p12_digest, 0, 0, 1, 4); +tabGrid->addWidget(new TQLabel(i18n("Signature:"), tab), 1, 0); +_p12_sig = new TQMultiLineEdit(tab); +tabGrid->addMultiCellWidget(_p12_sig, 1, 3, 1, 4); +_p12_sig->setReadOnly(true); + +_tabs->addTab(tab, i18n("Signature")); + + +// +// Make the third tab +// +tab = new TQFrame(_pkcsFrame); +tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), + KDialog::spacingHint() ); +tabGrid->addWidget(new TQLabel(i18n("Public key:"), tab), 0, 0); +_p12_pubkey = new TQMultiLineEdit(tab); +tabGrid->addMultiCellWidget(_p12_pubkey, 0, 3, 1, 4); +_p12_pubkey->setReadOnly(true); + + +_tabs->addTab(tab, i18n("Public Key")); + +_pkcsFrame->hide(); + +//------------------------------------------------------------------------ +// The X509 widget +//------------------------------------------------------------------------ +// Note: this is almost identical to the above, but I duplicate it for +// the simple reason that the above has potential to display much +// more information, and this one has potential to display different +// information. +_x509Frame = new TQFrame(_frame); + +grid = new TQGridLayout(_x509Frame, 12, 6, KDialog::marginHint(), + KDialog::spacingHint() ); +grid->addMultiCellWidget(new TQLabel(i18n("TDE Secure Certificate Import"), _x509Frame), 0, 0, 0, 5); + +grid->addWidget(new TQLabel(i18n("Subject:"), _x509Frame), 1, 0); +grid->addWidget(new TQLabel(i18n("Issued by:"), _x509Frame), 1, 3); +_ca_subject = KSSLInfoDlg::certInfoWidget(_x509Frame, TQString("")); +_ca_issuer = KSSLInfoDlg::certInfoWidget(_x509Frame, TQString("")); +grid->addMultiCellWidget(_ca_subject, 2, 5, 0, 2); +grid->addMultiCellWidget(_ca_issuer, 2, 5, 3, 5); + +grid->addWidget(new TQLabel(i18n("File:"), _x509Frame), 6, 0); +_ca_filenameLabel = new TQLabel("", _x509Frame); +grid->addWidget(_ca_filenameLabel, 6, 1); +grid->addWidget(new TQLabel(i18n("File format:"), _x509Frame), 6, 3); +grid->addWidget(new TQLabel("PEM or DER Encoded X.509", _x509Frame), 6, 4); + + +// +// Make the first tab +// +_tabs = new TQTabWidget(_x509Frame); +grid->addMultiCellWidget(_tabs, 7, 11, 0, 5); + +tab = new TQFrame(_x509Frame); +tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), + KDialog::spacingHint() ); +tabGrid->addWidget(new TQLabel(i18n("State:"), tab), 0, 0); +_ca_certState = new TQLabel("", tab); +tabGrid->addMultiCellWidget(_ca_certState, 0, 0, 1, 4); + +tabGrid->addWidget(new TQLabel(i18n("Valid from:"), tab), 1, 0); +_ca_validFrom = new TQLabel("", tab); +tabGrid->addMultiCellWidget(_ca_validFrom, 1, 1, 1, 4); + +tabGrid->addWidget(new TQLabel(i18n("Valid until:"), tab), 2, 0); +_ca_validUntil = new TQLabel("", tab); +tabGrid->addMultiCellWidget(_ca_validUntil, 2, 2, 1, 4); + +tabGrid->addWidget(new TQLabel(i18n("Serial number:"), tab), 3, 0); +_ca_serialNum = new TQLabel("", tab); +tabGrid->addWidget(_ca_serialNum, 3, 1); +_tabs->addTab(tab, i18n("State")); + + +// +// Make the second tab +// +tab = new TQFrame(_x509Frame); +tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), + KDialog::spacingHint() ); +tabGrid->addWidget(new TQLabel(i18n("MD5 digest:"), tab), 0, 0); +_ca_digest = new TQLabel(tab); +tabGrid->addMultiCellWidget(_ca_digest, 0, 0, 1, 4); +tabGrid->addWidget(new TQLabel(i18n("Signature:"), tab), 1, 0); +_ca_sig = new TQMultiLineEdit(tab); +tabGrid->addMultiCellWidget(_ca_sig, 1, 3, 1, 4); +_ca_sig->setReadOnly(true); + +_tabs->addTab(tab, i18n("Signature")); + + +// +// Make the third tab +// +tab = new TQFrame(_x509Frame); +tabGrid = new TQGridLayout(tab, 4, 5, KDialog::marginHint(), + KDialog::spacingHint() ); +tabGrid->addWidget(new TQLabel(i18n("Public key:"), tab), 0, 0); +_ca_pubkey = new TQMultiLineEdit(tab); +tabGrid->addMultiCellWidget(_ca_pubkey, 0, 3, 1, 4); +_ca_pubkey->setReadOnly(true); + + +_tabs->addTab(tab, i18n("Public Key")); + +_x509Frame->hide(); + + + + +//------------------------------------------------------------------------ +// The blank widget +//------------------------------------------------------------------------ +_blankFrame = new TQFrame(_frame); +grid = new TQGridLayout(_blankFrame, 1, 1, KDialog::marginHint(), + KDialog::spacingHint() ); +grid->addMultiCellWidget(new TQLabel(i18n("TDE Secure Certificate Import"), _blankFrame), 0, 0, 0, 0); +_blankFrame->show(); + + + +// +// Finish it off +// +_baseGrid->addMultiCellWidget(new KSeparator(KSeparator::HLine, _frame), 13, 13, 2, 8); +_launch = new TQPushButton(i18n("&Crypto Manager..."), _frame); +_import = new TQPushButton(i18n("&Import"), _frame); +_save = new TQPushButton(i18n("&Save..."), _frame); +_done = new TQPushButton(i18n("&Done"), _frame); +_baseGrid->addMultiCellWidget(_launch, 14, 14, 4, 5); +_baseGrid->addWidget(_import, 14, 6); +_baseGrid->addWidget(_save, 14, 7); +_baseGrid->addWidget(_done, 14, 8); +connect(_launch, TQT_SIGNAL(clicked()), TQT_SLOT(slotLaunch())); +connect(_import, TQT_SIGNAL(clicked()), TQT_SLOT(slotImport())); +connect(_save, TQT_SIGNAL(clicked()), TQT_SLOT(slotSave())); +connect(_done, TQT_SIGNAL(clicked()), TQT_SLOT(slotDone())); +_import->setEnabled(false); +_save->setEnabled(false); + + + +_baseGrid->addMultiCellWidget(_pkcsFrame, 0, 12, 2, 8); +_baseGrid->addMultiCellWidget(_x509Frame, 0, 12, 2, 8); +_baseGrid->addMultiCellWidget(_blankFrame, 0, 12, 2, 8); + +connect(_sideList, TQT_SIGNAL(selectionChanged(TQListViewItem*)), + this, TQT_SLOT(slotSelectionChanged(TQListViewItem*))); +setReadWrite(true); +} + + +KCertPart::~KCertPart() { + delete _signers; + delete d->browserExtension; + delete d; +} + + +void KCertPart::setReadWrite(bool rw) { + if (!rw) { + _import->setEnabled(false); + _save->setEnabled(false); + } + KParts::ReadWritePart::setReadWrite(rw); +} + + +bool KCertPart::saveFile() { +if (_p12) { + TQString certFile = KFileDialog::getSaveFileName(TQString::null, "application/x-pkcs12"); + if (certFile.isEmpty()) + return false; + + if (!_p12->toFile(certFile)) { + KMessageBox::sorry(_frame, i18n("Save failed."), i18n("Certificate Import")); + return false; + } + + return true; +} else if (_ca) { + TQString certFile = KFileDialog::getSaveFileName(TQString::null, "application/x-x509-ca-cert"); + if (certFile.isEmpty()) + return false; + + TQByteArray enc; + if (certFile.endsWith("der") || certFile.endsWith("crt")) { + enc = _ca->toDer(); + } else if (certFile.endsWith("netscape")) { + enc = _ca->toNetscape(); + } else { + enc = _ca->toPem(); + } + + TQFile of(certFile); + + if (!of.open(IO_WriteOnly) || (unsigned)of.writeBlock(enc) != enc.size()) { + KMessageBox::sorry(_frame, i18n("Save failed."), i18n("Certificate Import")); + return false; + } + + of.flush(); + + return true; +} else { + return false; +} +} + + +bool KCertPart::openFile() { +#ifndef HAVE_SSL + KMessageBox::sorry(_frame, i18n("You do not seem to have compiled TDE with SSL support."), i18n("Certificate Import")); + return false; +#else + +if (TQFileInfo(m_file).size() == 0) { + KMessageBox::sorry(_frame, i18n("Certificate file is empty."), i18n("Certificate Import")); + return false; +} + +TQString whatType = d->browserExtension->urlArgs().serviceType; +//whatType = KMimeType::findByURL(m_url,0,true)->name(); +if (whatType.isEmpty()) + whatType = KServiceTypeFactory::self()->findFromPattern(m_file)->name(); + +/* + TQString blah = "file: " + m_file + + "\nurl: " + m_url.url() + + "\nserviceType: " + d->browserExtension->urlArgs().serviceType + + "\nfactory: " + KServiceTypeFactory::self()->findFromPattern(m_file)->name() + + "\nmimeType: " + KMimeType::findByURL(m_url)->name(); + KMessageBox::information(_frame, blah, "ssl"); + */ + + +emit completed(); + +///////////////////////////////////////////////////////////////////////////// +// x-pkcs12 loading +///////////////////////////////////////////////////////////////////////////// +if (whatType == "application/x-pkcs12") { + TQString pass; + _p12 = KSSLPKCS12::loadCertFile(m_file); + + while (!_p12) { + // try prompting for a password. + int rc = KPasswordDialog::getPassword(pass, i18n("Certificate Password")); + if (rc != KPasswordDialog::Accepted) break; + + _p12 = KSSLPKCS12::loadCertFile(m_file, pass); + + if (!_p12) { + rc = KMessageBox::warningContinueCancel(_frame, i18n("The certificate file could not be loaded. Try a different password?"), i18n("Certificate Import"),i18n("Try Different")); + if (rc == KMessageBox::Continue) continue; + break; + } + } + + if (!_p12) return false; + + new KPKCS12Item(_parentP12, _p12); + _p12 = NULL; + return true; + ///////////////////////////////////////////////////////////////////////////// + // x-509-ca-cert loading + ///////////////////////////////////////////////////////////////////////////// +} else if (whatType == "application/x-x509-ca-cert" || + whatType == "application/binary-certificate") { + FILE *fp; + bool isPEM = false; + + _ca_filenameLabel->setText(m_file); + + ///////////// UGLY HACK TO GET AROUND OPENSSL PROBLEMS /////////// + if (whatType == "application/x-x509-ca-cert") { + // Check if it is PEM or not + TQFile qf(m_file); + qf.open(IO_ReadOnly); + TQByteArray theFile = qf.readAll(); + qf.close(); + + const char *signature = "-----BEGIN CERTIFICATE-----"; + theFile[(uint)(qf.size()-1)] = 0; + isPEM = (TQCString(theFile.data()).find(signature) >= 0); + } + + fp = fopen(m_file.local8Bit(), "r"); + if (!fp) { + KMessageBox::sorry(_frame, i18n("This file cannot be opened."), i18n("Certificate Import")); + return false; + } + + /* + kdDebug() << "Reading in a file in " + << (isPEM ? "PEM" : "DER") + << " format." << endl; + */ + + if (!isPEM) { + X509 *dx = KOSSL::self()->X509_d2i_fp(fp, NULL); + + if (dx) { + KSSLCertificate *xc = KSSLCertificate::fromX509(dx); + if (xc) { + if (xc->x509V3Extensions().certTypeCA()) + new KX509Item(_parentCA, xc); + else + new KX509Item(_sideList, xc); + fclose(fp); + return true; + } + KOSSL::self()->X509_free(dx); + } + return false; + } + + STACK_OF(X509_INFO) *sx5i = KOSSL::self()->PEM_X509_INFO_read(fp, NULL, KSSLPemCallback, NULL); + + if (!sx5i) { + KMessageBox::sorry(_frame, i18n("This file cannot be opened."), i18n("Certificate Import")); + fclose(fp); + return false; + } + + _ca_filenameLabel->setText(m_file); + for (int i = 0; i < KOSSL::self()->OPENSSL_sk_num(sx5i); i++) { + X509_INFO* x5i = reinterpret_cast(KOSSL::self()->OPENSSL_sk_value(sx5i, i)); + if (x5i->x_pkey && x5i->x509) { // a personal cert (like PKCS12) + KSSLCertificate *xc = KSSLCertificate::fromX509(x5i->x509); + new KX509Item(_sideList, xc); + } else if (x5i->x509) { // something else - maybe a CA file + KSSLCertificate *xc = KSSLCertificate::fromX509(x5i->x509); + if (xc->x509V3Extensions().certTypeCA()) + new KX509Item(_parentCA, xc); + else new KX509Item(_sideList, xc); + } else if (x5i->crl) { // a crl + kdDebug() << "Found a CRL..." << endl; + } + } + + KOSSL::self()->OPENSSL_sk_free(sx5i); + + fclose(fp); + return true; + ///////////////////////////////////////////////////////////////////////////// + // Dunno how to load this + ///////////////////////////////////////////////////////////////////////////// +} else { + TQString emsg = i18n("I do not know how to handle this type of file.") + "\n" + whatType; + KMessageBox::sorry(_frame, emsg, i18n("Certificate Import")); + return false; +} +#endif +} + + +void KCertPart::displayPKCS12() { + KSSLCertificate *xc = _p12->getCertificate(); + _p12_filenameLabel->setText(m_file); + displayPKCS12Cert(xc); + _p12_certState->setText(KSSLCertificate::verifyText(_p12->validate())); + + // Set the chain if it's there + if (xc->chain().depth() > 1) { + TQPtrList cl = xc->chain().getChain(); + int cnt = 0; + _p12_chain->setEnabled(true); + _p12_chain->clear(); + _p12_chain->insertItem(i18n("0 - Site Certificate")); + for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { + KSSLX509Map map(c->getSubject()); + _p12_chain->insertItem(TQString::number(++cnt)+" - "+map.getValue("CN")); + } + _p12_chain->setCurrentItem(0); + } else { + _p12_chain->clear(); + _p12_chain->setEnabled(false); + } +} + + +void KCertPart::displayCACert(KSSLCertificate *c) { + // We have the file, lets work with it. + _ca_subject->setValues(c->getSubject()); + _ca_issuer->setValues(c->getIssuer()); + + // Set the valid period + TQPalette cspl = _ca_validFrom->palette(); + if (TQDateTime::currentDateTime(Qt::UTC) < c->getQDTNotBefore()) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } else { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } + _ca_validFrom->setPalette(cspl); + _ca_validFrom->setText(c->getNotBefore()); + + cspl = _ca_validUntil->palette(); + if (TQDateTime::currentDateTime(Qt::UTC) > c->getQDTNotAfter()) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } else { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } + _ca_validUntil->setPalette(cspl); + _ca_validUntil->setText(c->getNotAfter()); + + _ca_serialNum->setText(c->getSerialNumber()); + cspl = _ca_certState->palette(); + if (!c->isValid()) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } else { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } + _ca_certState->setPalette(cspl); + _ca_certState->setText(KSSLCertificate::verifyText(c->validate())); + + _ca_pubkey->setText(c->getPublicKeyText()); + _ca_digest->setText(c->getMD5DigestText()); + _ca_sig->setText(c->getSignatureText()); +} + + + +void KCertPart::displayPKCS12Cert(KSSLCertificate *c) { + // We have the file, lets work with it. + _p12_subject->setValues(c->getSubject()); + _p12_issuer->setValues(c->getIssuer()); + + // Set the valid period + TQPalette cspl = _p12_validFrom->palette(); + if (TQDateTime::currentDateTime(Qt::UTC) < c->getQDTNotBefore()) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } else { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } + _p12_validFrom->setPalette(cspl); + _p12_validFrom->setText(c->getNotBefore()); + + cspl = _p12_validUntil->palette(); + if (TQDateTime::currentDateTime(Qt::UTC) > c->getQDTNotAfter()) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } else { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } + _p12_validUntil->setPalette(cspl); + _p12_validUntil->setText(c->getNotAfter()); + + _p12_serialNum->setText(c->getSerialNumber()); + cspl = _p12_certState->palette(); + if (!c->isValid()) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } else { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } + _p12_certState->setPalette(cspl); + _p12_certState->setText(KSSLCertificate::verifyText(c->validate())); + + _p12_pubkey->setText(c->getPublicKeyText()); + _p12_digest->setText(c->getMD5DigestText()); + _p12_sig->setText(c->getSignatureText()); +} + + + +void KCertPart::slotChain(int c) { + if (c == 0) { + displayPKCS12Cert(_p12->getCertificate()); + _p12_certState->setText(KSSLCertificate::verifyText(_p12->validate())); + } else { + displayPKCS12Cert(_p12->getCertificate()->chain().getChain().at(c-1)); + } +} + + +void KCertPart::slotImport() { + if (_p12) { + KSimpleConfig cfg("ksslcertificates", false); + + if (cfg.hasGroup(_p12->getCertificate()->getSubject())) { + TQString msg = _curName + "\n" + i18n("A certificate with that name already exists. Are you sure that you wish to replace it?"); + int rc= KMessageBox::warningContinueCancel(_frame, msg, i18n("Certificate Import"),i18n("Replace")); + if (rc == KMessageBox::Cancel) { + return; + } + } + + cfg.setGroup(_p12->getCertificate()->getSubject()); + cfg.writeEntry("PKCS12Base64", _p12->toString()); + cfg.writeEntry("Password", ""); + cfg.sync(); + if (!_silentImport) + KMessageBox::information(_frame, i18n("Certificate has been successfully imported into TDE.\nYou can manage your certificate settings from the Trinity Control Center."), i18n("Certificate Import")); + } else if (_ca) { + TDEConfig cfg("ksslcalist", true, false); + if (cfg.hasGroup(_ca->getSubject())) { + TQString msg = _curName + "\n" + i18n("A certificate with that name already exists. Are you sure that you wish to replace it?"); + int rc= KMessageBox::warningContinueCancel(_frame, msg, i18n("Certificate Import"),i18n("Replace")); + if (rc == KMessageBox::Cancel) { + return; + } + } + _signers->addCA(_ca->toString(), + _ca->x509V3Extensions().certTypeSSLCA(), + _ca->x509V3Extensions().certTypeEmailCA(), + _ca->x509V3Extensions().certTypeCodeCA()); + if (!_silentImport) + _signers->regenerate(); + + if (!_silentImport) + KMessageBox::information(_frame, i18n("Certificate has been successfully imported into TDE.\nYou can manage your certificate settings from the Trinity Control Center."), i18n("Certificate Import")); + } +} + + +void KCertPart::slotSave() { + saveFile(); +} + + +void KCertPart::slotDone() { + KParts::BrowserInterface *iface = d->browserExtension->browserInterface(); + iface->callMethod("goHistory(int)", -1); +} + + +void KCertPart::slotLaunch() { +KShellProcess p; +p << "tdecmshell" << "crypto"; +p.start(TDEProcess::DontCare); +} + + +void KCertPart::slotSelectionChanged(TQListViewItem *x) { + KX509Item *x5i = dynamic_cast(x); + KPKCS12Item *p12i = dynamic_cast(x); + _p12 = NULL; + _ca = NULL; + if (x && x->parent() == _parentCA) { + if (!x5i) { + return; + } + x5i->cert->revalidate(); + _blankFrame->hide(); + _pkcsFrame->hide(); + _x509Frame->show(); + _ca = x5i->cert; + _import->setEnabled(true); + _save->setEnabled(true); + _curName = x5i->_prettyName; + displayCACert(_ca); + } else if (x && x->parent() == NULL && x->rtti() == 1) { + if (!x5i) { + return; + } + x5i->cert->revalidate(); + _blankFrame->hide(); + _pkcsFrame->hide(); + _x509Frame->show(); + _ca = x5i->cert; + _import->setEnabled(false); + _save->setEnabled(false); + _curName = x5i->_prettyName; + displayCACert(_ca); + } else if (x && x->parent() == _parentP12) { + if (!p12i) { + return; + } + p12i->cert->revalidate(); + _blankFrame->hide(); + _x509Frame->hide(); + _pkcsFrame->show(); + _p12 = p12i->cert; + _import->setEnabled(true); + _save->setEnabled(true); + _curName = p12i->_prettyName; + displayPKCS12(); + } else { + _pkcsFrame->hide(); + _x509Frame->hide(); + _blankFrame->show(); + _import->setEnabled(false); + _save->setEnabled(false); + _curName = ""; + } +} + + +void KCertPart::slotImportAll() { +KSSLPKCS12 *p12Save = _p12; +KSSLCertificate *caSave = _ca; +TQString curNameSave = _curName; + +_p12 = NULL; +_ca = NULL; +_silentImport = true; + +for (KPKCS12Item *t = dynamic_cast(_parentP12->firstChild()); + t; + t = dynamic_cast(t->nextSibling())) { + if (t) { + _p12 = t->cert; + _curName = t->_prettyName; + } + slotImport(); +} +_p12 = NULL; + +for (KX509Item *t = dynamic_cast(_parentCA->firstChild()); + t; + t = dynamic_cast(t->nextSibling())) { + if (t) { + _ca = t->cert; + _curName = t->_prettyName; + } + slotImport(); +} +_ca = NULL; + +_signers->regenerate(); +_silentImport = false; +_p12 = p12Save; +_ca = caSave; +_curName = curNameSave; +KMessageBox::information(_frame, i18n("Certificates have been successfully imported into TDE.\nYou can manage your certificate settings from the Trinity Control Center."), i18n("Certificate Import")); +} + + +TDEAboutData *KCertPart::createAboutData() +{ + return new TDEAboutData("KCertPart", I18N_NOOP("TDE Certificate Part"), "1.0"); +} + +#include "tdecertpart.moc" + diff --git a/tdecore/tdeglobalsettings.h b/tdecore/tdeglobalsettings.h index 74b0d77a8..7a359b60e 100644 --- a/tdecore/tdeglobalsettings.h +++ b/tdecore/tdeglobalsettings.h @@ -238,7 +238,7 @@ class TDECORE_EXPORT TDEGlobalSettings * Use TDEIO::trash() to trash files, "trash:/" to list the trash contents. */ static TQString trashPath() { initPaths(); return *s_trashPath; } - // KDE4: if you want to remove the above, move it to kdesktop/init.cc, which needs + // KDE4: if you want to remove the above, move it to kdesktop/init.cpp, which needs // to know the old location of the trash /** diff --git a/tdecore/tests/kurltest.cpp b/tdecore/tests/kurltest.cpp index 0f57dd97c..081fdad55 100644 --- a/tdecore/tests/kurltest.cpp +++ b/tdecore/tests/kurltest.cpp @@ -271,14 +271,14 @@ int main(int argc, char *argv[]) #if 0 // This URL is broken, '#' should be escaped. - u1 = "file:/home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cc#"; + u1 = "file:/home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cpp#"; url1 = u1; - check("KURL::url()", url1.url(), "file:///home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cc#"); + check("KURL::url()", url1.url(), "file:///home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cpp#"); check("KURL::hasRef()", url1.hasRef() ? "yes" : "no", "no"); check("KURL::hasHTMLRef()", url1.hasHTMLRef() ? "yes" : "no", "no"); check("KURL::htmlRef()", url1.htmlRef(), ""); check("KURL::hasSubURL()", url1.hasSubURL() ? "yes" : "no", "yes"); - check("KURL::prettyURL()", url1.upURL().url(), "file:///home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cc#"); + check("KURL::prettyURL()", url1.upURL().url(), "file:///home/dfaure/cdrdao-1.1.5/dao/#CdrDriver.cpp#"); #endif u1 = "file:/home/dfaure/my%20tar%20file.tgz#gzip:/#tar:/README"; @@ -382,7 +382,7 @@ int main(int argc, char *argv[]) check("KURL::setFileName()", u2.url(), "file:///home/dfaure/myfile.txt"); u2.setFileName( "myotherfile.txt" ); check("KURL::setFileName()", u2.url(), "file:///home/dfaure/myotherfile.txt"); - // more tricky, renaming a directory (kpropsdlg.cc, line ~ 238) + // more tricky, renaming a directory (kpropsdlg.cpp, line ~ 238) TQString tmpurl = "file:/home/dfaure/myolddir/"; if ( tmpurl.at(tmpurl.length() - 1) == '/') // It's a directory, so strip the trailing slash first diff --git a/tdehtml/CMakeLists.txt b/tdehtml/CMakeLists.txt index aaf3074d3..187eff352 100644 --- a/tdehtml/CMakeLists.txt +++ b/tdehtml/CMakeLists.txt @@ -73,8 +73,8 @@ set( target tdehtml ) set( ${target}_SRCS tdehtmlview.cpp tdehtml_part.cpp tdehtml_run.cpp - tdehtml_factory.cpp tdehtml_settings.cc tdehtml_events.cpp - tdehtml_ext.cpp tdehtml_pagecache.cpp tdehtml_iface.cc + tdehtml_factory.cpp tdehtml_settings.cpp tdehtml_events.cpp + tdehtml_ext.cpp tdehtml_pagecache.cpp tdehtml_iface.cpp tdehtml_printsettings.cpp tdehtmlimage.cpp kjserrordlg.ui htmlpageinfo.ui tdehtml_iface.skel ) diff --git a/tdehtml/ChangeLog b/tdehtml/ChangeLog index eb70686e1..3a157f8f5 100644 --- a/tdehtml/ChangeLog +++ b/tdehtml/ChangeLog @@ -708,7 +708,7 @@ from innerHTML() and innerText() 2005-05-14 Ivor Hewitt - * tdehtml_settings.cc: Support full wildcard expressions in AdblocK + * tdehtml_settings.cpp: Support full wildcard expressions in AdblocK 2005-05-12 Luciano Montanaro * html/html_formimpl.cpp: Make a return keypress activate form @@ -2500,7 +2500,7 @@ repaint handling over here, since TableSections don't inherit RenderBox, but still have a background. - * tdehtml_settings.cc (init)/html4.css: MediumFontSize up to 12. Form elements + * tdehtml_settings.cpp (init)/html4.css: MediumFontSize up to 12. Form elements get font-size: small instead. 2004-02-24 Dirk Mueller @@ -3859,7 +3859,7 @@ 2003-10-04 Dirk Mueller - * tdehtml_settings.cc (init): change default for JS debugger to off. + * tdehtml_settings.cpp (init): change default for JS debugger to off. * html/html_elementimpl.cpp (createContextualFragment): Fix memory leaks. Adjust code style. Adjust return to avoid dangling return leaks. diff --git a/tdehtml/Makefile.am b/tdehtml/Makefile.am index 431b0b143..79ecf8a89 100644 --- a/tdehtml/Makefile.am +++ b/tdehtml/Makefile.am @@ -32,9 +32,9 @@ lib_LTLIBRARIES = libtdehtml.la kde_module_LTLIBRARIES = libtdehtmlpart.la tdehtmlimagepart.la libtdehtml_la_SOURCES = kjserrordlg.ui tdehtmlview.cpp tdehtml_part.cpp tdehtml_run.cpp\ - tdehtml_factory.cpp tdehtml_settings.cc tdehtml_events.cpp \ + tdehtml_factory.cpp tdehtml_settings.cpp tdehtml_events.cpp \ tdehtml_ext.cpp tdehtml_pagecache.cpp tdehtml_iface.skel \ - tdehtml_iface.cc tdehtml_printsettings.cpp htmlpageinfo.ui \ + tdehtml_iface.cpp tdehtml_printsettings.cpp htmlpageinfo.ui \ tdehtmlimage.cpp libtdehtml_la_METASOURCES = AUTO diff --git a/tdehtml/tdehtml_iface.cc b/tdehtml/tdehtml_iface.cc deleted file mode 100644 index 4bb4afd89..000000000 --- a/tdehtml/tdehtml_iface.cc +++ /dev/null @@ -1,233 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2002 Stephan Kulow - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "tdehtml_iface.h" -#include "tdehtml_part.h" -#include "tdehtmlview.h" -#include "tdehtml_ext.h" -#include -#include -#include - -TDEHTMLPartIface::TDEHTMLPartIface( TDEHTMLPart *_part ) - : DCOPObject( _part->dcopObjectId() ), part(_part) -{ -} - -TDEHTMLPartIface::~TDEHTMLPartIface() -{ -} - -KURL TDEHTMLPartIface::url() const -{ - return part->url(); -} - -void TDEHTMLPartIface::setJScriptEnabled( bool enable ) -{ - part->setJScriptEnabled(enable); -} - -bool TDEHTMLPartIface::jScriptEnabled() const -{ - return part->jScriptEnabled(); -} - -bool TDEHTMLPartIface::closeURL() -{ - return part->closeURL(); -} - -bool TDEHTMLPartIface::metaRefreshEnabled() const -{ - return part->metaRefreshEnabled(); -} - -void TDEHTMLPartIface::setDNDEnabled( bool b ) -{ - part->setDNDEnabled(b); -} - -bool TDEHTMLPartIface::dndEnabled() const -{ - return part->dndEnabled(); -} - -void TDEHTMLPartIface::setJavaEnabled( bool enable ) -{ - part->setJavaEnabled( enable ); -} - -bool TDEHTMLPartIface::javaEnabled() const -{ - return part->javaEnabled(); -} - -void TDEHTMLPartIface::setPluginsEnabled( bool enable ) -{ - part->setPluginsEnabled( enable ); -} - -bool TDEHTMLPartIface::pluginsEnabled() const -{ - return part->pluginsEnabled(); -} - -void TDEHTMLPartIface::setAutoloadImages( bool enable ) -{ - part->setAutoloadImages( enable ); -} - -bool TDEHTMLPartIface::autoloadImages() const -{ - return part->autoloadImages(); -} - -void TDEHTMLPartIface::setOnlyLocalReferences(bool enable) -{ - part->setOnlyLocalReferences(enable); -} - -void TDEHTMLPartIface::setMetaRefreshEnabled( bool enable ) -{ - part->setMetaRefreshEnabled(enable); -} - -bool TDEHTMLPartIface::onlyLocalReferences() const -{ - return part->onlyLocalReferences(); -} - -bool TDEHTMLPartIface::setEncoding( const TQString &name ) -{ - return part->setEncoding(name); -} - -TQString TDEHTMLPartIface::encoding() const -{ - return part->encoding(); -} - -void TDEHTMLPartIface::setFixedFont( const TQString &name ) -{ - part->setFixedFont(name); - -} - -bool TDEHTMLPartIface::gotoAnchor( const TQString &name ) -{ - return part->gotoAnchor(name); -} - -bool TDEHTMLPartIface::nextAnchor() -{ - return part->nextAnchor(); -} - -bool TDEHTMLPartIface::prevAnchor() -{ - return part->prevAnchor(); -} - -void TDEHTMLPartIface::activateNode() -{ - KParts::ReadOnlyPart* p = part->currentFrame(); - if ( p && p->widget() ) { - TQKeyEvent ev( TQKeyEvent::KeyPress, Qt::Key_Return, '\n', 0, "\n" ); - TQApplication::sendEvent( p->widget(), &ev ); - } -} - -void TDEHTMLPartIface::selectAll() -{ - part->selectAll(); -} - -TQString TDEHTMLPartIface::lastModified() const -{ - return part->lastModified(); -} - -void TDEHTMLPartIface::debugRenderTree() -{ - part->slotDebugRenderTree(); -} - -void TDEHTMLPartIface::debugDOMTree() -{ - part->slotDebugDOMTree(); -} - -void TDEHTMLPartIface::stopAnimations() -{ - part->slotStopAnimations(); -} - -void TDEHTMLPartIface::viewDocumentSource() -{ - part->slotViewDocumentSource(); -} - -void TDEHTMLPartIface::saveBackground(const TQString &destination) -{ - KURL back = part->backgroundURL(); - if (back.isEmpty()) - return; - - TDEIO::MetaData metaData; - metaData["referrer"] = part->referrer(); - TDEHTMLPopupGUIClient::saveURL( back, KURL( destination ), metaData ); -} - -void TDEHTMLPartIface::saveDocument(const TQString &destination) -{ - KURL srcURL( part->url() ); - - if ( srcURL.fileName(false).isEmpty() ) - srcURL.setFileName( "index.html" ); - - TDEIO::MetaData metaData; - // Referrer unknown? - TDEHTMLPopupGUIClient::saveURL( srcURL, KURL( destination ), metaData, part->cacheId() ); -} - -void TDEHTMLPartIface::setUserStyleSheet(const TQString &styleSheet) -{ - part->setUserStyleSheet(styleSheet); -} - -TQString TDEHTMLPartIface::selectedText() const -{ - return part->selectedText(); -} - -void TDEHTMLPartIface::viewFrameSource() -{ - part->slotViewFrameSource(); -} - -TQString TDEHTMLPartIface::evalJS(const TQString &script) -{ - return part->executeScript(DOM::Node(), script).toString(); -} - -void TDEHTMLPartIface::print( bool quick ) { - part->view()->print( quick ); -} diff --git a/tdehtml/tdehtml_iface.cpp b/tdehtml/tdehtml_iface.cpp new file mode 100644 index 000000000..4bb4afd89 --- /dev/null +++ b/tdehtml/tdehtml_iface.cpp @@ -0,0 +1,233 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2002 Stephan Kulow + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "tdehtml_iface.h" +#include "tdehtml_part.h" +#include "tdehtmlview.h" +#include "tdehtml_ext.h" +#include +#include +#include + +TDEHTMLPartIface::TDEHTMLPartIface( TDEHTMLPart *_part ) + : DCOPObject( _part->dcopObjectId() ), part(_part) +{ +} + +TDEHTMLPartIface::~TDEHTMLPartIface() +{ +} + +KURL TDEHTMLPartIface::url() const +{ + return part->url(); +} + +void TDEHTMLPartIface::setJScriptEnabled( bool enable ) +{ + part->setJScriptEnabled(enable); +} + +bool TDEHTMLPartIface::jScriptEnabled() const +{ + return part->jScriptEnabled(); +} + +bool TDEHTMLPartIface::closeURL() +{ + return part->closeURL(); +} + +bool TDEHTMLPartIface::metaRefreshEnabled() const +{ + return part->metaRefreshEnabled(); +} + +void TDEHTMLPartIface::setDNDEnabled( bool b ) +{ + part->setDNDEnabled(b); +} + +bool TDEHTMLPartIface::dndEnabled() const +{ + return part->dndEnabled(); +} + +void TDEHTMLPartIface::setJavaEnabled( bool enable ) +{ + part->setJavaEnabled( enable ); +} + +bool TDEHTMLPartIface::javaEnabled() const +{ + return part->javaEnabled(); +} + +void TDEHTMLPartIface::setPluginsEnabled( bool enable ) +{ + part->setPluginsEnabled( enable ); +} + +bool TDEHTMLPartIface::pluginsEnabled() const +{ + return part->pluginsEnabled(); +} + +void TDEHTMLPartIface::setAutoloadImages( bool enable ) +{ + part->setAutoloadImages( enable ); +} + +bool TDEHTMLPartIface::autoloadImages() const +{ + return part->autoloadImages(); +} + +void TDEHTMLPartIface::setOnlyLocalReferences(bool enable) +{ + part->setOnlyLocalReferences(enable); +} + +void TDEHTMLPartIface::setMetaRefreshEnabled( bool enable ) +{ + part->setMetaRefreshEnabled(enable); +} + +bool TDEHTMLPartIface::onlyLocalReferences() const +{ + return part->onlyLocalReferences(); +} + +bool TDEHTMLPartIface::setEncoding( const TQString &name ) +{ + return part->setEncoding(name); +} + +TQString TDEHTMLPartIface::encoding() const +{ + return part->encoding(); +} + +void TDEHTMLPartIface::setFixedFont( const TQString &name ) +{ + part->setFixedFont(name); + +} + +bool TDEHTMLPartIface::gotoAnchor( const TQString &name ) +{ + return part->gotoAnchor(name); +} + +bool TDEHTMLPartIface::nextAnchor() +{ + return part->nextAnchor(); +} + +bool TDEHTMLPartIface::prevAnchor() +{ + return part->prevAnchor(); +} + +void TDEHTMLPartIface::activateNode() +{ + KParts::ReadOnlyPart* p = part->currentFrame(); + if ( p && p->widget() ) { + TQKeyEvent ev( TQKeyEvent::KeyPress, Qt::Key_Return, '\n', 0, "\n" ); + TQApplication::sendEvent( p->widget(), &ev ); + } +} + +void TDEHTMLPartIface::selectAll() +{ + part->selectAll(); +} + +TQString TDEHTMLPartIface::lastModified() const +{ + return part->lastModified(); +} + +void TDEHTMLPartIface::debugRenderTree() +{ + part->slotDebugRenderTree(); +} + +void TDEHTMLPartIface::debugDOMTree() +{ + part->slotDebugDOMTree(); +} + +void TDEHTMLPartIface::stopAnimations() +{ + part->slotStopAnimations(); +} + +void TDEHTMLPartIface::viewDocumentSource() +{ + part->slotViewDocumentSource(); +} + +void TDEHTMLPartIface::saveBackground(const TQString &destination) +{ + KURL back = part->backgroundURL(); + if (back.isEmpty()) + return; + + TDEIO::MetaData metaData; + metaData["referrer"] = part->referrer(); + TDEHTMLPopupGUIClient::saveURL( back, KURL( destination ), metaData ); +} + +void TDEHTMLPartIface::saveDocument(const TQString &destination) +{ + KURL srcURL( part->url() ); + + if ( srcURL.fileName(false).isEmpty() ) + srcURL.setFileName( "index.html" ); + + TDEIO::MetaData metaData; + // Referrer unknown? + TDEHTMLPopupGUIClient::saveURL( srcURL, KURL( destination ), metaData, part->cacheId() ); +} + +void TDEHTMLPartIface::setUserStyleSheet(const TQString &styleSheet) +{ + part->setUserStyleSheet(styleSheet); +} + +TQString TDEHTMLPartIface::selectedText() const +{ + return part->selectedText(); +} + +void TDEHTMLPartIface::viewFrameSource() +{ + part->slotViewFrameSource(); +} + +TQString TDEHTMLPartIface::evalJS(const TQString &script) +{ + return part->executeScript(DOM::Node(), script).toString(); +} + +void TDEHTMLPartIface::print( bool quick ) { + part->view()->print( quick ); +} diff --git a/tdehtml/tdehtml_settings.cc b/tdehtml/tdehtml_settings.cc deleted file mode 100644 index 7f799e311..000000000 --- a/tdehtml/tdehtml_settings.cc +++ /dev/null @@ -1,1064 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1999 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include - -#include "tdehtml_settings.h" -#include "tdehtmldefaults.h" -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * @internal - * Contains all settings which are both available globally and per-domain - */ -struct KPerDomainSettings { - bool m_bEnableJava : 1; - bool m_bEnableJavaScript : 1; - bool m_bEnablePlugins : 1; - // don't forget to maintain the bitfields as the enums grow - TDEHTMLSettings::KJSWindowOpenPolicy m_windowOpenPolicy : 2; - TDEHTMLSettings::KJSWindowStatusPolicy m_windowStatusPolicy : 1; - TDEHTMLSettings::KJSWindowFocusPolicy m_windowFocusPolicy : 1; - TDEHTMLSettings::KJSWindowMovePolicy m_windowMovePolicy : 1; - TDEHTMLSettings::KJSWindowResizePolicy m_windowResizePolicy : 1; - -#ifdef DEBUG_SETTINGS - void dump(const TQString &infix = TQString::null) const { - kdDebug() << "KPerDomainSettings " << infix << " @" << this << ":" << endl; - kdDebug() << " m_bEnableJava: " << m_bEnableJava << endl; - kdDebug() << " m_bEnableJavaScript: " << m_bEnableJavaScript << endl; - kdDebug() << " m_bEnablePlugins: " << m_bEnablePlugins << endl; - kdDebug() << " m_windowOpenPolicy: " << m_windowOpenPolicy << endl; - kdDebug() << " m_windowStatusPolicy: " << m_windowStatusPolicy << endl; - kdDebug() << " m_windowFocusPolicy: " << m_windowFocusPolicy << endl; - kdDebug() << " m_windowMovePolicy: " << m_windowMovePolicy << endl; - kdDebug() << " m_windowResizePolicy: " << m_windowResizePolicy << endl; - } -#endif -}; - -typedef TQMap PolicyMap; - -class TDEHTMLSettingsPrivate -{ -public: - bool m_bChangeCursor : 1; - bool m_bOpenMiddleClick : 1; - bool m_bBackRightClick : 1; - bool m_underlineLink : 1; - bool m_hoverLink : 1; - bool m_bEnableJavaScriptDebug : 1; - bool m_bEnableJavaScriptErrorReporting : 1; - bool enforceCharset : 1; - bool m_bAutoLoadImages : 1; - bool m_bUnfinishedImageFrame : 1; - bool m_formCompletionEnabled : 1; - bool m_autoDelayedActionsEnabled : 1; - bool m_jsErrorsEnabled : 1; - bool m_follow_system_colors : 1; - bool m_allowTabulation : 1; - bool m_autoSpellCheck : 1; - bool m_adFilterEnabled : 1; - bool m_hideAdsEnabled : 1; - bool m_jsPopupBlockerPassivePopup : 1; - bool m_accessKeysEnabled : 1; - - // the virtual global "domain" - KPerDomainSettings global; - - int m_fontSize; - int m_minFontSize; - int m_maxFormCompletionItems; - TDEHTMLSettings::KAnimationAdvice m_showAnimations; - - TQString m_encoding; - TQString m_userSheet; - - TQColor m_textColor; - TQColor m_baseColor; - TQColor m_linkColor; - TQColor m_vLinkColor; - - PolicyMap domainPolicy; - TQStringList fonts; - TQStringList defaultFonts; - - TQValueVector adFilters; - TQValueList< TQPair< TQString, TQChar > > m_fallbackAccessKeysAssignments; -}; - - -/** Returns a writeable per-domains settings instance for the given domain - * or a deep copy of the global settings if not existent. - */ -static KPerDomainSettings &setup_per_domain_policy( - TDEHTMLSettingsPrivate *d, - const TQString &domain) { - if (domain.isEmpty()) { - kdWarning() << "setup_per_domain_policy: domain is empty" << endl; - } - const TQString ldomain = domain.lower(); - PolicyMap::iterator it = d->domainPolicy.find(ldomain); - if (it == d->domainPolicy.end()) { - // simply copy global domain settings (they should have been initialized - // by this time) - it = d->domainPolicy.insert(ldomain,d->global); - } - return *it; -} - - -TDEHTMLSettings::KJavaScriptAdvice TDEHTMLSettings::strToAdvice(const TQString& _str) -{ - KJavaScriptAdvice ret = KJavaScriptDunno; - - if (!_str) - ret = KJavaScriptDunno; - - if (_str.lower() == TQString::fromLatin1("accept")) - ret = KJavaScriptAccept; - else if (_str.lower() == TQString::fromLatin1("reject")) - ret = KJavaScriptReject; - - return ret; -} - -const char* TDEHTMLSettings::adviceToStr(KJavaScriptAdvice _advice) -{ - switch( _advice ) { - case KJavaScriptAccept: return I18N_NOOP("Accept"); - case KJavaScriptReject: return I18N_NOOP("Reject"); - default: return 0; - } - return 0; -} - - -void TDEHTMLSettings::splitDomainAdvice(const TQString& configStr, TQString &domain, - KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice& javaScriptAdvice) -{ - TQString tmp(configStr); - int splitIndex = tmp.find(':'); - if ( splitIndex == -1) - { - domain = configStr.lower(); - javaAdvice = KJavaScriptDunno; - javaScriptAdvice = KJavaScriptDunno; - } - else - { - domain = tmp.left(splitIndex).lower(); - TQString adviceString = tmp.mid( splitIndex+1, tmp.length() ); - int splitIndex2 = adviceString.find( ':' ); - if( splitIndex2 == -1 ) { - // Java advice only - javaAdvice = strToAdvice( adviceString ); - javaScriptAdvice = KJavaScriptDunno; - } else { - // Java and JavaScript advice - javaAdvice = strToAdvice( adviceString.left( splitIndex2 ) ); - javaScriptAdvice = strToAdvice( adviceString.mid( splitIndex2+1, - adviceString.length() ) ); - } - } -} - -void TDEHTMLSettings::readDomainSettings(TDEConfig *config, bool reset, - bool global, KPerDomainSettings &pd_settings) { - TQString jsPrefix = global ? TQString::null - : TQString::fromLatin1("javascript."); - TQString javaPrefix = global ? TQString::null - : TQString::fromLatin1("java."); - TQString pluginsPrefix = global ? TQString::null - : TQString::fromLatin1("plugins."); - - // The setting for Java - TQString key = javaPrefix + TQString::fromLatin1("EnableJava"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_bEnableJava = config->readBoolEntry( key, false ); - else if ( !global ) - pd_settings.m_bEnableJava = d->global.m_bEnableJava; - - // The setting for Plugins - key = pluginsPrefix + TQString::fromLatin1("EnablePlugins"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_bEnablePlugins = config->readBoolEntry( key, true ); - else if ( !global ) - pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins; - - // The setting for JavaScript - key = jsPrefix + TQString::fromLatin1("EnableJavaScript"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_bEnableJavaScript = config->readBoolEntry( key, true ); - else if ( !global ) - pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript; - - // window property policies - key = jsPrefix + TQString::fromLatin1("WindowOpenPolicy"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_windowOpenPolicy = (KJSWindowOpenPolicy) - config->readUnsignedNumEntry( key, KJSWindowOpenSmart ); - else if ( !global ) - pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy; - - key = jsPrefix + TQString::fromLatin1("WindowMovePolicy"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_windowMovePolicy = (KJSWindowMovePolicy) - config->readUnsignedNumEntry( key, KJSWindowMoveAllow ); - else if ( !global ) - pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy; - - key = jsPrefix + TQString::fromLatin1("WindowResizePolicy"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_windowResizePolicy = (KJSWindowResizePolicy) - config->readUnsignedNumEntry( key, KJSWindowResizeAllow ); - else if ( !global ) - pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy; - - key = jsPrefix + TQString::fromLatin1("WindowStatusPolicy"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_windowStatusPolicy = (KJSWindowStatusPolicy) - config->readUnsignedNumEntry( key, KJSWindowStatusAllow ); - else if ( !global ) - pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy; - - key = jsPrefix + TQString::fromLatin1("WindowFocusPolicy"); - if ( (global && reset) || config->hasKey( key ) ) - pd_settings.m_windowFocusPolicy = (KJSWindowFocusPolicy) - config->readUnsignedNumEntry( key, KJSWindowFocusAllow ); - else if ( !global ) - pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy; - -} - - -TDEHTMLSettings::TDEHTMLSettings() -{ - d = new TDEHTMLSettingsPrivate(); - init(); -} - -TDEHTMLSettings::TDEHTMLSettings(const TDEHTMLSettings &other) -{ - d = new TDEHTMLSettingsPrivate(); - *d = *other.d; -} - -TDEHTMLSettings::~TDEHTMLSettings() -{ - delete d; -} - -bool TDEHTMLSettings::changeCursor() const -{ - return d->m_bChangeCursor; -} - -bool TDEHTMLSettings::underlineLink() const -{ - return d->m_underlineLink; -} - -bool TDEHTMLSettings::hoverLink() const -{ - return d->m_hoverLink; -} - -void TDEHTMLSettings::init() -{ - TDEConfig global( "tdehtmlrc", true, false ); - init( &global, true ); - - TDEConfig *local = TDEGlobal::config(); - if ( !local ) - return; - - init( local, false ); -} - -void TDEHTMLSettings::init( TDEConfig * config, bool reset ) -{ - TQString group_save = config->group(); - if (reset || config->hasGroup("MainView Settings")) - { - config->setGroup( "MainView Settings" ); - - if ( reset || config->hasKey( "OpenMiddleClick" ) ) - d->m_bOpenMiddleClick = config->readBoolEntry( "OpenMiddleClick", true ); - - if ( reset || config->hasKey( "BackRightClick" ) ) - d->m_bBackRightClick = config->readBoolEntry( "BackRightClick", false ); - } - - if (reset || config->hasGroup("Access Keys")) { - config->setGroup( "Access Keys" ); - d->m_accessKeysEnabled = config->readBoolEntry( "Enabled", true ); - } - - if (reset || config->hasGroup("Filter Settings")) - { - config->setGroup( "Filter Settings" ); - d->m_adFilterEnabled = config->readBoolEntry("Enabled", false); - d->m_hideAdsEnabled = config->readBoolEntry("Shrink", false); - - d->adFilters.clear(); - - TQMap entryMap = config->entryMap("Filter Settings"); - TQMap::ConstIterator it; - d->adFilters.reserve(entryMap.count()); - for( it = entryMap.constBegin(); it != entryMap.constEnd(); ++it ) - { - TQString name = it.key(); - TQString url = it.data(); - - if (url.startsWith("!")) - continue; - - if (name.startsWith("Filter")) - { - if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') - { - TQString inside = url.mid(1, url.length()-2); - TQRegExp rx(inside); - d->adFilters.append(rx); - } - else - { - TQRegExp rx; - int left,right; - - for (right=url.length(); right>0 && url[right-1]=='*' ; --right); - for (left=0; leftadFilters.append(rx); - } - } - } - } - - - if (reset || config->hasGroup("HTML Settings")) - { - config->setGroup( "HTML Settings" ); - // Fonts and colors - if( reset ) { - d->defaultFonts = TQStringList(); - d->defaultFonts.append( config->readEntry( "StandardFont", TDEGlobalSettings::generalFont().family() ) ); - d->defaultFonts.append( config->readEntry( "FixedFont", TDEGlobalSettings::fixedFont().family() ) ); - d->defaultFonts.append( config->readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) ); - d->defaultFonts.append( config->readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) ); - d->defaultFonts.append( config->readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) ); - d->defaultFonts.append( config->readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) ); - d->defaultFonts.append( TQString( "0" ) ); // font size adjustment - } - - if ( reset || config->hasKey( "MinimumFontSize" ) ) - d->m_minFontSize = config->readNumEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE ); - - if ( reset || config->hasKey( "MediumFontSize" ) ) - d->m_fontSize = config->readNumEntry( "MediumFontSize", 12 ); - - d->fonts = config->readListEntry( "Fonts" ); - - if ( reset || config->hasKey( "DefaultEncoding" ) ) - d->m_encoding = config->readEntry( "DefaultEncoding", "" ); - - if ( reset || config->hasKey( "EnforceDefaultCharset" ) ) - d->enforceCharset = config->readBoolEntry( "EnforceDefaultCharset", false ); - - // Behavior - if ( reset || config->hasKey( "ChangeCursor" ) ) - d->m_bChangeCursor = config->readBoolEntry( "ChangeCursor", KDE_DEFAULT_CHANGECURSOR ); - - if ( reset || config->hasKey("UnderlineLinks") ) - d->m_underlineLink = config->readBoolEntry( "UnderlineLinks", true ); - - if ( reset || config->hasKey( "HoverLinks" ) ) - { - if ( ( d->m_hoverLink = config->readBoolEntry( "HoverLinks", false ) ) ) - d->m_underlineLink = false; - } - - if ( reset || config->hasKey( "AllowTabulation" ) ) - d->m_allowTabulation = config->readBoolEntry( "AllowTabulation", false ); - - if ( reset || config->hasKey( "AutoSpellCheck" ) ) - d->m_autoSpellCheck = config->readBoolEntry( "AutoSpellCheck", true ); - - // Other - if ( reset || config->hasKey( "AutoLoadImages" ) ) - d->m_bAutoLoadImages = config->readBoolEntry( "AutoLoadImages", true ); - - if ( reset || config->hasKey( "UnfinishedImageFrame" ) ) - d->m_bUnfinishedImageFrame = config->readBoolEntry( "UnfinishedImageFrame", true ); - - if ( reset || config->hasKey( "ShowAnimations" ) ) - { - TQString value = config->readEntry( "ShowAnimations").lower(); - if (value == "disabled") - d->m_showAnimations = KAnimationDisabled; - else if (value == "looponce") - d->m_showAnimations = KAnimationLoopOnce; - else - d->m_showAnimations = KAnimationEnabled; - } - - if ( config->readBoolEntry( "UserStyleSheetEnabled", false ) == true ) { - if ( reset || config->hasKey( "UserStyleSheet" ) ) - d->m_userSheet = config->readEntry( "UserStyleSheet", "" ); - } - - d->m_formCompletionEnabled = config->readBoolEntry("FormCompletion", true); - d->m_maxFormCompletionItems = config->readNumEntry("MaxFormCompletionItems", 10); - d->m_autoDelayedActionsEnabled = config->readBoolEntry ("AutoDelayedActions", true); - d->m_jsErrorsEnabled = config->readBoolEntry("ReportJSErrors", true); - TQStringList accesskeys = config->readListEntry("FallbackAccessKeysAssignments"); - d->m_fallbackAccessKeysAssignments.clear(); - for( TQStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it ) - if( (*it).length() > 2 && (*it)[ 1 ] == ':' ) - d->m_fallbackAccessKeysAssignments.append( tqMakePair( (*it).mid( 2 ), (*it)[ 0 ] )); - } - - // Colors - - if ( reset || config->hasKey( "FollowSystemColors" ) ) - d->m_follow_system_colors = config->readBoolEntry( "FollowSystemColors", false ); - - if ( reset || config->hasGroup( "General" ) ) - { - config->setGroup( "General" ); // group will be restored by cgs anyway - if ( reset || config->hasKey( "foreground" ) ) - d->m_textColor = config->readColorEntry( "foreground", &HTML_DEFAULT_TXT_COLOR ); - - if ( reset || config->hasKey( "linkColor" ) ) - d->m_linkColor = config->readColorEntry( "linkColor", &HTML_DEFAULT_LNK_COLOR ); - - if ( reset || config->hasKey( "visitedLinkColor" ) ) - d->m_vLinkColor = config->readColorEntry( "visitedLinkColor", &HTML_DEFAULT_VLNK_COLOR); - - if ( reset || config->hasKey( "background" ) ) - d->m_baseColor = config->readColorEntry( "background", &HTML_DEFAULT_BASE_COLOR); - } - - if( reset || config->hasGroup( "Java/JavaScript Settings" ) ) - { - config->setGroup( "Java/JavaScript Settings" ); - - // The global setting for JavaScript debugging - // This is currently always enabled by default - if ( reset || config->hasKey( "EnableJavaScriptDebug" ) ) - d->m_bEnableJavaScriptDebug = config->readBoolEntry( "EnableJavaScriptDebug", false ); - - // The global setting for JavaScript error reporting - if ( reset || config->hasKey( "ReportJavaScriptErrors" ) ) - d->m_bEnableJavaScriptErrorReporting = config->readBoolEntry( "ReportJavaScriptErrors", false ); - - // The global setting for popup block passive popup - if ( reset || config->hasKey( "PopupBlockerPassivePopup" ) ) - d->m_jsPopupBlockerPassivePopup = config->readBoolEntry("PopupBlockerPassivePopup", true); - - // Read options from the global "domain" - readDomainSettings(config,reset,true,d->global); -#ifdef DEBUG_SETTINGS - d->global.dump("init global"); -#endif - - // The domain-specific settings. - - static const char *const domain_keys[] = { // always keep order of keys - "ECMADomains", "JavaDomains", "PluginDomains" - }; - bool check_old_ecma_settings = true; - bool check_old_java_settings = true; - // merge all domains into one list - TQMap domainList; // why can't Qt have a QSet? - for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) { - if ( reset || config->hasKey(domain_keys[i]) ) { - if (i == 0) check_old_ecma_settings = false; - else if (i == 1) check_old_java_settings = false; - const TQStringList dl = config->readListEntry( domain_keys[i] ); - const TQMap::Iterator notfound = domainList.end(); - TQStringList::ConstIterator it = dl.begin(); - const TQStringList::ConstIterator itEnd = dl.end(); - for (; it != itEnd; ++it) { - const TQString domain = (*it).lower(); - TQMap::Iterator pos = domainList.find(domain); - if (pos == notfound) domainList.insert(domain,0); - }/*next it*/ - } - }/*next i*/ - - if (reset) - d->domainPolicy.clear(); - - TQString js_group_save = config->group(); - { - TQMap::ConstIterator it = domainList.begin(); - const TQMap::ConstIterator itEnd = domainList.end(); - for ( ; it != itEnd; ++it) - { - const TQString domain = it.key(); - config->setGroup(domain); - readDomainSettings(config,reset,false,d->domainPolicy[domain]); -#ifdef DEBUG_SETTINGS - d->domainPolicy[domain].dump("init "+domain); -#endif - } - } - config->setGroup(js_group_save); - - bool check_old_java = true; - if( ( reset || config->hasKey( "JavaDomainSettings" ) ) - && check_old_java_settings ) - { - check_old_java = false; - const TQStringList domainList = config->readListEntry( "JavaDomainSettings" ); - TQStringList::ConstIterator it = domainList.begin(); - const TQStringList::ConstIterator itEnd = domainList.end(); - for ( ; it != itEnd; ++it) - { - TQString domain; - KJavaScriptAdvice javaAdvice; - KJavaScriptAdvice javaScriptAdvice; - splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); - setup_per_domain_policy(d,domain).m_bEnableJava = - javaAdvice == KJavaScriptAccept; -#ifdef DEBUG_SETTINGS - setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain); -#endif - } - } - - bool check_old_ecma = true; - if( ( reset || config->hasKey( "ECMADomainSettings" ) ) - && check_old_ecma_settings ) - { - check_old_ecma = false; - const TQStringList domainList = config->readListEntry( "ECMADomainSettings" ); - TQStringList::ConstIterator it = domainList.begin(); - const TQStringList::ConstIterator itEnd = domainList.end(); - for ( ; it != itEnd; ++it) - { - TQString domain; - KJavaScriptAdvice javaAdvice; - KJavaScriptAdvice javaScriptAdvice; - splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); - setup_per_domain_policy(d,domain).m_bEnableJavaScript = - javaScriptAdvice == KJavaScriptAccept; -#ifdef DEBUG_SETTINGS - setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain); -#endif - } - } - - if( ( reset || config->hasKey( "JavaScriptDomainAdvice" ) ) - && ( check_old_java || check_old_ecma ) - && ( check_old_ecma_settings || check_old_java_settings ) ) - { - const TQStringList domainList = config->readListEntry( "JavaScriptDomainAdvice" ); - TQStringList::ConstIterator it = domainList.begin(); - const TQStringList::ConstIterator itEnd = domainList.end(); - for ( ; it != itEnd; ++it) - { - TQString domain; - KJavaScriptAdvice javaAdvice; - KJavaScriptAdvice javaScriptAdvice; - splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); - if( check_old_java ) - setup_per_domain_policy(d,domain).m_bEnableJava = - javaAdvice == KJavaScriptAccept; - if( check_old_ecma ) - setup_per_domain_policy(d,domain).m_bEnableJavaScript = - javaScriptAdvice == KJavaScriptAccept; -#ifdef DEBUG_SETTINGS - setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain); -#endif - } - - //save all the settings into the new keywords if they don't exist -#if 0 - if( check_old_java ) - { - TQStringList domainConfig; - PolicyMap::Iterator it; - for( it = d->javaDomainPolicy.begin(); it != d->javaDomainPolicy.end(); ++it ) - { - TQCString javaPolicy = adviceToStr( it.data() ); - TQCString javaScriptPolicy = adviceToStr( KJavaScriptDunno ); - domainConfig.append(TQString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy)); - } - config->writeEntry( "JavaDomainSettings", domainConfig ); - } - - if( check_old_ecma ) - { - TQStringList domainConfig; - PolicyMap::Iterator it; - for( it = d->javaScriptDomainPolicy.begin(); it != d->javaScriptDomainPolicy.end(); ++it ) - { - TQCString javaPolicy = adviceToStr( KJavaScriptDunno ); - TQCString javaScriptPolicy = adviceToStr( it.data() ); - domainConfig.append(TQString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy)); - } - config->writeEntry( "ECMADomainSettings", domainConfig ); - } -#endif - } - } - config->setGroup(group_save); -} - - -/** Local helper for retrieving per-domain settings. - * - * In case of doubt, the global domain is returned. - */ -static const KPerDomainSettings &lookup_hostname_policy( - const TDEHTMLSettingsPrivate *d, - const TQString& hostname) -{ -#ifdef DEBUG_SETTINGS - kdDebug() << "lookup_hostname_policy(" << hostname << ")" << endl; -#endif - if (hostname.isEmpty()) { -#ifdef DEBUG_SETTINGS - d->global.dump("global"); -#endif - return d->global; - } - - const PolicyMap::const_iterator notfound = d->domainPolicy.end(); - - // First check whether there is a perfect match. - PolicyMap::const_iterator it = d->domainPolicy.find(hostname); - if( it != notfound ) { -#ifdef DEBUG_SETTINGS - kdDebug() << "perfect match" << endl; - (*it).dump(hostname); -#endif - // yes, use it (unless dunno) - return *it; - } - - // Now, check for partial match. Chop host from the left until - // there's no dots left. - TQString host_part = hostname; - int dot_idx = -1; - while( (dot_idx = host_part.find(TQChar('.'))) >= 0 ) { - host_part.remove(0,dot_idx); - it = d->domainPolicy.find(host_part); - Q_ASSERT(notfound == d->domainPolicy.end()); - if( it != notfound ) { -#ifdef DEBUG_SETTINGS - kdDebug() << "partial match" << endl; - (*it).dump(host_part); -#endif - return *it; - } - // assert(host_part[0] == TQChar('.')); - host_part.remove(0,1); // Chop off the dot. - } - - // No domain-specific entry: use global domain -#ifdef DEBUG_SETTINGS - kdDebug() << "no match" << endl; - d->global.dump("global"); -#endif - return d->global; -} - -bool TDEHTMLSettings::isOpenMiddleClickEnabled() -{ - return d->m_bOpenMiddleClick; -} - -bool TDEHTMLSettings::isBackRightClickEnabled() -{ - return d->m_bBackRightClick; -} - -bool TDEHTMLSettings::accessKeysEnabled() const -{ - return d->m_accessKeysEnabled; -} - -bool TDEHTMLSettings::isAdFilterEnabled() const -{ - return d->m_adFilterEnabled; -} - -bool TDEHTMLSettings::isHideAdsEnabled() const -{ - return d->m_hideAdsEnabled; -} - -bool TDEHTMLSettings::isAdFiltered( const TQString &url ) const -{ - if (d->m_adFilterEnabled) - { - if (!url.startsWith("data:")) - { - TQValueVector::const_iterator it(d->adFilters.constBegin()); - TQValueVector::const_iterator end(d->adFilters.constEnd()); - for (; it != end; ++it) - { - if ((*it).search(url) != -1) - { - kdDebug( 6080 ) << "Filtered: " << url << endl; - return true; - } - } - } - } - return false; -} - -void TDEHTMLSettings::addAdFilter( const TQString &url ) -{ - TDEConfig config( "tdehtmlrc", false, false ); - config.setGroup( "Filter Settings" ); - - TQRegExp rx; - if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') - { - TQString inside = url.mid(1, url.length()-2); - rx.setWildcard(false); - rx.setPattern(inside); - } - else - { - int left,right; - - rx.setWildcard(true); - for (right=url.length(); right>0 && url[right-1]=='*' ; --right); - for (left=0; leftadFilters.append(rx); - } - else - { - KMessageBox::error(0, - rx.errorString(), - i18n("Filter error")); - } -} - -bool TDEHTMLSettings::isJavaEnabled( const TQString& hostname ) -{ - return lookup_hostname_policy(d,hostname.lower()).m_bEnableJava; -} - -bool TDEHTMLSettings::isJavaScriptEnabled( const TQString& hostname ) -{ - return lookup_hostname_policy(d,hostname.lower()).m_bEnableJavaScript; -} - -bool TDEHTMLSettings::isJavaScriptDebugEnabled( const TQString& /*hostname*/ ) -{ - // debug setting is global for now, but could change in the future - return d->m_bEnableJavaScriptDebug; -} - -bool TDEHTMLSettings::isJavaScriptErrorReportingEnabled( const TQString& /*hostname*/ ) const -{ - // error reporting setting is global for now, but could change in the future - return d->m_bEnableJavaScriptErrorReporting; -} - -bool TDEHTMLSettings::isPluginsEnabled( const TQString& hostname ) -{ - return lookup_hostname_policy(d,hostname.lower()).m_bEnablePlugins; -} - -TDEHTMLSettings::KJSWindowOpenPolicy TDEHTMLSettings::windowOpenPolicy( - const TQString& hostname) const { - return lookup_hostname_policy(d,hostname.lower()).m_windowOpenPolicy; -} - -TDEHTMLSettings::KJSWindowMovePolicy TDEHTMLSettings::windowMovePolicy( - const TQString& hostname) const { - return lookup_hostname_policy(d,hostname.lower()).m_windowMovePolicy; -} - -TDEHTMLSettings::KJSWindowResizePolicy TDEHTMLSettings::windowResizePolicy( - const TQString& hostname) const { - return lookup_hostname_policy(d,hostname.lower()).m_windowResizePolicy; -} - -TDEHTMLSettings::KJSWindowStatusPolicy TDEHTMLSettings::windowStatusPolicy( - const TQString& hostname) const { - return lookup_hostname_policy(d,hostname.lower()).m_windowStatusPolicy; -} - -TDEHTMLSettings::KJSWindowFocusPolicy TDEHTMLSettings::windowFocusPolicy( - const TQString& hostname) const { - return lookup_hostname_policy(d,hostname.lower()).m_windowFocusPolicy; -} - -int TDEHTMLSettings::mediumFontSize() const -{ - return d->m_fontSize; -} - -int TDEHTMLSettings::minFontSize() const -{ - return d->m_minFontSize; -} - -TQString TDEHTMLSettings::settingsToCSS() const -{ - // lets start with the link properties - TQString str = "a:link {\ncolor: "; - str += d->m_linkColor.name(); - str += ";"; - if(d->m_underlineLink) - str += "\ntext-decoration: underline;"; - - if( d->m_bChangeCursor ) - { - str += "\ncursor: pointer;"; - str += "\n}\ninput[type=image] { cursor: pointer;"; - } - str += "\n}\n"; - str += "a:visited {\ncolor: "; - str += d->m_vLinkColor.name(); - str += ";"; - if(d->m_underlineLink) - str += "\ntext-decoration: underline;"; - - if( d->m_bChangeCursor ) - str += "\ncursor: pointer;"; - str += "\n}\n"; - - if(d->m_hoverLink) - str += "a:link:hover, a:visited:hover { text-decoration: underline; }\n"; - - return str; -} - -const TQString &TDEHTMLSettings::availableFamilies() -{ - if ( !avFamilies ) { - avFamilies = new TQString; - TQFontDatabase db; - TQStringList families = db.families(); - TQStringList s; - TQRegExp foundryExp(" \\[.+\\]"); - - //remove foundry info - TQStringList::Iterator f = families.begin(); - const TQStringList::Iterator fEnd = families.end(); - - for ( ; f != fEnd; ++f ) { - (*f).replace( foundryExp, ""); - if (!s.contains(*f)) - s << *f; - } - s.sort(); - - *avFamilies = ',' + s.join(",") + ','; - } - - return *avFamilies; -} - -TQString TDEHTMLSettings::lookupFont(int i) const -{ - TQString font; - if (d->fonts.count() > (uint) i) - font = d->fonts[i]; - if (font.isEmpty()) - font = d->defaultFonts[i]; - return font; -} - -TQString TDEHTMLSettings::stdFontName() const -{ - return lookupFont(0); -} - -TQString TDEHTMLSettings::fixedFontName() const -{ - return lookupFont(1); -} - -TQString TDEHTMLSettings::serifFontName() const -{ - return lookupFont(2); -} - -TQString TDEHTMLSettings::sansSerifFontName() const -{ - return lookupFont(3); -} - -TQString TDEHTMLSettings::cursiveFontName() const -{ - return lookupFont(4); -} - -TQString TDEHTMLSettings::fantasyFontName() const -{ - return lookupFont(5); -} - -void TDEHTMLSettings::setStdFontName(const TQString &n) -{ - while(d->fonts.count() <= 0) - d->fonts.append(TQString::null); - d->fonts[0] = n; -} - -void TDEHTMLSettings::setFixedFontName(const TQString &n) -{ - while(d->fonts.count() <= 1) - d->fonts.append(TQString::null); - d->fonts[1] = n; -} - -TQString TDEHTMLSettings::userStyleSheet() const -{ - return d->m_userSheet; -} - -bool TDEHTMLSettings::isFormCompletionEnabled() const -{ - return d->m_formCompletionEnabled; -} - -int TDEHTMLSettings::maxFormCompletionItems() const -{ - return d->m_maxFormCompletionItems; -} - -const TQString &TDEHTMLSettings::encoding() const -{ - return d->m_encoding; -} - -bool TDEHTMLSettings::followSystemColors() const -{ - return d->m_follow_system_colors; -} - -const TQColor& TDEHTMLSettings::textColor() const -{ - return d->m_textColor; -} - -const TQColor& TDEHTMLSettings::baseColor() const -{ - return d->m_baseColor; -} - -const TQColor& TDEHTMLSettings::linkColor() const -{ - return d->m_linkColor; -} - -const TQColor& TDEHTMLSettings::vLinkColor() const -{ - return d->m_vLinkColor; -} - -bool TDEHTMLSettings::autoLoadImages() const -{ - return d->m_bAutoLoadImages; -} - -bool TDEHTMLSettings::unfinishedImageFrame() const -{ - return d->m_bUnfinishedImageFrame; -} - -TDEHTMLSettings::KAnimationAdvice TDEHTMLSettings::showAnimations() const -{ - return d->m_showAnimations; -} - -bool TDEHTMLSettings::isAutoDelayedActionsEnabled() const -{ - return d->m_autoDelayedActionsEnabled; -} - -bool TDEHTMLSettings::jsErrorsEnabled() const -{ - return d->m_jsErrorsEnabled; -} - -void TDEHTMLSettings::setJSErrorsEnabled(bool enabled) -{ - d->m_jsErrorsEnabled = enabled; - // save it - TDEConfig *config = TDEGlobal::config(); - config->setGroup("HTML Settings"); - config->writeEntry("ReportJSErrors", enabled); - config->sync(); -} - -bool TDEHTMLSettings::allowTabulation() const -{ - return d->m_allowTabulation; -} - -bool TDEHTMLSettings::autoSpellCheck() const -{ - return d->m_autoSpellCheck; -} - -TQValueList< TQPair< TQString, TQChar > > TDEHTMLSettings::fallbackAccessKeysAssignments() const -{ - return d->m_fallbackAccessKeysAssignments; -} - -void TDEHTMLSettings::setJSPopupBlockerPassivePopup(bool enabled) -{ - d->m_jsPopupBlockerPassivePopup = enabled; - // save it - TDEConfig *config = TDEGlobal::config(); - config->setGroup("Java/JavaScript Settings"); - config->writeEntry("PopupBlockerPassivePopup", enabled); - config->sync(); -} - -bool TDEHTMLSettings::jsPopupBlockerPassivePopup() const -{ - return d->m_jsPopupBlockerPassivePopup; -} diff --git a/tdehtml/tdehtml_settings.cpp b/tdehtml/tdehtml_settings.cpp new file mode 100644 index 000000000..7f799e311 --- /dev/null +++ b/tdehtml/tdehtml_settings.cpp @@ -0,0 +1,1064 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include "tdehtml_settings.h" +#include "tdehtmldefaults.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @internal + * Contains all settings which are both available globally and per-domain + */ +struct KPerDomainSettings { + bool m_bEnableJava : 1; + bool m_bEnableJavaScript : 1; + bool m_bEnablePlugins : 1; + // don't forget to maintain the bitfields as the enums grow + TDEHTMLSettings::KJSWindowOpenPolicy m_windowOpenPolicy : 2; + TDEHTMLSettings::KJSWindowStatusPolicy m_windowStatusPolicy : 1; + TDEHTMLSettings::KJSWindowFocusPolicy m_windowFocusPolicy : 1; + TDEHTMLSettings::KJSWindowMovePolicy m_windowMovePolicy : 1; + TDEHTMLSettings::KJSWindowResizePolicy m_windowResizePolicy : 1; + +#ifdef DEBUG_SETTINGS + void dump(const TQString &infix = TQString::null) const { + kdDebug() << "KPerDomainSettings " << infix << " @" << this << ":" << endl; + kdDebug() << " m_bEnableJava: " << m_bEnableJava << endl; + kdDebug() << " m_bEnableJavaScript: " << m_bEnableJavaScript << endl; + kdDebug() << " m_bEnablePlugins: " << m_bEnablePlugins << endl; + kdDebug() << " m_windowOpenPolicy: " << m_windowOpenPolicy << endl; + kdDebug() << " m_windowStatusPolicy: " << m_windowStatusPolicy << endl; + kdDebug() << " m_windowFocusPolicy: " << m_windowFocusPolicy << endl; + kdDebug() << " m_windowMovePolicy: " << m_windowMovePolicy << endl; + kdDebug() << " m_windowResizePolicy: " << m_windowResizePolicy << endl; + } +#endif +}; + +typedef TQMap PolicyMap; + +class TDEHTMLSettingsPrivate +{ +public: + bool m_bChangeCursor : 1; + bool m_bOpenMiddleClick : 1; + bool m_bBackRightClick : 1; + bool m_underlineLink : 1; + bool m_hoverLink : 1; + bool m_bEnableJavaScriptDebug : 1; + bool m_bEnableJavaScriptErrorReporting : 1; + bool enforceCharset : 1; + bool m_bAutoLoadImages : 1; + bool m_bUnfinishedImageFrame : 1; + bool m_formCompletionEnabled : 1; + bool m_autoDelayedActionsEnabled : 1; + bool m_jsErrorsEnabled : 1; + bool m_follow_system_colors : 1; + bool m_allowTabulation : 1; + bool m_autoSpellCheck : 1; + bool m_adFilterEnabled : 1; + bool m_hideAdsEnabled : 1; + bool m_jsPopupBlockerPassivePopup : 1; + bool m_accessKeysEnabled : 1; + + // the virtual global "domain" + KPerDomainSettings global; + + int m_fontSize; + int m_minFontSize; + int m_maxFormCompletionItems; + TDEHTMLSettings::KAnimationAdvice m_showAnimations; + + TQString m_encoding; + TQString m_userSheet; + + TQColor m_textColor; + TQColor m_baseColor; + TQColor m_linkColor; + TQColor m_vLinkColor; + + PolicyMap domainPolicy; + TQStringList fonts; + TQStringList defaultFonts; + + TQValueVector adFilters; + TQValueList< TQPair< TQString, TQChar > > m_fallbackAccessKeysAssignments; +}; + + +/** Returns a writeable per-domains settings instance for the given domain + * or a deep copy of the global settings if not existent. + */ +static KPerDomainSettings &setup_per_domain_policy( + TDEHTMLSettingsPrivate *d, + const TQString &domain) { + if (domain.isEmpty()) { + kdWarning() << "setup_per_domain_policy: domain is empty" << endl; + } + const TQString ldomain = domain.lower(); + PolicyMap::iterator it = d->domainPolicy.find(ldomain); + if (it == d->domainPolicy.end()) { + // simply copy global domain settings (they should have been initialized + // by this time) + it = d->domainPolicy.insert(ldomain,d->global); + } + return *it; +} + + +TDEHTMLSettings::KJavaScriptAdvice TDEHTMLSettings::strToAdvice(const TQString& _str) +{ + KJavaScriptAdvice ret = KJavaScriptDunno; + + if (!_str) + ret = KJavaScriptDunno; + + if (_str.lower() == TQString::fromLatin1("accept")) + ret = KJavaScriptAccept; + else if (_str.lower() == TQString::fromLatin1("reject")) + ret = KJavaScriptReject; + + return ret; +} + +const char* TDEHTMLSettings::adviceToStr(KJavaScriptAdvice _advice) +{ + switch( _advice ) { + case KJavaScriptAccept: return I18N_NOOP("Accept"); + case KJavaScriptReject: return I18N_NOOP("Reject"); + default: return 0; + } + return 0; +} + + +void TDEHTMLSettings::splitDomainAdvice(const TQString& configStr, TQString &domain, + KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice& javaScriptAdvice) +{ + TQString tmp(configStr); + int splitIndex = tmp.find(':'); + if ( splitIndex == -1) + { + domain = configStr.lower(); + javaAdvice = KJavaScriptDunno; + javaScriptAdvice = KJavaScriptDunno; + } + else + { + domain = tmp.left(splitIndex).lower(); + TQString adviceString = tmp.mid( splitIndex+1, tmp.length() ); + int splitIndex2 = adviceString.find( ':' ); + if( splitIndex2 == -1 ) { + // Java advice only + javaAdvice = strToAdvice( adviceString ); + javaScriptAdvice = KJavaScriptDunno; + } else { + // Java and JavaScript advice + javaAdvice = strToAdvice( adviceString.left( splitIndex2 ) ); + javaScriptAdvice = strToAdvice( adviceString.mid( splitIndex2+1, + adviceString.length() ) ); + } + } +} + +void TDEHTMLSettings::readDomainSettings(TDEConfig *config, bool reset, + bool global, KPerDomainSettings &pd_settings) { + TQString jsPrefix = global ? TQString::null + : TQString::fromLatin1("javascript."); + TQString javaPrefix = global ? TQString::null + : TQString::fromLatin1("java."); + TQString pluginsPrefix = global ? TQString::null + : TQString::fromLatin1("plugins."); + + // The setting for Java + TQString key = javaPrefix + TQString::fromLatin1("EnableJava"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_bEnableJava = config->readBoolEntry( key, false ); + else if ( !global ) + pd_settings.m_bEnableJava = d->global.m_bEnableJava; + + // The setting for Plugins + key = pluginsPrefix + TQString::fromLatin1("EnablePlugins"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_bEnablePlugins = config->readBoolEntry( key, true ); + else if ( !global ) + pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins; + + // The setting for JavaScript + key = jsPrefix + TQString::fromLatin1("EnableJavaScript"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_bEnableJavaScript = config->readBoolEntry( key, true ); + else if ( !global ) + pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript; + + // window property policies + key = jsPrefix + TQString::fromLatin1("WindowOpenPolicy"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_windowOpenPolicy = (KJSWindowOpenPolicy) + config->readUnsignedNumEntry( key, KJSWindowOpenSmart ); + else if ( !global ) + pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy; + + key = jsPrefix + TQString::fromLatin1("WindowMovePolicy"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_windowMovePolicy = (KJSWindowMovePolicy) + config->readUnsignedNumEntry( key, KJSWindowMoveAllow ); + else if ( !global ) + pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy; + + key = jsPrefix + TQString::fromLatin1("WindowResizePolicy"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_windowResizePolicy = (KJSWindowResizePolicy) + config->readUnsignedNumEntry( key, KJSWindowResizeAllow ); + else if ( !global ) + pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy; + + key = jsPrefix + TQString::fromLatin1("WindowStatusPolicy"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_windowStatusPolicy = (KJSWindowStatusPolicy) + config->readUnsignedNumEntry( key, KJSWindowStatusAllow ); + else if ( !global ) + pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy; + + key = jsPrefix + TQString::fromLatin1("WindowFocusPolicy"); + if ( (global && reset) || config->hasKey( key ) ) + pd_settings.m_windowFocusPolicy = (KJSWindowFocusPolicy) + config->readUnsignedNumEntry( key, KJSWindowFocusAllow ); + else if ( !global ) + pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy; + +} + + +TDEHTMLSettings::TDEHTMLSettings() +{ + d = new TDEHTMLSettingsPrivate(); + init(); +} + +TDEHTMLSettings::TDEHTMLSettings(const TDEHTMLSettings &other) +{ + d = new TDEHTMLSettingsPrivate(); + *d = *other.d; +} + +TDEHTMLSettings::~TDEHTMLSettings() +{ + delete d; +} + +bool TDEHTMLSettings::changeCursor() const +{ + return d->m_bChangeCursor; +} + +bool TDEHTMLSettings::underlineLink() const +{ + return d->m_underlineLink; +} + +bool TDEHTMLSettings::hoverLink() const +{ + return d->m_hoverLink; +} + +void TDEHTMLSettings::init() +{ + TDEConfig global( "tdehtmlrc", true, false ); + init( &global, true ); + + TDEConfig *local = TDEGlobal::config(); + if ( !local ) + return; + + init( local, false ); +} + +void TDEHTMLSettings::init( TDEConfig * config, bool reset ) +{ + TQString group_save = config->group(); + if (reset || config->hasGroup("MainView Settings")) + { + config->setGroup( "MainView Settings" ); + + if ( reset || config->hasKey( "OpenMiddleClick" ) ) + d->m_bOpenMiddleClick = config->readBoolEntry( "OpenMiddleClick", true ); + + if ( reset || config->hasKey( "BackRightClick" ) ) + d->m_bBackRightClick = config->readBoolEntry( "BackRightClick", false ); + } + + if (reset || config->hasGroup("Access Keys")) { + config->setGroup( "Access Keys" ); + d->m_accessKeysEnabled = config->readBoolEntry( "Enabled", true ); + } + + if (reset || config->hasGroup("Filter Settings")) + { + config->setGroup( "Filter Settings" ); + d->m_adFilterEnabled = config->readBoolEntry("Enabled", false); + d->m_hideAdsEnabled = config->readBoolEntry("Shrink", false); + + d->adFilters.clear(); + + TQMap entryMap = config->entryMap("Filter Settings"); + TQMap::ConstIterator it; + d->adFilters.reserve(entryMap.count()); + for( it = entryMap.constBegin(); it != entryMap.constEnd(); ++it ) + { + TQString name = it.key(); + TQString url = it.data(); + + if (url.startsWith("!")) + continue; + + if (name.startsWith("Filter")) + { + if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') + { + TQString inside = url.mid(1, url.length()-2); + TQRegExp rx(inside); + d->adFilters.append(rx); + } + else + { + TQRegExp rx; + int left,right; + + for (right=url.length(); right>0 && url[right-1]=='*' ; --right); + for (left=0; leftadFilters.append(rx); + } + } + } + } + + + if (reset || config->hasGroup("HTML Settings")) + { + config->setGroup( "HTML Settings" ); + // Fonts and colors + if( reset ) { + d->defaultFonts = TQStringList(); + d->defaultFonts.append( config->readEntry( "StandardFont", TDEGlobalSettings::generalFont().family() ) ); + d->defaultFonts.append( config->readEntry( "FixedFont", TDEGlobalSettings::fixedFont().family() ) ); + d->defaultFonts.append( config->readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) ); + d->defaultFonts.append( config->readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) ); + d->defaultFonts.append( config->readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) ); + d->defaultFonts.append( config->readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) ); + d->defaultFonts.append( TQString( "0" ) ); // font size adjustment + } + + if ( reset || config->hasKey( "MinimumFontSize" ) ) + d->m_minFontSize = config->readNumEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE ); + + if ( reset || config->hasKey( "MediumFontSize" ) ) + d->m_fontSize = config->readNumEntry( "MediumFontSize", 12 ); + + d->fonts = config->readListEntry( "Fonts" ); + + if ( reset || config->hasKey( "DefaultEncoding" ) ) + d->m_encoding = config->readEntry( "DefaultEncoding", "" ); + + if ( reset || config->hasKey( "EnforceDefaultCharset" ) ) + d->enforceCharset = config->readBoolEntry( "EnforceDefaultCharset", false ); + + // Behavior + if ( reset || config->hasKey( "ChangeCursor" ) ) + d->m_bChangeCursor = config->readBoolEntry( "ChangeCursor", KDE_DEFAULT_CHANGECURSOR ); + + if ( reset || config->hasKey("UnderlineLinks") ) + d->m_underlineLink = config->readBoolEntry( "UnderlineLinks", true ); + + if ( reset || config->hasKey( "HoverLinks" ) ) + { + if ( ( d->m_hoverLink = config->readBoolEntry( "HoverLinks", false ) ) ) + d->m_underlineLink = false; + } + + if ( reset || config->hasKey( "AllowTabulation" ) ) + d->m_allowTabulation = config->readBoolEntry( "AllowTabulation", false ); + + if ( reset || config->hasKey( "AutoSpellCheck" ) ) + d->m_autoSpellCheck = config->readBoolEntry( "AutoSpellCheck", true ); + + // Other + if ( reset || config->hasKey( "AutoLoadImages" ) ) + d->m_bAutoLoadImages = config->readBoolEntry( "AutoLoadImages", true ); + + if ( reset || config->hasKey( "UnfinishedImageFrame" ) ) + d->m_bUnfinishedImageFrame = config->readBoolEntry( "UnfinishedImageFrame", true ); + + if ( reset || config->hasKey( "ShowAnimations" ) ) + { + TQString value = config->readEntry( "ShowAnimations").lower(); + if (value == "disabled") + d->m_showAnimations = KAnimationDisabled; + else if (value == "looponce") + d->m_showAnimations = KAnimationLoopOnce; + else + d->m_showAnimations = KAnimationEnabled; + } + + if ( config->readBoolEntry( "UserStyleSheetEnabled", false ) == true ) { + if ( reset || config->hasKey( "UserStyleSheet" ) ) + d->m_userSheet = config->readEntry( "UserStyleSheet", "" ); + } + + d->m_formCompletionEnabled = config->readBoolEntry("FormCompletion", true); + d->m_maxFormCompletionItems = config->readNumEntry("MaxFormCompletionItems", 10); + d->m_autoDelayedActionsEnabled = config->readBoolEntry ("AutoDelayedActions", true); + d->m_jsErrorsEnabled = config->readBoolEntry("ReportJSErrors", true); + TQStringList accesskeys = config->readListEntry("FallbackAccessKeysAssignments"); + d->m_fallbackAccessKeysAssignments.clear(); + for( TQStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it ) + if( (*it).length() > 2 && (*it)[ 1 ] == ':' ) + d->m_fallbackAccessKeysAssignments.append( tqMakePair( (*it).mid( 2 ), (*it)[ 0 ] )); + } + + // Colors + + if ( reset || config->hasKey( "FollowSystemColors" ) ) + d->m_follow_system_colors = config->readBoolEntry( "FollowSystemColors", false ); + + if ( reset || config->hasGroup( "General" ) ) + { + config->setGroup( "General" ); // group will be restored by cgs anyway + if ( reset || config->hasKey( "foreground" ) ) + d->m_textColor = config->readColorEntry( "foreground", &HTML_DEFAULT_TXT_COLOR ); + + if ( reset || config->hasKey( "linkColor" ) ) + d->m_linkColor = config->readColorEntry( "linkColor", &HTML_DEFAULT_LNK_COLOR ); + + if ( reset || config->hasKey( "visitedLinkColor" ) ) + d->m_vLinkColor = config->readColorEntry( "visitedLinkColor", &HTML_DEFAULT_VLNK_COLOR); + + if ( reset || config->hasKey( "background" ) ) + d->m_baseColor = config->readColorEntry( "background", &HTML_DEFAULT_BASE_COLOR); + } + + if( reset || config->hasGroup( "Java/JavaScript Settings" ) ) + { + config->setGroup( "Java/JavaScript Settings" ); + + // The global setting for JavaScript debugging + // This is currently always enabled by default + if ( reset || config->hasKey( "EnableJavaScriptDebug" ) ) + d->m_bEnableJavaScriptDebug = config->readBoolEntry( "EnableJavaScriptDebug", false ); + + // The global setting for JavaScript error reporting + if ( reset || config->hasKey( "ReportJavaScriptErrors" ) ) + d->m_bEnableJavaScriptErrorReporting = config->readBoolEntry( "ReportJavaScriptErrors", false ); + + // The global setting for popup block passive popup + if ( reset || config->hasKey( "PopupBlockerPassivePopup" ) ) + d->m_jsPopupBlockerPassivePopup = config->readBoolEntry("PopupBlockerPassivePopup", true); + + // Read options from the global "domain" + readDomainSettings(config,reset,true,d->global); +#ifdef DEBUG_SETTINGS + d->global.dump("init global"); +#endif + + // The domain-specific settings. + + static const char *const domain_keys[] = { // always keep order of keys + "ECMADomains", "JavaDomains", "PluginDomains" + }; + bool check_old_ecma_settings = true; + bool check_old_java_settings = true; + // merge all domains into one list + TQMap domainList; // why can't Qt have a QSet? + for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) { + if ( reset || config->hasKey(domain_keys[i]) ) { + if (i == 0) check_old_ecma_settings = false; + else if (i == 1) check_old_java_settings = false; + const TQStringList dl = config->readListEntry( domain_keys[i] ); + const TQMap::Iterator notfound = domainList.end(); + TQStringList::ConstIterator it = dl.begin(); + const TQStringList::ConstIterator itEnd = dl.end(); + for (; it != itEnd; ++it) { + const TQString domain = (*it).lower(); + TQMap::Iterator pos = domainList.find(domain); + if (pos == notfound) domainList.insert(domain,0); + }/*next it*/ + } + }/*next i*/ + + if (reset) + d->domainPolicy.clear(); + + TQString js_group_save = config->group(); + { + TQMap::ConstIterator it = domainList.begin(); + const TQMap::ConstIterator itEnd = domainList.end(); + for ( ; it != itEnd; ++it) + { + const TQString domain = it.key(); + config->setGroup(domain); + readDomainSettings(config,reset,false,d->domainPolicy[domain]); +#ifdef DEBUG_SETTINGS + d->domainPolicy[domain].dump("init "+domain); +#endif + } + } + config->setGroup(js_group_save); + + bool check_old_java = true; + if( ( reset || config->hasKey( "JavaDomainSettings" ) ) + && check_old_java_settings ) + { + check_old_java = false; + const TQStringList domainList = config->readListEntry( "JavaDomainSettings" ); + TQStringList::ConstIterator it = domainList.begin(); + const TQStringList::ConstIterator itEnd = domainList.end(); + for ( ; it != itEnd; ++it) + { + TQString domain; + KJavaScriptAdvice javaAdvice; + KJavaScriptAdvice javaScriptAdvice; + splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); + setup_per_domain_policy(d,domain).m_bEnableJava = + javaAdvice == KJavaScriptAccept; +#ifdef DEBUG_SETTINGS + setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain); +#endif + } + } + + bool check_old_ecma = true; + if( ( reset || config->hasKey( "ECMADomainSettings" ) ) + && check_old_ecma_settings ) + { + check_old_ecma = false; + const TQStringList domainList = config->readListEntry( "ECMADomainSettings" ); + TQStringList::ConstIterator it = domainList.begin(); + const TQStringList::ConstIterator itEnd = domainList.end(); + for ( ; it != itEnd; ++it) + { + TQString domain; + KJavaScriptAdvice javaAdvice; + KJavaScriptAdvice javaScriptAdvice; + splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); + setup_per_domain_policy(d,domain).m_bEnableJavaScript = + javaScriptAdvice == KJavaScriptAccept; +#ifdef DEBUG_SETTINGS + setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain); +#endif + } + } + + if( ( reset || config->hasKey( "JavaScriptDomainAdvice" ) ) + && ( check_old_java || check_old_ecma ) + && ( check_old_ecma_settings || check_old_java_settings ) ) + { + const TQStringList domainList = config->readListEntry( "JavaScriptDomainAdvice" ); + TQStringList::ConstIterator it = domainList.begin(); + const TQStringList::ConstIterator itEnd = domainList.end(); + for ( ; it != itEnd; ++it) + { + TQString domain; + KJavaScriptAdvice javaAdvice; + KJavaScriptAdvice javaScriptAdvice; + splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); + if( check_old_java ) + setup_per_domain_policy(d,domain).m_bEnableJava = + javaAdvice == KJavaScriptAccept; + if( check_old_ecma ) + setup_per_domain_policy(d,domain).m_bEnableJavaScript = + javaScriptAdvice == KJavaScriptAccept; +#ifdef DEBUG_SETTINGS + setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain); +#endif + } + + //save all the settings into the new keywords if they don't exist +#if 0 + if( check_old_java ) + { + TQStringList domainConfig; + PolicyMap::Iterator it; + for( it = d->javaDomainPolicy.begin(); it != d->javaDomainPolicy.end(); ++it ) + { + TQCString javaPolicy = adviceToStr( it.data() ); + TQCString javaScriptPolicy = adviceToStr( KJavaScriptDunno ); + domainConfig.append(TQString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy)); + } + config->writeEntry( "JavaDomainSettings", domainConfig ); + } + + if( check_old_ecma ) + { + TQStringList domainConfig; + PolicyMap::Iterator it; + for( it = d->javaScriptDomainPolicy.begin(); it != d->javaScriptDomainPolicy.end(); ++it ) + { + TQCString javaPolicy = adviceToStr( KJavaScriptDunno ); + TQCString javaScriptPolicy = adviceToStr( it.data() ); + domainConfig.append(TQString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy)); + } + config->writeEntry( "ECMADomainSettings", domainConfig ); + } +#endif + } + } + config->setGroup(group_save); +} + + +/** Local helper for retrieving per-domain settings. + * + * In case of doubt, the global domain is returned. + */ +static const KPerDomainSettings &lookup_hostname_policy( + const TDEHTMLSettingsPrivate *d, + const TQString& hostname) +{ +#ifdef DEBUG_SETTINGS + kdDebug() << "lookup_hostname_policy(" << hostname << ")" << endl; +#endif + if (hostname.isEmpty()) { +#ifdef DEBUG_SETTINGS + d->global.dump("global"); +#endif + return d->global; + } + + const PolicyMap::const_iterator notfound = d->domainPolicy.end(); + + // First check whether there is a perfect match. + PolicyMap::const_iterator it = d->domainPolicy.find(hostname); + if( it != notfound ) { +#ifdef DEBUG_SETTINGS + kdDebug() << "perfect match" << endl; + (*it).dump(hostname); +#endif + // yes, use it (unless dunno) + return *it; + } + + // Now, check for partial match. Chop host from the left until + // there's no dots left. + TQString host_part = hostname; + int dot_idx = -1; + while( (dot_idx = host_part.find(TQChar('.'))) >= 0 ) { + host_part.remove(0,dot_idx); + it = d->domainPolicy.find(host_part); + Q_ASSERT(notfound == d->domainPolicy.end()); + if( it != notfound ) { +#ifdef DEBUG_SETTINGS + kdDebug() << "partial match" << endl; + (*it).dump(host_part); +#endif + return *it; + } + // assert(host_part[0] == TQChar('.')); + host_part.remove(0,1); // Chop off the dot. + } + + // No domain-specific entry: use global domain +#ifdef DEBUG_SETTINGS + kdDebug() << "no match" << endl; + d->global.dump("global"); +#endif + return d->global; +} + +bool TDEHTMLSettings::isOpenMiddleClickEnabled() +{ + return d->m_bOpenMiddleClick; +} + +bool TDEHTMLSettings::isBackRightClickEnabled() +{ + return d->m_bBackRightClick; +} + +bool TDEHTMLSettings::accessKeysEnabled() const +{ + return d->m_accessKeysEnabled; +} + +bool TDEHTMLSettings::isAdFilterEnabled() const +{ + return d->m_adFilterEnabled; +} + +bool TDEHTMLSettings::isHideAdsEnabled() const +{ + return d->m_hideAdsEnabled; +} + +bool TDEHTMLSettings::isAdFiltered( const TQString &url ) const +{ + if (d->m_adFilterEnabled) + { + if (!url.startsWith("data:")) + { + TQValueVector::const_iterator it(d->adFilters.constBegin()); + TQValueVector::const_iterator end(d->adFilters.constEnd()); + for (; it != end; ++it) + { + if ((*it).search(url) != -1) + { + kdDebug( 6080 ) << "Filtered: " << url << endl; + return true; + } + } + } + } + return false; +} + +void TDEHTMLSettings::addAdFilter( const TQString &url ) +{ + TDEConfig config( "tdehtmlrc", false, false ); + config.setGroup( "Filter Settings" ); + + TQRegExp rx; + if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') + { + TQString inside = url.mid(1, url.length()-2); + rx.setWildcard(false); + rx.setPattern(inside); + } + else + { + int left,right; + + rx.setWildcard(true); + for (right=url.length(); right>0 && url[right-1]=='*' ; --right); + for (left=0; leftadFilters.append(rx); + } + else + { + KMessageBox::error(0, + rx.errorString(), + i18n("Filter error")); + } +} + +bool TDEHTMLSettings::isJavaEnabled( const TQString& hostname ) +{ + return lookup_hostname_policy(d,hostname.lower()).m_bEnableJava; +} + +bool TDEHTMLSettings::isJavaScriptEnabled( const TQString& hostname ) +{ + return lookup_hostname_policy(d,hostname.lower()).m_bEnableJavaScript; +} + +bool TDEHTMLSettings::isJavaScriptDebugEnabled( const TQString& /*hostname*/ ) +{ + // debug setting is global for now, but could change in the future + return d->m_bEnableJavaScriptDebug; +} + +bool TDEHTMLSettings::isJavaScriptErrorReportingEnabled( const TQString& /*hostname*/ ) const +{ + // error reporting setting is global for now, but could change in the future + return d->m_bEnableJavaScriptErrorReporting; +} + +bool TDEHTMLSettings::isPluginsEnabled( const TQString& hostname ) +{ + return lookup_hostname_policy(d,hostname.lower()).m_bEnablePlugins; +} + +TDEHTMLSettings::KJSWindowOpenPolicy TDEHTMLSettings::windowOpenPolicy( + const TQString& hostname) const { + return lookup_hostname_policy(d,hostname.lower()).m_windowOpenPolicy; +} + +TDEHTMLSettings::KJSWindowMovePolicy TDEHTMLSettings::windowMovePolicy( + const TQString& hostname) const { + return lookup_hostname_policy(d,hostname.lower()).m_windowMovePolicy; +} + +TDEHTMLSettings::KJSWindowResizePolicy TDEHTMLSettings::windowResizePolicy( + const TQString& hostname) const { + return lookup_hostname_policy(d,hostname.lower()).m_windowResizePolicy; +} + +TDEHTMLSettings::KJSWindowStatusPolicy TDEHTMLSettings::windowStatusPolicy( + const TQString& hostname) const { + return lookup_hostname_policy(d,hostname.lower()).m_windowStatusPolicy; +} + +TDEHTMLSettings::KJSWindowFocusPolicy TDEHTMLSettings::windowFocusPolicy( + const TQString& hostname) const { + return lookup_hostname_policy(d,hostname.lower()).m_windowFocusPolicy; +} + +int TDEHTMLSettings::mediumFontSize() const +{ + return d->m_fontSize; +} + +int TDEHTMLSettings::minFontSize() const +{ + return d->m_minFontSize; +} + +TQString TDEHTMLSettings::settingsToCSS() const +{ + // lets start with the link properties + TQString str = "a:link {\ncolor: "; + str += d->m_linkColor.name(); + str += ";"; + if(d->m_underlineLink) + str += "\ntext-decoration: underline;"; + + if( d->m_bChangeCursor ) + { + str += "\ncursor: pointer;"; + str += "\n}\ninput[type=image] { cursor: pointer;"; + } + str += "\n}\n"; + str += "a:visited {\ncolor: "; + str += d->m_vLinkColor.name(); + str += ";"; + if(d->m_underlineLink) + str += "\ntext-decoration: underline;"; + + if( d->m_bChangeCursor ) + str += "\ncursor: pointer;"; + str += "\n}\n"; + + if(d->m_hoverLink) + str += "a:link:hover, a:visited:hover { text-decoration: underline; }\n"; + + return str; +} + +const TQString &TDEHTMLSettings::availableFamilies() +{ + if ( !avFamilies ) { + avFamilies = new TQString; + TQFontDatabase db; + TQStringList families = db.families(); + TQStringList s; + TQRegExp foundryExp(" \\[.+\\]"); + + //remove foundry info + TQStringList::Iterator f = families.begin(); + const TQStringList::Iterator fEnd = families.end(); + + for ( ; f != fEnd; ++f ) { + (*f).replace( foundryExp, ""); + if (!s.contains(*f)) + s << *f; + } + s.sort(); + + *avFamilies = ',' + s.join(",") + ','; + } + + return *avFamilies; +} + +TQString TDEHTMLSettings::lookupFont(int i) const +{ + TQString font; + if (d->fonts.count() > (uint) i) + font = d->fonts[i]; + if (font.isEmpty()) + font = d->defaultFonts[i]; + return font; +} + +TQString TDEHTMLSettings::stdFontName() const +{ + return lookupFont(0); +} + +TQString TDEHTMLSettings::fixedFontName() const +{ + return lookupFont(1); +} + +TQString TDEHTMLSettings::serifFontName() const +{ + return lookupFont(2); +} + +TQString TDEHTMLSettings::sansSerifFontName() const +{ + return lookupFont(3); +} + +TQString TDEHTMLSettings::cursiveFontName() const +{ + return lookupFont(4); +} + +TQString TDEHTMLSettings::fantasyFontName() const +{ + return lookupFont(5); +} + +void TDEHTMLSettings::setStdFontName(const TQString &n) +{ + while(d->fonts.count() <= 0) + d->fonts.append(TQString::null); + d->fonts[0] = n; +} + +void TDEHTMLSettings::setFixedFontName(const TQString &n) +{ + while(d->fonts.count() <= 1) + d->fonts.append(TQString::null); + d->fonts[1] = n; +} + +TQString TDEHTMLSettings::userStyleSheet() const +{ + return d->m_userSheet; +} + +bool TDEHTMLSettings::isFormCompletionEnabled() const +{ + return d->m_formCompletionEnabled; +} + +int TDEHTMLSettings::maxFormCompletionItems() const +{ + return d->m_maxFormCompletionItems; +} + +const TQString &TDEHTMLSettings::encoding() const +{ + return d->m_encoding; +} + +bool TDEHTMLSettings::followSystemColors() const +{ + return d->m_follow_system_colors; +} + +const TQColor& TDEHTMLSettings::textColor() const +{ + return d->m_textColor; +} + +const TQColor& TDEHTMLSettings::baseColor() const +{ + return d->m_baseColor; +} + +const TQColor& TDEHTMLSettings::linkColor() const +{ + return d->m_linkColor; +} + +const TQColor& TDEHTMLSettings::vLinkColor() const +{ + return d->m_vLinkColor; +} + +bool TDEHTMLSettings::autoLoadImages() const +{ + return d->m_bAutoLoadImages; +} + +bool TDEHTMLSettings::unfinishedImageFrame() const +{ + return d->m_bUnfinishedImageFrame; +} + +TDEHTMLSettings::KAnimationAdvice TDEHTMLSettings::showAnimations() const +{ + return d->m_showAnimations; +} + +bool TDEHTMLSettings::isAutoDelayedActionsEnabled() const +{ + return d->m_autoDelayedActionsEnabled; +} + +bool TDEHTMLSettings::jsErrorsEnabled() const +{ + return d->m_jsErrorsEnabled; +} + +void TDEHTMLSettings::setJSErrorsEnabled(bool enabled) +{ + d->m_jsErrorsEnabled = enabled; + // save it + TDEConfig *config = TDEGlobal::config(); + config->setGroup("HTML Settings"); + config->writeEntry("ReportJSErrors", enabled); + config->sync(); +} + +bool TDEHTMLSettings::allowTabulation() const +{ + return d->m_allowTabulation; +} + +bool TDEHTMLSettings::autoSpellCheck() const +{ + return d->m_autoSpellCheck; +} + +TQValueList< TQPair< TQString, TQChar > > TDEHTMLSettings::fallbackAccessKeysAssignments() const +{ + return d->m_fallbackAccessKeysAssignments; +} + +void TDEHTMLSettings::setJSPopupBlockerPassivePopup(bool enabled) +{ + d->m_jsPopupBlockerPassivePopup = enabled; + // save it + TDEConfig *config = TDEGlobal::config(); + config->setGroup("Java/JavaScript Settings"); + config->writeEntry("PopupBlockerPassivePopup", enabled); + config->sync(); +} + +bool TDEHTMLSettings::jsPopupBlockerPassivePopup() const +{ + return d->m_jsPopupBlockerPassivePopup; +} diff --git a/tdeio/Makefile.am b/tdeio/Makefile.am index 67a074f2a..b82616c8d 100644 --- a/tdeio/Makefile.am +++ b/tdeio/Makefile.am @@ -61,7 +61,7 @@ dummy.cpp: messages: $(EXTRACTRC) `find . ../tdeioslave -name "*.rc" -o -name "*.ui"` > rc.cpp - $(XGETTEXT) `find . ../tdeioslave -name "*.cpp" -o -name "*.cc" -o -name "*.h"` -o $(podir)/tdeio.pot + $(XGETTEXT) `find . ../tdeioslave -name "*.cpp" -o -name "*.h"` -o $(podir)/tdeio.pot rm -f rc.cpp SUFFIXES = .magic .magic.mgc diff --git a/tdeio/bookmarks/CMakeLists.txt b/tdeio/bookmarks/CMakeLists.txt index c4ed8c9b2..30ab617a2 100644 --- a/tdeio/bookmarks/CMakeLists.txt +++ b/tdeio/bookmarks/CMakeLists.txt @@ -41,11 +41,11 @@ install( FILES set( target kbookmarks ) set( ${target}_SRCS - kbookmark.cc kbookmarkbar.cc kbookmarkdrag.cc kbookmarkexporter.cc - kbookmarkimporter.cc kbookmarkmanager.cc kbookmarkmenu.cc - kbookmarkimporter_crash.cc kbookmarkimporter_opera.cc - kbookmarkimporter_ie.cc kbookmarkimporter_ns.cc - kbookmarkimporter_kde1.cc kbookmarkdombuilder.cc + kbookmark.cpp kbookmarkbar.cpp kbookmarkdrag.cpp kbookmarkexporter.cpp + kbookmarkimporter.cpp kbookmarkmanager.cpp kbookmarkmenu.cpp + kbookmarkimporter_crash.cpp kbookmarkimporter_opera.cpp + kbookmarkimporter_ie.cpp kbookmarkimporter_ns.cpp + kbookmarkimporter_kde1.cpp kbookmarkdombuilder.cpp kbookmarkmanager.skel kbookmarknotifier.skel ) diff --git a/tdeio/bookmarks/Makefile.am b/tdeio/bookmarks/Makefile.am index e1ec3a8df..d3bf34b93 100644 --- a/tdeio/bookmarks/Makefile.am +++ b/tdeio/bookmarks/Makefile.am @@ -31,10 +31,10 @@ include_HEADERS = \ kbookmarkimporter_crash.h kbookmarkimporter_opera.h kbookmarkimporter_ie.h \ kbookmarkimporter_ns.h kbookmarkimporter_kde1.h kbookmarkdombuilder.h libkbookmarks_la_SOURCES = \ - kbookmark.cc kbookmarkbar.cc kbookmarkdrag.cc kbookmarkexporter.cc \ - kbookmarkimporter.cc kbookmarkmanager.cc kbookmarkmenu.cc \ - kbookmarkimporter_crash.cc kbookmarkimporter_opera.cc kbookmarkimporter_ie.cc \ - kbookmarkimporter_ns.cc kbookmarkimporter_kde1.cc kbookmarkdombuilder.cc \ + kbookmark.cpp kbookmarkbar.cpp kbookmarkdrag.cpp kbookmarkexporter.cpp \ + kbookmarkimporter.cpp kbookmarkmanager.cpp kbookmarkmenu.cpp \ + kbookmarkimporter_crash.cpp kbookmarkimporter_opera.cpp kbookmarkimporter_ie.cpp \ + kbookmarkimporter_ns.cpp kbookmarkimporter_kde1.cpp kbookmarkdombuilder.cpp \ kbookmarkmanager.skel kbookmarknotifier.skel include $(top_srcdir)/admin/Doxyfile.am diff --git a/tdeio/bookmarks/kbookmark.cc b/tdeio/bookmarks/kbookmark.cc deleted file mode 100644 index 1e8bf8f7a..000000000 --- a/tdeio/bookmarks/kbookmark.cc +++ /dev/null @@ -1,538 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure - Copyright (C) 2003 Alexander Kellett - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmark.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -KBookmarkGroup::KBookmarkGroup() - : KBookmark( TQDomElement() ) -{ -} - -KBookmarkGroup::KBookmarkGroup( TQDomElement elem ) - : KBookmark(elem) -{ -} - -TQString KBookmarkGroup::groupAddress() const -{ - if (m_address.isEmpty()) - m_address = address(); - return m_address; -} - -bool KBookmarkGroup::isOpen() const -{ - return element.attribute("folded") == "no"; // default is: folded -} - -// Returns first element node equal to or after node n -static TQDomElement firstElement(TQDomNode n) -{ - while(!n.isNull() && !n.isElement()) - n = n.nextSibling(); - return n.toElement(); -} - -// Returns first element node equal to or before node n -static TQDomElement lastElement(TQDomNode n) -{ - while(!n.isNull() && !n.isElement()) - n = n.previousSibling(); - return n.toElement(); -} - -KBookmark KBookmarkGroup::first() const -{ - return KBookmark( nextKnownTag( firstElement(element.firstChild()), true ) ); -} - -KBookmark KBookmarkGroup::previous( const KBookmark & current ) const -{ - return KBookmark( nextKnownTag( lastElement(current.element.previousSibling()), false ) ); -} - -KBookmark KBookmarkGroup::next( const KBookmark & current ) const -{ - return KBookmark( nextKnownTag( firstElement(current.element.nextSibling()), true ) ); -} - -// KDE4: Change TQDomElement to TQDomNode so that we can get rid of -// firstElement() and lastElement() -TQDomElement KBookmarkGroup::nextKnownTag( TQDomElement start, bool goNext ) const -{ - static const TQString & bookmark = TDEGlobal::staticQString("bookmark"); - static const TQString & folder = TDEGlobal::staticQString("folder"); - static const TQString & separator = TDEGlobal::staticQString("separator"); - - for( TQDomNode n = start; !n.isNull(); ) - { - TQDomElement elem = n.toElement(); - TQString tag = elem.tagName(); - if (tag == folder || tag == bookmark || tag == separator) - return elem; - if (goNext) - n = n.nextSibling(); - else - n = n.previousSibling(); - } - return TQDomElement(); -} - -KBookmarkGroup KBookmarkGroup::createNewFolder( KBookmarkManager* mgr, const TQString & text, bool emitSignal ) -{ - TQString txt( text ); - if ( text.isEmpty() ) - { - bool ok; - TQString caption = parentGroup().fullText().isEmpty() ? - i18n( "Create New Bookmark Folder" ) : - i18n( "Create New Bookmark Folder in %1" ) - .arg( parentGroup().text() ); - txt = KInputDialog::getText( caption, i18n( "New folder:" ), - TQString::null, &ok ); - if ( !ok ) - return KBookmarkGroup(); - } - - Q_ASSERT(!element.isNull()); - TQDomDocument doc = element.ownerDocument(); - TQDomElement groupElem = doc.createElement( "folder" ); - element.appendChild( groupElem ); - TQDomElement textElem = doc.createElement( "title" ); - groupElem.appendChild( textElem ); - textElem.appendChild( doc.createTextNode( txt ) ); - - KBookmarkGroup grp(groupElem); - - if (emitSignal) - emit mgr->notifier().createdNewFolder( - mgr->path(), grp.fullText(), - grp.address() ); - - return grp; - -} - -KBookmark KBookmarkGroup::createNewSeparator() -{ - Q_ASSERT(!element.isNull()); - TQDomDocument doc = element.ownerDocument(); - Q_ASSERT(!doc.isNull()); - TQDomElement sepElem = doc.createElement( "separator" ); - element.appendChild( sepElem ); - return KBookmark(sepElem); -} - -bool KBookmarkGroup::moveItem( const KBookmark & item, const KBookmark & after ) -{ - TQDomNode n; - if ( !after.isNull() ) - n = element.insertAfter( item.element, after.element ); - else // first child - { - if ( element.firstChild().isNull() ) // Empty element -> set as real first child - n = element.insertBefore( item.element, TQDomElement() ); - - // we have to skip everything up to the first valid child - TQDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true); - if ( !firstChild.isNull() ) - n = element.insertBefore( item.element, firstChild ); - else - { - // No real first child -> append after the etc. - n = element.appendChild( item.element ); - } - } - return (!n.isNull()); -} - -KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const KBookmark &bm, bool emitSignal ) -{ - element.appendChild( bm.internalElement() ); - - if (emitSignal) { - if ( bm.hasMetaData() ) { - mgr->notifyCompleteChange( "" ); - } else { - emit mgr->notifier().addedBookmark( - mgr->path(), bm.url().url(), - bm.fullText(), bm.address(), bm.icon() ); - } - } - - return bm; -} - -KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const TQString & text, const KURL & url, const TQString & icon, bool emitSignal ) -{ - //kdDebug(7043) << "KBookmarkGroup::addBookmark " << text << " into " << m_address << endl; - TQDomDocument doc = element.ownerDocument(); - TQDomElement elem = doc.createElement( "bookmark" ); - elem.setAttribute( "href", url.url( 0, 106 ) ); // write utf8 URL (106 is mib enum for utf8) - TQString _icon = icon; - if ( _icon.isEmpty() ) - _icon = KMimeType::iconForURL( url ); - elem.setAttribute( "icon", _icon ); - - TQDomElement textElem = doc.createElement( "title" ); - elem.appendChild( textElem ); - textElem.appendChild( doc.createTextNode( text ) ); - - return addBookmark( mgr, KBookmark( elem ), emitSignal ); -} - -void KBookmarkGroup::deleteBookmark( KBookmark bk ) -{ - element.removeChild( bk.element ); -} - -bool KBookmarkGroup::isToolbarGroup() const -{ - return ( element.attribute("toolbar") == "yes" ); -} - -TQDomElement KBookmarkGroup::findToolbar() const -{ - if ( element.attribute("toolbar") == "yes" ) - return element; - for (TQDomNode n = element.firstChild(); !n.isNull() ; n = n.nextSibling() ) - { - TQDomElement e = n.toElement(); - // Search among the "folder" children only - if ( e.tagName() == "folder" ) - { - if ( e.attribute("toolbar") == "yes" ) - return e; - else - { - TQDomElement result = KBookmarkGroup(e).findToolbar(); - if (!result.isNull()) - return result; - } - } - } - return TQDomElement(); -} - -TQValueList<KURL> KBookmarkGroup::groupUrlList() const -{ - TQValueList<KURL> urlList; - for ( KBookmark bm = first(); !bm.isNull(); bm = next(bm) ) - { - if ( bm.isSeparator() || bm.isGroup() ) - continue; - urlList << bm.url(); - } - return urlList; -} - -////// - -bool KBookmark::isGroup() const -{ - TQString tag = element.tagName(); - return ( tag == "folder" - || tag == "xbel" ); // don't forget the toplevel group -} - -bool KBookmark::isSeparator() const -{ - return (element.tagName() == "separator"); -} - -bool KBookmark::hasParent() const -{ - TQDomElement parent = element.parentNode().toElement(); - return !parent.isNull(); -} - -TQString KBookmark::text() const -{ - return KStringHandler::csqueeze( fullText() ); -} - -TQString KBookmark::fullText() const -{ - if (isSeparator()) - return i18n("--- separator ---"); - - return element.namedItem("title").toElement().text(); -} - -KURL KBookmark::url() const -{ - return KURL(element.attribute("href"), 106); // Decode it from utf8 (106 is mib enum for utf8) -} - -TQString KBookmark::icon() const -{ - TQString icon = element.attribute("icon"); - if ( icon.isEmpty() ) { - // Default icon depends on URL for bookmarks, and is default directory - // icon for groups. - if ( isGroup() ) { - icon = "bookmark_folder"; - } - else { - if ( isSeparator() ) { - icon = "eraser"; // whatever - } - else { - icon = KMimeType::iconForURL( url() ); - } - } - } - return icon; -} - -KBookmarkGroup KBookmark::parentGroup() const -{ - return KBookmarkGroup( element.parentNode().toElement() ); -} - -KBookmarkGroup KBookmark::toGroup() const -{ - Q_ASSERT( isGroup() ); - return KBookmarkGroup(element); -} - -TQString KBookmark::address() const -{ - if ( element.tagName() == "xbel" ) - return ""; // not TQString::null ! - else - { - // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :) - if (!hasParent()) - { - Q_ASSERT(hasParent()); - return "ERROR"; // Avoid an infinite loop - } - KBookmarkGroup group = parentGroup(); - TQString parentAddress = group.address(); - uint counter = 0; - // Implementation note: we don't use QDomNode's childNode list because we - // would have to skip "TEXT", which KBookmarkGroup already does for us. - for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++counter ) - { - if ( bk.element == element ) - return parentAddress + "/" + TQString::number(counter); - } - kdWarning() << "KBookmark::address : this can't happen! " << parentAddress << endl; - return "ERROR"; - } -} - -KBookmark KBookmark::standaloneBookmark( const TQString & text, const KURL & url, const TQString & icon ) -{ - TQDomDocument doc("xbel"); - TQDomElement elem = doc.createElement("xbel"); - doc.appendChild( elem ); - KBookmarkGroup grp( elem ); - grp.addBookmark( 0L, text, url, icon, false ); - return grp.first(); -} - -// For some strange reason TQString("").left(0) returns TQString::null; -// That breaks commonParent() -TQString KBookmark::left(const TQString & str, uint len) -{ - //kdDebug()<<"********"<<TQString("").left(0).isNull()<<endl; - if(len == 0) - return TQString(""); - else - return str.left(len); -} - -TQString KBookmark::commonParent(TQString A, TQString B) -{ - TQString error("ERROR"); - if(A == error || B == error) - return error; - - A += "/"; - B += "/"; - - uint lastCommonSlash = 0; - uint lastPos = A.length() < B.length() ? A.length() : B.length(); - for(uint i=0; i < lastPos; ++i) - { - if(A[i] != B[i]) - return left(A, lastCommonSlash); - if(A[i] == '/') - lastCommonSlash = i; - } - return left(A, lastCommonSlash); -} - -static TQDomNode cd_or_create(TQDomNode node, TQString name) -{ - TQDomNode subnode = node.namedItem(name); - if (subnode.isNull()) - { - subnode = node.ownerDocument().createElement(name); - node.appendChild(subnode); - } - return subnode; -} - -static TQDomText get_or_create_text(TQDomNode node) -{ - TQDomNode subnode = node.firstChild(); - if (subnode.isNull()) - { - subnode = node.ownerDocument().createTextNode(""); - node.appendChild(subnode); - } - return subnode.toText(); -} - -// Look for a metadata with owner="http://www.kde.org" or without any owner (for compatibility) -static TQDomNode findOrCreateMetadata( TQDomNode& parent ) -{ - static const char kdeOwner[] = "http://www.kde.org"; - TQDomElement metadataElement; - for ( TQDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling() ) { - TQDomElement elem = _node.toElement(); - if ( !elem.isNull() && elem.tagName() == "metadata" ) { - const TQString owner = elem.attribute( "owner" ); - if ( owner == kdeOwner ) - return elem; - if ( owner.isEmpty() ) - metadataElement = elem; - } - } - if ( metadataElement.isNull() ) { - metadataElement = parent.ownerDocument().createElement( "metadata" ); - parent.appendChild(metadataElement); - } - metadataElement.setAttribute( "owner", kdeOwner ); - return metadataElement; -} - -bool KBookmark::hasMetaData() const -{ - // ### NOTE: this code creates <info> and <metadata>, despite its name and the const. - // It doesn't matter much in practice since it's only called for newly-created bookmarks, - // which will get metadata soon after anyway. - TQDomNode n = cd_or_create( internalElement(), "info" ); - return findOrCreateMetadata( n ).hasChildNodes(); -} - -void KBookmark::updateAccessMetadata() -{ - kdDebug(7043) << "KBookmark::updateAccessMetadata " << address() << " " << url().prettyURL() << endl; - - const uint timet = TQDateTime::currentDateTime().toTime_t(); - setMetaDataItem( "time_added", TQString::number( timet ), DontOverwriteMetaData ); - setMetaDataItem( "time_visited", TQString::number( timet ) ); - - TQString countStr = metaDataItem( "visit_count" ); // TODO use spec'ed name - bool ok; - int currentCount = countStr.toInt(&ok); - if (!ok) - currentCount = 0; - currentCount++; - setMetaDataItem( "visit_count", TQString::number( currentCount ) ); - - // TODO - for 4.0 - time_modified -} - -TQString KBookmark::metaDataItem( const TQString &key ) const -{ - TQDomNode infoNode = cd_or_create( internalElement(), "info" ); - infoNode = findOrCreateMetadata( infoNode ); - for ( TQDomNode n = infoNode.firstChild(); !n.isNull(); n = n.nextSibling() ) { - if ( !n.isElement() ) { - continue; - } - const TQDomElement e = n.toElement(); - if ( e.tagName() == key ) { - return e.text(); - } - } - return TQString::null; -} - -void KBookmark::setMetaDataItem( const TQString &key, const TQString &value, MetaDataOverwriteMode mode ) -{ - TQDomNode infoNode = cd_or_create( internalElement(), "info" ); - infoNode = findOrCreateMetadata( infoNode ); - - TQDomNode item = cd_or_create( infoNode, key ); - TQDomText text = get_or_create_text( item ); - if ( mode == DontOverwriteMetaData && !text.data().isEmpty() ) { - return; - } - - text.setData( value ); -} - -void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root) -{ - // non-recursive bookmark iterator - TQValueStack<KBookmarkGroup> stack; - stack.push(root); - KBookmark bk = stack.top().first(); - for (;;) { - if (bk.isNull()) - { - if (stack.isEmpty()) - return; - if (stack.count() > 1) - visitLeave(stack.top()); - bk = stack.pop(); - bk = stack.top().next(bk); - if (bk.isNull()) - continue; - } - - if (bk.isGroup()) - { - KBookmarkGroup gp = bk.toGroup(); - visitEnter(gp); - if (!gp.first().isNull()) - { - stack.push(gp); - bk = gp.first(); - continue; - } - // empty group - visitLeave(gp); - } - else - visit(bk); - - bk = stack.top().next(bk); - } - - // never reached -} - diff --git a/tdeio/bookmarks/kbookmark.cpp b/tdeio/bookmarks/kbookmark.cpp new file mode 100644 index 000000000..1e8bf8f7a --- /dev/null +++ b/tdeio/bookmarks/kbookmark.cpp @@ -0,0 +1,538 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org> + Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmark.h" +#include <tqvaluestack.h> +#include <kdebug.h> +#include <kmimetype.h> +#include <kstringhandler.h> +#include <kinputdialog.h> +#include <tdeglobal.h> +#include <tdelocale.h> +#include <assert.h> +#include <tdeapplication.h> +#include <dcopclient.h> +#include <kbookmarkmanager.h> + +KBookmarkGroup::KBookmarkGroup() + : KBookmark( TQDomElement() ) +{ +} + +KBookmarkGroup::KBookmarkGroup( TQDomElement elem ) + : KBookmark(elem) +{ +} + +TQString KBookmarkGroup::groupAddress() const +{ + if (m_address.isEmpty()) + m_address = address(); + return m_address; +} + +bool KBookmarkGroup::isOpen() const +{ + return element.attribute("folded") == "no"; // default is: folded +} + +// Returns first element node equal to or after node n +static TQDomElement firstElement(TQDomNode n) +{ + while(!n.isNull() && !n.isElement()) + n = n.nextSibling(); + return n.toElement(); +} + +// Returns first element node equal to or before node n +static TQDomElement lastElement(TQDomNode n) +{ + while(!n.isNull() && !n.isElement()) + n = n.previousSibling(); + return n.toElement(); +} + +KBookmark KBookmarkGroup::first() const +{ + return KBookmark( nextKnownTag( firstElement(element.firstChild()), true ) ); +} + +KBookmark KBookmarkGroup::previous( const KBookmark & current ) const +{ + return KBookmark( nextKnownTag( lastElement(current.element.previousSibling()), false ) ); +} + +KBookmark KBookmarkGroup::next( const KBookmark & current ) const +{ + return KBookmark( nextKnownTag( firstElement(current.element.nextSibling()), true ) ); +} + +// KDE4: Change TQDomElement to TQDomNode so that we can get rid of +// firstElement() and lastElement() +TQDomElement KBookmarkGroup::nextKnownTag( TQDomElement start, bool goNext ) const +{ + static const TQString & bookmark = TDEGlobal::staticQString("bookmark"); + static const TQString & folder = TDEGlobal::staticQString("folder"); + static const TQString & separator = TDEGlobal::staticQString("separator"); + + for( TQDomNode n = start; !n.isNull(); ) + { + TQDomElement elem = n.toElement(); + TQString tag = elem.tagName(); + if (tag == folder || tag == bookmark || tag == separator) + return elem; + if (goNext) + n = n.nextSibling(); + else + n = n.previousSibling(); + } + return TQDomElement(); +} + +KBookmarkGroup KBookmarkGroup::createNewFolder( KBookmarkManager* mgr, const TQString & text, bool emitSignal ) +{ + TQString txt( text ); + if ( text.isEmpty() ) + { + bool ok; + TQString caption = parentGroup().fullText().isEmpty() ? + i18n( "Create New Bookmark Folder" ) : + i18n( "Create New Bookmark Folder in %1" ) + .arg( parentGroup().text() ); + txt = KInputDialog::getText( caption, i18n( "New folder:" ), + TQString::null, &ok ); + if ( !ok ) + return KBookmarkGroup(); + } + + Q_ASSERT(!element.isNull()); + TQDomDocument doc = element.ownerDocument(); + TQDomElement groupElem = doc.createElement( "folder" ); + element.appendChild( groupElem ); + TQDomElement textElem = doc.createElement( "title" ); + groupElem.appendChild( textElem ); + textElem.appendChild( doc.createTextNode( txt ) ); + + KBookmarkGroup grp(groupElem); + + if (emitSignal) + emit mgr->notifier().createdNewFolder( + mgr->path(), grp.fullText(), + grp.address() ); + + return grp; + +} + +KBookmark KBookmarkGroup::createNewSeparator() +{ + Q_ASSERT(!element.isNull()); + TQDomDocument doc = element.ownerDocument(); + Q_ASSERT(!doc.isNull()); + TQDomElement sepElem = doc.createElement( "separator" ); + element.appendChild( sepElem ); + return KBookmark(sepElem); +} + +bool KBookmarkGroup::moveItem( const KBookmark & item, const KBookmark & after ) +{ + TQDomNode n; + if ( !after.isNull() ) + n = element.insertAfter( item.element, after.element ); + else // first child + { + if ( element.firstChild().isNull() ) // Empty element -> set as real first child + n = element.insertBefore( item.element, TQDomElement() ); + + // we have to skip everything up to the first valid child + TQDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true); + if ( !firstChild.isNull() ) + n = element.insertBefore( item.element, firstChild ); + else + { + // No real first child -> append after the <title> etc. + n = element.appendChild( item.element ); + } + } + return (!n.isNull()); +} + +KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const KBookmark &bm, bool emitSignal ) +{ + element.appendChild( bm.internalElement() ); + + if (emitSignal) { + if ( bm.hasMetaData() ) { + mgr->notifyCompleteChange( "" ); + } else { + emit mgr->notifier().addedBookmark( + mgr->path(), bm.url().url(), + bm.fullText(), bm.address(), bm.icon() ); + } + } + + return bm; +} + +KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const TQString & text, const KURL & url, const TQString & icon, bool emitSignal ) +{ + //kdDebug(7043) << "KBookmarkGroup::addBookmark " << text << " into " << m_address << endl; + TQDomDocument doc = element.ownerDocument(); + TQDomElement elem = doc.createElement( "bookmark" ); + elem.setAttribute( "href", url.url( 0, 106 ) ); // write utf8 URL (106 is mib enum for utf8) + TQString _icon = icon; + if ( _icon.isEmpty() ) + _icon = KMimeType::iconForURL( url ); + elem.setAttribute( "icon", _icon ); + + TQDomElement textElem = doc.createElement( "title" ); + elem.appendChild( textElem ); + textElem.appendChild( doc.createTextNode( text ) ); + + return addBookmark( mgr, KBookmark( elem ), emitSignal ); +} + +void KBookmarkGroup::deleteBookmark( KBookmark bk ) +{ + element.removeChild( bk.element ); +} + +bool KBookmarkGroup::isToolbarGroup() const +{ + return ( element.attribute("toolbar") == "yes" ); +} + +TQDomElement KBookmarkGroup::findToolbar() const +{ + if ( element.attribute("toolbar") == "yes" ) + return element; + for (TQDomNode n = element.firstChild(); !n.isNull() ; n = n.nextSibling() ) + { + TQDomElement e = n.toElement(); + // Search among the "folder" children only + if ( e.tagName() == "folder" ) + { + if ( e.attribute("toolbar") == "yes" ) + return e; + else + { + TQDomElement result = KBookmarkGroup(e).findToolbar(); + if (!result.isNull()) + return result; + } + } + } + return TQDomElement(); +} + +TQValueList<KURL> KBookmarkGroup::groupUrlList() const +{ + TQValueList<KURL> urlList; + for ( KBookmark bm = first(); !bm.isNull(); bm = next(bm) ) + { + if ( bm.isSeparator() || bm.isGroup() ) + continue; + urlList << bm.url(); + } + return urlList; +} + +////// + +bool KBookmark::isGroup() const +{ + TQString tag = element.tagName(); + return ( tag == "folder" + || tag == "xbel" ); // don't forget the toplevel group +} + +bool KBookmark::isSeparator() const +{ + return (element.tagName() == "separator"); +} + +bool KBookmark::hasParent() const +{ + TQDomElement parent = element.parentNode().toElement(); + return !parent.isNull(); +} + +TQString KBookmark::text() const +{ + return KStringHandler::csqueeze( fullText() ); +} + +TQString KBookmark::fullText() const +{ + if (isSeparator()) + return i18n("--- separator ---"); + + return element.namedItem("title").toElement().text(); +} + +KURL KBookmark::url() const +{ + return KURL(element.attribute("href"), 106); // Decode it from utf8 (106 is mib enum for utf8) +} + +TQString KBookmark::icon() const +{ + TQString icon = element.attribute("icon"); + if ( icon.isEmpty() ) { + // Default icon depends on URL for bookmarks, and is default directory + // icon for groups. + if ( isGroup() ) { + icon = "bookmark_folder"; + } + else { + if ( isSeparator() ) { + icon = "eraser"; // whatever + } + else { + icon = KMimeType::iconForURL( url() ); + } + } + } + return icon; +} + +KBookmarkGroup KBookmark::parentGroup() const +{ + return KBookmarkGroup( element.parentNode().toElement() ); +} + +KBookmarkGroup KBookmark::toGroup() const +{ + Q_ASSERT( isGroup() ); + return KBookmarkGroup(element); +} + +TQString KBookmark::address() const +{ + if ( element.tagName() == "xbel" ) + return ""; // not TQString::null ! + else + { + // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :) + if (!hasParent()) + { + Q_ASSERT(hasParent()); + return "ERROR"; // Avoid an infinite loop + } + KBookmarkGroup group = parentGroup(); + TQString parentAddress = group.address(); + uint counter = 0; + // Implementation note: we don't use QDomNode's childNode list because we + // would have to skip "TEXT", which KBookmarkGroup already does for us. + for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++counter ) + { + if ( bk.element == element ) + return parentAddress + "/" + TQString::number(counter); + } + kdWarning() << "KBookmark::address : this can't happen! " << parentAddress << endl; + return "ERROR"; + } +} + +KBookmark KBookmark::standaloneBookmark( const TQString & text, const KURL & url, const TQString & icon ) +{ + TQDomDocument doc("xbel"); + TQDomElement elem = doc.createElement("xbel"); + doc.appendChild( elem ); + KBookmarkGroup grp( elem ); + grp.addBookmark( 0L, text, url, icon, false ); + return grp.first(); +} + +// For some strange reason TQString("").left(0) returns TQString::null; +// That breaks commonParent() +TQString KBookmark::left(const TQString & str, uint len) +{ + //kdDebug()<<"********"<<TQString("").left(0).isNull()<<endl; + if(len == 0) + return TQString(""); + else + return str.left(len); +} + +TQString KBookmark::commonParent(TQString A, TQString B) +{ + TQString error("ERROR"); + if(A == error || B == error) + return error; + + A += "/"; + B += "/"; + + uint lastCommonSlash = 0; + uint lastPos = A.length() < B.length() ? A.length() : B.length(); + for(uint i=0; i < lastPos; ++i) + { + if(A[i] != B[i]) + return left(A, lastCommonSlash); + if(A[i] == '/') + lastCommonSlash = i; + } + return left(A, lastCommonSlash); +} + +static TQDomNode cd_or_create(TQDomNode node, TQString name) +{ + TQDomNode subnode = node.namedItem(name); + if (subnode.isNull()) + { + subnode = node.ownerDocument().createElement(name); + node.appendChild(subnode); + } + return subnode; +} + +static TQDomText get_or_create_text(TQDomNode node) +{ + TQDomNode subnode = node.firstChild(); + if (subnode.isNull()) + { + subnode = node.ownerDocument().createTextNode(""); + node.appendChild(subnode); + } + return subnode.toText(); +} + +// Look for a metadata with owner="http://www.kde.org" or without any owner (for compatibility) +static TQDomNode findOrCreateMetadata( TQDomNode& parent ) +{ + static const char kdeOwner[] = "http://www.kde.org"; + TQDomElement metadataElement; + for ( TQDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling() ) { + TQDomElement elem = _node.toElement(); + if ( !elem.isNull() && elem.tagName() == "metadata" ) { + const TQString owner = elem.attribute( "owner" ); + if ( owner == kdeOwner ) + return elem; + if ( owner.isEmpty() ) + metadataElement = elem; + } + } + if ( metadataElement.isNull() ) { + metadataElement = parent.ownerDocument().createElement( "metadata" ); + parent.appendChild(metadataElement); + } + metadataElement.setAttribute( "owner", kdeOwner ); + return metadataElement; +} + +bool KBookmark::hasMetaData() const +{ + // ### NOTE: this code creates <info> and <metadata>, despite its name and the const. + // It doesn't matter much in practice since it's only called for newly-created bookmarks, + // which will get metadata soon after anyway. + TQDomNode n = cd_or_create( internalElement(), "info" ); + return findOrCreateMetadata( n ).hasChildNodes(); +} + +void KBookmark::updateAccessMetadata() +{ + kdDebug(7043) << "KBookmark::updateAccessMetadata " << address() << " " << url().prettyURL() << endl; + + const uint timet = TQDateTime::currentDateTime().toTime_t(); + setMetaDataItem( "time_added", TQString::number( timet ), DontOverwriteMetaData ); + setMetaDataItem( "time_visited", TQString::number( timet ) ); + + TQString countStr = metaDataItem( "visit_count" ); // TODO use spec'ed name + bool ok; + int currentCount = countStr.toInt(&ok); + if (!ok) + currentCount = 0; + currentCount++; + setMetaDataItem( "visit_count", TQString::number( currentCount ) ); + + // TODO - for 4.0 - time_modified +} + +TQString KBookmark::metaDataItem( const TQString &key ) const +{ + TQDomNode infoNode = cd_or_create( internalElement(), "info" ); + infoNode = findOrCreateMetadata( infoNode ); + for ( TQDomNode n = infoNode.firstChild(); !n.isNull(); n = n.nextSibling() ) { + if ( !n.isElement() ) { + continue; + } + const TQDomElement e = n.toElement(); + if ( e.tagName() == key ) { + return e.text(); + } + } + return TQString::null; +} + +void KBookmark::setMetaDataItem( const TQString &key, const TQString &value, MetaDataOverwriteMode mode ) +{ + TQDomNode infoNode = cd_or_create( internalElement(), "info" ); + infoNode = findOrCreateMetadata( infoNode ); + + TQDomNode item = cd_or_create( infoNode, key ); + TQDomText text = get_or_create_text( item ); + if ( mode == DontOverwriteMetaData && !text.data().isEmpty() ) { + return; + } + + text.setData( value ); +} + +void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root) +{ + // non-recursive bookmark iterator + TQValueStack<KBookmarkGroup> stack; + stack.push(root); + KBookmark bk = stack.top().first(); + for (;;) { + if (bk.isNull()) + { + if (stack.isEmpty()) + return; + if (stack.count() > 1) + visitLeave(stack.top()); + bk = stack.pop(); + bk = stack.top().next(bk); + if (bk.isNull()) + continue; + } + + if (bk.isGroup()) + { + KBookmarkGroup gp = bk.toGroup(); + visitEnter(gp); + if (!gp.first().isNull()) + { + stack.push(gp); + bk = gp.first(); + continue; + } + // empty group + visitLeave(gp); + } + else + visit(bk); + + bk = stack.top().next(bk); + } + + // never reached +} + diff --git a/tdeio/bookmarks/kbookmarkbar.cc b/tdeio/bookmarks/kbookmarkbar.cc deleted file mode 100644 index 0f8f910c2..000000000 --- a/tdeio/bookmarks/kbookmarkbar.cc +++ /dev/null @@ -1,552 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1999 Kurt Granroth <granroth@kde.org> - Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -#include <tqregexp.h> -#include <tqfile.h> - -#include <kbookmarkbar.h> -#include <kbookmarkdrag.h> - -#include <kbookmarkmenu.h> -#include <kdebug.h> - -#include <tdetoolbar.h> -#include <tdetoolbarbutton.h> - -#include <tdeconfig.h> -#include <tdepopupmenu.h> - -#include "kbookmarkdrag.h" -#include "kbookmarkmenu_p.h" -#include "kbookmarkdombuilder.h" - -#include "dptrtemplate.h" - -#include <tqapplication.h> - -class KBookmarkBarPrivate : public dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate> -{ -public: - TQPtrList<TDEAction> m_actions; - bool m_readOnly; - KBookmarkManager* m_filteredMgr; - TDEToolBar* m_sepToolBar; - int m_sepIndex; - bool m_atFirst; - TQString m_dropAddress; - TQString m_highlightedAddress; -public: - KBookmarkBarPrivate() { - m_readOnly = false; - m_filteredMgr = 0; - m_sepToolBar = 0; - m_sepIndex = -1; - m_atFirst = false; - } -}; -template<> TQPtrDict<KBookmarkBarPrivate>* dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>::d_ptr = 0; - -KBookmarkBarPrivate* KBookmarkBar::dptr() const -{ - return KBookmarkBarPrivate::d( this ); -} - -// usage of KXBELBookmarkImporterImpl is just plain evil, but it reduces code dup. so... -class ToolbarFilter : public KXBELBookmarkImporterImpl -{ -public: - ToolbarFilter() : m_visible(false) { ; } - void filter( const KBookmarkGroup &grp ) { traverse(grp); } -private: - virtual void visit( const KBookmark & ); - virtual void visitEnter( const KBookmarkGroup & ); - virtual void visitLeave( const KBookmarkGroup & ); -private: - bool m_visible; - KBookmarkGroup m_visibleStart; -}; - -KBookmarkBar::KBookmarkBar( KBookmarkManager* mgr, - KBookmarkOwner *_owner, TDEToolBar *_toolBar, - TDEActionCollection *coll, - TQObject *parent, const char *name ) - : TQObject( parent, name ), m_pOwner(_owner), m_toolBar(_toolBar), - m_actionCollection( coll ), m_pManager(mgr) -{ - m_lstSubMenus.setAutoDelete( true ); - - m_toolBar->setAcceptDrops( true ); - m_toolBar->installEventFilter( this ); // for drops - - dptr()->m_actions.setAutoDelete( true ); - - connect( mgr, TQT_SIGNAL( changed(const TQString &, const TQString &) ), - TQT_SLOT( slotBookmarksChanged(const TQString &) ) ); - - KBookmarkGroup toolbar = getToolbar(); - fillBookmarkBar( toolbar ); -} - -TQString KBookmarkBar::parentAddress() -{ - return dptr()->m_filteredMgr ? TQString::null : m_pManager->toolbar().address(); -} - -#define CURRENT_TOOLBAR() ( \ - dptr()->m_filteredMgr ? dptr()->m_filteredMgr->root() \ - : m_pManager->toolbar() ) - -#define CURRENT_MANAGER() ( \ - dptr()->m_filteredMgr ? dptr()->m_filteredMgr \ - : m_pManager ) - -KBookmarkGroup KBookmarkBar::getToolbar() -{ - if ( KBookmarkSettings::self()->m_filteredtoolbar ) - { - if ( !dptr()->m_filteredMgr ) { - dptr()->m_filteredMgr = KBookmarkManager::createTempManager(); - } else { - KBookmarkGroup bkRoot = dptr()->m_filteredMgr->root(); - TQValueList<KBookmark> bks; - for (KBookmark bm = bkRoot.first(); !bm.isNull(); bm = bkRoot.next(bm)) - bks << bm; - for ( TQValueListConstIterator<KBookmark> it = bks.begin(); it != bks.end(); ++it ) - bkRoot.deleteBookmark( (*it) ); - } - ToolbarFilter filter; - KBookmarkDomBuilder builder( dptr()->m_filteredMgr->root(), - dptr()->m_filteredMgr ); - builder.connectImporter( &filter ); - filter.filter( m_pManager->root() ); - } - - return CURRENT_TOOLBAR(); -} - -KBookmarkBar::~KBookmarkBar() -{ - //clear(); - KBookmarkBarPrivate::delete_d(this); -} - -void KBookmarkBar::clear() -{ - TQPtrListIterator<TDEAction> it( dptr()->m_actions ); - m_toolBar->clear(); - for (; it.current(); ++it ) { - (*it)->unplugAll(); - } - dptr()->m_actions.clear(); - m_lstSubMenus.clear(); -} - -void KBookmarkBar::slotBookmarksChanged( const TQString & group ) -{ - KBookmarkGroup tb = getToolbar(); // heavy for non cached toolbar version - kdDebug(7043) << "slotBookmarksChanged( " << group << " )" << endl; - - if ( tb.isNull() ) - return; - - if ( KBookmark::commonParent(group, tb.address()) == group // Is group a parent of tb.address? - || KBookmarkSettings::self()->m_filteredtoolbar ) - { - clear(); - fillBookmarkBar( tb ); - } - else - { - // Iterate recursively into child menus - TQPtrListIterator<KBookmarkMenu> it( m_lstSubMenus ); - for (; it.current(); ++it ) - { - it.current()->slotBookmarksChanged( group ); - } - } -} - -void KBookmarkBar::fillBookmarkBar(KBookmarkGroup & parent) -{ - if (parent.isNull()) - return; - - for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm)) - { - TQString text = bm.text(); - text.replace( '&', "&&" ); - if (!bm.isGroup()) - { - if ( bm.isSeparator() ) - m_toolBar->insertLineSeparator(); - else - { - TDEAction *action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 ); - connect(action, TQT_SIGNAL( activated ( TDEAction::ActivationReason, TQt::ButtonState )), - this, TQT_SLOT( slotBookmarkSelected( TDEAction::ActivationReason, TQt::ButtonState ) )); - - action->setProperty( "url", bm.url().url() ); - action->setProperty( "address", bm.address() ); - - action->setToolTip( bm.url().pathOrURL() ); - - action->plug(m_toolBar); - - dptr()->m_actions.append( action ); - } - } - else - { - TDEActionMenu *action = new KBookmarkActionMenu( text, bm.icon(), - m_actionCollection, - "bookmarkbar-actionmenu"); - action->setProperty( "address", bm.address() ); - action->setProperty( "readOnly", dptr()->m_readOnly ); - action->setDelayed( false ); - - // this flag doesn't have any UI yet - TDEGlobal::config()->setGroup( "Settings" ); - bool addEntriesBookmarkBar = TDEGlobal::config()->readBoolEntry("AddEntriesBookmarkBar",true); - - KBookmarkMenu *menu = new KBookmarkMenu(CURRENT_MANAGER(), m_pOwner, action->popupMenu(), - m_actionCollection, false, addEntriesBookmarkBar, - bm.address()); - connect(menu, TQT_SIGNAL( aboutToShowContextMenu(const KBookmark &, TQPopupMenu * ) ), - this, TQT_SIGNAL( aboutToShowContextMenu(const KBookmark &, TQPopupMenu * ) )); - connect(menu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState) ), - this, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState) )); - menu->fillBookmarkMenu(); - action->plug(m_toolBar); - m_lstSubMenus.append( menu ); - - dptr()->m_actions.append( action ); - } - } -} - -void KBookmarkBar::setReadOnly(bool readOnly) -{ - dptr()->m_readOnly = readOnly; -} - -bool KBookmarkBar::isReadOnly() const -{ - return dptr()->m_readOnly; -} - -void KBookmarkBar::slotBookmarkSelected( TDEAction::ActivationReason /*reason*/, TQt::ButtonState state ) -{ - if (!m_pOwner) return; // this view doesn't handle bookmarks... - - const TDEAction* action = dynamic_cast<const TDEAction *>(sender()); - if(action) - { - const TQString & url = sender()->property("url").toString(); - m_pOwner->openBookmarkURL(url); - emit openBookmark( url, state ); - } -} - -void KBookmarkBar::slotBookmarkSelected() -{ - slotBookmarkSelected(TDEAction::ToolBarActivation, Qt::NoButton); -} - -static const int const_sepId = -9999; // FIXME this is ugly, - // surely there is another - // way of doing this... - -static void removeTempSep(KBookmarkBarPrivate* p) -{ - if (p->m_sepToolBar) { - p->m_sepToolBar->removeItem(const_sepId); - p->m_sepToolBar = 0; // needed? - } -} - -static TDEAction* findPluggedAction(TQPtrList<TDEAction> actions, TDEToolBar *tb, int id) -{ - TQPtrListIterator<TDEAction> it( actions ); - for (; (*it); ++it ) - if ((*it)->isPlugged(tb, id)) - return (*it); - return 0; -} - -/** - * Handle a TQDragMoveEvent event on a toolbar drop - * @return the address of the bookmark to be dropped after/before - * else a TQString::null if event should be ignored - * @param pos the current TQDragMoveEvent position - * @param the toolbar - * @param actions the list of actions plugged into the bar - * @param atFirst bool reference, when true the position before the - * returned action was dropped on - */ -static TQString handleToolbarDragMoveEvent( - KBookmarkBarPrivate *p, TDEToolBar *tb, TQPoint pos, TQPtrList<TDEAction> actions, - bool &atFirst, KBookmarkManager *mgr -) { - Q_UNUSED( mgr ); - Q_ASSERT( actions.isEmpty() || (tb == dynamic_cast<TDEToolBar*>(actions.first()->container(0))) ); - p->m_sepToolBar = tb; - p->m_sepToolBar->removeItemDelayed(const_sepId); - - int index = 0; - TDEToolBarButton* b; - - b = dynamic_cast<TDEToolBarButton*>(tb->childAt(pos)); - TDEAction *a = 0; - TQString address; - atFirst = false; - - if (b) - { - index = tb->itemIndex(b->id()); - TQRect r = b->geometry(); - if (pos.x() < ((r.left() + r.right())/2)) - { - // if in first half of button then - // we jump to previous index - if ( index == 0 ) - atFirst = true; - else { - index--; - b = tb->getButton(tb->idAt(index)); - } - } - } - else if (actions.isEmpty()) - { - atFirst = true; - index = 0; - // we skip the action related stuff - // and do what it should have... - // FIXME - here we want to get the - // parent address of the bookmark - // bar itself and return that + "/0" - p->m_sepIndex = 0; - goto skipact; - } - else // (!b) - { - index = actions.count() - 1; - b = tb->getButton(tb->idAt(index)); - // if !b and not past last button, we didn't find button - if (pos.x() <= b->geometry().left()) - goto skipact; // TODO - rename - } - - if ( !b ) - return TQString::null; // TODO Make it works for that case - - a = findPluggedAction(actions, tb, b->id()); - Q_ASSERT(a); - address = a->property("address").toString(); - p->m_sepIndex = index + (atFirst ? 0 : 1); - -#if 0 - { // ugly workaround to fix the goto scoping problems... - KBookmark bk = mgr->findByAddress( address ); - if (bk.isGroup()) // TODO - fix this ****!!!, manhatten distance should be used!!! - { - kdDebug() << "kbookmarkbar:: popping up " << bk.text() << endl; - KBookmarkActionMenu *menu = dynamic_cast<KBookmarkActionMenu*>(a); - Q_ASSERT(menu); - menu->popup(tb->mapToGlobal(b->geometry().center())); - } - } -#endif - -skipact: - tb->insertLineSeparator(p->m_sepIndex, const_sepId); - return address; -} - -// TODO - document!!!! -static TDEAction* handleToolbarMouseButton(TQPoint pos, TQPtrList<TDEAction> actions, - KBookmarkManager * /*mgr*/, TQPoint & pt) -{ - TDEAction *act = actions.first(); - if (!act) { - return 0; - } - - TDEToolBar *tb = dynamic_cast<TDEToolBar*>(act->container(0)); - Q_ASSERT(tb); - - TDEToolBarButton *b; - b = dynamic_cast<TDEToolBarButton*>(tb->childAt(pos)); - if (!b) - return 0; - - TDEAction *a = 0; - a = findPluggedAction(actions, tb, b->id()); - Q_ASSERT(a); - pt = tb->mapToGlobal(pos); - - return a; -} - -// TODO *** drop improvements *** -// open submenus on drop interactions - -// TODO *** generic rmb improvements *** -// don't *ever* show the rmb on press, always relase, possible??? - -class KBookmarkBarRMBAssoc : public dPtrTemplate<KBookmarkBar, RMB> { }; -template<> TQPtrDict<RMB>* dPtrTemplate<KBookmarkBar, RMB>::d_ptr = 0; - -static RMB* rmbSelf(KBookmarkBar *m) { return KBookmarkBarRMBAssoc::d(m); } - -void RMB::begin_rmb_action(KBookmarkBar *self) -{ - RMB *s = rmbSelf(self); - s->recv = self; - s->m_parentAddress = self->parentAddress(); - s->s_highlightedAddress = self->dptr()->m_highlightedAddress; // rename in RMB - s->m_pManager = self->m_pManager; - s->m_pOwner = self->m_pOwner; - s->m_parentMenu = 0; -} - -void KBookmarkBar::slotRMBActionEditAt( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); } - -void KBookmarkBar::slotRMBActionProperties( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); } - -void KBookmarkBar::slotRMBActionInsert( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); } - -void KBookmarkBar::slotRMBActionRemove( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); } - -void KBookmarkBar::slotRMBActionCopyLocation( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); } - -bool KBookmarkBar::eventFilter( TQObject *o, TQEvent *e ) -{ - if (dptr()->m_readOnly || dptr()->m_filteredMgr) // note, we assume m_pManager in various places, - // this shouldn't really be the case - return false; // todo: make this limit the actions - - if ( (e->type() == TQEvent::MouseButtonRelease) || (e->type() == TQEvent::MouseButtonPress) ) // FIXME, which one? - { - TQMouseEvent *mev = (TQMouseEvent*)e; - - TQPoint pt; - TDEAction *_a; - - // FIXME, see how this holds up on an empty toolbar - _a = handleToolbarMouseButton( mev->pos(), dptr()->m_actions, m_pManager, pt ); - if (_a && mev->button() == Qt::RightButton) - { - dptr()->m_highlightedAddress = _a->property("address").toString(); - KBookmark bookmark = m_pManager->findByAddress( dptr()->m_highlightedAddress ); - RMB::begin_rmb_action(this); - TDEPopupMenu *pm = new TDEPopupMenu; - rmbSelf(this)->fillContextMenu( pm, dptr()->m_highlightedAddress, 0 ); - emit aboutToShowContextMenu( rmbSelf(this)->atAddress( dptr()->m_highlightedAddress ), pm ); - rmbSelf(this)->fillContextMenu2( pm, dptr()->m_highlightedAddress, 0 ); - pm->popup( pt ); - mev->accept(); - } - - return !!_a; // ignore the event if we didn't find the button - } - else if ( e->type() == TQEvent::DragLeave ) - { - removeTempSep(dptr()); - dptr()->m_dropAddress = TQString::null; - } - else if ( e->type() == TQEvent::Drop ) - { - removeTempSep(dptr()); - TQDropEvent *dev = (TQDropEvent*)e; - if ( !KBookmarkDrag::canDecode( dev ) ) - return false; - TQValueList<KBookmark> list = KBookmarkDrag::decode( dev ); - if (list.count() > 1) - kdWarning(7043) << "Sorry, currently you can only drop one address " - "onto the bookmark bar!" << endl; - KBookmark toInsert = list.first(); - KBookmark bookmark = m_pManager->findByAddress( dptr()->m_dropAddress ); - Q_ASSERT(!bookmark.isNull()); - kdDebug(7043) << "inserting " - << TQString(dptr()->m_atFirst ? "before" : "after") - << " dptr()->m_dropAddress == " << dptr()->m_dropAddress << endl; - KBookmarkGroup parentBookmark = bookmark.parentGroup(); - Q_ASSERT(!parentBookmark.isNull()); - KBookmark newBookmark = parentBookmark.addBookmark( - m_pManager, toInsert.fullText(), - toInsert.url() ); - parentBookmark.moveItem( newBookmark, dptr()->m_atFirst ? KBookmark() : bookmark ); - m_pManager->emitChanged( parentBookmark ); - return true; - } - else if ( e->type() == TQEvent::DragMove ) - { - TQDragMoveEvent *dme = (TQDragMoveEvent*)e; - if (!KBookmarkDrag::canDecode( dme )) - return false; - bool _atFirst; - TQString dropAddress; - TDEToolBar *tb = (TDEToolBar*)o; - dropAddress = handleToolbarDragMoveEvent(dptr(), tb, dme->pos(), dptr()->m_actions, _atFirst, m_pManager); - if (!dropAddress.isNull()) - { - dptr()->m_dropAddress = dropAddress; - dptr()->m_atFirst = _atFirst; - dme->accept(); - } - } - return false; -} - -static bool showInToolbar( const KBookmark &bk ) { - return (bk.internalElement().attributes().namedItem("showintoolbar").toAttr().value() == "yes"); -} - -void ToolbarFilter::visit( const KBookmark &bk ) { - //kdDebug() << "visit(" << bk.text() << ")" << endl; - if ( m_visible || showInToolbar(bk) ) - KXBELBookmarkImporterImpl::visit(bk); -} - -void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) { - //kdDebug() << "visitEnter(" << grp.text() << ")" << endl; - if ( !m_visible && showInToolbar(grp) ) - { - m_visibleStart = grp; - m_visible = true; - } - if ( m_visible ) - KXBELBookmarkImporterImpl::visitEnter(grp); -} - -void ToolbarFilter::visitLeave( const KBookmarkGroup &grp ) { - //kdDebug() << "visitLeave()" << endl; - if ( m_visible ) - KXBELBookmarkImporterImpl::visitLeave(grp); - if ( m_visible && grp.address() == m_visibleStart.address() ) - m_visible = false; -} - -#include "kbookmarkbar.moc" diff --git a/tdeio/bookmarks/kbookmarkbar.cpp b/tdeio/bookmarks/kbookmarkbar.cpp new file mode 100644 index 000000000..0f8f910c2 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkbar.cpp @@ -0,0 +1,552 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Kurt Granroth <granroth@kde.org> + Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include <tqregexp.h> +#include <tqfile.h> + +#include <kbookmarkbar.h> +#include <kbookmarkdrag.h> + +#include <kbookmarkmenu.h> +#include <kdebug.h> + +#include <tdetoolbar.h> +#include <tdetoolbarbutton.h> + +#include <tdeconfig.h> +#include <tdepopupmenu.h> + +#include "kbookmarkdrag.h" +#include "kbookmarkmenu_p.h" +#include "kbookmarkdombuilder.h" + +#include "dptrtemplate.h" + +#include <tqapplication.h> + +class KBookmarkBarPrivate : public dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate> +{ +public: + TQPtrList<TDEAction> m_actions; + bool m_readOnly; + KBookmarkManager* m_filteredMgr; + TDEToolBar* m_sepToolBar; + int m_sepIndex; + bool m_atFirst; + TQString m_dropAddress; + TQString m_highlightedAddress; +public: + KBookmarkBarPrivate() { + m_readOnly = false; + m_filteredMgr = 0; + m_sepToolBar = 0; + m_sepIndex = -1; + m_atFirst = false; + } +}; +template<> TQPtrDict<KBookmarkBarPrivate>* dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>::d_ptr = 0; + +KBookmarkBarPrivate* KBookmarkBar::dptr() const +{ + return KBookmarkBarPrivate::d( this ); +} + +// usage of KXBELBookmarkImporterImpl is just plain evil, but it reduces code dup. so... +class ToolbarFilter : public KXBELBookmarkImporterImpl +{ +public: + ToolbarFilter() : m_visible(false) { ; } + void filter( const KBookmarkGroup &grp ) { traverse(grp); } +private: + virtual void visit( const KBookmark & ); + virtual void visitEnter( const KBookmarkGroup & ); + virtual void visitLeave( const KBookmarkGroup & ); +private: + bool m_visible; + KBookmarkGroup m_visibleStart; +}; + +KBookmarkBar::KBookmarkBar( KBookmarkManager* mgr, + KBookmarkOwner *_owner, TDEToolBar *_toolBar, + TDEActionCollection *coll, + TQObject *parent, const char *name ) + : TQObject( parent, name ), m_pOwner(_owner), m_toolBar(_toolBar), + m_actionCollection( coll ), m_pManager(mgr) +{ + m_lstSubMenus.setAutoDelete( true ); + + m_toolBar->setAcceptDrops( true ); + m_toolBar->installEventFilter( this ); // for drops + + dptr()->m_actions.setAutoDelete( true ); + + connect( mgr, TQT_SIGNAL( changed(const TQString &, const TQString &) ), + TQT_SLOT( slotBookmarksChanged(const TQString &) ) ); + + KBookmarkGroup toolbar = getToolbar(); + fillBookmarkBar( toolbar ); +} + +TQString KBookmarkBar::parentAddress() +{ + return dptr()->m_filteredMgr ? TQString::null : m_pManager->toolbar().address(); +} + +#define CURRENT_TOOLBAR() ( \ + dptr()->m_filteredMgr ? dptr()->m_filteredMgr->root() \ + : m_pManager->toolbar() ) + +#define CURRENT_MANAGER() ( \ + dptr()->m_filteredMgr ? dptr()->m_filteredMgr \ + : m_pManager ) + +KBookmarkGroup KBookmarkBar::getToolbar() +{ + if ( KBookmarkSettings::self()->m_filteredtoolbar ) + { + if ( !dptr()->m_filteredMgr ) { + dptr()->m_filteredMgr = KBookmarkManager::createTempManager(); + } else { + KBookmarkGroup bkRoot = dptr()->m_filteredMgr->root(); + TQValueList<KBookmark> bks; + for (KBookmark bm = bkRoot.first(); !bm.isNull(); bm = bkRoot.next(bm)) + bks << bm; + for ( TQValueListConstIterator<KBookmark> it = bks.begin(); it != bks.end(); ++it ) + bkRoot.deleteBookmark( (*it) ); + } + ToolbarFilter filter; + KBookmarkDomBuilder builder( dptr()->m_filteredMgr->root(), + dptr()->m_filteredMgr ); + builder.connectImporter( &filter ); + filter.filter( m_pManager->root() ); + } + + return CURRENT_TOOLBAR(); +} + +KBookmarkBar::~KBookmarkBar() +{ + //clear(); + KBookmarkBarPrivate::delete_d(this); +} + +void KBookmarkBar::clear() +{ + TQPtrListIterator<TDEAction> it( dptr()->m_actions ); + m_toolBar->clear(); + for (; it.current(); ++it ) { + (*it)->unplugAll(); + } + dptr()->m_actions.clear(); + m_lstSubMenus.clear(); +} + +void KBookmarkBar::slotBookmarksChanged( const TQString & group ) +{ + KBookmarkGroup tb = getToolbar(); // heavy for non cached toolbar version + kdDebug(7043) << "slotBookmarksChanged( " << group << " )" << endl; + + if ( tb.isNull() ) + return; + + if ( KBookmark::commonParent(group, tb.address()) == group // Is group a parent of tb.address? + || KBookmarkSettings::self()->m_filteredtoolbar ) + { + clear(); + fillBookmarkBar( tb ); + } + else + { + // Iterate recursively into child menus + TQPtrListIterator<KBookmarkMenu> it( m_lstSubMenus ); + for (; it.current(); ++it ) + { + it.current()->slotBookmarksChanged( group ); + } + } +} + +void KBookmarkBar::fillBookmarkBar(KBookmarkGroup & parent) +{ + if (parent.isNull()) + return; + + for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm)) + { + TQString text = bm.text(); + text.replace( '&', "&&" ); + if (!bm.isGroup()) + { + if ( bm.isSeparator() ) + m_toolBar->insertLineSeparator(); + else + { + TDEAction *action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 ); + connect(action, TQT_SIGNAL( activated ( TDEAction::ActivationReason, TQt::ButtonState )), + this, TQT_SLOT( slotBookmarkSelected( TDEAction::ActivationReason, TQt::ButtonState ) )); + + action->setProperty( "url", bm.url().url() ); + action->setProperty( "address", bm.address() ); + + action->setToolTip( bm.url().pathOrURL() ); + + action->plug(m_toolBar); + + dptr()->m_actions.append( action ); + } + } + else + { + TDEActionMenu *action = new KBookmarkActionMenu( text, bm.icon(), + m_actionCollection, + "bookmarkbar-actionmenu"); + action->setProperty( "address", bm.address() ); + action->setProperty( "readOnly", dptr()->m_readOnly ); + action->setDelayed( false ); + + // this flag doesn't have any UI yet + TDEGlobal::config()->setGroup( "Settings" ); + bool addEntriesBookmarkBar = TDEGlobal::config()->readBoolEntry("AddEntriesBookmarkBar",true); + + KBookmarkMenu *menu = new KBookmarkMenu(CURRENT_MANAGER(), m_pOwner, action->popupMenu(), + m_actionCollection, false, addEntriesBookmarkBar, + bm.address()); + connect(menu, TQT_SIGNAL( aboutToShowContextMenu(const KBookmark &, TQPopupMenu * ) ), + this, TQT_SIGNAL( aboutToShowContextMenu(const KBookmark &, TQPopupMenu * ) )); + connect(menu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState) ), + this, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState) )); + menu->fillBookmarkMenu(); + action->plug(m_toolBar); + m_lstSubMenus.append( menu ); + + dptr()->m_actions.append( action ); + } + } +} + +void KBookmarkBar::setReadOnly(bool readOnly) +{ + dptr()->m_readOnly = readOnly; +} + +bool KBookmarkBar::isReadOnly() const +{ + return dptr()->m_readOnly; +} + +void KBookmarkBar::slotBookmarkSelected( TDEAction::ActivationReason /*reason*/, TQt::ButtonState state ) +{ + if (!m_pOwner) return; // this view doesn't handle bookmarks... + + const TDEAction* action = dynamic_cast<const TDEAction *>(sender()); + if(action) + { + const TQString & url = sender()->property("url").toString(); + m_pOwner->openBookmarkURL(url); + emit openBookmark( url, state ); + } +} + +void KBookmarkBar::slotBookmarkSelected() +{ + slotBookmarkSelected(TDEAction::ToolBarActivation, Qt::NoButton); +} + +static const int const_sepId = -9999; // FIXME this is ugly, + // surely there is another + // way of doing this... + +static void removeTempSep(KBookmarkBarPrivate* p) +{ + if (p->m_sepToolBar) { + p->m_sepToolBar->removeItem(const_sepId); + p->m_sepToolBar = 0; // needed? + } +} + +static TDEAction* findPluggedAction(TQPtrList<TDEAction> actions, TDEToolBar *tb, int id) +{ + TQPtrListIterator<TDEAction> it( actions ); + for (; (*it); ++it ) + if ((*it)->isPlugged(tb, id)) + return (*it); + return 0; +} + +/** + * Handle a TQDragMoveEvent event on a toolbar drop + * @return the address of the bookmark to be dropped after/before + * else a TQString::null if event should be ignored + * @param pos the current TQDragMoveEvent position + * @param the toolbar + * @param actions the list of actions plugged into the bar + * @param atFirst bool reference, when true the position before the + * returned action was dropped on + */ +static TQString handleToolbarDragMoveEvent( + KBookmarkBarPrivate *p, TDEToolBar *tb, TQPoint pos, TQPtrList<TDEAction> actions, + bool &atFirst, KBookmarkManager *mgr +) { + Q_UNUSED( mgr ); + Q_ASSERT( actions.isEmpty() || (tb == dynamic_cast<TDEToolBar*>(actions.first()->container(0))) ); + p->m_sepToolBar = tb; + p->m_sepToolBar->removeItemDelayed(const_sepId); + + int index = 0; + TDEToolBarButton* b; + + b = dynamic_cast<TDEToolBarButton*>(tb->childAt(pos)); + TDEAction *a = 0; + TQString address; + atFirst = false; + + if (b) + { + index = tb->itemIndex(b->id()); + TQRect r = b->geometry(); + if (pos.x() < ((r.left() + r.right())/2)) + { + // if in first half of button then + // we jump to previous index + if ( index == 0 ) + atFirst = true; + else { + index--; + b = tb->getButton(tb->idAt(index)); + } + } + } + else if (actions.isEmpty()) + { + atFirst = true; + index = 0; + // we skip the action related stuff + // and do what it should have... + // FIXME - here we want to get the + // parent address of the bookmark + // bar itself and return that + "/0" + p->m_sepIndex = 0; + goto skipact; + } + else // (!b) + { + index = actions.count() - 1; + b = tb->getButton(tb->idAt(index)); + // if !b and not past last button, we didn't find button + if (pos.x() <= b->geometry().left()) + goto skipact; // TODO - rename + } + + if ( !b ) + return TQString::null; // TODO Make it works for that case + + a = findPluggedAction(actions, tb, b->id()); + Q_ASSERT(a); + address = a->property("address").toString(); + p->m_sepIndex = index + (atFirst ? 0 : 1); + +#if 0 + { // ugly workaround to fix the goto scoping problems... + KBookmark bk = mgr->findByAddress( address ); + if (bk.isGroup()) // TODO - fix this ****!!!, manhatten distance should be used!!! + { + kdDebug() << "kbookmarkbar:: popping up " << bk.text() << endl; + KBookmarkActionMenu *menu = dynamic_cast<KBookmarkActionMenu*>(a); + Q_ASSERT(menu); + menu->popup(tb->mapToGlobal(b->geometry().center())); + } + } +#endif + +skipact: + tb->insertLineSeparator(p->m_sepIndex, const_sepId); + return address; +} + +// TODO - document!!!! +static TDEAction* handleToolbarMouseButton(TQPoint pos, TQPtrList<TDEAction> actions, + KBookmarkManager * /*mgr*/, TQPoint & pt) +{ + TDEAction *act = actions.first(); + if (!act) { + return 0; + } + + TDEToolBar *tb = dynamic_cast<TDEToolBar*>(act->container(0)); + Q_ASSERT(tb); + + TDEToolBarButton *b; + b = dynamic_cast<TDEToolBarButton*>(tb->childAt(pos)); + if (!b) + return 0; + + TDEAction *a = 0; + a = findPluggedAction(actions, tb, b->id()); + Q_ASSERT(a); + pt = tb->mapToGlobal(pos); + + return a; +} + +// TODO *** drop improvements *** +// open submenus on drop interactions + +// TODO *** generic rmb improvements *** +// don't *ever* show the rmb on press, always relase, possible??? + +class KBookmarkBarRMBAssoc : public dPtrTemplate<KBookmarkBar, RMB> { }; +template<> TQPtrDict<RMB>* dPtrTemplate<KBookmarkBar, RMB>::d_ptr = 0; + +static RMB* rmbSelf(KBookmarkBar *m) { return KBookmarkBarRMBAssoc::d(m); } + +void RMB::begin_rmb_action(KBookmarkBar *self) +{ + RMB *s = rmbSelf(self); + s->recv = self; + s->m_parentAddress = self->parentAddress(); + s->s_highlightedAddress = self->dptr()->m_highlightedAddress; // rename in RMB + s->m_pManager = self->m_pManager; + s->m_pOwner = self->m_pOwner; + s->m_parentMenu = 0; +} + +void KBookmarkBar::slotRMBActionEditAt( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); } + +void KBookmarkBar::slotRMBActionProperties( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); } + +void KBookmarkBar::slotRMBActionInsert( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); } + +void KBookmarkBar::slotRMBActionRemove( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); } + +void KBookmarkBar::slotRMBActionCopyLocation( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); } + +bool KBookmarkBar::eventFilter( TQObject *o, TQEvent *e ) +{ + if (dptr()->m_readOnly || dptr()->m_filteredMgr) // note, we assume m_pManager in various places, + // this shouldn't really be the case + return false; // todo: make this limit the actions + + if ( (e->type() == TQEvent::MouseButtonRelease) || (e->type() == TQEvent::MouseButtonPress) ) // FIXME, which one? + { + TQMouseEvent *mev = (TQMouseEvent*)e; + + TQPoint pt; + TDEAction *_a; + + // FIXME, see how this holds up on an empty toolbar + _a = handleToolbarMouseButton( mev->pos(), dptr()->m_actions, m_pManager, pt ); + if (_a && mev->button() == Qt::RightButton) + { + dptr()->m_highlightedAddress = _a->property("address").toString(); + KBookmark bookmark = m_pManager->findByAddress( dptr()->m_highlightedAddress ); + RMB::begin_rmb_action(this); + TDEPopupMenu *pm = new TDEPopupMenu; + rmbSelf(this)->fillContextMenu( pm, dptr()->m_highlightedAddress, 0 ); + emit aboutToShowContextMenu( rmbSelf(this)->atAddress( dptr()->m_highlightedAddress ), pm ); + rmbSelf(this)->fillContextMenu2( pm, dptr()->m_highlightedAddress, 0 ); + pm->popup( pt ); + mev->accept(); + } + + return !!_a; // ignore the event if we didn't find the button + } + else if ( e->type() == TQEvent::DragLeave ) + { + removeTempSep(dptr()); + dptr()->m_dropAddress = TQString::null; + } + else if ( e->type() == TQEvent::Drop ) + { + removeTempSep(dptr()); + TQDropEvent *dev = (TQDropEvent*)e; + if ( !KBookmarkDrag::canDecode( dev ) ) + return false; + TQValueList<KBookmark> list = KBookmarkDrag::decode( dev ); + if (list.count() > 1) + kdWarning(7043) << "Sorry, currently you can only drop one address " + "onto the bookmark bar!" << endl; + KBookmark toInsert = list.first(); + KBookmark bookmark = m_pManager->findByAddress( dptr()->m_dropAddress ); + Q_ASSERT(!bookmark.isNull()); + kdDebug(7043) << "inserting " + << TQString(dptr()->m_atFirst ? "before" : "after") + << " dptr()->m_dropAddress == " << dptr()->m_dropAddress << endl; + KBookmarkGroup parentBookmark = bookmark.parentGroup(); + Q_ASSERT(!parentBookmark.isNull()); + KBookmark newBookmark = parentBookmark.addBookmark( + m_pManager, toInsert.fullText(), + toInsert.url() ); + parentBookmark.moveItem( newBookmark, dptr()->m_atFirst ? KBookmark() : bookmark ); + m_pManager->emitChanged( parentBookmark ); + return true; + } + else if ( e->type() == TQEvent::DragMove ) + { + TQDragMoveEvent *dme = (TQDragMoveEvent*)e; + if (!KBookmarkDrag::canDecode( dme )) + return false; + bool _atFirst; + TQString dropAddress; + TDEToolBar *tb = (TDEToolBar*)o; + dropAddress = handleToolbarDragMoveEvent(dptr(), tb, dme->pos(), dptr()->m_actions, _atFirst, m_pManager); + if (!dropAddress.isNull()) + { + dptr()->m_dropAddress = dropAddress; + dptr()->m_atFirst = _atFirst; + dme->accept(); + } + } + return false; +} + +static bool showInToolbar( const KBookmark &bk ) { + return (bk.internalElement().attributes().namedItem("showintoolbar").toAttr().value() == "yes"); +} + +void ToolbarFilter::visit( const KBookmark &bk ) { + //kdDebug() << "visit(" << bk.text() << ")" << endl; + if ( m_visible || showInToolbar(bk) ) + KXBELBookmarkImporterImpl::visit(bk); +} + +void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) { + //kdDebug() << "visitEnter(" << grp.text() << ")" << endl; + if ( !m_visible && showInToolbar(grp) ) + { + m_visibleStart = grp; + m_visible = true; + } + if ( m_visible ) + KXBELBookmarkImporterImpl::visitEnter(grp); +} + +void ToolbarFilter::visitLeave( const KBookmarkGroup &grp ) { + //kdDebug() << "visitLeave()" << endl; + if ( m_visible ) + KXBELBookmarkImporterImpl::visitLeave(grp); + if ( m_visible && grp.address() == m_visibleStart.address() ) + m_visible = false; +} + +#include "kbookmarkbar.moc" diff --git a/tdeio/bookmarks/kbookmarkdombuilder.cc b/tdeio/bookmarks/kbookmarkdombuilder.cc deleted file mode 100644 index 5c0882d05..000000000 --- a/tdeio/bookmarks/kbookmarkdombuilder.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2000 David Faure <faure@kde.org> - Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <kbookmarkmanager.h> -#include <kdebug.h> - -#include "kbookmarkdombuilder.h" - -KBookmarkDomBuilder::KBookmarkDomBuilder( - const KBookmarkGroup &bkGroup, KBookmarkManager *manager -) { - m_manager = manager; - m_stack.push(bkGroup); -} - -KBookmarkDomBuilder::~KBookmarkDomBuilder() { - m_list.clear(); - m_stack.clear(); -} - -void KBookmarkDomBuilder::connectImporter(const TQObject *importer) { - connect(importer, TQT_SIGNAL( newBookmark(const TQString &, const TQCString &, const TQString &) ), - TQT_SLOT( newBookmark(const TQString &, const TQCString &, const TQString &) )); - connect(importer, TQT_SIGNAL( newFolder(const TQString &, bool, const TQString &) ), - TQT_SLOT( newFolder(const TQString &, bool, const TQString &) )); - connect(importer, TQT_SIGNAL( newSeparator() ), - TQT_SLOT( newSeparator() ) ); - connect(importer, TQT_SIGNAL( endFolder() ), - TQT_SLOT( endFolder() ) ); -} - -void KBookmarkDomBuilder::newBookmark( - const TQString &text, const TQCString &url, const TQString &additionalInfo -) { - KBookmark bk = m_stack.top().addBookmark( - m_manager, text, - KURL( TQString::fromUtf8(url), 106 /*utf8*/ ), - TQString::null, false); - // store additional info - bk.internalElement().setAttribute("netscapeinfo", additionalInfo); -} - -void KBookmarkDomBuilder::newFolder( - const TQString & text, bool open, const TQString & additionalInfo -) { - // we use a qvaluelist so that we keep pointers to valid objects in the stack - KBookmarkGroup gp = m_stack.top().createNewFolder(m_manager, text, false); - m_list.append(gp); - m_stack.push(m_list.last()); - // store additional info - TQDomElement element = m_list.last().internalElement(); - element.setAttribute("netscapeinfo", additionalInfo); - element.setAttribute("folded", (open?"no":"yes")); -} - -void KBookmarkDomBuilder::newSeparator() { - m_stack.top().createNewSeparator(); -} - -void KBookmarkDomBuilder::endFolder() { - m_stack.pop(); -} - -#include "kbookmarkdombuilder.moc" diff --git a/tdeio/bookmarks/kbookmarkdombuilder.cpp b/tdeio/bookmarks/kbookmarkdombuilder.cpp new file mode 100644 index 000000000..5c0882d05 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkdombuilder.cpp @@ -0,0 +1,81 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <faure@kde.org> + Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kbookmarkmanager.h> +#include <kdebug.h> + +#include "kbookmarkdombuilder.h" + +KBookmarkDomBuilder::KBookmarkDomBuilder( + const KBookmarkGroup &bkGroup, KBookmarkManager *manager +) { + m_manager = manager; + m_stack.push(bkGroup); +} + +KBookmarkDomBuilder::~KBookmarkDomBuilder() { + m_list.clear(); + m_stack.clear(); +} + +void KBookmarkDomBuilder::connectImporter(const TQObject *importer) { + connect(importer, TQT_SIGNAL( newBookmark(const TQString &, const TQCString &, const TQString &) ), + TQT_SLOT( newBookmark(const TQString &, const TQCString &, const TQString &) )); + connect(importer, TQT_SIGNAL( newFolder(const TQString &, bool, const TQString &) ), + TQT_SLOT( newFolder(const TQString &, bool, const TQString &) )); + connect(importer, TQT_SIGNAL( newSeparator() ), + TQT_SLOT( newSeparator() ) ); + connect(importer, TQT_SIGNAL( endFolder() ), + TQT_SLOT( endFolder() ) ); +} + +void KBookmarkDomBuilder::newBookmark( + const TQString &text, const TQCString &url, const TQString &additionalInfo +) { + KBookmark bk = m_stack.top().addBookmark( + m_manager, text, + KURL( TQString::fromUtf8(url), 106 /*utf8*/ ), + TQString::null, false); + // store additional info + bk.internalElement().setAttribute("netscapeinfo", additionalInfo); +} + +void KBookmarkDomBuilder::newFolder( + const TQString & text, bool open, const TQString & additionalInfo +) { + // we use a qvaluelist so that we keep pointers to valid objects in the stack + KBookmarkGroup gp = m_stack.top().createNewFolder(m_manager, text, false); + m_list.append(gp); + m_stack.push(m_list.last()); + // store additional info + TQDomElement element = m_list.last().internalElement(); + element.setAttribute("netscapeinfo", additionalInfo); + element.setAttribute("folded", (open?"no":"yes")); +} + +void KBookmarkDomBuilder::newSeparator() { + m_stack.top().createNewSeparator(); +} + +void KBookmarkDomBuilder::endFolder() { + m_stack.pop(); +} + +#include "kbookmarkdombuilder.moc" diff --git a/tdeio/bookmarks/kbookmarkdrag.cc b/tdeio/bookmarks/kbookmarkdrag.cc deleted file mode 100644 index d5cf6cb47..000000000 --- a/tdeio/bookmarks/kbookmarkdrag.cc +++ /dev/null @@ -1,167 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure <faure@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmarkdrag.h" -#include <kurldrag.h> -#include <kdebug.h> - -KBookmarkDrag * KBookmarkDrag::newDrag( const TQValueList<KBookmark> & bookmarks, TQWidget * dragSource, const char * name ) -{ - KURL::List urls; - - for ( TQValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it ) { - urls.append( (*it).url() ); - } - - // See KURLDrag::newDrag - TQStrList uris; - KURL::List::ConstIterator uit = urls.begin(); - KURL::List::ConstIterator uEnd = urls.end(); - // Get each URL encoded in utf8 - and since we get it in escaped - // form on top of that, .latin1() is fine. - for ( ; uit != uEnd ; ++uit ) - uris.append( KURLDrag::urlToString(*uit).latin1() ); - - return new KBookmarkDrag( bookmarks, uris, dragSource, name ); -} - -KBookmarkDrag * KBookmarkDrag::newDrag( const KBookmark & bookmark, TQWidget * dragSource, const char * name ) -{ - TQValueList<KBookmark> bookmarks; - bookmarks.append( KBookmark(bookmark) ); - return newDrag(bookmarks, dragSource, name); -} - -KBookmarkDrag::KBookmarkDrag( const TQValueList<KBookmark> & bookmarks, const TQStrList & urls, - TQWidget * dragSource, const char * name ) - : TQUriDrag( urls, dragSource, name ), m_bookmarks( bookmarks ), m_doc("xbel") -{ - // We need to create the XML for this drag right now and not - // in encodedData because when cutting a folder, the children - // wouldn't be part of the bookmarks anymore, when encodedData - // is requested. - TQDomElement elem = m_doc.createElement("xbel"); - m_doc.appendChild( elem ); - for ( TQValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it ) { - elem.appendChild( (*it).internalElement().cloneNode( true /* deep */ ) ); - } - //kdDebug(7043) << "KBookmarkDrag::KBookmarkDrag " << m_doc.toString() << endl; -} - -const char* KBookmarkDrag::format( int i ) const -{ - if ( i == 0 ) - return "application/x-xbel"; - else if ( i == 1 ) - return "text/uri-list"; - else if ( i == 2 ) - return "text/plain"; - else return 0; -} - -TQByteArray KBookmarkDrag::encodedData( const char* mime ) const -{ - TQByteArray a; - TQCString mimetype( mime ); - if ( mimetype == "text/uri-list" ) - return TQUriDrag::encodedData( mime ); - else if ( mimetype == "application/x-xbel" ) - { - a = m_doc.toCString(); - //kdDebug(7043) << "KBookmarkDrag::encodedData " << m_doc.toCString() << endl; - } - else if ( mimetype == "text/plain" ) - { - KURL::List m_lstDragURLs; - if ( KURLDrag::decode( this, m_lstDragURLs ) ) - { - TQStringList uris; - KURL::List::ConstIterator uit = m_lstDragURLs.begin(); - KURL::List::ConstIterator uEnd = m_lstDragURLs.end(); - for ( ; uit != uEnd ; ++uit ) - uris.append( (*uit).prettyURL() ); - - TQCString s = uris.join( "\n" ).local8Bit(); - a.resize( s.length() + 1 ); // trailing zero - memcpy( a.data(), s.data(), s.length() + 1 ); - } - } - return a; -} - -bool KBookmarkDrag::canDecode( const TQMimeSource * e ) -{ - return e->provides("text/uri-list") || e->provides("application/x-xbel") || - e->provides("text/plain"); -} - -TQValueList<KBookmark> KBookmarkDrag::decode( const TQMimeSource * e ) -{ - TQValueList<KBookmark> bookmarks; - if ( e->provides("application/x-xbel") ) - { - TQByteArray s( e->encodedData("application/x-xbel") ); - //kdDebug(7043) << "KBookmarkDrag::decode s=" << TQCString(s) << endl; - TQDomDocument doc; - doc.setContent( s ); - TQDomElement elem = doc.documentElement(); - TQDomNodeList children = elem.childNodes(); - for ( uint childno = 0; childno < children.count(); childno++) - { - bookmarks.append( KBookmark( children.item(childno).cloneNode(true).toElement() )); - } - return bookmarks; - } - if ( e->provides("text/uri-list") ) - { - KURL::List m_lstDragURLs; - //kdDebug(7043) << "KBookmarkDrag::decode uri-list" << endl; - if ( KURLDrag::decode( e, m_lstDragURLs ) ) - { - KURL::List::ConstIterator uit = m_lstDragURLs.begin(); - KURL::List::ConstIterator uEnd = m_lstDragURLs.end(); - for ( ; uit != uEnd ; ++uit ) - { - //kdDebug(7043) << "KBookmarkDrag::decode url=" << (*uit).url() << endl; - bookmarks.append( KBookmark::standaloneBookmark( - (*uit).prettyURL(), (*uit) )); - } - return bookmarks; - } - } - if( e->provides("text/plain") ) - { - //kdDebug(7043) << "KBookmarkDrag::decode text/plain" << endl; - TQString s; - if(TQTextDrag::decode( e, s )) - { - - TQStringList listDragURLs = TQStringList::split(TQChar('\n'), s); - TQStringList::ConstIterator it = listDragURLs.begin(); - TQStringList::ConstIterator end = listDragURLs.end(); - for( ; it!=end; ++it) - { - //kdDebug(7043)<<"KBookmarkDrag::decode string"<<(*it)<<endl; - bookmarks.append( KBookmark::standaloneBookmark( KURL(*it).prettyURL(), KURL(*it))); - } - return bookmarks; - } - } - bookmarks.append( KBookmark() ); - return bookmarks; -} diff --git a/tdeio/bookmarks/kbookmarkdrag.cpp b/tdeio/bookmarks/kbookmarkdrag.cpp new file mode 100644 index 000000000..d5cf6cb47 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkdrag.cpp @@ -0,0 +1,167 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmarkdrag.h" +#include <kurldrag.h> +#include <kdebug.h> + +KBookmarkDrag * KBookmarkDrag::newDrag( const TQValueList<KBookmark> & bookmarks, TQWidget * dragSource, const char * name ) +{ + KURL::List urls; + + for ( TQValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it ) { + urls.append( (*it).url() ); + } + + // See KURLDrag::newDrag + TQStrList uris; + KURL::List::ConstIterator uit = urls.begin(); + KURL::List::ConstIterator uEnd = urls.end(); + // Get each URL encoded in utf8 - and since we get it in escaped + // form on top of that, .latin1() is fine. + for ( ; uit != uEnd ; ++uit ) + uris.append( KURLDrag::urlToString(*uit).latin1() ); + + return new KBookmarkDrag( bookmarks, uris, dragSource, name ); +} + +KBookmarkDrag * KBookmarkDrag::newDrag( const KBookmark & bookmark, TQWidget * dragSource, const char * name ) +{ + TQValueList<KBookmark> bookmarks; + bookmarks.append( KBookmark(bookmark) ); + return newDrag(bookmarks, dragSource, name); +} + +KBookmarkDrag::KBookmarkDrag( const TQValueList<KBookmark> & bookmarks, const TQStrList & urls, + TQWidget * dragSource, const char * name ) + : TQUriDrag( urls, dragSource, name ), m_bookmarks( bookmarks ), m_doc("xbel") +{ + // We need to create the XML for this drag right now and not + // in encodedData because when cutting a folder, the children + // wouldn't be part of the bookmarks anymore, when encodedData + // is requested. + TQDomElement elem = m_doc.createElement("xbel"); + m_doc.appendChild( elem ); + for ( TQValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it ) { + elem.appendChild( (*it).internalElement().cloneNode( true /* deep */ ) ); + } + //kdDebug(7043) << "KBookmarkDrag::KBookmarkDrag " << m_doc.toString() << endl; +} + +const char* KBookmarkDrag::format( int i ) const +{ + if ( i == 0 ) + return "application/x-xbel"; + else if ( i == 1 ) + return "text/uri-list"; + else if ( i == 2 ) + return "text/plain"; + else return 0; +} + +TQByteArray KBookmarkDrag::encodedData( const char* mime ) const +{ + TQByteArray a; + TQCString mimetype( mime ); + if ( mimetype == "text/uri-list" ) + return TQUriDrag::encodedData( mime ); + else if ( mimetype == "application/x-xbel" ) + { + a = m_doc.toCString(); + //kdDebug(7043) << "KBookmarkDrag::encodedData " << m_doc.toCString() << endl; + } + else if ( mimetype == "text/plain" ) + { + KURL::List m_lstDragURLs; + if ( KURLDrag::decode( this, m_lstDragURLs ) ) + { + TQStringList uris; + KURL::List::ConstIterator uit = m_lstDragURLs.begin(); + KURL::List::ConstIterator uEnd = m_lstDragURLs.end(); + for ( ; uit != uEnd ; ++uit ) + uris.append( (*uit).prettyURL() ); + + TQCString s = uris.join( "\n" ).local8Bit(); + a.resize( s.length() + 1 ); // trailing zero + memcpy( a.data(), s.data(), s.length() + 1 ); + } + } + return a; +} + +bool KBookmarkDrag::canDecode( const TQMimeSource * e ) +{ + return e->provides("text/uri-list") || e->provides("application/x-xbel") || + e->provides("text/plain"); +} + +TQValueList<KBookmark> KBookmarkDrag::decode( const TQMimeSource * e ) +{ + TQValueList<KBookmark> bookmarks; + if ( e->provides("application/x-xbel") ) + { + TQByteArray s( e->encodedData("application/x-xbel") ); + //kdDebug(7043) << "KBookmarkDrag::decode s=" << TQCString(s) << endl; + TQDomDocument doc; + doc.setContent( s ); + TQDomElement elem = doc.documentElement(); + TQDomNodeList children = elem.childNodes(); + for ( uint childno = 0; childno < children.count(); childno++) + { + bookmarks.append( KBookmark( children.item(childno).cloneNode(true).toElement() )); + } + return bookmarks; + } + if ( e->provides("text/uri-list") ) + { + KURL::List m_lstDragURLs; + //kdDebug(7043) << "KBookmarkDrag::decode uri-list" << endl; + if ( KURLDrag::decode( e, m_lstDragURLs ) ) + { + KURL::List::ConstIterator uit = m_lstDragURLs.begin(); + KURL::List::ConstIterator uEnd = m_lstDragURLs.end(); + for ( ; uit != uEnd ; ++uit ) + { + //kdDebug(7043) << "KBookmarkDrag::decode url=" << (*uit).url() << endl; + bookmarks.append( KBookmark::standaloneBookmark( + (*uit).prettyURL(), (*uit) )); + } + return bookmarks; + } + } + if( e->provides("text/plain") ) + { + //kdDebug(7043) << "KBookmarkDrag::decode text/plain" << endl; + TQString s; + if(TQTextDrag::decode( e, s )) + { + + TQStringList listDragURLs = TQStringList::split(TQChar('\n'), s); + TQStringList::ConstIterator it = listDragURLs.begin(); + TQStringList::ConstIterator end = listDragURLs.end(); + for( ; it!=end; ++it) + { + //kdDebug(7043)<<"KBookmarkDrag::decode string"<<(*it)<<endl; + bookmarks.append( KBookmark::standaloneBookmark( KURL(*it).prettyURL(), KURL(*it))); + } + return bookmarks; + } + } + bookmarks.append( KBookmark() ); + return bookmarks; +} diff --git a/tdeio/bookmarks/kbookmarkexporter.cc b/tdeio/bookmarks/kbookmarkexporter.cc deleted file mode 100644 index 7f4dca67f..000000000 --- a/tdeio/bookmarks/kbookmarkexporter.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -#include <stdio.h> - -#include <tqfile.h> -#include <tqtextcodec.h> -#include <tqstylesheet.h> - -#include <kdebug.h> -#include <tdelocale.h> - -#include "kbookmarkmanager.h" -#include "kbookmarkexporter.h" - -// todo - put stuff in here :) diff --git a/tdeio/bookmarks/kbookmarkexporter.cpp b/tdeio/bookmarks/kbookmarkexporter.cpp new file mode 100644 index 000000000..7f4dca67f --- /dev/null +++ b/tdeio/bookmarks/kbookmarkexporter.cpp @@ -0,0 +1,30 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include <stdio.h> + +#include <tqfile.h> +#include <tqtextcodec.h> +#include <tqstylesheet.h> + +#include <kdebug.h> +#include <tdelocale.h> + +#include "kbookmarkmanager.h" +#include "kbookmarkexporter.h" + +// todo - put stuff in here :) diff --git a/tdeio/bookmarks/kbookmarkimporter.cc b/tdeio/bookmarks/kbookmarkimporter.cc deleted file mode 100644 index a83e36c78..000000000 --- a/tdeio/bookmarks/kbookmarkimporter.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <tdefiledialog.h> -#include <kstringhandler.h> -#include <tdelocale.h> -#include <kdebug.h> -#include <kcharsets.h> -#include <tqtextcodec.h> - -#include <sys/types.h> -#include <stddef.h> -#include <dirent.h> -#include <sys/stat.h> -#include <assert.h> - -#include "kbookmarkmanager.h" - -#include "kbookmarkimporter_ns.h" -#include "kbookmarkimporter_opera.h" -#include "kbookmarkimporter_ie.h" - -#include "kbookmarkimporter.h" - -void KXBELBookmarkImporterImpl::parse() -{ - //kdDebug() << "KXBELBookmarkImporterImpl::parse()" << endl; - KBookmarkManager *manager = KBookmarkManager::managerForFile(m_fileName); - KBookmarkGroup root = manager->root(); - traverse(root); - // FIXME delete it! - // delete manager; -} - -void KXBELBookmarkImporterImpl::visit(const KBookmark &bk) -{ - //kdDebug() << "KXBELBookmarkImporterImpl::visit" << endl; - if (bk.isSeparator()) - emit newSeparator(); - else - emit newBookmark(bk.fullText(), bk.url().url().utf8(), ""); -} - -void KXBELBookmarkImporterImpl::visitEnter(const KBookmarkGroup &grp) -{ - //kdDebug() << "KXBELBookmarkImporterImpl::visitEnter" << endl; - emit newFolder(grp.fullText(), false, ""); -} - -void KXBELBookmarkImporterImpl::visitLeave(const KBookmarkGroup &) -{ - //kdDebug() << "KXBELBookmarkImporterImpl::visitLeave" << endl; - emit endFolder(); -} - -void KBookmarkImporterBase::setupSignalForwards(TQObject *src, TQObject *dst) -{ - connect(src, TQT_SIGNAL( newBookmark( const TQString &, const TQCString &, const TQString & ) ), - dst, TQT_SIGNAL( newBookmark( const TQString &, const TQCString &, const TQString & ) )); - connect(src, TQT_SIGNAL( newFolder( const TQString &, bool, const TQString & ) ), - dst, TQT_SIGNAL( newFolder( const TQString &, bool, const TQString & ) )); - connect(src, TQT_SIGNAL( newSeparator() ), - dst, TQT_SIGNAL( newSeparator() ) ); - connect(src, TQT_SIGNAL( endFolder() ), - dst, TQT_SIGNAL( endFolder() ) ); -} - -KBookmarkImporterBase* KBookmarkImporterBase::factory( const TQString &type ) -{ - if (type == "netscape") - return new KNSBookmarkImporterImpl; - else if (type == "mozilla") - return new KMozillaBookmarkImporterImpl; - else if (type == "xbel") - return new KXBELBookmarkImporterImpl; - else if (type == "ie") - return new KIEBookmarkImporterImpl; - else if (type == "opera") - return new KOperaBookmarkImporterImpl; - else - return 0; -} - -#include <kbookmarkimporter.moc> diff --git a/tdeio/bookmarks/kbookmarkimporter.cpp b/tdeio/bookmarks/kbookmarkimporter.cpp new file mode 100644 index 000000000..a83e36c78 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkimporter.cpp @@ -0,0 +1,99 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <tdefiledialog.h> +#include <kstringhandler.h> +#include <tdelocale.h> +#include <kdebug.h> +#include <kcharsets.h> +#include <tqtextcodec.h> + +#include <sys/types.h> +#include <stddef.h> +#include <dirent.h> +#include <sys/stat.h> +#include <assert.h> + +#include "kbookmarkmanager.h" + +#include "kbookmarkimporter_ns.h" +#include "kbookmarkimporter_opera.h" +#include "kbookmarkimporter_ie.h" + +#include "kbookmarkimporter.h" + +void KXBELBookmarkImporterImpl::parse() +{ + //kdDebug() << "KXBELBookmarkImporterImpl::parse()" << endl; + KBookmarkManager *manager = KBookmarkManager::managerForFile(m_fileName); + KBookmarkGroup root = manager->root(); + traverse(root); + // FIXME delete it! + // delete manager; +} + +void KXBELBookmarkImporterImpl::visit(const KBookmark &bk) +{ + //kdDebug() << "KXBELBookmarkImporterImpl::visit" << endl; + if (bk.isSeparator()) + emit newSeparator(); + else + emit newBookmark(bk.fullText(), bk.url().url().utf8(), ""); +} + +void KXBELBookmarkImporterImpl::visitEnter(const KBookmarkGroup &grp) +{ + //kdDebug() << "KXBELBookmarkImporterImpl::visitEnter" << endl; + emit newFolder(grp.fullText(), false, ""); +} + +void KXBELBookmarkImporterImpl::visitLeave(const KBookmarkGroup &) +{ + //kdDebug() << "KXBELBookmarkImporterImpl::visitLeave" << endl; + emit endFolder(); +} + +void KBookmarkImporterBase::setupSignalForwards(TQObject *src, TQObject *dst) +{ + connect(src, TQT_SIGNAL( newBookmark( const TQString &, const TQCString &, const TQString & ) ), + dst, TQT_SIGNAL( newBookmark( const TQString &, const TQCString &, const TQString & ) )); + connect(src, TQT_SIGNAL( newFolder( const TQString &, bool, const TQString & ) ), + dst, TQT_SIGNAL( newFolder( const TQString &, bool, const TQString & ) )); + connect(src, TQT_SIGNAL( newSeparator() ), + dst, TQT_SIGNAL( newSeparator() ) ); + connect(src, TQT_SIGNAL( endFolder() ), + dst, TQT_SIGNAL( endFolder() ) ); +} + +KBookmarkImporterBase* KBookmarkImporterBase::factory( const TQString &type ) +{ + if (type == "netscape") + return new KNSBookmarkImporterImpl; + else if (type == "mozilla") + return new KMozillaBookmarkImporterImpl; + else if (type == "xbel") + return new KXBELBookmarkImporterImpl; + else if (type == "ie") + return new KIEBookmarkImporterImpl; + else if (type == "opera") + return new KOperaBookmarkImporterImpl; + else + return 0; +} + +#include <kbookmarkimporter.moc> diff --git a/tdeio/bookmarks/kbookmarkimporter_crash.cc b/tdeio/bookmarks/kbookmarkimporter_crash.cc deleted file mode 100644 index 44c591ef4..000000000 --- a/tdeio/bookmarks/kbookmarkimporter_crash.cc +++ /dev/null @@ -1,213 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmarkimporter_crash.h" - -#include <tdefiledialog.h> -#include <kstringhandler.h> -#include <tdelocale.h> -#include <kdebug.h> -#include <tdeapplication.h> -#include <kstandarddirs.h> -#include <tqfile.h> -#include <tqdir.h> -#include <tqstring.h> -#include <tqtextcodec.h> -#include <dcopclient.h> - -#include <sys/types.h> -#include <stddef.h> -#include <dirent.h> -#include <sys/stat.h> - -typedef TQMap<TQString, TQString> ViewMap; - -// KDE 4.0: remove this BC keeping stub -void TDECrashBookmarkImporter::parseCrashLog( TQString /*filename*/, bool /*del*/ ) -{ - ; -} - -ViewMap TDECrashBookmarkImporterImpl::parseCrashLog_noemit( const TQString & filename, bool del ) -{ - static const int g_lineLimit = 16*1024; - - TQFile f( filename ); - ViewMap views; - - if ( !f.open( IO_ReadOnly ) ) - return views; - - TQCString s( g_lineLimit ); - - TQTextCodec * codec = TQTextCodec::codecForName( "UTF-8" ); - Q_ASSERT( codec ); - if ( !codec ) - return views; - - while ( f.readLine( s.data(), g_lineLimit ) >=0 ) - { - if ( s[s.length()-1] != '\n' ) - { - kdWarning() << "Crash bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl; - continue; - } - TQString t = codec->toUnicode( s.stripWhiteSpace() ); - TQRegExp rx( "(.*)\\((.*)\\):(.*)$" ); - rx.setMinimal( true ); - if ( !rx.exactMatch( t ) ) - continue; - if ( rx.cap(1) == "opened" ) - views[rx.cap(2)] = rx.cap(3); - else if ( rx.cap(1) == "close" ) - views.remove( rx.cap(2) ); - } - - f.close(); - - if ( del ) - f.remove(); - - return views; -} - -TQStringList TDECrashBookmarkImporter::getCrashLogs() -{ - return TDECrashBookmarkImporterImpl::getCrashLogs(); -} - -TQStringList TDECrashBookmarkImporterImpl::getCrashLogs() -{ - TQMap<TQString, bool> activeLogs; - - DCOPClient* dcop = kapp->dcopClient(); - - QCStringList apps = dcop->registeredApplications(); - for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it ) - { - TQCString &clientId = *it; - - if ( tqstrncmp(clientId, "konqueror", 9) != 0 ) - continue; - - TQByteArray data, replyData; - TQCString replyType; - TQDataStream arg( data, IO_WriteOnly ); - - if ( !dcop->call( clientId.data(), "KonquerorIface", - "crashLogFile()", data, replyType, replyData) ) - { - kdWarning() << "can't find dcop function KonquerorIface::crashLogFile()" << endl; - continue; - } - - if ( replyType != "TQString" ) - continue; - - TQDataStream reply( replyData, IO_ReadOnly ); - TQString ret; - reply >> ret; - activeLogs[ret] = true; - } - - TQDir d( TDECrashBookmarkImporterImpl().findDefaultLocation() ); - d.setSorting( TQDir::Time ); - d.setFilter( TQDir::Files ); - d.setNameFilter( "konqueror-crash-*.log" ); - - const TQFileInfoList *list = d.entryInfoList(); - TQFileInfoListIterator it( *list ); - - TQFileInfo *fi; - TQStringList crashFiles; - - int count = 0; - for ( ; (( fi = it.current() ) != 0) && (count < 20); ++it, ++count ) - { - bool stillAlive = activeLogs.contains( fi->absFilePath() ); - if ( !stillAlive ) - crashFiles << fi->absFilePath(); - } - // Delete remaining ones - for ( ; ( fi = it.current() ) != 0; ++it ) - { - TQFile::remove( fi->absFilePath() ); - } - - return crashFiles; -} - -void TDECrashBookmarkImporterImpl::parse() -{ - TQDict<bool> signatureMap; - TQStringList crashFiles = TDECrashBookmarkImporterImpl::getCrashLogs(); - int count = 1; - for ( TQStringList::Iterator it = crashFiles.begin(); it != crashFiles.end(); ++it ) - { - ViewMap views; - views = parseCrashLog_noemit( *it, m_shouldDelete ); - TQString signature; - for ( ViewMap::Iterator vit = views.begin(); vit != views.end(); ++vit ) - signature += "|"+vit.data(); - if (signatureMap[signature]) - { - // Duplicate... throw away and skip - TQFile::remove(*it); - continue; - } - - signatureMap.insert(signature, (bool *) true); // hack - - int outerFolder = ( crashFiles.count() > 1 ) && (views.count() > 0); - if ( outerFolder ) - emit newFolder( TQString("Konqueror Window %1").arg(count++), false, "" ); - for ( ViewMap::Iterator vit = views.begin(); vit != views.end(); ++vit ) - emit newBookmark( vit.data(), vit.data().latin1(), TQString("") ); - if ( outerFolder ) - emit endFolder(); - } -} - -TQString TDECrashBookmarkImporter::crashBookmarksDir() -{ - static TDECrashBookmarkImporterImpl *p = 0; - if (!p) - p = new TDECrashBookmarkImporterImpl; - return p->findDefaultLocation(); -} - -void TDECrashBookmarkImporterImpl::setShouldDelete( bool shouldDelete ) -{ - m_shouldDelete = shouldDelete; -} - -void TDECrashBookmarkImporter::parseCrashBookmarks( bool del ) -{ - TDECrashBookmarkImporterImpl importer; - importer.setFilename( m_fileName ); - importer.setShouldDelete( del ); - importer.setupSignalForwards( &importer, this ); - importer.parse(); -} - -TQString TDECrashBookmarkImporterImpl::findDefaultLocation( bool ) const -{ - return locateLocal( "tmp", "" ); -} - -#include "kbookmarkimporter_crash.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_crash.cpp b/tdeio/bookmarks/kbookmarkimporter_crash.cpp new file mode 100644 index 000000000..44c591ef4 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkimporter_crash.cpp @@ -0,0 +1,213 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmarkimporter_crash.h" + +#include <tdefiledialog.h> +#include <kstringhandler.h> +#include <tdelocale.h> +#include <kdebug.h> +#include <tdeapplication.h> +#include <kstandarddirs.h> +#include <tqfile.h> +#include <tqdir.h> +#include <tqstring.h> +#include <tqtextcodec.h> +#include <dcopclient.h> + +#include <sys/types.h> +#include <stddef.h> +#include <dirent.h> +#include <sys/stat.h> + +typedef TQMap<TQString, TQString> ViewMap; + +// KDE 4.0: remove this BC keeping stub +void TDECrashBookmarkImporter::parseCrashLog( TQString /*filename*/, bool /*del*/ ) +{ + ; +} + +ViewMap TDECrashBookmarkImporterImpl::parseCrashLog_noemit( const TQString & filename, bool del ) +{ + static const int g_lineLimit = 16*1024; + + TQFile f( filename ); + ViewMap views; + + if ( !f.open( IO_ReadOnly ) ) + return views; + + TQCString s( g_lineLimit ); + + TQTextCodec * codec = TQTextCodec::codecForName( "UTF-8" ); + Q_ASSERT( codec ); + if ( !codec ) + return views; + + while ( f.readLine( s.data(), g_lineLimit ) >=0 ) + { + if ( s[s.length()-1] != '\n' ) + { + kdWarning() << "Crash bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl; + continue; + } + TQString t = codec->toUnicode( s.stripWhiteSpace() ); + TQRegExp rx( "(.*)\\((.*)\\):(.*)$" ); + rx.setMinimal( true ); + if ( !rx.exactMatch( t ) ) + continue; + if ( rx.cap(1) == "opened" ) + views[rx.cap(2)] = rx.cap(3); + else if ( rx.cap(1) == "close" ) + views.remove( rx.cap(2) ); + } + + f.close(); + + if ( del ) + f.remove(); + + return views; +} + +TQStringList TDECrashBookmarkImporter::getCrashLogs() +{ + return TDECrashBookmarkImporterImpl::getCrashLogs(); +} + +TQStringList TDECrashBookmarkImporterImpl::getCrashLogs() +{ + TQMap<TQString, bool> activeLogs; + + DCOPClient* dcop = kapp->dcopClient(); + + QCStringList apps = dcop->registeredApplications(); + for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it ) + { + TQCString &clientId = *it; + + if ( tqstrncmp(clientId, "konqueror", 9) != 0 ) + continue; + + TQByteArray data, replyData; + TQCString replyType; + TQDataStream arg( data, IO_WriteOnly ); + + if ( !dcop->call( clientId.data(), "KonquerorIface", + "crashLogFile()", data, replyType, replyData) ) + { + kdWarning() << "can't find dcop function KonquerorIface::crashLogFile()" << endl; + continue; + } + + if ( replyType != "TQString" ) + continue; + + TQDataStream reply( replyData, IO_ReadOnly ); + TQString ret; + reply >> ret; + activeLogs[ret] = true; + } + + TQDir d( TDECrashBookmarkImporterImpl().findDefaultLocation() ); + d.setSorting( TQDir::Time ); + d.setFilter( TQDir::Files ); + d.setNameFilter( "konqueror-crash-*.log" ); + + const TQFileInfoList *list = d.entryInfoList(); + TQFileInfoListIterator it( *list ); + + TQFileInfo *fi; + TQStringList crashFiles; + + int count = 0; + for ( ; (( fi = it.current() ) != 0) && (count < 20); ++it, ++count ) + { + bool stillAlive = activeLogs.contains( fi->absFilePath() ); + if ( !stillAlive ) + crashFiles << fi->absFilePath(); + } + // Delete remaining ones + for ( ; ( fi = it.current() ) != 0; ++it ) + { + TQFile::remove( fi->absFilePath() ); + } + + return crashFiles; +} + +void TDECrashBookmarkImporterImpl::parse() +{ + TQDict<bool> signatureMap; + TQStringList crashFiles = TDECrashBookmarkImporterImpl::getCrashLogs(); + int count = 1; + for ( TQStringList::Iterator it = crashFiles.begin(); it != crashFiles.end(); ++it ) + { + ViewMap views; + views = parseCrashLog_noemit( *it, m_shouldDelete ); + TQString signature; + for ( ViewMap::Iterator vit = views.begin(); vit != views.end(); ++vit ) + signature += "|"+vit.data(); + if (signatureMap[signature]) + { + // Duplicate... throw away and skip + TQFile::remove(*it); + continue; + } + + signatureMap.insert(signature, (bool *) true); // hack + + int outerFolder = ( crashFiles.count() > 1 ) && (views.count() > 0); + if ( outerFolder ) + emit newFolder( TQString("Konqueror Window %1").arg(count++), false, "" ); + for ( ViewMap::Iterator vit = views.begin(); vit != views.end(); ++vit ) + emit newBookmark( vit.data(), vit.data().latin1(), TQString("") ); + if ( outerFolder ) + emit endFolder(); + } +} + +TQString TDECrashBookmarkImporter::crashBookmarksDir() +{ + static TDECrashBookmarkImporterImpl *p = 0; + if (!p) + p = new TDECrashBookmarkImporterImpl; + return p->findDefaultLocation(); +} + +void TDECrashBookmarkImporterImpl::setShouldDelete( bool shouldDelete ) +{ + m_shouldDelete = shouldDelete; +} + +void TDECrashBookmarkImporter::parseCrashBookmarks( bool del ) +{ + TDECrashBookmarkImporterImpl importer; + importer.setFilename( m_fileName ); + importer.setShouldDelete( del ); + importer.setupSignalForwards( &importer, this ); + importer.parse(); +} + +TQString TDECrashBookmarkImporterImpl::findDefaultLocation( bool ) const +{ + return locateLocal( "tmp", "" ); +} + +#include "kbookmarkimporter_crash.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_ie.cc b/tdeio/bookmarks/kbookmarkimporter_ie.cc deleted file mode 100644 index 966775e89..000000000 --- a/tdeio/bookmarks/kbookmarkimporter_ie.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <tdefiledialog.h> -#include <kstringhandler.h> -#include <tdelocale.h> -#include <kdebug.h> -#include <tqtextcodec.h> - -#include <sys/types.h> -#include <stddef.h> -#include <dirent.h> -#include <sys/stat.h> - -#include "kbookmarkimporter.h" -#include "kbookmarkimporter_ie.h" - -/* antlarr: KDE 4: Make them const TQString & */ -void KIEBookmarkImporter::parseIEBookmarks_url_file( TQString filename, TQString name ) { - static const int g_lineLimit = 16*1024; - - TQFile f(filename); - - if(f.open(IO_ReadOnly)) { - - TQCString s(g_lineLimit); - - while(f.readLine(s.data(), g_lineLimit)>=0) { - if ( s[s.length()-1] != '\n' ) // Gosh, this line is longer than g_lineLimit. Skipping. - { - kdWarning() << "IE bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl; - continue; - } - TQCString t = s.stripWhiteSpace(); - TQRegExp rx( "URL=(.*)" ); - if (rx.exactMatch(t)) { - emit newBookmark( name, TQString(rx.cap(1)).latin1(), TQString("") ); - } - } - - f.close(); - } -} - -/* antlarr: KDE 4: Make them const TQString & */ -void KIEBookmarkImporter::parseIEBookmarks_dir( TQString dirname, TQString foldername ) -{ - - TQDir dir(dirname); - dir.setFilter( TQDir::Files | TQDir::Dirs ); - dir.setSorting( TQDir::Name | TQDir::DirsFirst ); - dir.setNameFilter("*.url"); // AK - possibly add ";index.ini" ? - dir.setMatchAllDirs(true); - - const TQFileInfoList *list = dir.entryInfoList(); - if (!list) return; - - if (dirname != m_fileName) - emit newFolder( foldername, false, "" ); - - TQFileInfoListIterator it( *list ); - TQFileInfo *fi; - - while ( (fi = it.current()) != 0 ) { - ++it; - - if (fi->fileName() == "." || fi->fileName() == "..") continue; - - if (fi->isDir()) { - parseIEBookmarks_dir(fi->absFilePath(), fi->fileName()); - - } else if (fi->isFile()) { - if (fi->fileName().endsWith(".url")) { - TQString name = fi->fileName(); - name.truncate(name.length() - 4); // .url - parseIEBookmarks_url_file(fi->absFilePath(), name); - } - // AK - add index.ini - } - } - - if (dirname != m_fileName) - emit endFolder(); -} - - -void KIEBookmarkImporter::parseIEBookmarks( ) -{ - parseIEBookmarks_dir( m_fileName ); -} - -TQString KIEBookmarkImporter::IEBookmarksDir() -{ - static KIEBookmarkImporterImpl* p = 0; - if (!p) - p = new KIEBookmarkImporterImpl; - return p->findDefaultLocation(); -} - -void KIEBookmarkImporterImpl::parse() { - KIEBookmarkImporter importer(m_fileName); - setupSignalForwards(&importer, this); - importer.parseIEBookmarks(); -} - -TQString KIEBookmarkImporterImpl::findDefaultLocation(bool) const -{ - // notify user that they must give a new dir such - // as "Favourites" as otherwise it'll just place - // lots of .url files in the given dir and gui - // stuff in the exporter is ugly so that exclues - // the possibility of just writing to Favourites - // and checking if overwriting... - return KFileDialog::getExistingDirectory(); -} - -///////////////////////////////////////////////// - -class IEExporter : private KBookmarkGroupTraverser { -public: - IEExporter( const TQString & ); - void write( const KBookmarkGroup &grp ) { traverse(grp); }; -private: - virtual void visit( const KBookmark & ); - virtual void visitEnter( const KBookmarkGroup & ); - virtual void visitLeave( const KBookmarkGroup & ); -private: - TQDir m_currentDir; -}; - -static TQString ieStyleQuote( const TQString &str ) { - TQString s(str); - s.replace(TQRegExp("[/\\:*?\"<>|]"), "_"); - return s; -} - -IEExporter::IEExporter( const TQString & dname ) { - m_currentDir.setPath( dname ); -} - -void IEExporter::visit( const KBookmark &bk ) { - TQString fname = m_currentDir.path() + "/" + ieStyleQuote( bk.fullText() ) + ".url"; - // kdDebug() << "visit(" << bk.text() << "), fname == " << fname << endl; - TQFile file( fname ); - file.open( IO_WriteOnly ); - TQTextStream ts( &file ); - ts << "[InternetShortcut]\r\n"; - ts << "URL=" << bk.url().url().utf8() << "\r\n"; -} - -void IEExporter::visitEnter( const KBookmarkGroup &grp ) { - TQString dname = m_currentDir.path() + "/" + ieStyleQuote( grp.fullText() ); - // kdDebug() << "visitEnter(" << grp.text() << "), dname == " << dname << endl; - m_currentDir.mkdir( dname ); - m_currentDir.cd( dname ); -} - -void IEExporter::visitLeave( const KBookmarkGroup & ) { - // kdDebug() << "visitLeave()" << endl; - m_currentDir.cdUp(); -} - -void KIEBookmarkExporterImpl::write(KBookmarkGroup parent) { - IEExporter exporter( m_fileName ); - exporter.write( parent ); -} - -#include "kbookmarkimporter_ie.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_ie.cpp b/tdeio/bookmarks/kbookmarkimporter_ie.cpp new file mode 100644 index 000000000..966775e89 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkimporter_ie.cpp @@ -0,0 +1,183 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <tdefiledialog.h> +#include <kstringhandler.h> +#include <tdelocale.h> +#include <kdebug.h> +#include <tqtextcodec.h> + +#include <sys/types.h> +#include <stddef.h> +#include <dirent.h> +#include <sys/stat.h> + +#include "kbookmarkimporter.h" +#include "kbookmarkimporter_ie.h" + +/* antlarr: KDE 4: Make them const TQString & */ +void KIEBookmarkImporter::parseIEBookmarks_url_file( TQString filename, TQString name ) { + static const int g_lineLimit = 16*1024; + + TQFile f(filename); + + if(f.open(IO_ReadOnly)) { + + TQCString s(g_lineLimit); + + while(f.readLine(s.data(), g_lineLimit)>=0) { + if ( s[s.length()-1] != '\n' ) // Gosh, this line is longer than g_lineLimit. Skipping. + { + kdWarning() << "IE bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl; + continue; + } + TQCString t = s.stripWhiteSpace(); + TQRegExp rx( "URL=(.*)" ); + if (rx.exactMatch(t)) { + emit newBookmark( name, TQString(rx.cap(1)).latin1(), TQString("") ); + } + } + + f.close(); + } +} + +/* antlarr: KDE 4: Make them const TQString & */ +void KIEBookmarkImporter::parseIEBookmarks_dir( TQString dirname, TQString foldername ) +{ + + TQDir dir(dirname); + dir.setFilter( TQDir::Files | TQDir::Dirs ); + dir.setSorting( TQDir::Name | TQDir::DirsFirst ); + dir.setNameFilter("*.url"); // AK - possibly add ";index.ini" ? + dir.setMatchAllDirs(true); + + const TQFileInfoList *list = dir.entryInfoList(); + if (!list) return; + + if (dirname != m_fileName) + emit newFolder( foldername, false, "" ); + + TQFileInfoListIterator it( *list ); + TQFileInfo *fi; + + while ( (fi = it.current()) != 0 ) { + ++it; + + if (fi->fileName() == "." || fi->fileName() == "..") continue; + + if (fi->isDir()) { + parseIEBookmarks_dir(fi->absFilePath(), fi->fileName()); + + } else if (fi->isFile()) { + if (fi->fileName().endsWith(".url")) { + TQString name = fi->fileName(); + name.truncate(name.length() - 4); // .url + parseIEBookmarks_url_file(fi->absFilePath(), name); + } + // AK - add index.ini + } + } + + if (dirname != m_fileName) + emit endFolder(); +} + + +void KIEBookmarkImporter::parseIEBookmarks( ) +{ + parseIEBookmarks_dir( m_fileName ); +} + +TQString KIEBookmarkImporter::IEBookmarksDir() +{ + static KIEBookmarkImporterImpl* p = 0; + if (!p) + p = new KIEBookmarkImporterImpl; + return p->findDefaultLocation(); +} + +void KIEBookmarkImporterImpl::parse() { + KIEBookmarkImporter importer(m_fileName); + setupSignalForwards(&importer, this); + importer.parseIEBookmarks(); +} + +TQString KIEBookmarkImporterImpl::findDefaultLocation(bool) const +{ + // notify user that they must give a new dir such + // as "Favourites" as otherwise it'll just place + // lots of .url files in the given dir and gui + // stuff in the exporter is ugly so that exclues + // the possibility of just writing to Favourites + // and checking if overwriting... + return KFileDialog::getExistingDirectory(); +} + +///////////////////////////////////////////////// + +class IEExporter : private KBookmarkGroupTraverser { +public: + IEExporter( const TQString & ); + void write( const KBookmarkGroup &grp ) { traverse(grp); }; +private: + virtual void visit( const KBookmark & ); + virtual void visitEnter( const KBookmarkGroup & ); + virtual void visitLeave( const KBookmarkGroup & ); +private: + TQDir m_currentDir; +}; + +static TQString ieStyleQuote( const TQString &str ) { + TQString s(str); + s.replace(TQRegExp("[/\\:*?\"<>|]"), "_"); + return s; +} + +IEExporter::IEExporter( const TQString & dname ) { + m_currentDir.setPath( dname ); +} + +void IEExporter::visit( const KBookmark &bk ) { + TQString fname = m_currentDir.path() + "/" + ieStyleQuote( bk.fullText() ) + ".url"; + // kdDebug() << "visit(" << bk.text() << "), fname == " << fname << endl; + TQFile file( fname ); + file.open( IO_WriteOnly ); + TQTextStream ts( &file ); + ts << "[InternetShortcut]\r\n"; + ts << "URL=" << bk.url().url().utf8() << "\r\n"; +} + +void IEExporter::visitEnter( const KBookmarkGroup &grp ) { + TQString dname = m_currentDir.path() + "/" + ieStyleQuote( grp.fullText() ); + // kdDebug() << "visitEnter(" << grp.text() << "), dname == " << dname << endl; + m_currentDir.mkdir( dname ); + m_currentDir.cd( dname ); +} + +void IEExporter::visitLeave( const KBookmarkGroup & ) { + // kdDebug() << "visitLeave()" << endl; + m_currentDir.cdUp(); +} + +void KIEBookmarkExporterImpl::write(KBookmarkGroup parent) { + IEExporter exporter( m_fileName ); + exporter.write( parent ); +} + +#include "kbookmarkimporter_ie.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_kde1.cc b/tdeio/bookmarks/kbookmarkimporter_kde1.cc deleted file mode 100644 index 9b59d1e33..000000000 --- a/tdeio/bookmarks/kbookmarkimporter_kde1.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure <faure@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmarkimporter_kde1.h" -#include <tdefiledialog.h> -#include <kstringhandler.h> -#include <tdelocale.h> -#include <kdebug.h> -#include <kcharsets.h> -#include <tqtextcodec.h> - -#include <sys/types.h> -#include <stddef.h> -#include <dirent.h> -#include <sys/stat.h> -#include <assert.h> - -//////////////////// - -void KBookmarkImporter::import( const TQString & path ) -{ - TQDomElement elem = m_pDoc->documentElement(); - Q_ASSERT(!elem.isNull()); - scanIntern( elem, path ); -} - -void KBookmarkImporter::scanIntern( TQDomElement & parentElem, const TQString & _path ) -{ - kdDebug(7043) << "KBookmarkImporter::scanIntern " << _path << endl; - // Substitute all symbolic links in the path - TQDir dir( _path ); - TQString canonical = dir.canonicalPath(); - - if ( m_lstParsedDirs.contains(canonical) ) - { - kdWarning() << "Directory " << canonical << " already parsed" << endl; - return; - } - - m_lstParsedDirs.append( canonical ); - - DIR *dp; - struct dirent *ep; - dp = opendir( TQFile::encodeName(_path) ); - if ( dp == 0L ) - return; - - // Loop thru all directory entries - while ( ( ep = readdir( dp ) ) != 0L ) - { - if ( strcmp( ep->d_name, "." ) != 0 && strcmp( ep->d_name, ".." ) != 0 ) - { - KURL file; - file.setPath( TQString( _path ) + '/' + TQFile::decodeName(ep->d_name) ); - - KMimeType::Ptr res = KMimeType::findByURL( file, 0, true ); - //kdDebug(7043) << " - " << file.url() << " -> " << res->name() << endl; - - if ( res->name() == "inode/directory" ) - { - // We could use KBookmarkGroup::createNewFolder, but then it - // would notify about the change, so we'd need a flag, etc. - TQDomElement groupElem = m_pDoc->createElement( "folder" ); - parentElem.appendChild( groupElem ); - TQDomElement textElem = m_pDoc->createElement( "title" ); - groupElem.appendChild( textElem ); - textElem.appendChild( m_pDoc->createTextNode( TDEIO::decodeFileName( ep->d_name ) ) ); - if ( TDEIO::decodeFileName( ep->d_name ) == "Toolbar" ) - groupElem.setAttribute("toolbar","yes"); - scanIntern( groupElem, file.path() ); - } - else if ( (res->name() == "application/x-desktop") - || (res->name() == "media/builtin-mydocuments") - || (res->name() == "media/builtin-mycomputer") - || (res->name() == "media/builtin-mynetworkplaces") - || (res->name() == "media/builtin-printers") - || (res->name() == "media/builtin-trash") - || (res->name() == "media/builtin-webbrowser") ) - { - KSimpleConfig cfg( file.path(), true ); - cfg.setDesktopGroup(); - TQString type = cfg.readEntry( "Type" ); - // Is it really a bookmark file ? - if ( type == "Link" ) - parseBookmark( parentElem, ep->d_name, cfg, 0 /* desktop group */ ); - else - kdWarning(7043) << " Not a link ? Type=" << type << endl; - } - else if ( res->name() == "text/plain") - { - // maybe its an IE Favourite.. - KSimpleConfig cfg( file.path(), true ); - TQStringList grp = cfg.groupList().grep( "internetshortcut", false ); - if ( grp.count() == 0 ) - continue; - cfg.setGroup( *grp.begin() ); - - TQString url = cfg.readPathEntry("URL"); - if (!url.isEmpty() ) - parseBookmark( parentElem, ep->d_name, cfg, *grp.begin() ); - } else - kdWarning(7043) << "Invalid bookmark : found mimetype='" << res->name() << "' for file='" << file.path() << "'!" << endl; - } - } - - closedir( dp ); -} - -void KBookmarkImporter::parseBookmark( TQDomElement & parentElem, TQCString _text, - KSimpleConfig& _cfg, const TQString &_group ) -{ - if ( !_group.isEmpty() ) - _cfg.setGroup( _group ); - else - _cfg.setDesktopGroup(); - - TQString url = _cfg.readPathEntry( "URL" ); - TQString icon = _cfg.readEntry( "Icon" ); - if (icon.right( 4 ) == ".xpm" ) // prevent warnings - icon.truncate( icon.length() - 4 ); - - TQString text = TDEIO::decodeFileName( TQString::fromLocal8Bit(_text) ); - if ( text.length() > 8 && text.right( 8 ) == ".desktop" ) - text.truncate( text.length() - 8 ); - if ( text.length() > 7 && text.right( 7 ) == ".kdelnk" ) - text.truncate( text.length() - 7 ); - - TQDomElement elem = m_pDoc->createElement( "bookmark" ); - parentElem.appendChild( elem ); - elem.setAttribute( "href", url ); - //if ( icon != "www" ) // No need to save the default - // Hmm, after all, it makes KBookmark::pixmapFile faster, - // and it shows a nice feature to those reading the file - elem.setAttribute( "icon", icon ); - TQDomElement textElem = m_pDoc->createElement( "title" ); - elem.appendChild( textElem ); - textElem.appendChild( m_pDoc->createTextNode( text ) ); - kdDebug(7043) << "KBookmarkImporter::parseBookmark text=" << text << endl; -} diff --git a/tdeio/bookmarks/kbookmarkimporter_kde1.cpp b/tdeio/bookmarks/kbookmarkimporter_kde1.cpp new file mode 100644 index 000000000..9b59d1e33 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkimporter_kde1.cpp @@ -0,0 +1,154 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure <faure@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmarkimporter_kde1.h" +#include <tdefiledialog.h> +#include <kstringhandler.h> +#include <tdelocale.h> +#include <kdebug.h> +#include <kcharsets.h> +#include <tqtextcodec.h> + +#include <sys/types.h> +#include <stddef.h> +#include <dirent.h> +#include <sys/stat.h> +#include <assert.h> + +//////////////////// + +void KBookmarkImporter::import( const TQString & path ) +{ + TQDomElement elem = m_pDoc->documentElement(); + Q_ASSERT(!elem.isNull()); + scanIntern( elem, path ); +} + +void KBookmarkImporter::scanIntern( TQDomElement & parentElem, const TQString & _path ) +{ + kdDebug(7043) << "KBookmarkImporter::scanIntern " << _path << endl; + // Substitute all symbolic links in the path + TQDir dir( _path ); + TQString canonical = dir.canonicalPath(); + + if ( m_lstParsedDirs.contains(canonical) ) + { + kdWarning() << "Directory " << canonical << " already parsed" << endl; + return; + } + + m_lstParsedDirs.append( canonical ); + + DIR *dp; + struct dirent *ep; + dp = opendir( TQFile::encodeName(_path) ); + if ( dp == 0L ) + return; + + // Loop thru all directory entries + while ( ( ep = readdir( dp ) ) != 0L ) + { + if ( strcmp( ep->d_name, "." ) != 0 && strcmp( ep->d_name, ".." ) != 0 ) + { + KURL file; + file.setPath( TQString( _path ) + '/' + TQFile::decodeName(ep->d_name) ); + + KMimeType::Ptr res = KMimeType::findByURL( file, 0, true ); + //kdDebug(7043) << " - " << file.url() << " -> " << res->name() << endl; + + if ( res->name() == "inode/directory" ) + { + // We could use KBookmarkGroup::createNewFolder, but then it + // would notify about the change, so we'd need a flag, etc. + TQDomElement groupElem = m_pDoc->createElement( "folder" ); + parentElem.appendChild( groupElem ); + TQDomElement textElem = m_pDoc->createElement( "title" ); + groupElem.appendChild( textElem ); + textElem.appendChild( m_pDoc->createTextNode( TDEIO::decodeFileName( ep->d_name ) ) ); + if ( TDEIO::decodeFileName( ep->d_name ) == "Toolbar" ) + groupElem.setAttribute("toolbar","yes"); + scanIntern( groupElem, file.path() ); + } + else if ( (res->name() == "application/x-desktop") + || (res->name() == "media/builtin-mydocuments") + || (res->name() == "media/builtin-mycomputer") + || (res->name() == "media/builtin-mynetworkplaces") + || (res->name() == "media/builtin-printers") + || (res->name() == "media/builtin-trash") + || (res->name() == "media/builtin-webbrowser") ) + { + KSimpleConfig cfg( file.path(), true ); + cfg.setDesktopGroup(); + TQString type = cfg.readEntry( "Type" ); + // Is it really a bookmark file ? + if ( type == "Link" ) + parseBookmark( parentElem, ep->d_name, cfg, 0 /* desktop group */ ); + else + kdWarning(7043) << " Not a link ? Type=" << type << endl; + } + else if ( res->name() == "text/plain") + { + // maybe its an IE Favourite.. + KSimpleConfig cfg( file.path(), true ); + TQStringList grp = cfg.groupList().grep( "internetshortcut", false ); + if ( grp.count() == 0 ) + continue; + cfg.setGroup( *grp.begin() ); + + TQString url = cfg.readPathEntry("URL"); + if (!url.isEmpty() ) + parseBookmark( parentElem, ep->d_name, cfg, *grp.begin() ); + } else + kdWarning(7043) << "Invalid bookmark : found mimetype='" << res->name() << "' for file='" << file.path() << "'!" << endl; + } + } + + closedir( dp ); +} + +void KBookmarkImporter::parseBookmark( TQDomElement & parentElem, TQCString _text, + KSimpleConfig& _cfg, const TQString &_group ) +{ + if ( !_group.isEmpty() ) + _cfg.setGroup( _group ); + else + _cfg.setDesktopGroup(); + + TQString url = _cfg.readPathEntry( "URL" ); + TQString icon = _cfg.readEntry( "Icon" ); + if (icon.right( 4 ) == ".xpm" ) // prevent warnings + icon.truncate( icon.length() - 4 ); + + TQString text = TDEIO::decodeFileName( TQString::fromLocal8Bit(_text) ); + if ( text.length() > 8 && text.right( 8 ) == ".desktop" ) + text.truncate( text.length() - 8 ); + if ( text.length() > 7 && text.right( 7 ) == ".kdelnk" ) + text.truncate( text.length() - 7 ); + + TQDomElement elem = m_pDoc->createElement( "bookmark" ); + parentElem.appendChild( elem ); + elem.setAttribute( "href", url ); + //if ( icon != "www" ) // No need to save the default + // Hmm, after all, it makes KBookmark::pixmapFile faster, + // and it shows a nice feature to those reading the file + elem.setAttribute( "icon", icon ); + TQDomElement textElem = m_pDoc->createElement( "title" ); + elem.appendChild( textElem ); + textElem.appendChild( m_pDoc->createTextNode( text ) ); + kdDebug(7043) << "KBookmarkImporter::parseBookmark text=" << text << endl; +} diff --git a/tdeio/bookmarks/kbookmarkimporter_ns.cc b/tdeio/bookmarks/kbookmarkimporter_ns.cc deleted file mode 100644 index 6e27f364b..000000000 --- a/tdeio/bookmarks/kbookmarkimporter_ns.cc +++ /dev/null @@ -1,241 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 1996-1998 Martin R. Jones <mjones@kde.org> - Copyright (C) 2000 David Faure <faure@kde.org> - Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmarkimporter.h" -#include "kbookmarkexporter.h" -#include "kbookmarkmanager.h" -#include <tdefiledialog.h> -#include <kstringhandler.h> -#include <tdelocale.h> -#include <kdebug.h> -#include <kcharsets.h> -#include <tqtextcodec.h> -#include <tqstylesheet.h> - -#include <sys/types.h> -#include <stddef.h> -#include <dirent.h> -#include <sys/stat.h> -#include <assert.h> - -void KNSBookmarkImporterImpl::parse() -{ - TQFile f(m_fileName); - TQTextCodec * codec = m_utf8 ? TQTextCodec::codecForName("UTF-8") : TQTextCodec::codecForLocale(); - Q_ASSERT(codec); - if (!codec) - return; - - if(f.open(IO_ReadOnly)) { - - static const int g_lineLimit = 16*1024; - TQCString s(g_lineLimit); - // skip header - while(f.readLine(s.data(), g_lineLimit) >= 0 && !s.contains("<DL>")); - - while(f.readLine(s.data(), g_lineLimit)>=0) { - if ( s[s.length()-1] != '\n' ) // Gosh, this line is longer than g_lineLimit. Skipping. - { - kdWarning() << "Netscape bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl; - continue; - } - TQCString t = s.stripWhiteSpace(); - if(t.left(12).upper() == "<DT><A HREF=" || - t.left(16).upper() == "<DT><H3><A HREF=") { - int firstQuotes = t.find('"')+1; - int secondQuotes = t.find('"', firstQuotes); - if (firstQuotes != -1 && secondQuotes != -1) - { - TQCString link = t.mid(firstQuotes, secondQuotes-firstQuotes); - int endTag = t.find('>', secondQuotes+1); - TQCString name = t.mid(endTag+1); - name = name.left(name.findRev('<')); - if ( name.right(4) == "</A>" ) - name = name.left( name.length() - 4 ); - TQString qname = KCharsets::resolveEntities( codec->toUnicode( name ) ); - TQCString additionalInfo = t.mid( secondQuotes+1, endTag-secondQuotes-1 ); - - emit newBookmark( qname, - link, codec->toUnicode(additionalInfo) ); - } - } - else if(t.left(7).upper() == "<DT><H3") { - int endTag = t.find('>', 7); - TQCString name = t.mid(endTag+1); - name = name.left(name.findRev('<')); - TQString qname = KCharsets::resolveEntities( codec->toUnicode( name ) ); - TQCString additionalInfo = t.mid( 8, endTag-8 ); - bool folded = (additionalInfo.left(6) == "FOLDED"); - if (folded) additionalInfo.remove(0,7); - - emit newFolder( qname, - !folded, - codec->toUnicode(additionalInfo) ); - } - else if(t.left(4).upper() == "<HR>") - emit newSeparator(); - else if(t.left(8).upper() == "</DL><P>") - emit endFolder(); - } - - f.close(); - } -} - -TQString KNSBookmarkImporterImpl::findDefaultLocation(bool forSaving) const -{ - if (m_utf8) - { - if ( forSaving ) - return KFileDialog::getSaveFileName( TQDir::homeDirPath() + "/.mozilla", - i18n("*.html|HTML Files (*.html)") ); - else - return KFileDialog::getOpenFileName( TQDir::homeDirPath() + "/.mozilla", - i18n("*.html|HTML Files (*.html)") ); - } - else - { - return TQDir::homeDirPath() + "/.netscape/bookmarks.html"; - } -} - -//////////////////////////////////////////////////////////////// - - -void KNSBookmarkImporter::parseNSBookmarks( bool utf8 ) -{ - KNSBookmarkImporterImpl importer; - importer.setFilename(m_fileName); - importer.setUtf8(utf8); - importer.setupSignalForwards(&importer, this); - importer.parse(); -} - -TQString KNSBookmarkImporter::netscapeBookmarksFile( bool forSaving ) -{ - static KNSBookmarkImporterImpl *p = 0; - if (!p) - { - p = new KNSBookmarkImporterImpl; - p->setUtf8(false); - } - return p->findDefaultLocation(forSaving); -} - -TQString KNSBookmarkImporter::mozillaBookmarksFile( bool forSaving ) -{ - static KNSBookmarkImporterImpl *p = 0; - if (!p) - { - p = new KNSBookmarkImporterImpl; - p->setUtf8(true); - } - return p->findDefaultLocation(forSaving); -} - - -//////////////////////////////////////////////////////////////// -// compat only -//////////////////////////////////////////////////////////////// - -void KNSBookmarkExporter::write(bool utf8) { - KNSBookmarkExporterImpl exporter(m_pManager, m_fileName); - exporter.setUtf8(utf8); - exporter.write(m_pManager->root()); -} - -void KNSBookmarkExporter::writeFolder(TQTextStream &/*stream*/, KBookmarkGroup /*gp*/) { - // TODO - requires a d pointer workaround hack? -} - -//////////////////////////////////////////////////////////////// - -void KNSBookmarkExporterImpl::setUtf8(bool utf8) { - m_utf8 = utf8; -} - -void KNSBookmarkExporterImpl::write(KBookmarkGroup parent) { - if (TQFile::exists(m_fileName)) { - ::rename( - TQFile::encodeName(m_fileName), - TQFile::encodeName(m_fileName + ".beforekde")); - } - - TQFile file(m_fileName); - - if (!file.open(IO_WriteOnly)) { - kdError(7043) << "Can't write to file " << m_fileName << endl; - return; - } - - TQTextStream fstream(&file); - fstream.setEncoding(m_utf8 ? TQTextStream::UnicodeUTF8 : TQTextStream::Locale); - - TQString charset - = m_utf8 ? "UTF-8" : TQString::fromLatin1(TQTextCodec::codecForLocale()->name()).upper(); - - fstream << "<!DOCTYPE NETSCAPE-Bookmark-file-1>" << endl - << i18n("<!-- This file was generated by Konqueror -->") << endl - << "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=" - << charset << "\">" << endl - << "<TITLE>" << i18n("Bookmarks") << "" << endl - << "

" << i18n("Bookmarks") << "

" << endl - << "

" << endl - << folderAsString(parent) - << "

" << endl; -} - -TQString KNSBookmarkExporterImpl::folderAsString(KBookmarkGroup parent) const { - TQString str; - TQTextStream fstream(&str, IO_WriteOnly); - - for (KBookmark bk = parent.first(); !bk.isNull(); bk = parent.next(bk)) { - if (bk.isSeparator()) { - fstream << "


" << endl; - continue; - } - - TQString text = TQStyleSheet::escape(bk.fullText()); - - if (bk.isGroup() ) { - fstream << "

" - << text << "

" << endl - << "

" << endl - << folderAsString(bk.toGroup()) - << "

" << endl; - continue; - - } else { - // note - netscape seems to use local8bit for url... - fstream << "

" - << text << "" << endl; - continue; - } - } - - return str; -} - -//// - -#include "kbookmarkimporter_ns.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_ns.cpp b/tdeio/bookmarks/kbookmarkimporter_ns.cpp new file mode 100644 index 000000000..6e27f364b --- /dev/null +++ b/tdeio/bookmarks/kbookmarkimporter_ns.cpp @@ -0,0 +1,241 @@ +/* This file is part of the KDE libraries + Copyright (C) 1996-1998 Martin R. Jones + Copyright (C) 2000 David Faure + Copyright (C) 2003 Alexander Kellett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmarkimporter.h" +#include "kbookmarkexporter.h" +#include "kbookmarkmanager.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void KNSBookmarkImporterImpl::parse() +{ + TQFile f(m_fileName); + TQTextCodec * codec = m_utf8 ? TQTextCodec::codecForName("UTF-8") : TQTextCodec::codecForLocale(); + Q_ASSERT(codec); + if (!codec) + return; + + if(f.open(IO_ReadOnly)) { + + static const int g_lineLimit = 16*1024; + TQCString s(g_lineLimit); + // skip header + while(f.readLine(s.data(), g_lineLimit) >= 0 && !s.contains("
")); + + while(f.readLine(s.data(), g_lineLimit)>=0) { + if ( s[s.length()-1] != '\n' ) // Gosh, this line is longer than g_lineLimit. Skipping. + { + kdWarning() << "Netscape bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl; + continue; + } + TQCString t = s.stripWhiteSpace(); + if(t.left(12).upper() == "

', secondQuotes+1); + TQCString name = t.mid(endTag+1); + name = name.left(name.findRev('<')); + if ( name.right(4) == "" ) + name = name.left( name.length() - 4 ); + TQString qname = KCharsets::resolveEntities( codec->toUnicode( name ) ); + TQCString additionalInfo = t.mid( secondQuotes+1, endTag-secondQuotes-1 ); + + emit newBookmark( qname, + link, codec->toUnicode(additionalInfo) ); + } + } + else if(t.left(7).upper() == "
', 7); + TQCString name = t.mid(endTag+1); + name = name.left(name.findRev('<')); + TQString qname = KCharsets::resolveEntities( codec->toUnicode( name ) ); + TQCString additionalInfo = t.mid( 8, endTag-8 ); + bool folded = (additionalInfo.left(6) == "FOLDED"); + if (folded) additionalInfo.remove(0,7); + + emit newFolder( qname, + !folded, + codec->toUnicode(additionalInfo) ); + } + else if(t.left(4).upper() == "
") + emit newSeparator(); + else if(t.left(8).upper() == "

") + emit endFolder(); + } + + f.close(); + } +} + +TQString KNSBookmarkImporterImpl::findDefaultLocation(bool forSaving) const +{ + if (m_utf8) + { + if ( forSaving ) + return KFileDialog::getSaveFileName( TQDir::homeDirPath() + "/.mozilla", + i18n("*.html|HTML Files (*.html)") ); + else + return KFileDialog::getOpenFileName( TQDir::homeDirPath() + "/.mozilla", + i18n("*.html|HTML Files (*.html)") ); + } + else + { + return TQDir::homeDirPath() + "/.netscape/bookmarks.html"; + } +} + +//////////////////////////////////////////////////////////////// + + +void KNSBookmarkImporter::parseNSBookmarks( bool utf8 ) +{ + KNSBookmarkImporterImpl importer; + importer.setFilename(m_fileName); + importer.setUtf8(utf8); + importer.setupSignalForwards(&importer, this); + importer.parse(); +} + +TQString KNSBookmarkImporter::netscapeBookmarksFile( bool forSaving ) +{ + static KNSBookmarkImporterImpl *p = 0; + if (!p) + { + p = new KNSBookmarkImporterImpl; + p->setUtf8(false); + } + return p->findDefaultLocation(forSaving); +} + +TQString KNSBookmarkImporter::mozillaBookmarksFile( bool forSaving ) +{ + static KNSBookmarkImporterImpl *p = 0; + if (!p) + { + p = new KNSBookmarkImporterImpl; + p->setUtf8(true); + } + return p->findDefaultLocation(forSaving); +} + + +//////////////////////////////////////////////////////////////// +// compat only +//////////////////////////////////////////////////////////////// + +void KNSBookmarkExporter::write(bool utf8) { + KNSBookmarkExporterImpl exporter(m_pManager, m_fileName); + exporter.setUtf8(utf8); + exporter.write(m_pManager->root()); +} + +void KNSBookmarkExporter::writeFolder(TQTextStream &/*stream*/, KBookmarkGroup /*gp*/) { + // TODO - requires a d pointer workaround hack? +} + +//////////////////////////////////////////////////////////////// + +void KNSBookmarkExporterImpl::setUtf8(bool utf8) { + m_utf8 = utf8; +} + +void KNSBookmarkExporterImpl::write(KBookmarkGroup parent) { + if (TQFile::exists(m_fileName)) { + ::rename( + TQFile::encodeName(m_fileName), + TQFile::encodeName(m_fileName + ".beforekde")); + } + + TQFile file(m_fileName); + + if (!file.open(IO_WriteOnly)) { + kdError(7043) << "Can't write to file " << m_fileName << endl; + return; + } + + TQTextStream fstream(&file); + fstream.setEncoding(m_utf8 ? TQTextStream::UnicodeUTF8 : TQTextStream::Locale); + + TQString charset + = m_utf8 ? "UTF-8" : TQString::fromLatin1(TQTextCodec::codecForLocale()->name()).upper(); + + fstream << "" << endl + << i18n("") << endl + << "" << endl + << "" << i18n("Bookmarks") << "" << endl + << "

" << i18n("Bookmarks") << "

" << endl + << "

" << endl + << folderAsString(parent) + << "

" << endl; +} + +TQString KNSBookmarkExporterImpl::folderAsString(KBookmarkGroup parent) const { + TQString str; + TQTextStream fstream(&str, IO_WriteOnly); + + for (KBookmark bk = parent.first(); !bk.isNull(); bk = parent.next(bk)) { + if (bk.isSeparator()) { + fstream << "


" << endl; + continue; + } + + TQString text = TQStyleSheet::escape(bk.fullText()); + + if (bk.isGroup() ) { + fstream << "

" + << text << "

" << endl + << "

" << endl + << folderAsString(bk.toGroup()) + << "

" << endl; + continue; + + } else { + // note - netscape seems to use local8bit for url... + fstream << "

" + << text << "" << endl; + continue; + } + } + + return str; +} + +//// + +#include "kbookmarkimporter_ns.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_opera.cc b/tdeio/bookmarks/kbookmarkimporter_opera.cc deleted file mode 100644 index 6f95b399e..000000000 --- a/tdeio/bookmarks/kbookmarkimporter_opera.cc +++ /dev/null @@ -1,168 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2002-2003 Alexander Kellett - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "kbookmarkimporter.h" -#include "kbookmarkimporter_opera.h" - -void KOperaBookmarkImporter::parseOperaBookmarks( ) -{ - TQFile file(m_fileName); - if(!file.open(IO_ReadOnly)) { - return; - } - - TQTextCodec * codec = TQTextCodec::codecForName("UTF-8"); - Q_ASSERT(codec); - if (!codec) - return; - - int lineno = 0; - TQString url, name, type; - static const int g_lineLimit = 16*1024; - TQCString line(g_lineLimit); - - while ( file.readLine(line.data(), g_lineLimit) >=0 ) { - lineno++; - - // skip lines that didn't fit in buffer and first two headers lines - if ( line[line.length()-1] != '\n' || lineno <= 2 ) - continue; - - TQString currentLine = codec->toUnicode(line).stripWhiteSpace(); - - if (currentLine.isEmpty()) { - // end of data block - if (type.isNull()) - continue; - else if ( type == "URL") - emit newBookmark( name, url.latin1(), "" ); - else if (type == "FOLDER" ) - emit newFolder( name, false, "" ); - - type = TQString::null; - name = TQString::null; - url = TQString::null; - - } else if (currentLine == "-") { - // end of folder - emit endFolder(); - - } else { - // data block line - TQString tag; - if ( tag = "#", currentLine.startsWith( tag ) ) - type = currentLine.remove( 0, tag.length() ); - else if ( tag = "NAME=", currentLine.startsWith( tag ) ) - name = currentLine.remove(0, tag.length()); - else if ( tag = "URL=", currentLine.startsWith( tag ) ) - url = currentLine.remove(0, tag.length()); - } - } - -} - -TQString KOperaBookmarkImporter::operaBookmarksFile() -{ - static KOperaBookmarkImporterImpl *p = 0; - if (!p) - p = new KOperaBookmarkImporterImpl; - return p->findDefaultLocation(); -} - -void KOperaBookmarkImporterImpl::parse() { - KOperaBookmarkImporter importer(m_fileName); - setupSignalForwards(&importer, this); - importer.parseOperaBookmarks(); -} - -TQString KOperaBookmarkImporterImpl::findDefaultLocation(bool saving) const -{ - return saving ? KFileDialog::getSaveFileName( - TQDir::homeDirPath() + "/.opera", - i18n("*.adr|Opera Bookmark Files (*.adr)") ) - : KFileDialog::getOpenFileName( - TQDir::homeDirPath() + "/.opera", - i18n("*.adr|Opera Bookmark Files (*.adr)") ); -} - -///////////////////////////////////////////////// - -class OperaExporter : private KBookmarkGroupTraverser { -public: - OperaExporter(); - TQString generate( const KBookmarkGroup &grp ) { traverse(grp); return m_string; }; -private: - virtual void visit( const KBookmark & ); - virtual void visitEnter( const KBookmarkGroup & ); - virtual void visitLeave( const KBookmarkGroup & ); -private: - TQString m_string; - TQTextStream m_out; -}; - -OperaExporter::OperaExporter() : m_out(&m_string, IO_WriteOnly) { - m_out << "Opera Hotlist version 2.0" << endl; - m_out << "Options: encoding = utf8, version=3" << endl; -} - -void OperaExporter::visit( const KBookmark &bk ) { - // kdDebug() << "visit(" << bk.text() << ")" << endl; - m_out << "#URL" << endl; - m_out << "\tNAME=" << bk.fullText() << endl; - m_out << "\tURL=" << bk.url().url().utf8() << endl; - m_out << endl; -} - -void OperaExporter::visitEnter( const KBookmarkGroup &grp ) { - // kdDebug() << "visitEnter(" << grp.text() << ")" << endl; - m_out << "#FOLDER" << endl; - m_out << "\tNAME="<< grp.fullText() << endl; - m_out << endl; -} - -void OperaExporter::visitLeave( const KBookmarkGroup & ) { - // kdDebug() << "visitLeave()" << endl; - m_out << "-" << endl; - m_out << endl; -} - -void KOperaBookmarkExporterImpl::write(KBookmarkGroup parent) { - OperaExporter exporter; - TQString content = exporter.generate( parent ); - TQFile file(m_fileName); - if (!file.open(IO_WriteOnly)) { - kdError(7043) << "Can't write to file " << m_fileName << endl; - return; - } - TQTextStream fstream(&file); - fstream.setEncoding(TQTextStream::UnicodeUTF8); - fstream << content; -} - -#include "kbookmarkimporter_opera.moc" diff --git a/tdeio/bookmarks/kbookmarkimporter_opera.cpp b/tdeio/bookmarks/kbookmarkimporter_opera.cpp new file mode 100644 index 000000000..6f95b399e --- /dev/null +++ b/tdeio/bookmarks/kbookmarkimporter_opera.cpp @@ -0,0 +1,168 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002-2003 Alexander Kellett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kbookmarkimporter.h" +#include "kbookmarkimporter_opera.h" + +void KOperaBookmarkImporter::parseOperaBookmarks( ) +{ + TQFile file(m_fileName); + if(!file.open(IO_ReadOnly)) { + return; + } + + TQTextCodec * codec = TQTextCodec::codecForName("UTF-8"); + Q_ASSERT(codec); + if (!codec) + return; + + int lineno = 0; + TQString url, name, type; + static const int g_lineLimit = 16*1024; + TQCString line(g_lineLimit); + + while ( file.readLine(line.data(), g_lineLimit) >=0 ) { + lineno++; + + // skip lines that didn't fit in buffer and first two headers lines + if ( line[line.length()-1] != '\n' || lineno <= 2 ) + continue; + + TQString currentLine = codec->toUnicode(line).stripWhiteSpace(); + + if (currentLine.isEmpty()) { + // end of data block + if (type.isNull()) + continue; + else if ( type == "URL") + emit newBookmark( name, url.latin1(), "" ); + else if (type == "FOLDER" ) + emit newFolder( name, false, "" ); + + type = TQString::null; + name = TQString::null; + url = TQString::null; + + } else if (currentLine == "-") { + // end of folder + emit endFolder(); + + } else { + // data block line + TQString tag; + if ( tag = "#", currentLine.startsWith( tag ) ) + type = currentLine.remove( 0, tag.length() ); + else if ( tag = "NAME=", currentLine.startsWith( tag ) ) + name = currentLine.remove(0, tag.length()); + else if ( tag = "URL=", currentLine.startsWith( tag ) ) + url = currentLine.remove(0, tag.length()); + } + } + +} + +TQString KOperaBookmarkImporter::operaBookmarksFile() +{ + static KOperaBookmarkImporterImpl *p = 0; + if (!p) + p = new KOperaBookmarkImporterImpl; + return p->findDefaultLocation(); +} + +void KOperaBookmarkImporterImpl::parse() { + KOperaBookmarkImporter importer(m_fileName); + setupSignalForwards(&importer, this); + importer.parseOperaBookmarks(); +} + +TQString KOperaBookmarkImporterImpl::findDefaultLocation(bool saving) const +{ + return saving ? KFileDialog::getSaveFileName( + TQDir::homeDirPath() + "/.opera", + i18n("*.adr|Opera Bookmark Files (*.adr)") ) + : KFileDialog::getOpenFileName( + TQDir::homeDirPath() + "/.opera", + i18n("*.adr|Opera Bookmark Files (*.adr)") ); +} + +///////////////////////////////////////////////// + +class OperaExporter : private KBookmarkGroupTraverser { +public: + OperaExporter(); + TQString generate( const KBookmarkGroup &grp ) { traverse(grp); return m_string; }; +private: + virtual void visit( const KBookmark & ); + virtual void visitEnter( const KBookmarkGroup & ); + virtual void visitLeave( const KBookmarkGroup & ); +private: + TQString m_string; + TQTextStream m_out; +}; + +OperaExporter::OperaExporter() : m_out(&m_string, IO_WriteOnly) { + m_out << "Opera Hotlist version 2.0" << endl; + m_out << "Options: encoding = utf8, version=3" << endl; +} + +void OperaExporter::visit( const KBookmark &bk ) { + // kdDebug() << "visit(" << bk.text() << ")" << endl; + m_out << "#URL" << endl; + m_out << "\tNAME=" << bk.fullText() << endl; + m_out << "\tURL=" << bk.url().url().utf8() << endl; + m_out << endl; +} + +void OperaExporter::visitEnter( const KBookmarkGroup &grp ) { + // kdDebug() << "visitEnter(" << grp.text() << ")" << endl; + m_out << "#FOLDER" << endl; + m_out << "\tNAME="<< grp.fullText() << endl; + m_out << endl; +} + +void OperaExporter::visitLeave( const KBookmarkGroup & ) { + // kdDebug() << "visitLeave()" << endl; + m_out << "-" << endl; + m_out << endl; +} + +void KOperaBookmarkExporterImpl::write(KBookmarkGroup parent) { + OperaExporter exporter; + TQString content = exporter.generate( parent ); + TQFile file(m_fileName); + if (!file.open(IO_WriteOnly)) { + kdError(7043) << "Can't write to file " << m_fileName << endl; + return; + } + TQTextStream fstream(&file); + fstream.setEncoding(TQTextStream::UnicodeUTF8); + fstream << content; +} + +#include "kbookmarkimporter_opera.moc" diff --git a/tdeio/bookmarks/kbookmarkmanager.cc b/tdeio/bookmarks/kbookmarkmanager.cc deleted file mode 100644 index d36d13151..000000000 --- a/tdeio/bookmarks/kbookmarkmanager.cc +++ /dev/null @@ -1,731 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure - Copyright (C) 2003 Alexander Kellett - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmarkmanager.h" -#include "kbookmarkmenu.h" -#include "kbookmarkmenu_p.h" -#include "kbookmarkimporter.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dptrtemplate.h" - -class KBookmarkManagerPrivate : public dPtrTemplate { -public: - KBookmarkManagerPrivate() - { m_browserEditor = true; } - TQString m_editorCaption; - bool m_browserEditor; -}; -template<> TQPtrDict* dPtrTemplate::d_ptr = 0; - -KBookmarkManagerPrivate* KBookmarkManager::dptr() const { - return KBookmarkManagerPrivate::d( this ); -} - -// TODO - clean this stuff up by just using the above dptrtemplate? -TQPtrList* KBookmarkManager::s_pSelf; -static KStaticDeleter > sdbm; - -class KBookmarkMap : private KBookmarkGroupTraverser { -public: - KBookmarkMap( KBookmarkManager * ); - void update(); - TQValueList find( const TQString &url ) const - { return m_bk_map[url]; } -private: - virtual void visit(const KBookmark &); - virtual void visitEnter(const KBookmarkGroup &) { ; } - virtual void visitLeave(const KBookmarkGroup &) { ; } -private: - typedef TQValueList KBookmarkList; - TQMap m_bk_map; - KBookmarkManager *m_manager; -}; - -static KBookmarkMap *s_bk_map = 0; - -KBookmarkMap::KBookmarkMap( KBookmarkManager *manager ) { - m_manager = manager; -} - -void KBookmarkMap::update() -{ - m_bk_map.clear(); - KBookmarkGroup root = m_manager->root(); - traverse(root); -} - -void KBookmarkMap::visit(const KBookmark &bk) -{ - if (!bk.isSeparator()) { - // add bookmark to url map - m_bk_map[bk.internalElement().attribute("href")].append(bk); - } -} - - -KBookmarkManager* KBookmarkManager::managerForFile( const TQString& bookmarksFile, bool bImportDesktopFiles ) -{ - if ( !s_pSelf ) { - sdbm.setObject( s_pSelf, new TQPtrList ); - s_pSelf->setAutoDelete( true ); - } - TQPtrListIterator it ( *s_pSelf ); - for ( ; it.current() ; ++it ) - if ( it.current()->path() == bookmarksFile ) - return it.current(); - - KBookmarkManager* mgr = new KBookmarkManager( bookmarksFile, bImportDesktopFiles ); - s_pSelf->append( mgr ); - return mgr; -} - -// principally used for filtered toolbars -KBookmarkManager* KBookmarkManager::createTempManager() -{ - if ( !s_pSelf ) { - sdbm.setObject( s_pSelf, new TQPtrList ); - s_pSelf->setAutoDelete( true ); - } - KBookmarkManager* mgr = new KBookmarkManager(); - s_pSelf->append( mgr ); - return mgr; -} - -#define PI_DATA "version=\"1.0\" encoding=\"UTF-8\"" - -KBookmarkManager::KBookmarkManager( const TQString & bookmarksFile, bool bImportDesktopFiles ) - : DCOPObject(TQCString("KBookmarkManager-")+bookmarksFile.utf8()), m_doc("xbel"), m_docIsLoaded(false) -{ - m_toolbarDoc.clear(); - - m_update = true; - m_showNSBookmarks = true; - - Q_ASSERT( !bookmarksFile.isEmpty() ); - m_bookmarksFile = bookmarksFile; - - if ( !TQFile::exists(m_bookmarksFile) ) - { - TQDomElement topLevel = m_doc.createElement("xbel"); - m_doc.appendChild( topLevel ); - m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel ); - if ( bImportDesktopFiles ) - importDesktopFiles(); - m_docIsLoaded = true; - } - - connectDCOPSignal(0, objId(), "bookmarksChanged(TQString)", "notifyChanged(TQString)", false); - connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false); -} - -KBookmarkManager::KBookmarkManager( ) - : DCOPObject(TQCString("KBookmarkManager-generated")), m_doc("xbel"), m_docIsLoaded(true) -{ - m_toolbarDoc.clear(); // strange ;-) - - m_update = false; // TODO - make it read/write - m_showNSBookmarks = true; - - m_bookmarksFile = TQString::null; // AK - check all codepaths for this one - - TQDomElement topLevel = m_doc.createElement("xbel"); - m_doc.appendChild( topLevel ); - m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel ); - - // TODO - enable this via some sort of api and fix the above DCOPObject script somehow -#if 0 - connectDCOPSignal(0, objId(), "bookmarksChanged(TQString)", "notifyChanged(TQString)", false); - connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false); -#endif -} - -KBookmarkManager::~KBookmarkManager() -{ - if ( s_pSelf ) - s_pSelf->removeRef( this ); -} - -void KBookmarkManager::setUpdate( bool update ) -{ - m_update = update; -} - -const TQDomDocument &KBookmarkManager::internalDocument() const -{ - if(!m_docIsLoaded) - { - parse(); - m_toolbarDoc.clear(); - } - return m_doc; -} - - -void KBookmarkManager::parse() const -{ - m_docIsLoaded = true; - //kdDebug(7043) << "KBookmarkManager::parse " << m_bookmarksFile << endl; - TQFile file( m_bookmarksFile ); - if ( !file.open( IO_ReadOnly ) ) - { - kdWarning() << "Can't open " << m_bookmarksFile << endl; - return; - } - m_doc = TQDomDocument("xbel"); - m_doc.setContent( &file ); - - TQDomElement docElem = m_doc.documentElement(); - if ( docElem.isNull() ) - kdWarning() << "KBookmarkManager::parse : can't parse " << m_bookmarksFile << endl; - else - { - TQString mainTag = docElem.tagName(); - if ( mainTag == "BOOKMARKS" ) - { - kdWarning() << "Old style bookmarks found. Calling convertToXBEL." << endl; - docElem.setTagName("xbel"); - if ( docElem.hasAttribute( "HIDE_NSBK" ) && m_showNSBookmarks ) // non standard either, but we need it - { - docElem.setAttribute( "hide_nsbk", docElem.attribute( "HIDE_NSBK" ) == "1" ? "yes" : "no" ); - docElem.removeAttribute( "HIDE_NSBK" ); - } - - convertToXBEL( docElem ); - save(); - } - else if ( mainTag != "xbel" ) - kdWarning() << "KBookmarkManager::parse : unknown main tag " << mainTag << endl; - - TQDomNode n = m_doc.documentElement().previousSibling(); - if ( n.isProcessingInstruction() ) - { - TQDomProcessingInstruction pi = n.toProcessingInstruction(); - pi.parentNode().removeChild(pi); - } - - TQDomProcessingInstruction pi; - pi = m_doc.createProcessingInstruction( "xml", PI_DATA ); - m_doc.insertBefore( pi, docElem ); - } - - file.close(); - if ( !s_bk_map ) - s_bk_map = new KBookmarkMap( const_cast( this ) ); - s_bk_map->update(); -} - -void KBookmarkManager::convertToXBEL( TQDomElement & group ) -{ - TQDomNode n = group.firstChild(); - while( !n.isNull() ) - { - TQDomElement e = n.toElement(); - if ( !e.isNull() ) - { - if ( e.tagName() == "TEXT" ) - { - e.setTagName("title"); - } - else if ( e.tagName() == "SEPARATOR" ) - { - e.setTagName("separator"); // so close... - } - else if ( e.tagName() == "GROUP" ) - { - e.setTagName("folder"); - convertAttribute(e, "ICON","icon"); // non standard, but we need it - if ( e.hasAttribute( "TOOLBAR" ) ) // non standard either, but we need it - { - e.setAttribute( "toolbar", e.attribute( "TOOLBAR" ) == "1" ? "yes" : "no" ); - e.removeAttribute( "TOOLBAR" ); - } - - convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem - bool open = (e.attribute("OPEN") == "1"); - e.removeAttribute("OPEN"); - e.setAttribute("folded", open ? "no" : "yes"); - convertToXBEL( e ); - } - else - { - if ( e.tagName() == "BOOKMARK" ) - { - e.setTagName("bookmark"); // so much difference :-) - convertAttribute(e, "ICON","icon"); // non standard, but we need it - convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem - convertAttribute(e, "URL","href"); - TQString text = e.text(); - while ( !e.firstChild().isNull() ) // clean up the old contained text - e.removeChild(e.firstChild()); - TQDomElement titleElem = e.ownerDocument().createElement("title"); - e.appendChild( titleElem ); // should be the only child anyway - titleElem.appendChild( e.ownerDocument().createTextNode( text ) ); - } - else - { - kdWarning(7043) << "Unknown tag " << e.tagName() << endl; - } - } - } - n = n.nextSibling(); - } -} - -void KBookmarkManager::convertAttribute( TQDomElement elem, const TQString & oldName, const TQString & newName ) -{ - if ( elem.hasAttribute( oldName ) ) - { - elem.setAttribute( newName, elem.attribute( oldName ) ); - elem.removeAttribute( oldName ); - } -} - -void KBookmarkManager::importDesktopFiles() -{ - KBookmarkImporter importer( const_cast(&internalDocument()) ); - TQString path(TDEGlobal::dirs()->saveLocation("data", "kfm/bookmarks", true)); - importer.import( path ); - //kdDebug(7043) << internalDocument().toCString() << endl; - - save(); -} - -bool KBookmarkManager::save( bool toolbarCache ) const -{ - return saveAs( m_bookmarksFile, toolbarCache ); -} - -bool KBookmarkManager::saveAs( const TQString & filename, bool toolbarCache ) const -{ - kdDebug(7043) << "KBookmarkManager::save " << filename << endl; - - // Save the bookmark toolbar folder for quick loading - // but only when it will actually make things quicker - const TQString cacheFilename = filename + TQString::fromLatin1(".tbcache"); - if(toolbarCache && !root().isToolbarGroup()) - { - KSaveFile cacheFile( cacheFilename ); - if ( cacheFile.status() == 0 ) - { - TQString str; - TQTextStream stream(&str, IO_WriteOnly); - stream << root().findToolbar(); - TQCString cstr = str.utf8(); - cacheFile.file()->writeBlock( cstr.data(), cstr.length() ); - cacheFile.close(); - } - } - else // remove any (now) stale cache - { - TQFile::remove( cacheFilename ); - } - - KSaveFile file( filename ); - if ( file.status() == 0 ) - { - file.backupFile( file.name(), TQString::null, ".bak" ); - TQCString cstr; - cstr = internalDocument().toCString(); // is in UTF8 - file.file()->writeBlock( cstr.data(), cstr.length() ); - if ( file.close() ) - return true; - } - - static int hadSaveError = false; - file.abort(); - if ( !hadSaveError ) { - TQString error = i18n("Unable to save bookmarks in %1. Reported error was: %2. " - "This error message will only be shown once. The cause " - "of the error needs to be fixed as quickly as possible, " - "which is most likely a full hard drive.") - .arg(filename).arg(TQString::fromLocal8Bit(strerror(file.status()))); - if (tqApp->type() != TQApplication::Tty) - KMessageBox::error( 0L, error ); - else - kdError() << error << endl; - } - hadSaveError = true; - return false; -} - -KBookmarkGroup KBookmarkManager::root() const -{ - return KBookmarkGroup(internalDocument().documentElement()); -} - -KBookmarkGroup KBookmarkManager::toolbar() -{ - kdDebug(7043) << "KBookmarkManager::toolbar begin" << endl; - // Only try to read from a toolbar cache if the full document isn't loaded - if(!m_docIsLoaded) - { - kdDebug(7043) << "KBookmarkManager::toolbar trying cache" << endl; - const TQString cacheFilename = m_bookmarksFile + TQString::fromLatin1(".tbcache"); - TQFileInfo bmInfo(m_bookmarksFile); - TQFileInfo cacheInfo(cacheFilename); - if (m_toolbarDoc.isNull() && - TQFile::exists(cacheFilename) && - bmInfo.lastModified() < cacheInfo.lastModified()) - { - kdDebug(7043) << "KBookmarkManager::toolbar reading file" << endl; - TQFile file( cacheFilename ); - - if ( file.open( IO_ReadOnly ) ) - { - m_toolbarDoc = TQDomDocument("cache"); - m_toolbarDoc.setContent( &file ); - kdDebug(7043) << "KBookmarkManager::toolbar opened" << endl; - } - } - if (!m_toolbarDoc.isNull()) - { - kdDebug(7043) << "KBookmarkManager::toolbar returning element" << endl; - TQDomElement elem = m_toolbarDoc.firstChild().toElement(); - return KBookmarkGroup(elem); - } - } - - // Fallback to the normal way if there is no cache or if the bookmark file - // is already loaded - TQDomElement elem = root().findToolbar(); - if (elem.isNull()) - return root(); // Root is the bookmark toolbar if none has been set. - else - return KBookmarkGroup(root().findToolbar()); -} - -KBookmark KBookmarkManager::findByAddress( const TQString & address, bool tolerant ) -{ - //kdDebug(7043) << "KBookmarkManager::findByAddress " << address << endl; - KBookmark result = root(); - // The address is something like /5/10/2+ - TQStringList addresses = TQStringList::split(TQRegExp("[/+]"),address); - // kdWarning() << addresses.join(",") << endl; - for ( TQStringList::Iterator it = addresses.begin() ; it != addresses.end() ; ) - { - bool append = ((*it) == "+"); - uint number = (*it).toUInt(); - Q_ASSERT(result.isGroup()); - KBookmarkGroup group = result.toGroup(); - KBookmark bk = group.first(), lbk = bk; // last non-null bookmark - for ( uint i = 0 ; ( (i restart search from the beginning - ch = parentBookmark.first(); - break; - } - else - { - // this exact URL already exists - return TQString::null; - } - } - ch = parentBookmark.next( ch ); - } - } while ( !ch.isNull() ); - - return uniqueTitle; -} - -KBookmarkGroup KBookmarkManager::addBookmarkDialog( - const TQString & _url, const TQString & _title, - const TQString & _parentBookmarkAddress -) { - TQString url = _url; - TQString title = _title; - TQString parentBookmarkAddress = _parentBookmarkAddress; - - if ( url.isEmpty() ) - { - KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL.")); - return KBookmarkGroup(); - } - - if ( title.isEmpty() ) - title = url; - - if ( KBookmarkSettings::self()->m_advancedaddbookmark) - { - KBookmarkEditDialog dlg( title, url, this, KBookmarkEditDialog::InsertionMode, parentBookmarkAddress ); - if ( dlg.exec() != KDialogBase::Accepted ) - return KBookmarkGroup(); - title = dlg.finalTitle(); - url = dlg.finalUrl(); - parentBookmarkAddress = dlg.finalAddress(); - } - - KBookmarkGroup parentBookmark; - parentBookmark = findByAddress( parentBookmarkAddress ).toGroup(); - Q_ASSERT( !parentBookmark.isNull() ); - - TQString uniqueTitle = pickUnusedTitle( parentBookmark, title, url ); - if ( !uniqueTitle.isNull() ) - parentBookmark.addBookmark( this, uniqueTitle, KURL( url )); - - return parentBookmark; -} - - -void KBookmarkManager::emitChanged( /*KDE4 const*/ KBookmarkGroup & group ) -{ - save(); - - // Tell the other processes too - // kdDebug(7043) << "KBookmarkManager::emitChanged : broadcasting change " << group.address() << endl; - - TQByteArray data; - TQDataStream ds( data, IO_WriteOnly ); - ds << group.address(); - - emitDCOPSignal("bookmarksChanged(TQString)", data); - - // We do get our own broadcast, so no need for this anymore - //emit changed( group ); -} - -void KBookmarkManager::emitConfigChanged() -{ - emitDCOPSignal("bookmarkConfigChanged()", TQByteArray()); -} - -void KBookmarkManager::notifyCompleteChange( TQString caller ) // DCOP call -{ - if (!m_update) return; - - //kdDebug(7043) << "KBookmarkManager::notifyCompleteChange" << endl; - // The bk editor tells us we should reload everything - // Reparse - parse(); - // Tell our GUI - // (emit where group is "" to directly mark the root menu as dirty) - emit changed( "", caller ); -} - -void KBookmarkManager::notifyConfigChanged() // DCOP call -{ - kdDebug() << "reloaded bookmark config!" << endl; - KBookmarkSettings::self()->readSettings(); - parse(); // reload, and thusly recreate the menus -} - -void KBookmarkManager::notifyChanged( TQString groupAddress ) // DCOP call -{ - if (!m_update) return; - - // Reparse (the whole file, no other choice) - // if someone else notified us - if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId()) - parse(); - - //kdDebug(7043) << "KBookmarkManager::notifyChanged " << groupAddress << endl; - //KBookmarkGroup group = findByAddress( groupAddress ).toGroup(); - //Q_ASSERT(!group.isNull()); - emit changed( groupAddress, TQString::null ); -} - -bool KBookmarkManager::showNSBookmarks() const -{ - return KBookmarkMenu::showDynamicBookmarks("netscape").show; -} - -void KBookmarkManager::setShowNSBookmarks( bool show ) -{ - m_showNSBookmarks = show; - if (this->path() != userBookmarksFile()) - return; - KBookmarkMenu::DynMenuInfo info - = KBookmarkMenu::showDynamicBookmarks("netscape"); - info.show = show; - KBookmarkMenu::setDynamicBookmarks("netscape", info); -} - -void KBookmarkManager::setEditorOptions( const TQString& caption, bool browser ) -{ - dptr()->m_editorCaption = caption; - dptr()->m_browserEditor = browser; -} - -void KBookmarkManager::slotEditBookmarks() -{ - TDEProcess proc; - proc << TQString::fromLatin1("keditbookmarks"); - if (!dptr()->m_editorCaption.isNull()) - proc << TQString::fromLatin1("--customcaption") << dptr()->m_editorCaption; - if (!dptr()->m_browserEditor) - proc << TQString::fromLatin1("--nobrowser"); - proc << m_bookmarksFile; - proc.start(TDEProcess::DontCare); -} - -void KBookmarkManager::slotEditBookmarksAtAddress( const TQString& address ) -{ - TDEProcess proc; - proc << TQString::fromLatin1("keditbookmarks") - << TQString::fromLatin1("--address") << address - << m_bookmarksFile; - proc.start(TDEProcess::DontCare); -} - -/////// - -void KBookmarkOwner::openBookmarkURL( const TQString& url ) -{ - (void) new KRun(KURL( url )); -} - -void KBookmarkOwner::virtual_hook( int, void* ) -{ /*BASE::virtual_hook( id, data );*/ } - -bool KBookmarkManager::updateAccessMetadata( const TQString & url, bool emitSignal ) -{ - if (!s_bk_map) { - s_bk_map = new KBookmarkMap(this); - s_bk_map->update(); - } - - TQValueList list = s_bk_map->find(url); - if ( list.count() == 0 ) - return false; - - for ( TQValueList::iterator it = list.begin(); - it != list.end(); ++it ) - (*it).updateAccessMetadata(); - - if (emitSignal) - emit notifier().updatedAccessMetadata( path(), url ); - - return true; -} - -void KBookmarkManager::updateFavicon( const TQString &url, const TQString &faviconurl, bool emitSignal ) -{ - Q_UNUSED(faviconurl); - - if (!s_bk_map) { - s_bk_map = new KBookmarkMap(this); - s_bk_map->update(); - } - - TQValueList list = s_bk_map->find(url); - for ( TQValueList::iterator it = list.begin(); - it != list.end(); ++it ) - { - // TODO - update favicon data based on faviconurl - // but only when the previously used icon - // isn't a manually set one. - } - - if (emitSignal) - { - // TODO - // emit notifier().updatedFavicon( path(), url, faviconurl ); - } -} - -TQString KBookmarkManager::userBookmarksFile() -{ - return locateLocal("data", TQString::fromLatin1("konqueror/bookmarks.xml")); -} - -KBookmarkManager* KBookmarkManager::userBookmarksManager() -{ - return KBookmarkManager::managerForFile( userBookmarksFile() ); -} - -KBookmarkSettings* KBookmarkSettings::s_self = 0; - -void KBookmarkSettings::readSettings() -{ - TDEConfig config("kbookmarkrc", false, false); - config.setGroup("Bookmarks"); - - // add bookmark dialog usage - no reparse - s_self->m_advancedaddbookmark = config.readBoolEntry("AdvancedAddBookmarkDialog", false); - - // these three alter the menu, therefore all need a reparse - s_self->m_contextmenu = config.readBoolEntry("ContextMenuActions", true); - s_self->m_quickactions = config.readBoolEntry("QuickActionSubmenu", false); - s_self->m_filteredtoolbar = config.readBoolEntry("FilteredToolbar", false); -} - -KBookmarkSettings *KBookmarkSettings::self() -{ - if (!s_self) - { - s_self = new KBookmarkSettings; - readSettings(); - } - return s_self; -} - -#include "kbookmarkmanager.moc" diff --git a/tdeio/bookmarks/kbookmarkmanager.cpp b/tdeio/bookmarks/kbookmarkmanager.cpp new file mode 100644 index 000000000..d36d13151 --- /dev/null +++ b/tdeio/bookmarks/kbookmarkmanager.cpp @@ -0,0 +1,731 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure + Copyright (C) 2003 Alexander Kellett + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmarkmanager.h" +#include "kbookmarkmenu.h" +#include "kbookmarkmenu_p.h" +#include "kbookmarkimporter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dptrtemplate.h" + +class KBookmarkManagerPrivate : public dPtrTemplate { +public: + KBookmarkManagerPrivate() + { m_browserEditor = true; } + TQString m_editorCaption; + bool m_browserEditor; +}; +template<> TQPtrDict* dPtrTemplate::d_ptr = 0; + +KBookmarkManagerPrivate* KBookmarkManager::dptr() const { + return KBookmarkManagerPrivate::d( this ); +} + +// TODO - clean this stuff up by just using the above dptrtemplate? +TQPtrList* KBookmarkManager::s_pSelf; +static KStaticDeleter > sdbm; + +class KBookmarkMap : private KBookmarkGroupTraverser { +public: + KBookmarkMap( KBookmarkManager * ); + void update(); + TQValueList find( const TQString &url ) const + { return m_bk_map[url]; } +private: + virtual void visit(const KBookmark &); + virtual void visitEnter(const KBookmarkGroup &) { ; } + virtual void visitLeave(const KBookmarkGroup &) { ; } +private: + typedef TQValueList KBookmarkList; + TQMap m_bk_map; + KBookmarkManager *m_manager; +}; + +static KBookmarkMap *s_bk_map = 0; + +KBookmarkMap::KBookmarkMap( KBookmarkManager *manager ) { + m_manager = manager; +} + +void KBookmarkMap::update() +{ + m_bk_map.clear(); + KBookmarkGroup root = m_manager->root(); + traverse(root); +} + +void KBookmarkMap::visit(const KBookmark &bk) +{ + if (!bk.isSeparator()) { + // add bookmark to url map + m_bk_map[bk.internalElement().attribute("href")].append(bk); + } +} + + +KBookmarkManager* KBookmarkManager::managerForFile( const TQString& bookmarksFile, bool bImportDesktopFiles ) +{ + if ( !s_pSelf ) { + sdbm.setObject( s_pSelf, new TQPtrList ); + s_pSelf->setAutoDelete( true ); + } + TQPtrListIterator it ( *s_pSelf ); + for ( ; it.current() ; ++it ) + if ( it.current()->path() == bookmarksFile ) + return it.current(); + + KBookmarkManager* mgr = new KBookmarkManager( bookmarksFile, bImportDesktopFiles ); + s_pSelf->append( mgr ); + return mgr; +} + +// principally used for filtered toolbars +KBookmarkManager* KBookmarkManager::createTempManager() +{ + if ( !s_pSelf ) { + sdbm.setObject( s_pSelf, new TQPtrList ); + s_pSelf->setAutoDelete( true ); + } + KBookmarkManager* mgr = new KBookmarkManager(); + s_pSelf->append( mgr ); + return mgr; +} + +#define PI_DATA "version=\"1.0\" encoding=\"UTF-8\"" + +KBookmarkManager::KBookmarkManager( const TQString & bookmarksFile, bool bImportDesktopFiles ) + : DCOPObject(TQCString("KBookmarkManager-")+bookmarksFile.utf8()), m_doc("xbel"), m_docIsLoaded(false) +{ + m_toolbarDoc.clear(); + + m_update = true; + m_showNSBookmarks = true; + + Q_ASSERT( !bookmarksFile.isEmpty() ); + m_bookmarksFile = bookmarksFile; + + if ( !TQFile::exists(m_bookmarksFile) ) + { + TQDomElement topLevel = m_doc.createElement("xbel"); + m_doc.appendChild( topLevel ); + m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel ); + if ( bImportDesktopFiles ) + importDesktopFiles(); + m_docIsLoaded = true; + } + + connectDCOPSignal(0, objId(), "bookmarksChanged(TQString)", "notifyChanged(TQString)", false); + connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false); +} + +KBookmarkManager::KBookmarkManager( ) + : DCOPObject(TQCString("KBookmarkManager-generated")), m_doc("xbel"), m_docIsLoaded(true) +{ + m_toolbarDoc.clear(); // strange ;-) + + m_update = false; // TODO - make it read/write + m_showNSBookmarks = true; + + m_bookmarksFile = TQString::null; // AK - check all codepaths for this one + + TQDomElement topLevel = m_doc.createElement("xbel"); + m_doc.appendChild( topLevel ); + m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel ); + + // TODO - enable this via some sort of api and fix the above DCOPObject script somehow +#if 0 + connectDCOPSignal(0, objId(), "bookmarksChanged(TQString)", "notifyChanged(TQString)", false); + connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false); +#endif +} + +KBookmarkManager::~KBookmarkManager() +{ + if ( s_pSelf ) + s_pSelf->removeRef( this ); +} + +void KBookmarkManager::setUpdate( bool update ) +{ + m_update = update; +} + +const TQDomDocument &KBookmarkManager::internalDocument() const +{ + if(!m_docIsLoaded) + { + parse(); + m_toolbarDoc.clear(); + } + return m_doc; +} + + +void KBookmarkManager::parse() const +{ + m_docIsLoaded = true; + //kdDebug(7043) << "KBookmarkManager::parse " << m_bookmarksFile << endl; + TQFile file( m_bookmarksFile ); + if ( !file.open( IO_ReadOnly ) ) + { + kdWarning() << "Can't open " << m_bookmarksFile << endl; + return; + } + m_doc = TQDomDocument("xbel"); + m_doc.setContent( &file ); + + TQDomElement docElem = m_doc.documentElement(); + if ( docElem.isNull() ) + kdWarning() << "KBookmarkManager::parse : can't parse " << m_bookmarksFile << endl; + else + { + TQString mainTag = docElem.tagName(); + if ( mainTag == "BOOKMARKS" ) + { + kdWarning() << "Old style bookmarks found. Calling convertToXBEL." << endl; + docElem.setTagName("xbel"); + if ( docElem.hasAttribute( "HIDE_NSBK" ) && m_showNSBookmarks ) // non standard either, but we need it + { + docElem.setAttribute( "hide_nsbk", docElem.attribute( "HIDE_NSBK" ) == "1" ? "yes" : "no" ); + docElem.removeAttribute( "HIDE_NSBK" ); + } + + convertToXBEL( docElem ); + save(); + } + else if ( mainTag != "xbel" ) + kdWarning() << "KBookmarkManager::parse : unknown main tag " << mainTag << endl; + + TQDomNode n = m_doc.documentElement().previousSibling(); + if ( n.isProcessingInstruction() ) + { + TQDomProcessingInstruction pi = n.toProcessingInstruction(); + pi.parentNode().removeChild(pi); + } + + TQDomProcessingInstruction pi; + pi = m_doc.createProcessingInstruction( "xml", PI_DATA ); + m_doc.insertBefore( pi, docElem ); + } + + file.close(); + if ( !s_bk_map ) + s_bk_map = new KBookmarkMap( const_cast( this ) ); + s_bk_map->update(); +} + +void KBookmarkManager::convertToXBEL( TQDomElement & group ) +{ + TQDomNode n = group.firstChild(); + while( !n.isNull() ) + { + TQDomElement e = n.toElement(); + if ( !e.isNull() ) + { + if ( e.tagName() == "TEXT" ) + { + e.setTagName("title"); + } + else if ( e.tagName() == "SEPARATOR" ) + { + e.setTagName("separator"); // so close... + } + else if ( e.tagName() == "GROUP" ) + { + e.setTagName("folder"); + convertAttribute(e, "ICON","icon"); // non standard, but we need it + if ( e.hasAttribute( "TOOLBAR" ) ) // non standard either, but we need it + { + e.setAttribute( "toolbar", e.attribute( "TOOLBAR" ) == "1" ? "yes" : "no" ); + e.removeAttribute( "TOOLBAR" ); + } + + convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem + bool open = (e.attribute("OPEN") == "1"); + e.removeAttribute("OPEN"); + e.setAttribute("folded", open ? "no" : "yes"); + convertToXBEL( e ); + } + else + { + if ( e.tagName() == "BOOKMARK" ) + { + e.setTagName("bookmark"); // so much difference :-) + convertAttribute(e, "ICON","icon"); // non standard, but we need it + convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem + convertAttribute(e, "URL","href"); + TQString text = e.text(); + while ( !e.firstChild().isNull() ) // clean up the old contained text + e.removeChild(e.firstChild()); + TQDomElement titleElem = e.ownerDocument().createElement("title"); + e.appendChild( titleElem ); // should be the only child anyway + titleElem.appendChild( e.ownerDocument().createTextNode( text ) ); + } + else + { + kdWarning(7043) << "Unknown tag " << e.tagName() << endl; + } + } + } + n = n.nextSibling(); + } +} + +void KBookmarkManager::convertAttribute( TQDomElement elem, const TQString & oldName, const TQString & newName ) +{ + if ( elem.hasAttribute( oldName ) ) + { + elem.setAttribute( newName, elem.attribute( oldName ) ); + elem.removeAttribute( oldName ); + } +} + +void KBookmarkManager::importDesktopFiles() +{ + KBookmarkImporter importer( const_cast(&internalDocument()) ); + TQString path(TDEGlobal::dirs()->saveLocation("data", "kfm/bookmarks", true)); + importer.import( path ); + //kdDebug(7043) << internalDocument().toCString() << endl; + + save(); +} + +bool KBookmarkManager::save( bool toolbarCache ) const +{ + return saveAs( m_bookmarksFile, toolbarCache ); +} + +bool KBookmarkManager::saveAs( const TQString & filename, bool toolbarCache ) const +{ + kdDebug(7043) << "KBookmarkManager::save " << filename << endl; + + // Save the bookmark toolbar folder for quick loading + // but only when it will actually make things quicker + const TQString cacheFilename = filename + TQString::fromLatin1(".tbcache"); + if(toolbarCache && !root().isToolbarGroup()) + { + KSaveFile cacheFile( cacheFilename ); + if ( cacheFile.status() == 0 ) + { + TQString str; + TQTextStream stream(&str, IO_WriteOnly); + stream << root().findToolbar(); + TQCString cstr = str.utf8(); + cacheFile.file()->writeBlock( cstr.data(), cstr.length() ); + cacheFile.close(); + } + } + else // remove any (now) stale cache + { + TQFile::remove( cacheFilename ); + } + + KSaveFile file( filename ); + if ( file.status() == 0 ) + { + file.backupFile( file.name(), TQString::null, ".bak" ); + TQCString cstr; + cstr = internalDocument().toCString(); // is in UTF8 + file.file()->writeBlock( cstr.data(), cstr.length() ); + if ( file.close() ) + return true; + } + + static int hadSaveError = false; + file.abort(); + if ( !hadSaveError ) { + TQString error = i18n("Unable to save bookmarks in %1. Reported error was: %2. " + "This error message will only be shown once. The cause " + "of the error needs to be fixed as quickly as possible, " + "which is most likely a full hard drive.") + .arg(filename).arg(TQString::fromLocal8Bit(strerror(file.status()))); + if (tqApp->type() != TQApplication::Tty) + KMessageBox::error( 0L, error ); + else + kdError() << error << endl; + } + hadSaveError = true; + return false; +} + +KBookmarkGroup KBookmarkManager::root() const +{ + return KBookmarkGroup(internalDocument().documentElement()); +} + +KBookmarkGroup KBookmarkManager::toolbar() +{ + kdDebug(7043) << "KBookmarkManager::toolbar begin" << endl; + // Only try to read from a toolbar cache if the full document isn't loaded + if(!m_docIsLoaded) + { + kdDebug(7043) << "KBookmarkManager::toolbar trying cache" << endl; + const TQString cacheFilename = m_bookmarksFile + TQString::fromLatin1(".tbcache"); + TQFileInfo bmInfo(m_bookmarksFile); + TQFileInfo cacheInfo(cacheFilename); + if (m_toolbarDoc.isNull() && + TQFile::exists(cacheFilename) && + bmInfo.lastModified() < cacheInfo.lastModified()) + { + kdDebug(7043) << "KBookmarkManager::toolbar reading file" << endl; + TQFile file( cacheFilename ); + + if ( file.open( IO_ReadOnly ) ) + { + m_toolbarDoc = TQDomDocument("cache"); + m_toolbarDoc.setContent( &file ); + kdDebug(7043) << "KBookmarkManager::toolbar opened" << endl; + } + } + if (!m_toolbarDoc.isNull()) + { + kdDebug(7043) << "KBookmarkManager::toolbar returning element" << endl; + TQDomElement elem = m_toolbarDoc.firstChild().toElement(); + return KBookmarkGroup(elem); + } + } + + // Fallback to the normal way if there is no cache or if the bookmark file + // is already loaded + TQDomElement elem = root().findToolbar(); + if (elem.isNull()) + return root(); // Root is the bookmark toolbar if none has been set. + else + return KBookmarkGroup(root().findToolbar()); +} + +KBookmark KBookmarkManager::findByAddress( const TQString & address, bool tolerant ) +{ + //kdDebug(7043) << "KBookmarkManager::findByAddress " << address << endl; + KBookmark result = root(); + // The address is something like /5/10/2+ + TQStringList addresses = TQStringList::split(TQRegExp("[/+]"),address); + // kdWarning() << addresses.join(",") << endl; + for ( TQStringList::Iterator it = addresses.begin() ; it != addresses.end() ; ) + { + bool append = ((*it) == "+"); + uint number = (*it).toUInt(); + Q_ASSERT(result.isGroup()); + KBookmarkGroup group = result.toGroup(); + KBookmark bk = group.first(), lbk = bk; // last non-null bookmark + for ( uint i = 0 ; ( (i restart search from the beginning + ch = parentBookmark.first(); + break; + } + else + { + // this exact URL already exists + return TQString::null; + } + } + ch = parentBookmark.next( ch ); + } + } while ( !ch.isNull() ); + + return uniqueTitle; +} + +KBookmarkGroup KBookmarkManager::addBookmarkDialog( + const TQString & _url, const TQString & _title, + const TQString & _parentBookmarkAddress +) { + TQString url = _url; + TQString title = _title; + TQString parentBookmarkAddress = _parentBookmarkAddress; + + if ( url.isEmpty() ) + { + KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL.")); + return KBookmarkGroup(); + } + + if ( title.isEmpty() ) + title = url; + + if ( KBookmarkSettings::self()->m_advancedaddbookmark) + { + KBookmarkEditDialog dlg( title, url, this, KBookmarkEditDialog::InsertionMode, parentBookmarkAddress ); + if ( dlg.exec() != KDialogBase::Accepted ) + return KBookmarkGroup(); + title = dlg.finalTitle(); + url = dlg.finalUrl(); + parentBookmarkAddress = dlg.finalAddress(); + } + + KBookmarkGroup parentBookmark; + parentBookmark = findByAddress( parentBookmarkAddress ).toGroup(); + Q_ASSERT( !parentBookmark.isNull() ); + + TQString uniqueTitle = pickUnusedTitle( parentBookmark, title, url ); + if ( !uniqueTitle.isNull() ) + parentBookmark.addBookmark( this, uniqueTitle, KURL( url )); + + return parentBookmark; +} + + +void KBookmarkManager::emitChanged( /*KDE4 const*/ KBookmarkGroup & group ) +{ + save(); + + // Tell the other processes too + // kdDebug(7043) << "KBookmarkManager::emitChanged : broadcasting change " << group.address() << endl; + + TQByteArray data; + TQDataStream ds( data, IO_WriteOnly ); + ds << group.address(); + + emitDCOPSignal("bookmarksChanged(TQString)", data); + + // We do get our own broadcast, so no need for this anymore + //emit changed( group ); +} + +void KBookmarkManager::emitConfigChanged() +{ + emitDCOPSignal("bookmarkConfigChanged()", TQByteArray()); +} + +void KBookmarkManager::notifyCompleteChange( TQString caller ) // DCOP call +{ + if (!m_update) return; + + //kdDebug(7043) << "KBookmarkManager::notifyCompleteChange" << endl; + // The bk editor tells us we should reload everything + // Reparse + parse(); + // Tell our GUI + // (emit where group is "" to directly mark the root menu as dirty) + emit changed( "", caller ); +} + +void KBookmarkManager::notifyConfigChanged() // DCOP call +{ + kdDebug() << "reloaded bookmark config!" << endl; + KBookmarkSettings::self()->readSettings(); + parse(); // reload, and thusly recreate the menus +} + +void KBookmarkManager::notifyChanged( TQString groupAddress ) // DCOP call +{ + if (!m_update) return; + + // Reparse (the whole file, no other choice) + // if someone else notified us + if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId()) + parse(); + + //kdDebug(7043) << "KBookmarkManager::notifyChanged " << groupAddress << endl; + //KBookmarkGroup group = findByAddress( groupAddress ).toGroup(); + //Q_ASSERT(!group.isNull()); + emit changed( groupAddress, TQString::null ); +} + +bool KBookmarkManager::showNSBookmarks() const +{ + return KBookmarkMenu::showDynamicBookmarks("netscape").show; +} + +void KBookmarkManager::setShowNSBookmarks( bool show ) +{ + m_showNSBookmarks = show; + if (this->path() != userBookmarksFile()) + return; + KBookmarkMenu::DynMenuInfo info + = KBookmarkMenu::showDynamicBookmarks("netscape"); + info.show = show; + KBookmarkMenu::setDynamicBookmarks("netscape", info); +} + +void KBookmarkManager::setEditorOptions( const TQString& caption, bool browser ) +{ + dptr()->m_editorCaption = caption; + dptr()->m_browserEditor = browser; +} + +void KBookmarkManager::slotEditBookmarks() +{ + TDEProcess proc; + proc << TQString::fromLatin1("keditbookmarks"); + if (!dptr()->m_editorCaption.isNull()) + proc << TQString::fromLatin1("--customcaption") << dptr()->m_editorCaption; + if (!dptr()->m_browserEditor) + proc << TQString::fromLatin1("--nobrowser"); + proc << m_bookmarksFile; + proc.start(TDEProcess::DontCare); +} + +void KBookmarkManager::slotEditBookmarksAtAddress( const TQString& address ) +{ + TDEProcess proc; + proc << TQString::fromLatin1("keditbookmarks") + << TQString::fromLatin1("--address") << address + << m_bookmarksFile; + proc.start(TDEProcess::DontCare); +} + +/////// + +void KBookmarkOwner::openBookmarkURL( const TQString& url ) +{ + (void) new KRun(KURL( url )); +} + +void KBookmarkOwner::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +bool KBookmarkManager::updateAccessMetadata( const TQString & url, bool emitSignal ) +{ + if (!s_bk_map) { + s_bk_map = new KBookmarkMap(this); + s_bk_map->update(); + } + + TQValueList list = s_bk_map->find(url); + if ( list.count() == 0 ) + return false; + + for ( TQValueList::iterator it = list.begin(); + it != list.end(); ++it ) + (*it).updateAccessMetadata(); + + if (emitSignal) + emit notifier().updatedAccessMetadata( path(), url ); + + return true; +} + +void KBookmarkManager::updateFavicon( const TQString &url, const TQString &faviconurl, bool emitSignal ) +{ + Q_UNUSED(faviconurl); + + if (!s_bk_map) { + s_bk_map = new KBookmarkMap(this); + s_bk_map->update(); + } + + TQValueList list = s_bk_map->find(url); + for ( TQValueList::iterator it = list.begin(); + it != list.end(); ++it ) + { + // TODO - update favicon data based on faviconurl + // but only when the previously used icon + // isn't a manually set one. + } + + if (emitSignal) + { + // TODO + // emit notifier().updatedFavicon( path(), url, faviconurl ); + } +} + +TQString KBookmarkManager::userBookmarksFile() +{ + return locateLocal("data", TQString::fromLatin1("konqueror/bookmarks.xml")); +} + +KBookmarkManager* KBookmarkManager::userBookmarksManager() +{ + return KBookmarkManager::managerForFile( userBookmarksFile() ); +} + +KBookmarkSettings* KBookmarkSettings::s_self = 0; + +void KBookmarkSettings::readSettings() +{ + TDEConfig config("kbookmarkrc", false, false); + config.setGroup("Bookmarks"); + + // add bookmark dialog usage - no reparse + s_self->m_advancedaddbookmark = config.readBoolEntry("AdvancedAddBookmarkDialog", false); + + // these three alter the menu, therefore all need a reparse + s_self->m_contextmenu = config.readBoolEntry("ContextMenuActions", true); + s_self->m_quickactions = config.readBoolEntry("QuickActionSubmenu", false); + s_self->m_filteredtoolbar = config.readBoolEntry("FilteredToolbar", false); +} + +KBookmarkSettings *KBookmarkSettings::self() +{ + if (!s_self) + { + s_self = new KBookmarkSettings; + readSettings(); + } + return s_self; +} + +#include "kbookmarkmanager.moc" diff --git a/tdeio/bookmarks/kbookmarkmenu.cc b/tdeio/bookmarks/kbookmarkmenu.cc deleted file mode 100644 index fd35736dd..000000000 --- a/tdeio/bookmarks/kbookmarkmenu.cc +++ /dev/null @@ -1,1185 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 1998, 1999 Torben Weis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "kbookmarkmenu.h" -#include "kbookmarkmenu_p.h" -#include "kbookmarkimporter.h" -#include "kbookmarkimporter_opera.h" -#include "kbookmarkimporter_ie.h" -#include "kbookmarkdrag.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -template class TQPtrList; - -static TQString makeTextNodeMod(KBookmark bk, const TQString &m_nodename, const TQString &m_newText) { - TQDomNode subnode = bk.internalElement().namedItem(m_nodename); - if (subnode.isNull()) { - subnode = bk.internalElement().ownerDocument().createElement(m_nodename); - bk.internalElement().appendChild(subnode); - } - - if (subnode.firstChild().isNull()) { - TQDomText domtext = subnode.ownerDocument().createTextNode(""); - subnode.appendChild(domtext); - } - - TQDomText domtext = subnode.firstChild().toText(); - - TQString m_oldText = domtext.data(); - domtext.setData(m_newText); - - return m_oldText; -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -KBookmarkMenu::KBookmarkMenu( KBookmarkManager* mgr, - KBookmarkOwner * _owner, TDEPopupMenu * _parentMenu, - TDEActionCollection *collec, bool _isRoot, bool _add, - const TQString & parentAddress ) - : TQObject(), - m_bIsRoot(_isRoot), m_bAddBookmark(_add), - m_bAddShortcuts(true), - m_pManager(mgr), m_pOwner(_owner), - m_parentMenu( _parentMenu ), - m_actionCollection( collec ), - m_parentAddress( parentAddress ) -{ - m_parentMenu->setKeyboardShortcutsEnabled( true ); - - m_lstSubMenus.setAutoDelete( true ); - m_actions.setAutoDelete( true ); - - if (m_actionCollection) - { - m_actionCollection->setHighlightingEnabled(true); - disconnect( m_actionCollection, TQT_SIGNAL( actionHighlighted( TDEAction * ) ), 0, 0 ); - connect( m_actionCollection, TQT_SIGNAL( actionHighlighted( TDEAction * ) ), - this, TQT_SLOT( slotActionHighlighted( TDEAction * ) ) ); - } - - m_bNSBookmark = m_parentAddress.isNull(); - if ( !m_bNSBookmark ) // not for the netscape bookmark - { - //kdDebug(7043) << "KBookmarkMenu::KBookmarkMenu " << this << " address : " << m_parentAddress << endl; - - connect( _parentMenu, TQT_SIGNAL( aboutToShow() ), - TQT_SLOT( slotAboutToShow() ) ); - - if ( KBookmarkSettings::self()->m_contextmenu ) - { - (void) _parentMenu->contextMenu(); - connect( _parentMenu, TQT_SIGNAL( aboutToShowContextMenu(TDEPopupMenu*, int, TQPopupMenu*) ), - this, TQT_SLOT( slotAboutToShowContextMenu(TDEPopupMenu*, int, TQPopupMenu*) )); - } - - if ( m_bIsRoot ) - { - connect( m_pManager, TQT_SIGNAL( changed(const TQString &, const TQString &) ), - TQT_SLOT( slotBookmarksChanged(const TQString &) ) ); - } - } - - // add entries that possibly have a shortcut, so they are available _before_ first popup - if ( m_bIsRoot ) - { - if ( m_bAddBookmark ) - { - addAddBookmark(); - if ( extOwner() ) - addAddBookmarksList(); // FIXME - } - - addEditBookmarks(); - } - - m_bDirty = true; -} - -KBookmarkMenu::~KBookmarkMenu() -{ - //kdDebug(7043) << "KBookmarkMenu::~KBookmarkMenu() " << this << endl; - TQPtrListIterator it( m_actions ); - for (; it.current(); ++it ) - it.current()->unplugAll(); - - m_lstSubMenus.clear(); - m_actions.clear(); -} - -void KBookmarkMenu::ensureUpToDate() -{ - slotAboutToShow(); -} - -void KBookmarkMenu::slotAboutToShow() -{ - // Did the bookmarks change since the last time we showed them ? - if ( m_bDirty ) - { - m_bDirty = false; - refill(); - } -} - -TQString KBookmarkMenu::s_highlightedAddress; -TQString KBookmarkMenu::s_highlightedImportType; -TQString KBookmarkMenu::s_highlightedImportLocation; - -void KBookmarkMenu::slotActionHighlighted( TDEAction* action ) -{ - if (action->isA("KBookmarkActionMenu") || action->isA("KBookmarkAction")) - { - s_highlightedAddress = action->property("address").toString(); - //kdDebug() << "KBookmarkMenu::slotActionHighlighted" << s_highlightedAddress << endl; - } - else if (action->isA("KImportedBookmarksActionMenu")) - { - s_highlightedImportType = action->property("type").toString(); - s_highlightedImportLocation = action->property("location").toString(); - } - else - { - s_highlightedAddress = TQString::null; - s_highlightedImportType = TQString::null; - s_highlightedImportLocation = TQString::null; - } -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -class KBookmarkMenuRMBAssoc : public dPtrTemplate { }; -template<> TQPtrDict* dPtrTemplate::d_ptr = 0; - -static RMB* rmbSelf(KBookmarkMenu *m) { return KBookmarkMenuRMBAssoc::d(m); } - -// TODO check via dcop before making any changes to the bookmarks file??? - -void RMB::begin_rmb_action(KBookmarkMenu *self) -{ - RMB *s = rmbSelf(self); - s->recv = self; - s->m_parentAddress = self->m_parentAddress; - s->s_highlightedAddress = KBookmarkMenu::s_highlightedAddress; - s->m_pManager = self->m_pManager; - s->m_pOwner = self->m_pOwner; - s->m_parentMenu = self->m_parentMenu; -} - -bool RMB::invalid( int val ) -{ - bool valid = true; - - if (val == 1) - s_highlightedAddress = m_parentAddress; - - if (s_highlightedAddress.isNull()) - valid = false; - - return !valid; -} - -KBookmark RMB::atAddress(const TQString & address) -{ - KBookmark bookmark = m_pManager->findByAddress( address ); - Q_ASSERT(!bookmark.isNull()); - return bookmark; -} - -void KBookmarkMenu::slotAboutToShowContextMenu( TDEPopupMenu*, int, TQPopupMenu* contextMenu ) -{ - //kdDebug(7043) << "KBookmarkMenu::slotAboutToShowContextMenu" << s_highlightedAddress << endl; - if (s_highlightedAddress.isNull()) - { - TDEPopupMenu::contextMenuFocus()->hideContextMenu(); - return; - } - contextMenu->clear(); - fillContextMenu( contextMenu, s_highlightedAddress, 0 ); -} - -void RMB::fillContextMenu( TQPopupMenu* contextMenu, const TQString & address, int val ) -{ - KBookmark bookmark = atAddress(address); - - int id; - - // binner: - // "Add Bookmark Here" when pointing at a bookmark looks strange and if you - // call it you have to close and reopen the menu to see an entry was added? - // - // TODO rename these, but, message freeze... umm... - -// if (bookmark.isGroup()) { - id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, TQT_SLOT(slotRMBActionInsert(int)) ); - contextMenu->setItemParameter( id, val ); -/* } - else - { - id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, TQT_SLOT(slotRMBActionInsert(int)) ); - contextMenu->setItemParameter( id, val ); - }*/ -} - -void RMB::fillContextMenu2( TQPopupMenu* contextMenu, const TQString & address, int val ) -{ - KBookmark bookmark = atAddress(address); - - int id; - - if (bookmark.isGroup()) { - id = contextMenu->insertItem( i18n( "Open Folder in Bookmark Editor" ), recv, TQT_SLOT(slotRMBActionEditAt(int)) ); - contextMenu->setItemParameter( id, val ); - contextMenu->insertSeparator(); - id = contextMenu->insertItem( SmallIcon("edit-delete"), i18n( "Delete Folder" ), recv, TQT_SLOT(slotRMBActionRemove(int)) ); - contextMenu->setItemParameter( id, val ); - contextMenu->insertSeparator(); - id = contextMenu->insertItem( i18n( "Properties" ), recv, TQT_SLOT(slotRMBActionProperties(int)) ); - contextMenu->setItemParameter( id, val ); - } - else - { - id = contextMenu->insertItem( i18n( "Copy Link Address" ), recv, TQT_SLOT(slotRMBActionCopyLocation(int)) ); - contextMenu->setItemParameter( id, val ); - contextMenu->insertSeparator(); - id = contextMenu->insertItem( SmallIcon("edit-delete"), i18n( "Delete Bookmark" ), recv, TQT_SLOT(slotRMBActionRemove(int)) ); - contextMenu->setItemParameter( id, val ); - contextMenu->insertSeparator(); - id = contextMenu->insertItem( i18n( "Properties" ), recv, TQT_SLOT(slotRMBActionProperties(int)) ); - contextMenu->setItemParameter( id, val ); - } -} - -void RMB::slotRMBActionEditAt( int val ) -{ - kdDebug(7043) << "KBookmarkMenu::slotRMBActionEditAt" << s_highlightedAddress << endl; - if (invalid(val)) { hidePopup(); return; } - - KBookmark bookmark = atAddress(s_highlightedAddress); - - m_pManager->slotEditBookmarksAtAddress( s_highlightedAddress ); -} - -void RMB::slotRMBActionProperties( int val ) -{ - kdDebug(7043) << "KBookmarkMenu::slotRMBActionProperties" << s_highlightedAddress << endl; - if (invalid(val)) { hidePopup(); return; } - - KBookmark bookmark = atAddress(s_highlightedAddress); - - TQString folder = bookmark.isGroup() ? TQString::null : bookmark.url().pathOrURL(); - KBookmarkEditDialog dlg( bookmark.fullText(), folder, - m_pManager, KBookmarkEditDialog::ModifyMode, 0, - 0, 0, i18n("Bookmark Properties") ); - if ( dlg.exec() != KDialogBase::Accepted ) - return; - - makeTextNodeMod(bookmark, "title", dlg.finalTitle()); - if ( !dlg.finalUrl().isNull() ) - { - KURL u = KURL::fromPathOrURL(dlg.finalUrl()); - bookmark.internalElement().setAttribute("href", u.url(0, 106)); - } - - kdDebug(7043) << "Requested move to " << dlg.finalAddress() << "!" << endl; - - KBookmarkGroup parentBookmark = atAddress(m_parentAddress).toGroup(); - m_pManager->emitChanged( parentBookmark ); -} - -void RMB::slotRMBActionInsert( int val ) -{ - kdDebug(7043) << "KBookmarkMenu::slotRMBActionInsert" << s_highlightedAddress << endl; - if (invalid(val)) { hidePopup(); return; } - - TQString url = m_pOwner->currentURL(); - if (url.isEmpty()) - { - KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL.")); - return; - } - TQString title = m_pOwner->currentTitle(); - if (title.isEmpty()) - title = url; - - KBookmark bookmark = atAddress( s_highlightedAddress ); - - // TODO use unique title - - if (bookmark.isGroup()) - { - KBookmarkGroup parentBookmark = bookmark.toGroup(); - Q_ASSERT(!parentBookmark.isNull()); - parentBookmark.addBookmark( m_pManager, title, KURL( url ) ); - m_pManager->emitChanged( parentBookmark ); - } - else - { - KBookmarkGroup parentBookmark = bookmark.parentGroup(); - Q_ASSERT(!parentBookmark.isNull()); - KBookmark newBookmark = parentBookmark.addBookmark( m_pManager, title, KURL( url ) ); - parentBookmark.moveItem( newBookmark, parentBookmark.previous(bookmark) ); - m_pManager->emitChanged( parentBookmark ); - } -} - -void RMB::slotRMBActionRemove( int val ) -{ - //kdDebug(7043) << "KBookmarkMenu::slotRMBActionRemove" << s_highlightedAddress << endl; - if (invalid(val)) { hidePopup(); return; } - - KBookmark bookmark = atAddress( s_highlightedAddress ); - bool folder = bookmark.isGroup(); - - if (KMessageBox::warningContinueCancel( - m_parentMenu, - folder ? i18n("Are you sure you wish to remove the bookmark folder\n\"%1\"?").arg(bookmark.text()) - : i18n("Are you sure you wish to remove the bookmark\n\"%1\"?").arg(bookmark.text()), - folder ? i18n("Bookmark Folder Deletion") - : i18n("Bookmark Deletion"), - KStdGuiItem::del()) - != KMessageBox::Continue - ) - return; - - KBookmarkGroup parentBookmark = atAddress( m_parentAddress ).toGroup(); - parentBookmark.deleteBookmark( bookmark ); - m_pManager->emitChanged( parentBookmark ); - if (m_parentMenu) - m_parentMenu->hide(); -} - -void RMB::slotRMBActionCopyLocation( int val ) -{ - //kdDebug(7043) << "KBookmarkMenu::slotRMBActionCopyLocation" << s_highlightedAddress << endl; - if (invalid(val)) { hidePopup(); return; } - - KBookmark bookmark = atAddress( s_highlightedAddress ); - - if ( !bookmark.isGroup() ) - { - kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0), - TQClipboard::Selection ); - kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0), - TQClipboard::Clipboard ); - } -} - -void RMB::hidePopup() { - TDEPopupMenu::contextMenuFocus()->hideContextMenu(); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -void KBookmarkMenu::fillContextMenu( TQPopupMenu* contextMenu, const TQString & address, int val ) -{ - RMB::begin_rmb_action(this); - rmbSelf(this)->fillContextMenu(contextMenu, address, val); - emit aboutToShowContextMenu( rmbSelf(this)->atAddress(address), contextMenu); - rmbSelf(this)->fillContextMenu2(contextMenu, address, val); -} - -void KBookmarkMenu::slotRMBActionEditAt( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); } - -void KBookmarkMenu::slotRMBActionProperties( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); } - -void KBookmarkMenu::slotRMBActionInsert( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); } - -void KBookmarkMenu::slotRMBActionRemove( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); } - -void KBookmarkMenu::slotRMBActionCopyLocation( int val ) -{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); } - -void KBookmarkMenu::slotBookmarksChanged( const TQString & groupAddress ) -{ - if (m_bNSBookmark) - return; - - if ( groupAddress == m_parentAddress ) - { - //kdDebug(7043) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress << endl; - m_bDirty = true; - } - else - { - // Iterate recursively into child menus - TQPtrListIterator it( m_lstSubMenus ); - for (; it.current(); ++it ) - { - it.current()->slotBookmarksChanged( groupAddress ); - } - } -} - -void KBookmarkMenu::refill() -{ - //kdDebug(7043) << "KBookmarkMenu::refill()" << endl; - m_lstSubMenus.clear(); - - TQPtrListIterator it( m_actions ); - for (; it.current(); ++it ) - it.current()->unplug( m_parentMenu ); - - m_parentMenu->clear(); - m_actions.clear(); - - fillBookmarkMenu(); - m_parentMenu->adjustSize(); -} - -void KBookmarkMenu::addAddBookmarksList() -{ - if (!kapp->authorizeTDEAction("bookmarks")) - return; - - TQString title = i18n( "Bookmark Tabs as Folder..." ); - - TDEAction * paAddBookmarksList = new TDEAction( title, - "bookmarks_list_add", - 0, - this, - TQT_SLOT( slotAddBookmarksList() ), - m_actionCollection, m_bIsRoot ? "add_bookmarks_list" : 0 ); - - paAddBookmarksList->setToolTip( i18n( "Add a folder of bookmarks for all open tabs." ) ); - - paAddBookmarksList->plug( m_parentMenu ); - m_actions.append( paAddBookmarksList ); -} - -void KBookmarkMenu::addAddBookmark() -{ - if (!kapp->authorizeTDEAction("bookmarks")) - return; - - TQString title = i18n( "Add Bookmark" ); - - TDEAction * paAddBookmarks = new TDEAction( title, - "bookmark_add", - m_bIsRoot && m_bAddShortcuts ? TDEStdAccel::addBookmark() : TDEShortcut(), - this, - TQT_SLOT( slotAddBookmark() ), - m_actionCollection, m_bIsRoot ? "add_bookmark" : 0 ); - - paAddBookmarks->setToolTip( i18n( "Add a bookmark for the current document" ) ); - - paAddBookmarks->plug( m_parentMenu ); - m_actions.append( paAddBookmarks ); -} - -void KBookmarkMenu::addEditBookmarks() -{ - if (!kapp->authorizeTDEAction("bookmarks")) - return; - - TDEAction * m_paEditBookmarks = KStdAction::editBookmarks( m_pManager, TQT_SLOT( slotEditBookmarks() ), - m_actionCollection, "edit_bookmarks" ); - m_paEditBookmarks->plug( m_parentMenu ); - m_paEditBookmarks->setToolTip( i18n( "Edit your bookmark collection in a separate window" ) ); - m_actions.append( m_paEditBookmarks ); -} - -void KBookmarkMenu::addNewFolder() -{ - if (!kapp->authorizeTDEAction("bookmarks")) - return; - - TQString title = i18n( "&New Bookmark Folder..." ); - int p; - while ( ( p = title.find( '&' ) ) >= 0 ) - title.remove( p, 1 ); - - TDEAction * paNewFolder = new TDEAction( title, - "folder-new", //"folder", - 0, - this, - TQT_SLOT( slotNewFolder() ), - m_actionCollection ); - - paNewFolder->setToolTip( i18n( "Create a new bookmark folder in this menu" ) ); - - paNewFolder->plug( m_parentMenu ); - m_actions.append( paNewFolder ); -} - -void KBookmarkMenu::fillBookmarkMenu() -{ - if (!kapp->authorizeTDEAction("bookmarks")) - return; - - if ( m_bIsRoot ) - { - if ( m_bAddBookmark ) - { - addAddBookmark(); - if ( extOwner() ) - addAddBookmarksList(); // FIXME - } - - addEditBookmarks(); - - if ( m_bAddBookmark && !KBookmarkSettings::self()->m_advancedaddbookmark ) - addNewFolder(); - } - - if ( m_bIsRoot - && KBookmarkManager::userBookmarksFile() == m_pManager->path() ) - { - bool haveSep = false; - - TQValueList keys = KBookmarkMenu::dynamicBookmarksList(); - TQValueList::const_iterator it; - for ( it = keys.begin(); it != keys.end(); ++it ) - { - DynMenuInfo info; - info = showDynamicBookmarks((*it)); - - if ( !info.show || !TQFile::exists( info.location ) ) - continue; - - if (!haveSep) - { - m_parentMenu->insertSeparator(); - haveSep = true; - } - - TDEActionMenu * actionMenu; - actionMenu = new KImportedBookmarksActionMenu( - info.name, info.type, - m_actionCollection, "kbookmarkmenu" ); - - actionMenu->setProperty( "type", info.type ); - actionMenu->setProperty( "location", info.location ); - - actionMenu->plug( m_parentMenu ); - m_actions.append( actionMenu ); - - KBookmarkMenu *subMenu = - new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(), - m_actionCollection, false, - m_bAddBookmark, TQString::null ); - connect( subMenu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) ), - this, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) )); - m_lstSubMenus.append(subMenu); - - connect(actionMenu->popupMenu(), TQT_SIGNAL(aboutToShow()), subMenu, TQT_SLOT(slotNSLoad())); - } - } - - KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); - Q_ASSERT(!parentBookmark.isNull()); - bool separatorInserted = false; - for ( KBookmark bm = parentBookmark.first(); !bm.isNull(); bm = parentBookmark.next(bm) ) - { - TQString text = KStringHandler::csqueeze(bm.fullText(), 60); - text.replace( '&', "&&" ); - if ( !separatorInserted && m_bIsRoot) { - // inserted before the first konq bookmark, to avoid the separator if no konq bookmark - m_parentMenu->insertSeparator(); - separatorInserted = true; - } - if ( !bm.isGroup() ) - { - if ( bm.isSeparator() ) - { - m_parentMenu->insertSeparator(); - } - else - { - //kdDebug(7043) << "Creating URL bookmark menu item for " << bm.text() << endl; - TDEAction * action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 ); - connect(action, TQT_SIGNAL( activated ( TDEAction::ActivationReason, TQt::ButtonState )), - this, TQT_SLOT( slotBookmarkSelected( TDEAction::ActivationReason, TQt::ButtonState ) )); - - action->setProperty( "url", bm.url().url() ); - action->setProperty( "address", bm.address() ); - - action->setToolTip( bm.url().pathOrURL() ); - - action->plug( m_parentMenu ); - m_actions.append( action ); - } - } - else - { - //kdDebug(7043) << "Creating bookmark submenu named " << bm.text() << endl; - TDEActionMenu * actionMenu = new KBookmarkActionMenu( text, bm.icon(), - m_actionCollection, - "kbookmarkmenu" ); - actionMenu->setProperty( "address", bm.address() ); - actionMenu->plug( m_parentMenu ); - m_actions.append( actionMenu ); - - KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(), - m_actionCollection, false, - m_bAddBookmark, - bm.address() ); - - connect(subMenu, TQT_SIGNAL( aboutToShowContextMenu( const KBookmark &, TQPopupMenu * ) ), - this, TQT_SIGNAL( aboutToShowContextMenu( const KBookmark &, TQPopupMenu * ) )); - connect(subMenu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) ), - this, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) )); - m_lstSubMenus.append( subMenu ); - } - } - - if ( !m_bIsRoot && m_bAddBookmark ) - { - if ( m_parentMenu->count() > 0 ) - m_parentMenu->insertSeparator(); - - if ( KBookmarkSettings::self()->m_quickactions ) - { - TDEActionMenu * actionMenu = new TDEActionMenu( i18n("Quick Actions"), m_actionCollection, 0L ); - fillContextMenu( actionMenu->popupMenu(), m_parentAddress, 1 ); - actionMenu->plug( m_parentMenu ); - m_actions.append( actionMenu ); - } - else - { - addAddBookmark(); - if ( extOwner() ) - addAddBookmarksList(); // FIXME - addNewFolder(); - } - } -} - -void KBookmarkMenu::slotAddBookmarksList() -{ - KExtendedBookmarkOwner *extOwner = dynamic_cast(m_pOwner); - if (!extOwner) - { - kdWarning() << "erm, sorry ;-)" << endl; - return; - } - - KExtendedBookmarkOwner::QStringPairList list; - extOwner->fillBookmarksList( list ); - - KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); - Q_ASSERT(!parentBookmark.isNull()); - KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager ); - if ( group.isNull() ) - return; // user canceled i guess - - KExtendedBookmarkOwner::QStringPairList::const_iterator it; - for ( it = list.begin(); it != list.end(); ++it ) - group.addBookmark( m_pManager, (*it).first, KURL((*it).second) ); - - m_pManager->emitChanged( parentBookmark ); -} - - -void KBookmarkMenu::slotAddBookmark() -{ - KBookmarkGroup parentBookmark; - parentBookmark = m_pManager->addBookmarkDialog(m_pOwner->currentURL(), m_pOwner->currentTitle(), m_parentAddress); - if (!parentBookmark.isNull()) - m_pManager->emitChanged( parentBookmark ); -} - -void KBookmarkMenu::slotNewFolder() -{ - if ( !m_pOwner ) return; // this view doesn't handle bookmarks... - KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); - Q_ASSERT(!parentBookmark.isNull()); - KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager ); - if ( !group.isNull() ) - { - KBookmarkGroup parentGroup = group.parentGroup(); - m_pManager->emitChanged( parentGroup ); - } -} - -void KBookmarkMenu::slotBookmarkSelected( TDEAction::ActivationReason /*reason*/, TQt::ButtonState state ) -{ - kdDebug(7043) << "KBookmarkMenu::slotBookmarkSelected()" << endl; - if ( !m_pOwner ) return; // this view doesn't handle bookmarks... - const TDEAction* action = dynamic_cast(sender()); - if(action) - { - const TQString& url = sender()->property("url").toString(); - m_pOwner->openBookmarkURL( url ); - emit openBookmark( url, state ); - } -} - -void KBookmarkMenu::slotBookmarkSelected() -{ - slotBookmarkSelected(TDEAction::PopupMenuActivation, Qt::NoButton); -} - -KExtendedBookmarkOwner* KBookmarkMenu::extOwner() -{ - return dynamic_cast(m_pOwner); -} - -void KBookmarkMenu::slotNSLoad() -{ - // only fill menu once - m_parentMenu->disconnect(TQT_SIGNAL(aboutToShow())); - - // not NSImporter, but kept old name for BC reasons - KBookmarkMenuNSImporter importer( m_pManager, this, m_actionCollection ); - importer.openBookmarks(s_highlightedImportLocation, s_highlightedImportType); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -KBookmarkEditFields::KBookmarkEditFields(TQWidget *main, TQBoxLayout *vbox, FieldsSet fieldsSet) -{ - bool isF = (fieldsSet != FolderFieldsSet); - - TQGridLayout *grid = new TQGridLayout( vbox, 2, isF ? 2 : 1 ); - - m_title = new KLineEdit( main ); - grid->addWidget( m_title, 0, 1 ); - grid->addWidget( new TQLabel( m_title, i18n( "Name:" ), main ), 0, 0 ); - m_title->setFocus(); - if (isF) - { - m_url = new KLineEdit( main ); - grid->addWidget( m_url, 1, 1 ); - grid->addWidget( new TQLabel( m_url, i18n( "Location:" ), main ), 1, 0 ); - } - else - { - m_url = 0; - } - - main->setMinimumSize( 300, 0 ); -} - -void KBookmarkEditFields::setName(const TQString &str) -{ - m_title->setText(str); -} - -void KBookmarkEditFields::setLocation(const TQString &str) -{ - m_url->setText(str); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -// TODO - make the dialog use Properties as a title when in Modify mode... (dirk noticed the bug...) -KBookmarkEditDialog::KBookmarkEditDialog(const TQString& title, const TQString& url, KBookmarkManager * mgr, BookmarkEditType editType, const TQString& address, - TQWidget * parent, const char * name, const TQString& caption ) - : KDialogBase(parent, name, true, caption, - (editType == InsertionMode) ? (User1|Ok|Cancel) : (Ok|Cancel), - Ok, false, KGuiItem()), - m_folderTree(0), m_mgr(mgr), m_editType(editType), m_address(address) -{ - setButtonOK( (editType == InsertionMode) ? KGuiItem( i18n( "&Add" ), "bookmark_add") : i18n( "&Update" ) ); - if (editType == InsertionMode) { - setButtonGuiItem( User1, KGuiItem( i18n( "&New Folder..." ), "folder-new") ); - } - - bool folder = url.isNull(); - - m_main = new TQWidget( this ); - setMainWidget( m_main ); - - TQBoxLayout *vbox = new TQVBoxLayout( m_main, 0, spacingHint() ); - KBookmarkEditFields::FieldsSet fs = - folder ? KBookmarkEditFields::FolderFieldsSet - : KBookmarkEditFields::BookmarkFieldsSet; - m_fields = new KBookmarkEditFields(m_main, vbox, fs); - m_fields->setName(title); - if ( !folder ) - m_fields->setLocation(url); - - if ( editType == InsertionMode ) - { - m_folderTree = KBookmarkFolderTree::createTree( m_mgr, m_main, name, m_address ); - connect( m_folderTree, TQT_SIGNAL( doubleClicked(TQListViewItem*) ), - this, TQT_SLOT( slotDoubleClicked(TQListViewItem*) ) ); - vbox->addWidget( m_folderTree ); - connect( this, TQT_SIGNAL( user1Clicked() ), TQT_SLOT( slotUser1() ) ); - } -} - -void KBookmarkEditDialog::slotDoubleClicked( TQListViewItem* item ) -{ - Q_ASSERT( m_folderTree ); - m_folderTree->setCurrentItem( item ); - accept(); -} - -void KBookmarkEditDialog::slotOk() -{ - accept(); -} - -void KBookmarkEditDialog::slotCancel() -{ - reject(); -} - -TQString KBookmarkEditDialog::finalAddress() const -{ - Q_ASSERT( m_folderTree ); - return KBookmarkFolderTree::selectedAddress( m_folderTree ); -} - -TQString KBookmarkEditDialog::finalUrl() const -{ - return m_fields->m_url ? m_fields->m_url->text() : TQString::null; -} - -TQString KBookmarkEditDialog::finalTitle() const -{ - return m_fields->m_title ? m_fields->m_title->text() : TQString::null; -} - -void KBookmarkEditDialog::slotUser1() -{ - // kdDebug(7043) << "KBookmarkEditDialog::slotUser1" << endl; - Q_ASSERT( m_folderTree ); - - TQString address = KBookmarkFolderTree::selectedAddress( m_folderTree ); - if ( address.isNull() ) return; - KBookmarkGroup bm = m_mgr->findByAddress( address ).toGroup(); - Q_ASSERT(!bm.isNull()); - Q_ASSERT(m_editType == InsertionMode); - - KBookmarkGroup group = bm.createNewFolder( m_mgr ); - if ( !group.isNull() ) - { - KBookmarkGroup parentGroup = group.parentGroup(); - m_mgr->emitChanged( parentGroup ); - } - KBookmarkFolderTree::fillTree( m_folderTree, m_mgr ); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -static void fillGroup( TQListView* listview, KBookmarkFolderTreeItem * parentItem, KBookmarkGroup group, bool expandOpenGroups = true, const TQString& address = TQString::null ) -{ - bool noSubGroups = true; - KBookmarkFolderTreeItem * lastItem = 0L; - KBookmarkFolderTreeItem * item = 0L; - for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk) ) - { - if ( bk.isGroup() ) - { - KBookmarkGroup grp = bk.toGroup(); - item = new KBookmarkFolderTreeItem( parentItem, lastItem, grp ); - fillGroup( listview, item, grp, expandOpenGroups, address ); - if ( expandOpenGroups && grp.isOpen() ) - item->setOpen( true ); - lastItem = item; - noSubGroups = false; - } - if (bk.address() == address) { - listview->setCurrentItem( lastItem ); - listview->ensureItemVisible( item ); - } - } - if ( noSubGroups ) { - parentItem->setOpen( true ); - } -} - -TQListView* KBookmarkFolderTree::createTree( KBookmarkManager* mgr, TQWidget* parent, const char* name, const TQString& address ) -{ - TQListView *listview = new TQListView( parent, name ); - - listview->setRootIsDecorated( false ); - listview->header()->hide(); - listview->addColumn( i18n("Bookmark"), 200 ); - listview->setSorting( -1, false ); - listview->setSelectionMode( TQListView::Single ); - listview->setAllColumnsShowFocus( true ); - listview->setResizeMode( TQListView::AllColumns ); - listview->setMinimumSize( 60, 100 ); - - fillTree( listview, mgr, address ); - - return listview; -} - -void KBookmarkFolderTree::fillTree( TQListView *listview, KBookmarkManager* mgr, const TQString& address ) -{ - listview->clear(); - - KBookmarkGroup root = mgr->root(); - KBookmarkFolderTreeItem * rootItem = new KBookmarkFolderTreeItem( listview, root ); - listview->setCurrentItem( rootItem ); - rootItem->setSelected( true ); - fillGroup( listview, rootItem, root, (address == root.groupAddress() || address.isNull()) ? true : false, address ); - rootItem->setOpen( true ); -} - -static KBookmarkFolderTreeItem* ft_cast( TQListViewItem *i ) -{ - return static_cast( i ); -} - -TQString KBookmarkFolderTree::selectedAddress( TQListView *listview ) -{ - if ( !listview) - return TQString::null; - KBookmarkFolderTreeItem *item = ft_cast( listview->currentItem() ); - return item ? item->m_bookmark.address() : TQString::null; -} - -void KBookmarkFolderTree::setAddress( TQListView *listview, const TQString & address ) -{ - KBookmarkFolderTreeItem* it = ft_cast( listview->firstChild() ); - while ( true ) { - kdDebug(7043) << it->m_bookmark.address() << endl; - it = ft_cast( it->itemBelow() ); - if ( !it ) - return; - if ( it->m_bookmark.address() == address ) - break; - } - it->setSelected( true ); - listview->setCurrentItem( it ); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -// toplevel item -KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( TQListView *parent, const KBookmark & gp ) - : TQListViewItem(parent, i18n("Bookmarks")), m_bookmark(gp) -{ - setPixmap(0, SmallIcon("bookmark")); - setExpandable(true); -} - -// group -KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( KBookmarkFolderTreeItem *parent, TQListViewItem *after, const KBookmarkGroup & gp ) - : TQListViewItem(parent, after, gp.fullText()), m_bookmark(gp) -{ - setPixmap(0, SmallIcon( gp.icon() ) ); - setExpandable(true); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -// NOTE - KBookmarkMenuNSImporter is really === KBookmarkMenuImporter -// i.e, it is _not_ ns specific. and in KDE4 it should be renamed. - -void KBookmarkMenuNSImporter::openNSBookmarks() -{ - openBookmarks( KNSBookmarkImporter::netscapeBookmarksFile(), "netscape" ); -} - -void KBookmarkMenuNSImporter::openBookmarks( const TQString &location, const TQString &type ) -{ - mstack.push(m_menu); - - KBookmarkImporterBase *importer = KBookmarkImporterBase::factory(type); - if (!importer) - return; - importer->setFilename(location); - connectToImporter(*importer); - importer->parse(); - - delete importer; -} - -void KBookmarkMenuNSImporter::connectToImporter(const TQObject &importer) -{ - connect( &importer, TQT_SIGNAL( newBookmark( const TQString &, const TQCString &, const TQString & ) ), - TQT_SLOT( newBookmark( const TQString &, const TQCString &, const TQString & ) ) ); - connect( &importer, TQT_SIGNAL( newFolder( const TQString &, bool, const TQString & ) ), - TQT_SLOT( newFolder( const TQString &, bool, const TQString & ) ) ); - connect( &importer, TQT_SIGNAL( newSeparator() ), TQT_SLOT( newSeparator() ) ); - connect( &importer, TQT_SIGNAL( endFolder() ), TQT_SLOT( endFolder() ) ); -} - -void KBookmarkMenuNSImporter::newBookmark( const TQString & text, const TQCString & url, const TQString & ) -{ - TQString _text = KStringHandler::csqueeze(text); - _text.replace( '&', "&&" ); - TDEAction * action = new KBookmarkAction(_text, "text-html", 0, 0, "", m_actionCollection, 0); - connect(action, TQT_SIGNAL( activated ( TDEAction::ActivationReason, TQt::ButtonState )), - m_menu, TQT_SLOT( slotBookmarkSelected( TDEAction::ActivationReason, TQt::ButtonState ) )); - action->setProperty( "url", url ); - action->setToolTip( url ); - action->plug( mstack.top()->m_parentMenu ); - mstack.top()->m_actions.append( action ); -} - -void KBookmarkMenuNSImporter::newFolder( const TQString & text, bool, const TQString & ) -{ - TQString _text = KStringHandler::csqueeze(text); - _text.replace( '&', "&&" ); - TDEActionMenu * actionMenu = new TDEActionMenu( _text, "folder", m_actionCollection, 0L ); - actionMenu->plug( mstack.top()->m_parentMenu ); - mstack.top()->m_actions.append( actionMenu ); - KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_menu->m_pOwner, actionMenu->popupMenu(), - m_actionCollection, false, - m_menu->m_bAddBookmark, TQString::null ); - connect( subMenu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) ), - m_menu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) )); - mstack.top()->m_lstSubMenus.append( subMenu ); - - mstack.push(subMenu); -} - -void KBookmarkMenuNSImporter::newSeparator() -{ - mstack.top()->m_parentMenu->insertSeparator(); -} - -void KBookmarkMenuNSImporter::endFolder() -{ - mstack.pop(); -} - -/********************************************************************/ -/********************************************************************/ -/********************************************************************/ - -KBookmarkMenu::DynMenuInfo KBookmarkMenu::showDynamicBookmarks( const TQString &id ) -{ - TDEConfig config("kbookmarkrc", false, false); - config.setGroup("Bookmarks"); - - DynMenuInfo info; - info.show = false; - - if (!config.hasKey("DynamicMenus")) { - // upgrade path - if (id == "netscape") { - KBookmarkManager *manager = KBookmarkManager::userBookmarksManager(); - info.show = manager->root().internalElement().attribute("hide_nsbk") != "yes"; - info.location = KNSBookmarkImporter::netscapeBookmarksFile(); - info.type = "netscape"; - info.name = i18n("Netscape Bookmarks"); - } // else, no show - - } else { - // have new version config - if (config.hasGroup("DynamicMenu-" + id)) { - config.setGroup("DynamicMenu-" + id); - info.show = config.readBoolEntry("Show"); - info.location = config.readPathEntry("Location"); - info.type = config.readEntry("Type"); - info.name = config.readEntry("Name"); - } // else, no show - } - - return info; -} - -TQStringList KBookmarkMenu::dynamicBookmarksList() -{ - TDEConfig config("kbookmarkrc", false, false); - config.setGroup("Bookmarks"); - - TQStringList mlist; - if (config.hasKey("DynamicMenus")) - mlist = config.readListEntry("DynamicMenus"); - else - mlist << "netscape"; - - return mlist; -} - -void KBookmarkMenu::setDynamicBookmarks(const TQString &id, const DynMenuInfo &newMenu) -{ - TDEConfig config("kbookmarkrc", false, false); - - // add group unconditionally - config.setGroup("DynamicMenu-" + id); - config.writeEntry("Show", newMenu.show); - config.writePathEntry("Location", newMenu.location); - config.writeEntry("Type", newMenu.type); - config.writeEntry("Name", newMenu.name); - - TQStringList elist; - - config.setGroup("Bookmarks"); - if (!config.hasKey("DynamicMenus")) { - if (newMenu.type != "netscape") { - // update from old xbel method to new rc method - // though only if not writing the netscape setting - config.setGroup("DynamicMenu-" "netscape"); - DynMenuInfo xbelSetting; - xbelSetting = showDynamicBookmarks("netscape"); - config.writeEntry("Show", xbelSetting.show); - config.writePathEntry("Location", xbelSetting.location); - config.writeEntry("Type", xbelSetting.type); - config.writeEntry("Name", xbelSetting.name); - } - } else { - elist = config.readListEntry("DynamicMenus"); - } - - // make sure list includes type - config.setGroup("Bookmarks"); - if (elist.contains(id) < 1) { - elist << id; - config.writeEntry("DynamicMenus", elist); - } - - config.sync(); -} - -#include "kbookmarkmenu.moc" -#include "kbookmarkmenu_p.moc" diff --git a/tdeio/bookmarks/kbookmarkmenu.cpp b/tdeio/bookmarks/kbookmarkmenu.cpp new file mode 100644 index 000000000..fd35736dd --- /dev/null +++ b/tdeio/bookmarks/kbookmarkmenu.cpp @@ -0,0 +1,1185 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kbookmarkmenu.h" +#include "kbookmarkmenu_p.h" +#include "kbookmarkimporter.h" +#include "kbookmarkimporter_opera.h" +#include "kbookmarkimporter_ie.h" +#include "kbookmarkdrag.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +template class TQPtrList; + +static TQString makeTextNodeMod(KBookmark bk, const TQString &m_nodename, const TQString &m_newText) { + TQDomNode subnode = bk.internalElement().namedItem(m_nodename); + if (subnode.isNull()) { + subnode = bk.internalElement().ownerDocument().createElement(m_nodename); + bk.internalElement().appendChild(subnode); + } + + if (subnode.firstChild().isNull()) { + TQDomText domtext = subnode.ownerDocument().createTextNode(""); + subnode.appendChild(domtext); + } + + TQDomText domtext = subnode.firstChild().toText(); + + TQString m_oldText = domtext.data(); + domtext.setData(m_newText); + + return m_oldText; +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +KBookmarkMenu::KBookmarkMenu( KBookmarkManager* mgr, + KBookmarkOwner * _owner, TDEPopupMenu * _parentMenu, + TDEActionCollection *collec, bool _isRoot, bool _add, + const TQString & parentAddress ) + : TQObject(), + m_bIsRoot(_isRoot), m_bAddBookmark(_add), + m_bAddShortcuts(true), + m_pManager(mgr), m_pOwner(_owner), + m_parentMenu( _parentMenu ), + m_actionCollection( collec ), + m_parentAddress( parentAddress ) +{ + m_parentMenu->setKeyboardShortcutsEnabled( true ); + + m_lstSubMenus.setAutoDelete( true ); + m_actions.setAutoDelete( true ); + + if (m_actionCollection) + { + m_actionCollection->setHighlightingEnabled(true); + disconnect( m_actionCollection, TQT_SIGNAL( actionHighlighted( TDEAction * ) ), 0, 0 ); + connect( m_actionCollection, TQT_SIGNAL( actionHighlighted( TDEAction * ) ), + this, TQT_SLOT( slotActionHighlighted( TDEAction * ) ) ); + } + + m_bNSBookmark = m_parentAddress.isNull(); + if ( !m_bNSBookmark ) // not for the netscape bookmark + { + //kdDebug(7043) << "KBookmarkMenu::KBookmarkMenu " << this << " address : " << m_parentAddress << endl; + + connect( _parentMenu, TQT_SIGNAL( aboutToShow() ), + TQT_SLOT( slotAboutToShow() ) ); + + if ( KBookmarkSettings::self()->m_contextmenu ) + { + (void) _parentMenu->contextMenu(); + connect( _parentMenu, TQT_SIGNAL( aboutToShowContextMenu(TDEPopupMenu*, int, TQPopupMenu*) ), + this, TQT_SLOT( slotAboutToShowContextMenu(TDEPopupMenu*, int, TQPopupMenu*) )); + } + + if ( m_bIsRoot ) + { + connect( m_pManager, TQT_SIGNAL( changed(const TQString &, const TQString &) ), + TQT_SLOT( slotBookmarksChanged(const TQString &) ) ); + } + } + + // add entries that possibly have a shortcut, so they are available _before_ first popup + if ( m_bIsRoot ) + { + if ( m_bAddBookmark ) + { + addAddBookmark(); + if ( extOwner() ) + addAddBookmarksList(); // FIXME + } + + addEditBookmarks(); + } + + m_bDirty = true; +} + +KBookmarkMenu::~KBookmarkMenu() +{ + //kdDebug(7043) << "KBookmarkMenu::~KBookmarkMenu() " << this << endl; + TQPtrListIterator it( m_actions ); + for (; it.current(); ++it ) + it.current()->unplugAll(); + + m_lstSubMenus.clear(); + m_actions.clear(); +} + +void KBookmarkMenu::ensureUpToDate() +{ + slotAboutToShow(); +} + +void KBookmarkMenu::slotAboutToShow() +{ + // Did the bookmarks change since the last time we showed them ? + if ( m_bDirty ) + { + m_bDirty = false; + refill(); + } +} + +TQString KBookmarkMenu::s_highlightedAddress; +TQString KBookmarkMenu::s_highlightedImportType; +TQString KBookmarkMenu::s_highlightedImportLocation; + +void KBookmarkMenu::slotActionHighlighted( TDEAction* action ) +{ + if (action->isA("KBookmarkActionMenu") || action->isA("KBookmarkAction")) + { + s_highlightedAddress = action->property("address").toString(); + //kdDebug() << "KBookmarkMenu::slotActionHighlighted" << s_highlightedAddress << endl; + } + else if (action->isA("KImportedBookmarksActionMenu")) + { + s_highlightedImportType = action->property("type").toString(); + s_highlightedImportLocation = action->property("location").toString(); + } + else + { + s_highlightedAddress = TQString::null; + s_highlightedImportType = TQString::null; + s_highlightedImportLocation = TQString::null; + } +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +class KBookmarkMenuRMBAssoc : public dPtrTemplate { }; +template<> TQPtrDict* dPtrTemplate::d_ptr = 0; + +static RMB* rmbSelf(KBookmarkMenu *m) { return KBookmarkMenuRMBAssoc::d(m); } + +// TODO check via dcop before making any changes to the bookmarks file??? + +void RMB::begin_rmb_action(KBookmarkMenu *self) +{ + RMB *s = rmbSelf(self); + s->recv = self; + s->m_parentAddress = self->m_parentAddress; + s->s_highlightedAddress = KBookmarkMenu::s_highlightedAddress; + s->m_pManager = self->m_pManager; + s->m_pOwner = self->m_pOwner; + s->m_parentMenu = self->m_parentMenu; +} + +bool RMB::invalid( int val ) +{ + bool valid = true; + + if (val == 1) + s_highlightedAddress = m_parentAddress; + + if (s_highlightedAddress.isNull()) + valid = false; + + return !valid; +} + +KBookmark RMB::atAddress(const TQString & address) +{ + KBookmark bookmark = m_pManager->findByAddress( address ); + Q_ASSERT(!bookmark.isNull()); + return bookmark; +} + +void KBookmarkMenu::slotAboutToShowContextMenu( TDEPopupMenu*, int, TQPopupMenu* contextMenu ) +{ + //kdDebug(7043) << "KBookmarkMenu::slotAboutToShowContextMenu" << s_highlightedAddress << endl; + if (s_highlightedAddress.isNull()) + { + TDEPopupMenu::contextMenuFocus()->hideContextMenu(); + return; + } + contextMenu->clear(); + fillContextMenu( contextMenu, s_highlightedAddress, 0 ); +} + +void RMB::fillContextMenu( TQPopupMenu* contextMenu, const TQString & address, int val ) +{ + KBookmark bookmark = atAddress(address); + + int id; + + // binner: + // "Add Bookmark Here" when pointing at a bookmark looks strange and if you + // call it you have to close and reopen the menu to see an entry was added? + // + // TODO rename these, but, message freeze... umm... + +// if (bookmark.isGroup()) { + id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, TQT_SLOT(slotRMBActionInsert(int)) ); + contextMenu->setItemParameter( id, val ); +/* } + else + { + id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, TQT_SLOT(slotRMBActionInsert(int)) ); + contextMenu->setItemParameter( id, val ); + }*/ +} + +void RMB::fillContextMenu2( TQPopupMenu* contextMenu, const TQString & address, int val ) +{ + KBookmark bookmark = atAddress(address); + + int id; + + if (bookmark.isGroup()) { + id = contextMenu->insertItem( i18n( "Open Folder in Bookmark Editor" ), recv, TQT_SLOT(slotRMBActionEditAt(int)) ); + contextMenu->setItemParameter( id, val ); + contextMenu->insertSeparator(); + id = contextMenu->insertItem( SmallIcon("edit-delete"), i18n( "Delete Folder" ), recv, TQT_SLOT(slotRMBActionRemove(int)) ); + contextMenu->setItemParameter( id, val ); + contextMenu->insertSeparator(); + id = contextMenu->insertItem( i18n( "Properties" ), recv, TQT_SLOT(slotRMBActionProperties(int)) ); + contextMenu->setItemParameter( id, val ); + } + else + { + id = contextMenu->insertItem( i18n( "Copy Link Address" ), recv, TQT_SLOT(slotRMBActionCopyLocation(int)) ); + contextMenu->setItemParameter( id, val ); + contextMenu->insertSeparator(); + id = contextMenu->insertItem( SmallIcon("edit-delete"), i18n( "Delete Bookmark" ), recv, TQT_SLOT(slotRMBActionRemove(int)) ); + contextMenu->setItemParameter( id, val ); + contextMenu->insertSeparator(); + id = contextMenu->insertItem( i18n( "Properties" ), recv, TQT_SLOT(slotRMBActionProperties(int)) ); + contextMenu->setItemParameter( id, val ); + } +} + +void RMB::slotRMBActionEditAt( int val ) +{ + kdDebug(7043) << "KBookmarkMenu::slotRMBActionEditAt" << s_highlightedAddress << endl; + if (invalid(val)) { hidePopup(); return; } + + KBookmark bookmark = atAddress(s_highlightedAddress); + + m_pManager->slotEditBookmarksAtAddress( s_highlightedAddress ); +} + +void RMB::slotRMBActionProperties( int val ) +{ + kdDebug(7043) << "KBookmarkMenu::slotRMBActionProperties" << s_highlightedAddress << endl; + if (invalid(val)) { hidePopup(); return; } + + KBookmark bookmark = atAddress(s_highlightedAddress); + + TQString folder = bookmark.isGroup() ? TQString::null : bookmark.url().pathOrURL(); + KBookmarkEditDialog dlg( bookmark.fullText(), folder, + m_pManager, KBookmarkEditDialog::ModifyMode, 0, + 0, 0, i18n("Bookmark Properties") ); + if ( dlg.exec() != KDialogBase::Accepted ) + return; + + makeTextNodeMod(bookmark, "title", dlg.finalTitle()); + if ( !dlg.finalUrl().isNull() ) + { + KURL u = KURL::fromPathOrURL(dlg.finalUrl()); + bookmark.internalElement().setAttribute("href", u.url(0, 106)); + } + + kdDebug(7043) << "Requested move to " << dlg.finalAddress() << "!" << endl; + + KBookmarkGroup parentBookmark = atAddress(m_parentAddress).toGroup(); + m_pManager->emitChanged( parentBookmark ); +} + +void RMB::slotRMBActionInsert( int val ) +{ + kdDebug(7043) << "KBookmarkMenu::slotRMBActionInsert" << s_highlightedAddress << endl; + if (invalid(val)) { hidePopup(); return; } + + TQString url = m_pOwner->currentURL(); + if (url.isEmpty()) + { + KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL.")); + return; + } + TQString title = m_pOwner->currentTitle(); + if (title.isEmpty()) + title = url; + + KBookmark bookmark = atAddress( s_highlightedAddress ); + + // TODO use unique title + + if (bookmark.isGroup()) + { + KBookmarkGroup parentBookmark = bookmark.toGroup(); + Q_ASSERT(!parentBookmark.isNull()); + parentBookmark.addBookmark( m_pManager, title, KURL( url ) ); + m_pManager->emitChanged( parentBookmark ); + } + else + { + KBookmarkGroup parentBookmark = bookmark.parentGroup(); + Q_ASSERT(!parentBookmark.isNull()); + KBookmark newBookmark = parentBookmark.addBookmark( m_pManager, title, KURL( url ) ); + parentBookmark.moveItem( newBookmark, parentBookmark.previous(bookmark) ); + m_pManager->emitChanged( parentBookmark ); + } +} + +void RMB::slotRMBActionRemove( int val ) +{ + //kdDebug(7043) << "KBookmarkMenu::slotRMBActionRemove" << s_highlightedAddress << endl; + if (invalid(val)) { hidePopup(); return; } + + KBookmark bookmark = atAddress( s_highlightedAddress ); + bool folder = bookmark.isGroup(); + + if (KMessageBox::warningContinueCancel( + m_parentMenu, + folder ? i18n("Are you sure you wish to remove the bookmark folder\n\"%1\"?").arg(bookmark.text()) + : i18n("Are you sure you wish to remove the bookmark\n\"%1\"?").arg(bookmark.text()), + folder ? i18n("Bookmark Folder Deletion") + : i18n("Bookmark Deletion"), + KStdGuiItem::del()) + != KMessageBox::Continue + ) + return; + + KBookmarkGroup parentBookmark = atAddress( m_parentAddress ).toGroup(); + parentBookmark.deleteBookmark( bookmark ); + m_pManager->emitChanged( parentBookmark ); + if (m_parentMenu) + m_parentMenu->hide(); +} + +void RMB::slotRMBActionCopyLocation( int val ) +{ + //kdDebug(7043) << "KBookmarkMenu::slotRMBActionCopyLocation" << s_highlightedAddress << endl; + if (invalid(val)) { hidePopup(); return; } + + KBookmark bookmark = atAddress( s_highlightedAddress ); + + if ( !bookmark.isGroup() ) + { + kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0), + TQClipboard::Selection ); + kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0), + TQClipboard::Clipboard ); + } +} + +void RMB::hidePopup() { + TDEPopupMenu::contextMenuFocus()->hideContextMenu(); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +void KBookmarkMenu::fillContextMenu( TQPopupMenu* contextMenu, const TQString & address, int val ) +{ + RMB::begin_rmb_action(this); + rmbSelf(this)->fillContextMenu(contextMenu, address, val); + emit aboutToShowContextMenu( rmbSelf(this)->atAddress(address), contextMenu); + rmbSelf(this)->fillContextMenu2(contextMenu, address, val); +} + +void KBookmarkMenu::slotRMBActionEditAt( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); } + +void KBookmarkMenu::slotRMBActionProperties( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); } + +void KBookmarkMenu::slotRMBActionInsert( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); } + +void KBookmarkMenu::slotRMBActionRemove( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); } + +void KBookmarkMenu::slotRMBActionCopyLocation( int val ) +{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); } + +void KBookmarkMenu::slotBookmarksChanged( const TQString & groupAddress ) +{ + if (m_bNSBookmark) + return; + + if ( groupAddress == m_parentAddress ) + { + //kdDebug(7043) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress << endl; + m_bDirty = true; + } + else + { + // Iterate recursively into child menus + TQPtrListIterator it( m_lstSubMenus ); + for (; it.current(); ++it ) + { + it.current()->slotBookmarksChanged( groupAddress ); + } + } +} + +void KBookmarkMenu::refill() +{ + //kdDebug(7043) << "KBookmarkMenu::refill()" << endl; + m_lstSubMenus.clear(); + + TQPtrListIterator it( m_actions ); + for (; it.current(); ++it ) + it.current()->unplug( m_parentMenu ); + + m_parentMenu->clear(); + m_actions.clear(); + + fillBookmarkMenu(); + m_parentMenu->adjustSize(); +} + +void KBookmarkMenu::addAddBookmarksList() +{ + if (!kapp->authorizeTDEAction("bookmarks")) + return; + + TQString title = i18n( "Bookmark Tabs as Folder..." ); + + TDEAction * paAddBookmarksList = new TDEAction( title, + "bookmarks_list_add", + 0, + this, + TQT_SLOT( slotAddBookmarksList() ), + m_actionCollection, m_bIsRoot ? "add_bookmarks_list" : 0 ); + + paAddBookmarksList->setToolTip( i18n( "Add a folder of bookmarks for all open tabs." ) ); + + paAddBookmarksList->plug( m_parentMenu ); + m_actions.append( paAddBookmarksList ); +} + +void KBookmarkMenu::addAddBookmark() +{ + if (!kapp->authorizeTDEAction("bookmarks")) + return; + + TQString title = i18n( "Add Bookmark" ); + + TDEAction * paAddBookmarks = new TDEAction( title, + "bookmark_add", + m_bIsRoot && m_bAddShortcuts ? TDEStdAccel::addBookmark() : TDEShortcut(), + this, + TQT_SLOT( slotAddBookmark() ), + m_actionCollection, m_bIsRoot ? "add_bookmark" : 0 ); + + paAddBookmarks->setToolTip( i18n( "Add a bookmark for the current document" ) ); + + paAddBookmarks->plug( m_parentMenu ); + m_actions.append( paAddBookmarks ); +} + +void KBookmarkMenu::addEditBookmarks() +{ + if (!kapp->authorizeTDEAction("bookmarks")) + return; + + TDEAction * m_paEditBookmarks = KStdAction::editBookmarks( m_pManager, TQT_SLOT( slotEditBookmarks() ), + m_actionCollection, "edit_bookmarks" ); + m_paEditBookmarks->plug( m_parentMenu ); + m_paEditBookmarks->setToolTip( i18n( "Edit your bookmark collection in a separate window" ) ); + m_actions.append( m_paEditBookmarks ); +} + +void KBookmarkMenu::addNewFolder() +{ + if (!kapp->authorizeTDEAction("bookmarks")) + return; + + TQString title = i18n( "&New Bookmark Folder..." ); + int p; + while ( ( p = title.find( '&' ) ) >= 0 ) + title.remove( p, 1 ); + + TDEAction * paNewFolder = new TDEAction( title, + "folder-new", //"folder", + 0, + this, + TQT_SLOT( slotNewFolder() ), + m_actionCollection ); + + paNewFolder->setToolTip( i18n( "Create a new bookmark folder in this menu" ) ); + + paNewFolder->plug( m_parentMenu ); + m_actions.append( paNewFolder ); +} + +void KBookmarkMenu::fillBookmarkMenu() +{ + if (!kapp->authorizeTDEAction("bookmarks")) + return; + + if ( m_bIsRoot ) + { + if ( m_bAddBookmark ) + { + addAddBookmark(); + if ( extOwner() ) + addAddBookmarksList(); // FIXME + } + + addEditBookmarks(); + + if ( m_bAddBookmark && !KBookmarkSettings::self()->m_advancedaddbookmark ) + addNewFolder(); + } + + if ( m_bIsRoot + && KBookmarkManager::userBookmarksFile() == m_pManager->path() ) + { + bool haveSep = false; + + TQValueList keys = KBookmarkMenu::dynamicBookmarksList(); + TQValueList::const_iterator it; + for ( it = keys.begin(); it != keys.end(); ++it ) + { + DynMenuInfo info; + info = showDynamicBookmarks((*it)); + + if ( !info.show || !TQFile::exists( info.location ) ) + continue; + + if (!haveSep) + { + m_parentMenu->insertSeparator(); + haveSep = true; + } + + TDEActionMenu * actionMenu; + actionMenu = new KImportedBookmarksActionMenu( + info.name, info.type, + m_actionCollection, "kbookmarkmenu" ); + + actionMenu->setProperty( "type", info.type ); + actionMenu->setProperty( "location", info.location ); + + actionMenu->plug( m_parentMenu ); + m_actions.append( actionMenu ); + + KBookmarkMenu *subMenu = + new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(), + m_actionCollection, false, + m_bAddBookmark, TQString::null ); + connect( subMenu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) ), + this, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) )); + m_lstSubMenus.append(subMenu); + + connect(actionMenu->popupMenu(), TQT_SIGNAL(aboutToShow()), subMenu, TQT_SLOT(slotNSLoad())); + } + } + + KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); + Q_ASSERT(!parentBookmark.isNull()); + bool separatorInserted = false; + for ( KBookmark bm = parentBookmark.first(); !bm.isNull(); bm = parentBookmark.next(bm) ) + { + TQString text = KStringHandler::csqueeze(bm.fullText(), 60); + text.replace( '&', "&&" ); + if ( !separatorInserted && m_bIsRoot) { + // inserted before the first konq bookmark, to avoid the separator if no konq bookmark + m_parentMenu->insertSeparator(); + separatorInserted = true; + } + if ( !bm.isGroup() ) + { + if ( bm.isSeparator() ) + { + m_parentMenu->insertSeparator(); + } + else + { + //kdDebug(7043) << "Creating URL bookmark menu item for " << bm.text() << endl; + TDEAction * action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 ); + connect(action, TQT_SIGNAL( activated ( TDEAction::ActivationReason, TQt::ButtonState )), + this, TQT_SLOT( slotBookmarkSelected( TDEAction::ActivationReason, TQt::ButtonState ) )); + + action->setProperty( "url", bm.url().url() ); + action->setProperty( "address", bm.address() ); + + action->setToolTip( bm.url().pathOrURL() ); + + action->plug( m_parentMenu ); + m_actions.append( action ); + } + } + else + { + //kdDebug(7043) << "Creating bookmark submenu named " << bm.text() << endl; + TDEActionMenu * actionMenu = new KBookmarkActionMenu( text, bm.icon(), + m_actionCollection, + "kbookmarkmenu" ); + actionMenu->setProperty( "address", bm.address() ); + actionMenu->plug( m_parentMenu ); + m_actions.append( actionMenu ); + + KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(), + m_actionCollection, false, + m_bAddBookmark, + bm.address() ); + + connect(subMenu, TQT_SIGNAL( aboutToShowContextMenu( const KBookmark &, TQPopupMenu * ) ), + this, TQT_SIGNAL( aboutToShowContextMenu( const KBookmark &, TQPopupMenu * ) )); + connect(subMenu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) ), + this, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) )); + m_lstSubMenus.append( subMenu ); + } + } + + if ( !m_bIsRoot && m_bAddBookmark ) + { + if ( m_parentMenu->count() > 0 ) + m_parentMenu->insertSeparator(); + + if ( KBookmarkSettings::self()->m_quickactions ) + { + TDEActionMenu * actionMenu = new TDEActionMenu( i18n("Quick Actions"), m_actionCollection, 0L ); + fillContextMenu( actionMenu->popupMenu(), m_parentAddress, 1 ); + actionMenu->plug( m_parentMenu ); + m_actions.append( actionMenu ); + } + else + { + addAddBookmark(); + if ( extOwner() ) + addAddBookmarksList(); // FIXME + addNewFolder(); + } + } +} + +void KBookmarkMenu::slotAddBookmarksList() +{ + KExtendedBookmarkOwner *extOwner = dynamic_cast(m_pOwner); + if (!extOwner) + { + kdWarning() << "erm, sorry ;-)" << endl; + return; + } + + KExtendedBookmarkOwner::QStringPairList list; + extOwner->fillBookmarksList( list ); + + KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); + Q_ASSERT(!parentBookmark.isNull()); + KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager ); + if ( group.isNull() ) + return; // user canceled i guess + + KExtendedBookmarkOwner::QStringPairList::const_iterator it; + for ( it = list.begin(); it != list.end(); ++it ) + group.addBookmark( m_pManager, (*it).first, KURL((*it).second) ); + + m_pManager->emitChanged( parentBookmark ); +} + + +void KBookmarkMenu::slotAddBookmark() +{ + KBookmarkGroup parentBookmark; + parentBookmark = m_pManager->addBookmarkDialog(m_pOwner->currentURL(), m_pOwner->currentTitle(), m_parentAddress); + if (!parentBookmark.isNull()) + m_pManager->emitChanged( parentBookmark ); +} + +void KBookmarkMenu::slotNewFolder() +{ + if ( !m_pOwner ) return; // this view doesn't handle bookmarks... + KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); + Q_ASSERT(!parentBookmark.isNull()); + KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager ); + if ( !group.isNull() ) + { + KBookmarkGroup parentGroup = group.parentGroup(); + m_pManager->emitChanged( parentGroup ); + } +} + +void KBookmarkMenu::slotBookmarkSelected( TDEAction::ActivationReason /*reason*/, TQt::ButtonState state ) +{ + kdDebug(7043) << "KBookmarkMenu::slotBookmarkSelected()" << endl; + if ( !m_pOwner ) return; // this view doesn't handle bookmarks... + const TDEAction* action = dynamic_cast(sender()); + if(action) + { + const TQString& url = sender()->property("url").toString(); + m_pOwner->openBookmarkURL( url ); + emit openBookmark( url, state ); + } +} + +void KBookmarkMenu::slotBookmarkSelected() +{ + slotBookmarkSelected(TDEAction::PopupMenuActivation, Qt::NoButton); +} + +KExtendedBookmarkOwner* KBookmarkMenu::extOwner() +{ + return dynamic_cast(m_pOwner); +} + +void KBookmarkMenu::slotNSLoad() +{ + // only fill menu once + m_parentMenu->disconnect(TQT_SIGNAL(aboutToShow())); + + // not NSImporter, but kept old name for BC reasons + KBookmarkMenuNSImporter importer( m_pManager, this, m_actionCollection ); + importer.openBookmarks(s_highlightedImportLocation, s_highlightedImportType); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +KBookmarkEditFields::KBookmarkEditFields(TQWidget *main, TQBoxLayout *vbox, FieldsSet fieldsSet) +{ + bool isF = (fieldsSet != FolderFieldsSet); + + TQGridLayout *grid = new TQGridLayout( vbox, 2, isF ? 2 : 1 ); + + m_title = new KLineEdit( main ); + grid->addWidget( m_title, 0, 1 ); + grid->addWidget( new TQLabel( m_title, i18n( "Name:" ), main ), 0, 0 ); + m_title->setFocus(); + if (isF) + { + m_url = new KLineEdit( main ); + grid->addWidget( m_url, 1, 1 ); + grid->addWidget( new TQLabel( m_url, i18n( "Location:" ), main ), 1, 0 ); + } + else + { + m_url = 0; + } + + main->setMinimumSize( 300, 0 ); +} + +void KBookmarkEditFields::setName(const TQString &str) +{ + m_title->setText(str); +} + +void KBookmarkEditFields::setLocation(const TQString &str) +{ + m_url->setText(str); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +// TODO - make the dialog use Properties as a title when in Modify mode... (dirk noticed the bug...) +KBookmarkEditDialog::KBookmarkEditDialog(const TQString& title, const TQString& url, KBookmarkManager * mgr, BookmarkEditType editType, const TQString& address, + TQWidget * parent, const char * name, const TQString& caption ) + : KDialogBase(parent, name, true, caption, + (editType == InsertionMode) ? (User1|Ok|Cancel) : (Ok|Cancel), + Ok, false, KGuiItem()), + m_folderTree(0), m_mgr(mgr), m_editType(editType), m_address(address) +{ + setButtonOK( (editType == InsertionMode) ? KGuiItem( i18n( "&Add" ), "bookmark_add") : i18n( "&Update" ) ); + if (editType == InsertionMode) { + setButtonGuiItem( User1, KGuiItem( i18n( "&New Folder..." ), "folder-new") ); + } + + bool folder = url.isNull(); + + m_main = new TQWidget( this ); + setMainWidget( m_main ); + + TQBoxLayout *vbox = new TQVBoxLayout( m_main, 0, spacingHint() ); + KBookmarkEditFields::FieldsSet fs = + folder ? KBookmarkEditFields::FolderFieldsSet + : KBookmarkEditFields::BookmarkFieldsSet; + m_fields = new KBookmarkEditFields(m_main, vbox, fs); + m_fields->setName(title); + if ( !folder ) + m_fields->setLocation(url); + + if ( editType == InsertionMode ) + { + m_folderTree = KBookmarkFolderTree::createTree( m_mgr, m_main, name, m_address ); + connect( m_folderTree, TQT_SIGNAL( doubleClicked(TQListViewItem*) ), + this, TQT_SLOT( slotDoubleClicked(TQListViewItem*) ) ); + vbox->addWidget( m_folderTree ); + connect( this, TQT_SIGNAL( user1Clicked() ), TQT_SLOT( slotUser1() ) ); + } +} + +void KBookmarkEditDialog::slotDoubleClicked( TQListViewItem* item ) +{ + Q_ASSERT( m_folderTree ); + m_folderTree->setCurrentItem( item ); + accept(); +} + +void KBookmarkEditDialog::slotOk() +{ + accept(); +} + +void KBookmarkEditDialog::slotCancel() +{ + reject(); +} + +TQString KBookmarkEditDialog::finalAddress() const +{ + Q_ASSERT( m_folderTree ); + return KBookmarkFolderTree::selectedAddress( m_folderTree ); +} + +TQString KBookmarkEditDialog::finalUrl() const +{ + return m_fields->m_url ? m_fields->m_url->text() : TQString::null; +} + +TQString KBookmarkEditDialog::finalTitle() const +{ + return m_fields->m_title ? m_fields->m_title->text() : TQString::null; +} + +void KBookmarkEditDialog::slotUser1() +{ + // kdDebug(7043) << "KBookmarkEditDialog::slotUser1" << endl; + Q_ASSERT( m_folderTree ); + + TQString address = KBookmarkFolderTree::selectedAddress( m_folderTree ); + if ( address.isNull() ) return; + KBookmarkGroup bm = m_mgr->findByAddress( address ).toGroup(); + Q_ASSERT(!bm.isNull()); + Q_ASSERT(m_editType == InsertionMode); + + KBookmarkGroup group = bm.createNewFolder( m_mgr ); + if ( !group.isNull() ) + { + KBookmarkGroup parentGroup = group.parentGroup(); + m_mgr->emitChanged( parentGroup ); + } + KBookmarkFolderTree::fillTree( m_folderTree, m_mgr ); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +static void fillGroup( TQListView* listview, KBookmarkFolderTreeItem * parentItem, KBookmarkGroup group, bool expandOpenGroups = true, const TQString& address = TQString::null ) +{ + bool noSubGroups = true; + KBookmarkFolderTreeItem * lastItem = 0L; + KBookmarkFolderTreeItem * item = 0L; + for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk) ) + { + if ( bk.isGroup() ) + { + KBookmarkGroup grp = bk.toGroup(); + item = new KBookmarkFolderTreeItem( parentItem, lastItem, grp ); + fillGroup( listview, item, grp, expandOpenGroups, address ); + if ( expandOpenGroups && grp.isOpen() ) + item->setOpen( true ); + lastItem = item; + noSubGroups = false; + } + if (bk.address() == address) { + listview->setCurrentItem( lastItem ); + listview->ensureItemVisible( item ); + } + } + if ( noSubGroups ) { + parentItem->setOpen( true ); + } +} + +TQListView* KBookmarkFolderTree::createTree( KBookmarkManager* mgr, TQWidget* parent, const char* name, const TQString& address ) +{ + TQListView *listview = new TQListView( parent, name ); + + listview->setRootIsDecorated( false ); + listview->header()->hide(); + listview->addColumn( i18n("Bookmark"), 200 ); + listview->setSorting( -1, false ); + listview->setSelectionMode( TQListView::Single ); + listview->setAllColumnsShowFocus( true ); + listview->setResizeMode( TQListView::AllColumns ); + listview->setMinimumSize( 60, 100 ); + + fillTree( listview, mgr, address ); + + return listview; +} + +void KBookmarkFolderTree::fillTree( TQListView *listview, KBookmarkManager* mgr, const TQString& address ) +{ + listview->clear(); + + KBookmarkGroup root = mgr->root(); + KBookmarkFolderTreeItem * rootItem = new KBookmarkFolderTreeItem( listview, root ); + listview->setCurrentItem( rootItem ); + rootItem->setSelected( true ); + fillGroup( listview, rootItem, root, (address == root.groupAddress() || address.isNull()) ? true : false, address ); + rootItem->setOpen( true ); +} + +static KBookmarkFolderTreeItem* ft_cast( TQListViewItem *i ) +{ + return static_cast( i ); +} + +TQString KBookmarkFolderTree::selectedAddress( TQListView *listview ) +{ + if ( !listview) + return TQString::null; + KBookmarkFolderTreeItem *item = ft_cast( listview->currentItem() ); + return item ? item->m_bookmark.address() : TQString::null; +} + +void KBookmarkFolderTree::setAddress( TQListView *listview, const TQString & address ) +{ + KBookmarkFolderTreeItem* it = ft_cast( listview->firstChild() ); + while ( true ) { + kdDebug(7043) << it->m_bookmark.address() << endl; + it = ft_cast( it->itemBelow() ); + if ( !it ) + return; + if ( it->m_bookmark.address() == address ) + break; + } + it->setSelected( true ); + listview->setCurrentItem( it ); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +// toplevel item +KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( TQListView *parent, const KBookmark & gp ) + : TQListViewItem(parent, i18n("Bookmarks")), m_bookmark(gp) +{ + setPixmap(0, SmallIcon("bookmark")); + setExpandable(true); +} + +// group +KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( KBookmarkFolderTreeItem *parent, TQListViewItem *after, const KBookmarkGroup & gp ) + : TQListViewItem(parent, after, gp.fullText()), m_bookmark(gp) +{ + setPixmap(0, SmallIcon( gp.icon() ) ); + setExpandable(true); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +// NOTE - KBookmarkMenuNSImporter is really === KBookmarkMenuImporter +// i.e, it is _not_ ns specific. and in KDE4 it should be renamed. + +void KBookmarkMenuNSImporter::openNSBookmarks() +{ + openBookmarks( KNSBookmarkImporter::netscapeBookmarksFile(), "netscape" ); +} + +void KBookmarkMenuNSImporter::openBookmarks( const TQString &location, const TQString &type ) +{ + mstack.push(m_menu); + + KBookmarkImporterBase *importer = KBookmarkImporterBase::factory(type); + if (!importer) + return; + importer->setFilename(location); + connectToImporter(*importer); + importer->parse(); + + delete importer; +} + +void KBookmarkMenuNSImporter::connectToImporter(const TQObject &importer) +{ + connect( &importer, TQT_SIGNAL( newBookmark( const TQString &, const TQCString &, const TQString & ) ), + TQT_SLOT( newBookmark( const TQString &, const TQCString &, const TQString & ) ) ); + connect( &importer, TQT_SIGNAL( newFolder( const TQString &, bool, const TQString & ) ), + TQT_SLOT( newFolder( const TQString &, bool, const TQString & ) ) ); + connect( &importer, TQT_SIGNAL( newSeparator() ), TQT_SLOT( newSeparator() ) ); + connect( &importer, TQT_SIGNAL( endFolder() ), TQT_SLOT( endFolder() ) ); +} + +void KBookmarkMenuNSImporter::newBookmark( const TQString & text, const TQCString & url, const TQString & ) +{ + TQString _text = KStringHandler::csqueeze(text); + _text.replace( '&', "&&" ); + TDEAction * action = new KBookmarkAction(_text, "text-html", 0, 0, "", m_actionCollection, 0); + connect(action, TQT_SIGNAL( activated ( TDEAction::ActivationReason, TQt::ButtonState )), + m_menu, TQT_SLOT( slotBookmarkSelected( TDEAction::ActivationReason, TQt::ButtonState ) )); + action->setProperty( "url", url ); + action->setToolTip( url ); + action->plug( mstack.top()->m_parentMenu ); + mstack.top()->m_actions.append( action ); +} + +void KBookmarkMenuNSImporter::newFolder( const TQString & text, bool, const TQString & ) +{ + TQString _text = KStringHandler::csqueeze(text); + _text.replace( '&', "&&" ); + TDEActionMenu * actionMenu = new TDEActionMenu( _text, "folder", m_actionCollection, 0L ); + actionMenu->plug( mstack.top()->m_parentMenu ); + mstack.top()->m_actions.append( actionMenu ); + KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_menu->m_pOwner, actionMenu->popupMenu(), + m_actionCollection, false, + m_menu->m_bAddBookmark, TQString::null ); + connect( subMenu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) ), + m_menu, TQT_SIGNAL( openBookmark( const TQString &, TQt::ButtonState ) )); + mstack.top()->m_lstSubMenus.append( subMenu ); + + mstack.push(subMenu); +} + +void KBookmarkMenuNSImporter::newSeparator() +{ + mstack.top()->m_parentMenu->insertSeparator(); +} + +void KBookmarkMenuNSImporter::endFolder() +{ + mstack.pop(); +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + +KBookmarkMenu::DynMenuInfo KBookmarkMenu::showDynamicBookmarks( const TQString &id ) +{ + TDEConfig config("kbookmarkrc", false, false); + config.setGroup("Bookmarks"); + + DynMenuInfo info; + info.show = false; + + if (!config.hasKey("DynamicMenus")) { + // upgrade path + if (id == "netscape") { + KBookmarkManager *manager = KBookmarkManager::userBookmarksManager(); + info.show = manager->root().internalElement().attribute("hide_nsbk") != "yes"; + info.location = KNSBookmarkImporter::netscapeBookmarksFile(); + info.type = "netscape"; + info.name = i18n("Netscape Bookmarks"); + } // else, no show + + } else { + // have new version config + if (config.hasGroup("DynamicMenu-" + id)) { + config.setGroup("DynamicMenu-" + id); + info.show = config.readBoolEntry("Show"); + info.location = config.readPathEntry("Location"); + info.type = config.readEntry("Type"); + info.name = config.readEntry("Name"); + } // else, no show + } + + return info; +} + +TQStringList KBookmarkMenu::dynamicBookmarksList() +{ + TDEConfig config("kbookmarkrc", false, false); + config.setGroup("Bookmarks"); + + TQStringList mlist; + if (config.hasKey("DynamicMenus")) + mlist = config.readListEntry("DynamicMenus"); + else + mlist << "netscape"; + + return mlist; +} + +void KBookmarkMenu::setDynamicBookmarks(const TQString &id, const DynMenuInfo &newMenu) +{ + TDEConfig config("kbookmarkrc", false, false); + + // add group unconditionally + config.setGroup("DynamicMenu-" + id); + config.writeEntry("Show", newMenu.show); + config.writePathEntry("Location", newMenu.location); + config.writeEntry("Type", newMenu.type); + config.writeEntry("Name", newMenu.name); + + TQStringList elist; + + config.setGroup("Bookmarks"); + if (!config.hasKey("DynamicMenus")) { + if (newMenu.type != "netscape") { + // update from old xbel method to new rc method + // though only if not writing the netscape setting + config.setGroup("DynamicMenu-" "netscape"); + DynMenuInfo xbelSetting; + xbelSetting = showDynamicBookmarks("netscape"); + config.writeEntry("Show", xbelSetting.show); + config.writePathEntry("Location", xbelSetting.location); + config.writeEntry("Type", xbelSetting.type); + config.writeEntry("Name", xbelSetting.name); + } + } else { + elist = config.readListEntry("DynamicMenus"); + } + + // make sure list includes type + config.setGroup("Bookmarks"); + if (elist.contains(id) < 1) { + elist << id; + config.writeEntry("DynamicMenus", elist); + } + + config.sync(); +} + +#include "kbookmarkmenu.moc" +#include "kbookmarkmenu_p.moc" diff --git a/tdeio/httpfilter/CMakeLists.txt b/tdeio/httpfilter/CMakeLists.txt index b40f10fdc..70564652e 100644 --- a/tdeio/httpfilter/CMakeLists.txt +++ b/tdeio/httpfilter/CMakeLists.txt @@ -24,7 +24,7 @@ include_directories( set( target httpfilter ) set( ${target}_SRCS - httpfilter.cc + httpfilter.cpp ) tde_add_library( ${target} STATIC_PIC AUTOMOC diff --git a/tdeio/httpfilter/Makefile.am b/tdeio/httpfilter/Makefile.am index 2da25d1b6..b80ed9d71 100644 --- a/tdeio/httpfilter/Makefile.am +++ b/tdeio/httpfilter/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = $(all_includes) METASOURCES = AUTO noinst_LTLIBRARIES = libhttpfilter.la -libhttpfilter_la_SOURCES = httpfilter.cc +libhttpfilter_la_SOURCES = httpfilter.cpp libhttpfilter_la_LIBADD = $(LIBZ) libhttpfilter_la_LDFLAGS = $(all_libraries) diff --git a/tdeio/httpfilter/httpfilter.cc b/tdeio/httpfilter/httpfilter.cc deleted file mode 100644 index 0f6a45790..000000000 --- a/tdeio/httpfilter/httpfilter.cc +++ /dev/null @@ -1,372 +0,0 @@ -/* - This file is part of the KDE libraries - Copyright (c) 2002 Waldo Bastian - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include - -#include - -#include "httpfilter.h" - -HTTPFilterBase::HTTPFilterBase() - : last(0) -{ -} - -HTTPFilterBase::~HTTPFilterBase() -{ - delete last; -} - -void -HTTPFilterBase::chain(HTTPFilterBase *previous) -{ - last = previous; - connect(last, TQT_SIGNAL(output(const TQByteArray &)), - this, TQT_SLOT(slotInput(const TQByteArray &))); -} - -HTTPFilterChain::HTTPFilterChain() - : first(0) -{ -} - -void -HTTPFilterChain::addFilter(HTTPFilterBase *filter) -{ - if (!last) - { - first = filter; - } - else - { - disconnect(last, TQT_SIGNAL(output(const TQByteArray &)), 0, 0); - filter->chain(last); - } - last = filter; - connect(filter, TQT_SIGNAL(output(const TQByteArray &)), - this, TQT_SIGNAL(output(const TQByteArray &))); - connect(filter, TQT_SIGNAL(error(int, const TQString &)), - this, TQT_SIGNAL(error(int, const TQString &))); -} - -void -HTTPFilterChain::slotInput(const TQByteArray &d) -{ - if (first) - first->slotInput(d); - else - emit output(d); -} - -HTTPFilterMD5::HTTPFilterMD5() -{ -} - -TQString -HTTPFilterMD5::md5() -{ - return TQString::fromLatin1(context.base64Digest()); -} - -void -HTTPFilterMD5::slotInput(const TQByteArray &d) -{ - context.update(d); - emit output(d); -} - - -HTTPFilterGZip::HTTPFilterGZip() -{ -#ifdef DO_GZIP - bHasHeader = false; - bHasFinished = false; - bPlainText = false; - bEatTrailer = false; - bEof = false; - zstr.next_in = (Bytef *) Z_NULL; - zstr.avail_in = 0; - zstr.zalloc = Z_NULL; - zstr.zfree = Z_NULL; - zstr.opaque = Z_NULL; - - inflateInit2(&zstr, -MAX_WBITS); - - iTrailer = 8; -#endif -} - -HTTPFilterGZip::~HTTPFilterGZip() -{ -#ifdef DO_GZIP - inflateEnd(&zstr); -#endif - -} - -/* The get_byte() and checkHeader() functions are modified version from */ -/* the correpsonding functions that can be found in zlib, the following */ -/* copyright notice applies to these functions: */ - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.3, July 9th, 1998 - - Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -int -HTTPFilterGZip::get_byte() -{ -#ifdef DO_GZIP - if (bEof) return EOF; - if (zstr.avail_in == 0) - { - bEof = true; - return EOF; - } - zstr.avail_in--; - zstr.total_in++; - return *(zstr.next_in)++; -#else - return 0; -#endif -} - -#ifdef DO_GZIP - -static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ -#endif - -// 0 : ok -// 1 : not gzip -// 2 : no header -int -HTTPFilterGZip::checkHeader() -{ -#ifdef DO_GZIP - uInt len; - int c; - - /* Check the gzip magic header */ - for (len = 0; len < 2; len++) { - c = get_byte(); - if (c != gz_magic[len]) { - if (len != 0) - { - zstr.avail_in++; - zstr.next_in--; - } - if (c != EOF) { - zstr.avail_in++; - zstr.next_in--; - return 1; - } - return 2; - } - } - - int method = get_byte(); /* method byte */ - int flags = get_byte(); /* flags byte */ - - if (method != Z_DEFLATED || (flags & RESERVED) != 0) { - return bEof ? 2 : 1; - } - - /* Discard time, xflags and OS code: */ - for (len = 0; len < 6; len++) (void)get_byte(); - - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)get_byte(); - len += ((uInt)get_byte())<<8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte() != EOF) ; - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = get_byte()) != 0 && c != EOF) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = get_byte()) != 0 && c != EOF) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(); - } - - return bEof ? 2 : 0; -#else - return 0; -#endif -} - -void -HTTPFilterGZip::slotInput(const TQByteArray &d) -{ -#ifdef DO_GZIP - if (bPlainText) - { - emit output(d); - return; - } - if (d.size() == 0) - { - if (bEatTrailer) - bHasFinished = true; - if (!bHasFinished) - { - // Make sure we get the last bytes still in the pipe. - // Needed with "deflate". - TQByteArray flush(4); - flush.fill(0); - slotInput(flush); - if (!bHasFinished && !bHasHeader) - { - // Send as-is - emit output(headerData); - bHasFinished = true; - // End of data - emit output(TQByteArray()); - } - } - if (!bHasFinished) - emit error( TDEIO::ERR_SLAVE_DEFINED, i18n("Unexpected end of data, some information may be lost.")); - return; - } - if (bHasFinished) - return; - - if (bEatTrailer) - { - iTrailer -= d.size(); - if (iTrailer <= 0) - { - bHasFinished = true; - // End of data - emit output(TQByteArray()); - } - return; - } - - if (!bHasHeader) - { - bEof = false; - - // Add data to header. - int orig_size = headerData.size(); - headerData.resize(orig_size+d.size()); - memcpy(headerData.data()+orig_size, d.data(), d.size()); - - zstr.avail_in = headerData.size(); - zstr.next_in = (Bytef *) headerData.data(); - - int result = checkHeader(); - if (result == 1) - { - bPlainText = true; - output(headerData); - return; - } - - if (result != 0) - return; // next time better - - bHasHeader = true; - } - else - { - zstr.avail_in = d.size(); - zstr.next_in = (Bytef *) d.data(); - } - - while( zstr.avail_in ) - { - char buf[8192]; - zstr.next_out = (Bytef *) buf; - zstr.avail_out = 8192; - int result = inflate( &zstr, Z_NO_FLUSH ); - if ((result != Z_OK) && (result != Z_STREAM_END)) - { - emit error( TDEIO::ERR_SLAVE_DEFINED, i18n("Receiving corrupt data.")); - break; - } - int bytesOut = 8192 - zstr.avail_out; - if (bytesOut) - { - TQByteArray d; - d.setRawData( buf, bytesOut ); - emit output(d); - d.resetRawData( buf, bytesOut ); - } - if (result == Z_STREAM_END) - { - if (iTrailer) - { - bEatTrailer = true; - } - else - { - bHasFinished = true; - // End of data - emit output(TQByteArray()); - } - return; - } - } -#endif -} - -HTTPFilterDeflate::HTTPFilterDeflate() -{ -#ifdef DO_GZIP - bHasHeader = true; - iTrailer = 0; -#endif -} - -#include "httpfilter.moc" diff --git a/tdeio/httpfilter/httpfilter.cpp b/tdeio/httpfilter/httpfilter.cpp new file mode 100644 index 000000000..0f6a45790 --- /dev/null +++ b/tdeio/httpfilter/httpfilter.cpp @@ -0,0 +1,372 @@ +/* + This file is part of the KDE libraries + Copyright (c) 2002 Waldo Bastian + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include + +#include "httpfilter.h" + +HTTPFilterBase::HTTPFilterBase() + : last(0) +{ +} + +HTTPFilterBase::~HTTPFilterBase() +{ + delete last; +} + +void +HTTPFilterBase::chain(HTTPFilterBase *previous) +{ + last = previous; + connect(last, TQT_SIGNAL(output(const TQByteArray &)), + this, TQT_SLOT(slotInput(const TQByteArray &))); +} + +HTTPFilterChain::HTTPFilterChain() + : first(0) +{ +} + +void +HTTPFilterChain::addFilter(HTTPFilterBase *filter) +{ + if (!last) + { + first = filter; + } + else + { + disconnect(last, TQT_SIGNAL(output(const TQByteArray &)), 0, 0); + filter->chain(last); + } + last = filter; + connect(filter, TQT_SIGNAL(output(const TQByteArray &)), + this, TQT_SIGNAL(output(const TQByteArray &))); + connect(filter, TQT_SIGNAL(error(int, const TQString &)), + this, TQT_SIGNAL(error(int, const TQString &))); +} + +void +HTTPFilterChain::slotInput(const TQByteArray &d) +{ + if (first) + first->slotInput(d); + else + emit output(d); +} + +HTTPFilterMD5::HTTPFilterMD5() +{ +} + +TQString +HTTPFilterMD5::md5() +{ + return TQString::fromLatin1(context.base64Digest()); +} + +void +HTTPFilterMD5::slotInput(const TQByteArray &d) +{ + context.update(d); + emit output(d); +} + + +HTTPFilterGZip::HTTPFilterGZip() +{ +#ifdef DO_GZIP + bHasHeader = false; + bHasFinished = false; + bPlainText = false; + bEatTrailer = false; + bEof = false; + zstr.next_in = (Bytef *) Z_NULL; + zstr.avail_in = 0; + zstr.zalloc = Z_NULL; + zstr.zfree = Z_NULL; + zstr.opaque = Z_NULL; + + inflateInit2(&zstr, -MAX_WBITS); + + iTrailer = 8; +#endif +} + +HTTPFilterGZip::~HTTPFilterGZip() +{ +#ifdef DO_GZIP + inflateEnd(&zstr); +#endif + +} + +/* The get_byte() and checkHeader() functions are modified version from */ +/* the correpsonding functions that can be found in zlib, the following */ +/* copyright notice applies to these functions: */ + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +int +HTTPFilterGZip::get_byte() +{ +#ifdef DO_GZIP + if (bEof) return EOF; + if (zstr.avail_in == 0) + { + bEof = true; + return EOF; + } + zstr.avail_in--; + zstr.total_in++; + return *(zstr.next_in)++; +#else + return 0; +#endif +} + +#ifdef DO_GZIP + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ +#endif + +// 0 : ok +// 1 : not gzip +// 2 : no header +int +HTTPFilterGZip::checkHeader() +{ +#ifdef DO_GZIP + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(); + if (c != gz_magic[len]) { + if (len != 0) + { + zstr.avail_in++; + zstr.next_in--; + } + if (c != EOF) { + zstr.avail_in++; + zstr.next_in--; + return 1; + } + return 2; + } + } + + int method = get_byte(); /* method byte */ + int flags = get_byte(); /* flags byte */ + + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + return bEof ? 2 : 1; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(); + len += ((uInt)get_byte())<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte() != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte()) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte()) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(); + } + + return bEof ? 2 : 0; +#else + return 0; +#endif +} + +void +HTTPFilterGZip::slotInput(const TQByteArray &d) +{ +#ifdef DO_GZIP + if (bPlainText) + { + emit output(d); + return; + } + if (d.size() == 0) + { + if (bEatTrailer) + bHasFinished = true; + if (!bHasFinished) + { + // Make sure we get the last bytes still in the pipe. + // Needed with "deflate". + TQByteArray flush(4); + flush.fill(0); + slotInput(flush); + if (!bHasFinished && !bHasHeader) + { + // Send as-is + emit output(headerData); + bHasFinished = true; + // End of data + emit output(TQByteArray()); + } + } + if (!bHasFinished) + emit error( TDEIO::ERR_SLAVE_DEFINED, i18n("Unexpected end of data, some information may be lost.")); + return; + } + if (bHasFinished) + return; + + if (bEatTrailer) + { + iTrailer -= d.size(); + if (iTrailer <= 0) + { + bHasFinished = true; + // End of data + emit output(TQByteArray()); + } + return; + } + + if (!bHasHeader) + { + bEof = false; + + // Add data to header. + int orig_size = headerData.size(); + headerData.resize(orig_size+d.size()); + memcpy(headerData.data()+orig_size, d.data(), d.size()); + + zstr.avail_in = headerData.size(); + zstr.next_in = (Bytef *) headerData.data(); + + int result = checkHeader(); + if (result == 1) + { + bPlainText = true; + output(headerData); + return; + } + + if (result != 0) + return; // next time better + + bHasHeader = true; + } + else + { + zstr.avail_in = d.size(); + zstr.next_in = (Bytef *) d.data(); + } + + while( zstr.avail_in ) + { + char buf[8192]; + zstr.next_out = (Bytef *) buf; + zstr.avail_out = 8192; + int result = inflate( &zstr, Z_NO_FLUSH ); + if ((result != Z_OK) && (result != Z_STREAM_END)) + { + emit error( TDEIO::ERR_SLAVE_DEFINED, i18n("Receiving corrupt data.")); + break; + } + int bytesOut = 8192 - zstr.avail_out; + if (bytesOut) + { + TQByteArray d; + d.setRawData( buf, bytesOut ); + emit output(d); + d.resetRawData( buf, bytesOut ); + } + if (result == Z_STREAM_END) + { + if (iTrailer) + { + bEatTrailer = true; + } + else + { + bHasFinished = true; + // End of data + emit output(TQByteArray()); + } + return; + } + } +#endif +} + +HTTPFilterDeflate::HTTPFilterDeflate() +{ +#ifdef DO_GZIP + bHasHeader = true; + iTrailer = 0; +#endif +} + +#include "httpfilter.moc" diff --git a/tdeio/kssl/CMakeLists.txt b/tdeio/kssl/CMakeLists.txt index a2c9f00d6..bb49a0ea6 100644 --- a/tdeio/kssl/CMakeLists.txt +++ b/tdeio/kssl/CMakeLists.txt @@ -42,14 +42,14 @@ install( FILES set( target kssl ) set( ${target}_SRCS - kssl.cc ksslcertificatehome.cc ksslsettings.cc - ksslcertificate.cc ksslconnectioninfo.cc ksslcertificatefactory.cc - ksslcertificatecache.cc ksslpeerinfo.cc ksslinfodlg.cc - ksslcertdlg.cc ksslutils.cc kopenssl.cc ksslpkcs12.cc - ksslcertchain.cc ksslkeygen.cc ksslx509v3.cc - ksslsigners.cc ksslpkcs7.cc ksslpemcallback.cc - ksslx509map.cc ksslsession.cc keygenwizard.ui - keygenwizard2.ui ksmimecrypto.cc ksslcsessioncache.cc + kssl.cpp ksslcertificatehome.cpp ksslsettings.cpp + ksslcertificate.cpp ksslconnectioninfo.cpp ksslcertificatefactory.cpp + ksslcertificatecache.cpp ksslpeerinfo.cpp ksslinfodlg.cpp + ksslcertdlg.cpp ksslutils.cpp kopenssl.cpp ksslpkcs12.cpp + ksslcertchain.cpp ksslkeygen.cpp ksslx509v3.cpp + ksslsigners.cpp ksslpkcs7.cpp ksslpemcallback.cpp + ksslx509map.cpp ksslsession.cpp keygenwizard.ui + keygenwizard2.ui ksmimecrypto.cpp ksslcsessioncache.cpp ) tde_add_library( ${target} STATIC_PIC AUTOMOC diff --git a/tdeio/kssl/Makefile.am b/tdeio/kssl/Makefile.am index 5d57ab7ab..1f9038be7 100644 --- a/tdeio/kssl/Makefile.am +++ b/tdeio/kssl/Makefile.am @@ -40,31 +40,31 @@ noinst_HEADERS = ksslcsessioncache.h libkssl_la_SOURCES = \ - kssl.cc \ - ksslcertificatehome.cc \ - ksslsettings.cc \ - ksslcertificate.cc \ - ksslconnectioninfo.cc \ - ksslcertificatefactory.cc \ - ksslcertificatecache.cc \ - ksslpeerinfo.cc \ - ksslinfodlg.cc \ - ksslcertdlg.cc \ - ksslutils.cc \ - kopenssl.cc \ - ksslpkcs12.cc \ - ksslcertchain.cc \ - ksslkeygen.cc \ - ksslx509v3.cc \ - ksslsigners.cc \ - ksslpkcs7.cc \ - ksslpemcallback.cc \ - ksslx509map.cc \ - ksslsession.cc \ + kssl.cpp \ + ksslcertificatehome.cpp \ + ksslsettings.cpp \ + ksslcertificate.cpp \ + ksslconnectioninfo.cpp \ + ksslcertificatefactory.cpp \ + ksslcertificatecache.cpp \ + ksslpeerinfo.cpp \ + ksslinfodlg.cpp \ + ksslcertdlg.cpp \ + ksslutils.cpp \ + kopenssl.cpp \ + ksslpkcs12.cpp \ + ksslcertchain.cpp \ + ksslkeygen.cpp \ + ksslx509v3.cpp \ + ksslsigners.cpp \ + ksslpkcs7.cpp \ + ksslpemcallback.cpp \ + ksslx509map.cpp \ + ksslsession.cpp \ keygenwizard.ui \ keygenwizard2.ui \ - ksmimecrypto.cc \ - ksslcsessioncache.cc + ksmimecrypto.cpp \ + ksslcsessioncache.cpp SUBDIRS = kssl diff --git a/tdeio/kssl/kopenssl.cc b/tdeio/kssl/kopenssl.cc deleted file mode 100644 index a009bd7e9..000000000 --- a/tdeio/kssl/kopenssl.cc +++ /dev/null @@ -1,2123 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2001-2003 George Staikos - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef KSSL_HAVE_SSL -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include "kopenssl.h" - -#define GET_CRYPTOLIB_SYMBOL(a) ((_cryptoLib->hasSymbol(a)) ? _cryptoLib->symbol(a) : NULL) -#define GET_SSLLIB_SYMBOL(a) ((_sslLib->hasSymbol(a)) ? _sslLib->symbol(a) : NULL) - -// taken from OpenSSL 1.1 header, used to call OPENSSL_init_crypto -#if !defined(OPENSSL_INIT_ADD_ALL_CIPHERS) -# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L -# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L -# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L -#endif - -extern "C" { -#ifdef KSSL_HAVE_SSL -static int (*K_SSL_connect) (SSL *) = 0L; -static int (*K_SSL_accept) (SSL *) = 0L; -static int (*K_SSL_read) (SSL *, void *, int) = 0L; -static int (*K_SSL_write) (SSL *, const void *, int) = 0L; -static SSL *(*K_SSL_new) (SSL_CTX *) = 0L; -static void (*K_SSL_free) (SSL *) = 0L; -static int (*K_SSL_shutdown) (SSL *) = 0L; -static SSL_CTX *(*K_SSL_CTX_new)(SSL_METHOD *) = 0L; -static void (*K_SSL_CTX_free) (SSL_CTX *) = 0L; -static int (*K_SSL_set_fd) (SSL *, int) = 0L; -static int (*K_SSL_pending) (SSL *) = 0L; -static int (*K_SSL_peek) (SSL *, void *, int) = 0L; -static int (*K_SSL_CTX_set_cipher_list)(SSL_CTX *, const char *) = 0L; -static void (*K_SSL_CTX_set_verify)(SSL_CTX *, int, - int (*)(int, X509_STORE_CTX *)) = 0L; -static int (*K_SSL_use_certificate)(SSL *, X509 *) = 0L; -static SSL_CIPHER *(*K_SSL_get_current_cipher)(SSL *) = 0L; -static long (*K_SSL_set_options)(SSL *ssl, long options) = 0L; -static int (*K_SSL_session_reused)(SSL *ssl) = 0L; -static long (*K_SSL_ctrl) (SSL *,int, long, void *) = 0L; -static int (*K_RAND_egd) (const char *) = 0L; -static const char* (*K_RAND_file_name) (char *, size_t) = 0L; -static int (*K_RAND_load_file) (const char *, long) = 0L; -static int (*K_RAND_write_file) (const char *) = 0L; -static SSL_METHOD * (*K_TLSv1_client_method) () = 0L; -static SSL_METHOD * (*K_SSLv2_client_method) () = 0L; -static SSL_METHOD * (*K_SSLv3_client_method) () = 0L; -static SSL_METHOD * (*K_TLS_client_method) () = 0L; -static X509 * (*K_SSL_get_peer_certificate) (SSL *) = 0L; -static int (*K_SSL_CIPHER_get_bits) (SSL_CIPHER *,int *) = 0L; -static char * (*K_SSL_CIPHER_get_version) (SSL_CIPHER *) = 0L; -static const char * (*K_SSL_CIPHER_get_name) (SSL_CIPHER *) = 0L; -static char * (*K_SSL_CIPHER_description) (SSL_CIPHER *, char *, int) = 0L; -static X509 * (*K_d2i_X509) (X509 **,unsigned char **,long) = 0L; -static X509_CRL * (*K_d2i_X509_CRL) (X509_CRL **,unsigned char **,long) = 0L; -static int (*K_i2d_X509) (X509 *,unsigned char **) = 0L; -static int (*K_X509_cmp) (X509 *, X509 *) = 0L; -static int (*K_X509_subject_name_cmp) (const X509 *, const X509 *) = 0L; -static void (*K_X509_STORE_CTX_free) (X509_STORE_CTX *) = 0L; -static int (*K_X509_verify_cert) (X509_STORE_CTX *) = 0L; -static X509_STORE_CTX *(*K_X509_STORE_CTX_new) (void) = 0L; -static void (*K_X509_STORE_free) (X509_STORE *) = 0L; -static X509_STORE *(*K_X509_STORE_new) (void) = 0L; -static void (*K_X509_free) (X509 *) = 0L; -static void (*K_X509_CRL_free) (X509_CRL *) = 0L; -static char *(*K_X509_NAME_oneline) (X509_NAME *,char *,int) = 0L; -static X509_NAME *(*K_X509_get_subject_name) (X509 *) = 0L; -static X509_NAME *(*K_X509_get_issuer_name) (X509 *) = 0L; -static X509_LOOKUP *(*K_X509_STORE_add_lookup) (X509_STORE *, X509_LOOKUP_METHOD *) = 0L; -static X509_LOOKUP_METHOD *(*K_X509_LOOKUP_file)(void) = 0L; -static void (*K_X509_LOOKUP_free)(X509_LOOKUP *) = 0L; -static int (*K_X509_LOOKUP_ctrl)(X509_LOOKUP *, int, const char *, long, char **) = 0L; -static void (*K_X509_STORE_CTX_init)(X509_STORE_CTX *, X509_STORE *, X509 *, STACK_OF(X509) *) = 0L; -static void (*K_CRYPTO_free) (void *) = 0L; -static X509* (*K_X509_dup) (X509 *) = 0L; -static void (*K_X509_get0_signature)(const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg, const X509 *x) = 0L; -static BIO_METHOD *(*K_BIO_s_mem) (void) = 0L; -static BIO* (*K_BIO_new) (BIO_METHOD *) = 0L; -static BIO* (*K_BIO_new_fp) (FILE *, int) = 0L; -static BIO* (*K_BIO_new_mem_buf) (void *, int) = 0L; -static int (*K_BIO_free) (BIO *) = 0L; -static long (*K_BIO_ctrl) (BIO *,int,long,void *) = 0L; -static int (*K_BIO_write) (BIO *b, const void *data, int len) = 0L; -static void* (*K_BIO_get_data) (BIO *a) = 0L; -static int (*K_PEM_ASN1_write_bio) (int (*)(),const char *,BIO *,char *, - const EVP_CIPHER *,unsigned char *,int , - pem_password_cb *, void *) = 0L; -#if OPENSSL_VERSION_NUMBER >= 0x10000000L -static int (*K_ASN1_item_i2d_fp)(ASN1_ITEM *,FILE *,unsigned char *) = 0L; -static ASN1_ITEM *K_NETSCAPE_X509_it = 0L; -#else -static ASN1_METHOD* (*K_X509_asn1_meth) (void) = 0L; -static int (*K_ASN1_i2d_fp)(int (*)(),FILE *,unsigned char *) = 0L; -static int (*K_i2d_ASN1_HEADER)(ASN1_HEADER *, unsigned char **) = 0L; -#endif -static int (*K_X509_print_fp) (FILE *, X509*) = 0L; -static int (*K_i2d_PKCS12) (PKCS12*, unsigned char**) = 0L; -static int (*K_i2d_PKCS12_fp) (FILE *, PKCS12*) = 0L; -static int (*K_PKCS12_newpass) (PKCS12*, char*, char*) = 0L; -static PKCS12* (*K_d2i_PKCS12_fp) (FILE*, PKCS12**) = 0L; -static PKCS12* (*K_PKCS12_new) (void) = 0L; -static void (*K_PKCS12_free) (PKCS12 *) = 0L; -static int (*K_PKCS12_parse) (PKCS12*, const char *, EVP_PKEY**, - X509**, STACK_OF(X509)**) = 0L; -static void (*K_EVP_PKEY_free) (EVP_PKEY *) = 0L; -static EVP_PKEY* (*K_EVP_PKEY_new) () = 0L; -static int (*K_EVP_PKEY_base_id)(const EVP_PKEY *pkey) = 0L; -static RSA* (*K_EVP_PKEY_get0_RSA)(EVP_PKEY *pkey) = 0L; -static DSA* (*K_EVP_PKEY_get0_DSA)(EVP_PKEY *pkey) = 0L; -static void (*K_X509_REQ_free) (X509_REQ *) = 0L; -static X509_REQ* (*K_X509_REQ_new) () = 0L; -static int (*K_SSL_CTX_use_PrivateKey) (SSL_CTX*, EVP_PKEY*) = 0L; -static int (*K_SSL_CTX_use_certificate) (SSL_CTX*, X509*) = 0L; -static int (*K_SSL_get_error) (SSL*, int) = 0L; -static STACK_OF(X509)* (*K_SSL_get_peer_cert_chain) (SSL*) = 0L; -static void (*K_X509_STORE_CTX_set0_untrusted) (X509_STORE_CTX *, STACK_OF(X509)*) = 0L; -static void (*K_X509_STORE_CTX_set_purpose) (X509_STORE_CTX *, int) = 0L; -static void (*K_sk_free) (STACK*) = 0L; -static int (*K_sk_num) (STACK*) = 0L; -static char* (*K_sk_pop) (STACK*) = 0L; -static char* (*K_sk_value) (STACK*, int) = 0L; -static STACK* (*K_sk_new) (int (*)()) = 0L; -static int (*K_sk_push) (STACK*, char*) = 0L; -static STACK* (*K_sk_dup) (const STACK *) = 0L; -static char * (*K_i2s_ASN1_INTEGER) (X509V3_EXT_METHOD *, ASN1_INTEGER *) =0L; -static ASN1_INTEGER * (*K_X509_get_serialNumber) (X509 *) = 0L; -static EVP_PKEY *(*K_X509_get_pubkey)(X509 *) = 0L; -static int (*K_i2d_PublicKey)(EVP_PKEY *, unsigned char **) = 0L; -static int (*K_X509_check_private_key)(X509 *, EVP_PKEY *) = 0L; -static char * (*K_BN_bn2hex)(const BIGNUM *) = 0L; -static int (*K_X509_digest)(const X509 *,const EVP_MD *, unsigned char *, unsigned int *) = 0L; -static EVP_MD* (*K_EVP_md5)() = 0L; -static void (*K_ASN1_INTEGER_free)(ASN1_INTEGER *) = 0L; -static int (*K_OBJ_obj2nid)(ASN1_OBJECT *) = 0L; -static const char * (*K_OBJ_nid2ln)(int) = 0L; -static int (*K_X509_get_ext_count)(X509*) = 0L; -static int (*K_X509_get_ext_by_NID)(X509*, int, int) = 0L; -static int (*K_X509_get_ext_by_OBJ)(X509*,ASN1_OBJECT*,int) = 0L; -static X509_EXTENSION *(*K_X509_get_ext)(X509*, int loc) = 0L; -static X509_EXTENSION *(*K_X509_delete_ext)(X509*, int) = 0L; -static int (*K_X509_add_ext)(X509*, X509_EXTENSION*, int) = 0L; -static void *(*K_X509_get_ext_d2i)(X509*, int, int*, int*) = 0L; -static char *(*K_i2s_ASN1_OCTET_STRING)(X509V3_EXT_METHOD*, ASN1_OCTET_STRING*) = 0L; -static int (*K_ASN1_BIT_STRING_get_bit)(ASN1_BIT_STRING*, int) = 0L; -static PKCS7 *(*K_PKCS7_new)() = 0L; -static void (*K_PKCS7_free)(PKCS7*) = 0L; -static void (*K_PKCS7_content_free)(PKCS7*) = 0L; -static int (*K_i2d_PKCS7)(PKCS7*, unsigned char**) = 0L; -static PKCS7 *(*K_d2i_PKCS7)(PKCS7**, unsigned char**,long) = 0L; -static int (*K_i2d_PKCS7_fp)(FILE*,PKCS7*) = 0L; -static PKCS7* (*K_d2i_PKCS7_fp)(FILE*,PKCS7**) = 0L; -static int (*K_i2d_PKCS7_bio)(BIO *bp,PKCS7 *p7) = 0L; -static PKCS7 *(*K_d2i_PKCS7_bio)(BIO *bp,PKCS7 **p7) = 0L; -static PKCS7* (*K_PKCS7_dup)(PKCS7*) = 0L; -static STACK_OF(X509_NAME) *(*K_SSL_load_client_CA_file)(const char*) = 0L; -static STACK_OF(X509_INFO) *(*K_PEM_X509_INFO_read)(FILE*, STACK_OF(X509_INFO)*, pem_password_cb*, void*) = 0L; -static char *(*K_ASN1_d2i_fp)(char *(*)(),char *(*)(),FILE*,unsigned char**) = 0L; -static X509 *(*K_X509_new)() = 0L; -static int (*K_X509_PURPOSE_get_count)() = 0L; -static int (*K_X509_PURPOSE_get_id)(X509_PURPOSE *) = 0L; -static int (*K_X509_check_purpose)(X509*,int,int) = 0L; -static X509_PURPOSE* (*K_X509_PURPOSE_get0)(int) = 0L; -static int (*K_EVP_PKEY_assign)(EVP_PKEY*, int, char*) = 0L; -static int (*K_X509_REQ_set_pubkey)(X509_REQ*, EVP_PKEY*) = 0L; -static void (*K_RSA_get0_key)(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) = 0L; -static RSA *(*K_RSA_generate_key)(int, unsigned long, void (*)(int,int,void *), void *) = 0L; -static void (*K_DSA_get0_pqg)(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) = 0L; -static void (*K_DSA_get0_key)(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) = 0L; -static int (*K_i2d_X509_REQ_fp)(FILE*, X509_REQ*) = 0L; -static void (*K_ERR_clear_error)() = 0L; -static unsigned long (*K_ERR_get_error)() = 0L; -static void (*K_ERR_print_errors_fp)(FILE*) = 0L; -static PKCS7 *(*K_PKCS7_sign)(X509*, EVP_PKEY*, STACK_OF(X509)*, BIO*, int) = 0L; -static int (*K_PKCS7_verify)(PKCS7*,STACK_OF(X509)*,X509_STORE*,BIO*,BIO*,int) = 0L; -static STACK_OF(X509) *(*K_PKCS7_get0_signers)(PKCS7 *, STACK_OF(X509) *, int) = 0L; -static PKCS7 *(*K_PKCS7_encrypt)(STACK_OF(X509) *, BIO *, EVP_CIPHER *, int) = 0L; -static int (*K_PKCS7_decrypt)(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int) = 0L; -static SSL_SESSION* (*K_SSL_get1_session)(SSL*) = 0L; -static void (*K_SSL_SESSION_free)(SSL_SESSION*) = 0L; -static int (*K_SSL_set_session)(SSL*,SSL_SESSION*) = 0L; -static SSL_SESSION* (*K_d2i_SSL_SESSION)(SSL_SESSION**,unsigned char**, long) = 0L; -static int (*K_i2d_SSL_SESSION)(SSL_SESSION*,unsigned char**) = 0L; -static STACK *(*K_X509_get1_email)(X509 *x) = 0L; -static void (*K_X509_email_free)(STACK *sk) = 0L; -static EVP_CIPHER *(*K_EVP_des_ede3_cbc)() = 0L; -static EVP_CIPHER *(*K_EVP_des_cbc)() = 0L; -static EVP_CIPHER *(*K_EVP_rc2_cbc)() = 0L; -static EVP_CIPHER *(*K_EVP_rc2_64_cbc)() = 0L; -static EVP_CIPHER *(*K_EVP_rc2_40_cbc)() = 0L; -static int (*K_i2d_PrivateKey_fp)(FILE*,EVP_PKEY*) = 0L; -static int (*K_i2d_PKCS8PrivateKey_fp)(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*) = 0L; -static void (*K_RSA_free)(RSA*) = 0L; -static EVP_CIPHER *(*K_EVP_bf_cbc)() = 0L; -static int (*K_X509_REQ_sign)(X509_REQ*, EVP_PKEY*, const EVP_MD*) = 0L; -static int (*K_X509_NAME_add_entry_by_txt)(X509_NAME*, char*, int, unsigned char*, int, int, int) = 0L; -static X509_NAME *(*K_X509_NAME_new)() = 0L; -static int (*K_X509_REQ_set_subject_name)(X509_REQ*,X509_NAME*) = 0L; -static unsigned char *(*K_ASN1_STRING_data)(ASN1_STRING*) = 0L; -static int (*K_ASN1_STRING_length)(ASN1_STRING*) = 0L; -static STACK_OF(SSL_CIPHER) *(*K_SSL_get_ciphers)(const SSL *ssl) = 0L; -static const ASN1_TIME* (*K_X509_CRL_get0_lastUpdate)(const X509_CRL *crl) = 0L; -static const ASN1_TIME* (*K_X509_CRL_get0_nextUpdate)(const X509_CRL *crl) = 0L; -static X509* (*K_X509_STORE_CTX_get_current_cert)(X509_STORE_CTX *ctx) = 0L; -static int (*K_X509_STORE_CTX_get_error)(X509_STORE_CTX *ctx) = 0L; -static int (*K_X509_STORE_CTX_get_error_depth)(X509_STORE_CTX *ctx) = 0L; -static void (*K_X509_STORE_CTX_set_error)(X509_STORE_CTX *ctx, int s) = 0L; -static void (*K_X509_STORE_set_verify_cb)(X509_STORE *ctx, - X509_STORE_CTX_verify_cb verify_cb) = 0L; -static STACK_OF(X509_OBJECT)* (*K_X509_STORE_get0_objects)(X509_STORE *v) = 0L; -static X509_LOOKUP_TYPE (*K_X509_OBJECT_get_type)(const X509_OBJECT *a) = 0L; -static X509* (*K_X509_OBJECT_get0_X509)(const X509_OBJECT *a) = 0L; -static ASN1_TIME* (*K_X509_getm_notAfter)(const X509 *x) = 0L; -static ASN1_TIME* (*K_X509_getm_notBefore)(const X509 *x) = 0L; -#endif -} - - -bool KOpenSSLProxy::hasLibSSL() const { - return _sslLib != 0L; -} - - -bool KOpenSSLProxy::hasLibCrypto() const { - return _cryptoLib != 0L; -} - - -void KOpenSSLProxy::destroy() { - delete this; - _me = 0L; -} - -#ifdef __OpenBSD__ -#include -#include -#include - -static TQString findMostRecentLib(TQString dir, TQString name) -{ - // Grab all shared libraries in the directory - TQString filter = "lib"+name+".so.*"; - TQDir d(dir, filter); - if (!d.exists()) - return 0L; - TQStringList l = d.entryList(); - - // Find the best one - int bestmaj = -1; - int bestmin = -1; - TQString best = 0L; - // where do we start - uint s = filter.length()-1; - for (TQStringList::Iterator it = l.begin(); it != l.end(); ++it) { - TQString numberpart = (*it).mid(s); - uint endmaj = numberpart.find('.'); - if (endmaj == -1) - continue; - bool ok; - int maj = numberpart.left(endmaj).toInt(&ok); - if (!ok) - continue; - int min = numberpart.mid(endmaj+1).toInt(&ok); - if (!ok) - continue; - if (maj > bestmaj || (maj == bestmaj && min > bestmin)) { - bestmaj = maj; - bestmin = min; - best = (*it); - } - } - if (best.isNull()) - return 0L; - else - return dir+"/"+best; -} -#endif - - -KOpenSSLProxy::KOpenSSLProxy() { -KLibLoader *ll = KLibLoader::self(); -_ok = false; -TQStringList libpaths, libnamesc, libnamess; -TDEConfig *cfg; - - _cryptoLib = 0L; - _sslLib = 0L; - - cfg = new TDEConfig("cryptodefaults", false, false); - cfg->setGroup("OpenSSL"); - TQString upath = cfg->readPathEntry("Path"); - if (!upath.isEmpty()) - libpaths << upath; - - delete cfg; - -#ifdef __OpenBSD__ - { - TQString libname = findMostRecentLib("/usr/" SYSTEM_LIBDIR, "crypto"); - if (!libname.isNull()) - _cryptoLib = ll->globalLibrary(libname.latin1()); - } -#elif defined(__CYGWIN__) - libpaths << "/usr/bin/" - << "/usr/local/bin" - << "/usr/local/openssl/bin" - << "/opt/openssl/bin" - << "/opt/trinity/bin" - << ""; - - libnamess << "cygssl-0.9.7.dll" - << "cygssl.dll" - << "libssl.dll" - << ""; - - libnamesc << "cygcrypto.dll" - << "libcrypto.dll" - << ""; -#else - libpaths - #ifdef _AIX - << "/opt/freeware/lib/" - #endif - << "/usr/" SYSTEM_LIBDIR "/" - << "/usr/ssl/" SYSTEM_LIBDIR "/" - << "/usr/local/" SYSTEM_LIBDIR "/" - << "/usr/local/openssl/" SYSTEM_LIBDIR "/" - << "/usr/local/ssl/" SYSTEM_LIBDIR "/" - << "/opt/openssl/" SYSTEM_LIBDIR "/" - << "/" SYSTEM_LIBDIR "/" - << ""; - -// FIXME: #define here for the various OS types to optimize - libnamess - #ifdef hpux - << "libssl.sl" - #elif defined(_AIX) - << "libssl.a(libssl.so.0)" - #elif defined(__APPLE__) - << "libssl.dylib" - << "libssl.0.9.dylib" - #else - #ifdef SHLIB_VERSION_NUMBER - << "libssl.so." SHLIB_VERSION_NUMBER - #endif - << "libssl.so" - << "libssl.so.0" - #endif - ; - - libnamesc - #ifdef hpux - << "libcrypto.sl" - #elif defined(_AIX) - << "libcrypto.a(libcrypto.so.0)" - #elif defined(__APPLE__) - << "libcrypto.dylib" - << "libcrypto.0.9.dylib" - #else - #ifdef SHLIB_VERSION_NUMBER - << "libcrypto.so." SHLIB_VERSION_NUMBER - #endif - << "libcrypto.so" - << "libcrypto.so.0" - #endif - ; -#endif - - for (TQStringList::Iterator it = libpaths.begin(); - it != libpaths.end(); - ++it) { - for (TQStringList::Iterator shit = libnamesc.begin(); - shit != libnamesc.end(); - ++shit) { - TQString alib = *it; - if (!alib.isEmpty() && !alib.endsWith("/")) - alib += "/"; - alib += *shit; - TQString tmpStr(alib.latin1()); - tmpStr.replace(TQRegExp("\\(.*\\)"), ""); - if (!access(tmpStr.latin1(), R_OK)) - _cryptoLib = ll->globalLibrary(alib.latin1()); - if (_cryptoLib) break; - } - if (_cryptoLib) break; - } - - if (_cryptoLib) { -#ifdef KSSL_HAVE_SSL - K_X509_free = (void (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_free"); - K_X509_CRL_free = (void (*) (X509_CRL *)) GET_CRYPTOLIB_SYMBOL("X509_CRL_free"); - K_RAND_egd = (int (*)(const char *)) GET_CRYPTOLIB_SYMBOL("RAND_egd"); - K_RAND_load_file = (int (*)(const char *, long)) GET_CRYPTOLIB_SYMBOL("RAND_load_file"); - K_RAND_file_name = (const char* (*)(char *, size_t)) GET_CRYPTOLIB_SYMBOL("RAND_file_name"); - K_RAND_write_file = (int (*)(const char *)) GET_CRYPTOLIB_SYMBOL("RAND_write_file"); - K_CRYPTO_free = (void (*) (void *)) GET_CRYPTOLIB_SYMBOL("CRYPTO_free"); - K_d2i_X509 = (X509 * (*)(X509 **,unsigned char **,long)) GET_CRYPTOLIB_SYMBOL("d2i_X509"); - K_d2i_X509_CRL = (X509_CRL * (*)(X509_CRL **,unsigned char **,long)) GET_CRYPTOLIB_SYMBOL("d2i_X509_CRL"); - K_i2d_X509 = (int (*)(X509 *,unsigned char **)) GET_CRYPTOLIB_SYMBOL("i2d_X509"); - K_X509_cmp = (int (*)(X509 *, X509 *)) GET_CRYPTOLIB_SYMBOL("X509_cmp"); - K_X509_subject_name_cmp = (int (*)(const X509 *, const X509 *)) GET_CRYPTOLIB_SYMBOL("X509_subject_name_cmp"); - K_X509_STORE_CTX_new = (X509_STORE_CTX * (*) (void)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_new"); - K_X509_STORE_CTX_free = (void (*) (X509_STORE_CTX *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_free"); - K_X509_verify_cert = (int (*) (X509_STORE_CTX *)) GET_CRYPTOLIB_SYMBOL("X509_verify_cert"); - K_X509_STORE_new = (X509_STORE * (*) (void)) GET_CRYPTOLIB_SYMBOL("X509_STORE_new"); - K_X509_STORE_free = (void (*) (X509_STORE *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_free"); - K_X509_NAME_oneline = (char * (*) (X509_NAME *,char *,int)) GET_CRYPTOLIB_SYMBOL("X509_NAME_oneline"); - K_X509_get_subject_name = (X509_NAME * (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_subject_name"); - K_X509_get_issuer_name = (X509_NAME * (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_issuer_name"); - K_X509_STORE_add_lookup = (X509_LOOKUP *(*) (X509_STORE *, X509_LOOKUP_METHOD *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_add_lookup"); - K_X509_LOOKUP_file = (X509_LOOKUP_METHOD *(*)(void)) GET_CRYPTOLIB_SYMBOL("X509_LOOKUP_file"); - K_X509_LOOKUP_free = (void (*)(X509_LOOKUP *)) GET_CRYPTOLIB_SYMBOL("X509_LOOKUP_free"); - K_X509_LOOKUP_ctrl = (int (*)(X509_LOOKUP *, int, const char *, long, char **)) GET_CRYPTOLIB_SYMBOL("X509_LOOKUP_ctrl"); - K_X509_STORE_CTX_init = (void (*)(X509_STORE_CTX *, X509_STORE *, X509 *, STACK_OF(X509) *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_init"); - K_X509_dup = (X509* (*)(X509*)) GET_CRYPTOLIB_SYMBOL("X509_dup"); - K_X509_get0_signature = (void (*)(const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg, const X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_get0_signature"); - K_BIO_s_mem = (BIO_METHOD *(*) (void)) GET_CRYPTOLIB_SYMBOL("BIO_s_mem"); - K_BIO_new = (BIO* (*)(BIO_METHOD *)) GET_CRYPTOLIB_SYMBOL("BIO_new"); - K_BIO_new_fp = (BIO* (*)(FILE*, int)) GET_CRYPTOLIB_SYMBOL("BIO_new_fp"); - K_BIO_new_mem_buf = (BIO* (*)(void *, int)) GET_CRYPTOLIB_SYMBOL("BIO_new_mem_buf"); - K_BIO_free = (int (*)(BIO*)) GET_CRYPTOLIB_SYMBOL("BIO_free"); - K_BIO_ctrl = (long (*) (BIO *,int,long,void *)) GET_CRYPTOLIB_SYMBOL("BIO_ctrl"); - K_BIO_write = (int (*) (BIO *b, const void *data, int len)) GET_CRYPTOLIB_SYMBOL("BIO_write"); - K_BIO_get_data = (void* (*)(BIO *a)) GET_CRYPTOLIB_SYMBOL("BIO_get_data"); - K_PEM_ASN1_write_bio = (int (*)(int (*)(), const char *,BIO*, char*, const EVP_CIPHER *, unsigned char *, int, pem_password_cb *, void *)) GET_CRYPTOLIB_SYMBOL("PEM_ASN1_write_bio"); -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - K_ASN1_item_i2d_fp = (int (*)(ASN1_ITEM *, FILE*, unsigned char *)) GET_CRYPTOLIB_SYMBOL("ASN1_item_i2d_fp"); - K_NETSCAPE_X509_it = (ASN1_ITEM *) GET_CRYPTOLIB_SYMBOL("NETSCAPE_X509_it"); -#else - K_X509_asn1_meth = (ASN1_METHOD* (*)(void)) GET_CRYPTOLIB_SYMBOL("X509_asn1_meth"); - K_ASN1_i2d_fp = (int (*)(int (*)(), FILE*, unsigned char *)) GET_CRYPTOLIB_SYMBOL("ASN1_i2d_fp"); - K_i2d_ASN1_HEADER = (int (*)(ASN1_HEADER *, unsigned char **)) GET_CRYPTOLIB_SYMBOL("i2d_ASN1_HEADER"); -#endif - K_X509_print_fp = (int (*)(FILE*, X509*)) GET_CRYPTOLIB_SYMBOL("X509_print_fp"); - K_i2d_PKCS12 = (int (*)(PKCS12*, unsigned char**)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS12"); - K_i2d_PKCS12_fp = (int (*)(FILE *, PKCS12*)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS12_fp"); - K_PKCS12_newpass = (int (*)(PKCS12*, char*, char*)) GET_CRYPTOLIB_SYMBOL("PKCS12_newpass"); - K_d2i_PKCS12_fp = (PKCS12* (*)(FILE*, PKCS12**)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS12_fp"); - K_PKCS12_new = (PKCS12* (*)()) GET_CRYPTOLIB_SYMBOL("PKCS12_new"); - K_PKCS12_free = (void (*)(PKCS12 *)) GET_CRYPTOLIB_SYMBOL("PKCS12_free"); - K_PKCS12_parse = (int (*)(PKCS12*, const char *, EVP_PKEY**, - X509**, STACK_OF(X509)**)) GET_CRYPTOLIB_SYMBOL("PKCS12_parse"); - K_EVP_PKEY_free = (void (*) (EVP_PKEY *)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_free"); - K_EVP_PKEY_new = (EVP_PKEY* (*)()) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_new"); - K_EVP_PKEY_base_id = (int (*)(const EVP_PKEY *pkey)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_base_id"); - K_EVP_PKEY_get0_RSA = (RSA* (*)(EVP_PKEY *pkey)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_get0_RSA"); - K_EVP_PKEY_get0_DSA = (DSA* (*)(EVP_PKEY *pkey)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_get0_DSA"); - K_X509_REQ_free = (void (*)(X509_REQ*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_free"); - K_X509_REQ_new = (X509_REQ* (*)()) GET_CRYPTOLIB_SYMBOL("X509_REQ_new"); - K_X509_STORE_CTX_set0_untrusted = (void (*)(X509_STORE_CTX *, STACK_OF(X509)*)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set0_untrusted"); - if (!K_X509_STORE_CTX_set0_untrusted) K_X509_STORE_CTX_set0_untrusted = (void (*)(X509_STORE_CTX *, STACK_OF(X509)*)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set_chain"); - K_X509_STORE_CTX_set_purpose = (void (*)(X509_STORE_CTX *, int)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set_purpose"); - K_sk_free = (void (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_free"); - if (!K_sk_free) K_sk_free = (void (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("sk_free"); - K_sk_num = (int (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_num"); - if (!K_sk_num) K_sk_num = (int (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("sk_num"); - K_sk_pop = (char* (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_pop"); - if (!K_sk_pop) K_sk_pop = (char* (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("sk_pop"); - K_sk_value = (char* (*) (STACK *, int)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_value"); - if (!K_sk_value) K_sk_value = (char* (*) (STACK *, int)) GET_CRYPTOLIB_SYMBOL("sk_value"); - K_sk_new = (STACK* (*) (int (*)())) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_new"); - if (!K_sk_new) K_sk_new = (STACK* (*) (int (*)())) GET_CRYPTOLIB_SYMBOL("sk_new"); - K_sk_push = (int (*) (STACK*, char*)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_push"); - if (!K_sk_push) K_sk_push = (int (*) (STACK*, char*)) GET_CRYPTOLIB_SYMBOL("sk_push"); - K_sk_dup = (STACK* (*) (const STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_dup"); - if (!K_sk_dup) K_sk_dup = (STACK* (*) (const STACK *)) GET_CRYPTOLIB_SYMBOL("sk_dup"); - K_i2s_ASN1_INTEGER = (char *(*) (X509V3_EXT_METHOD *, ASN1_INTEGER *)) GET_CRYPTOLIB_SYMBOL("i2s_ASN1_INTEGER"); - K_X509_get_serialNumber = (ASN1_INTEGER * (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_serialNumber"); - K_X509_get_pubkey = (EVP_PKEY *(*)(X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_pubkey"); - K_i2d_PublicKey = (int (*)(EVP_PKEY *, unsigned char **)) GET_CRYPTOLIB_SYMBOL("i2d_PublicKey"); - K_X509_check_private_key = (int (*)(X509 *, EVP_PKEY *)) GET_CRYPTOLIB_SYMBOL("X509_check_private_key"); - K_BN_bn2hex = (char *(*)(const BIGNUM *)) GET_CRYPTOLIB_SYMBOL("BN_bn2hex"); - K_X509_digest = (int (*)(const X509 *,const EVP_MD *, unsigned char *, unsigned int *)) GET_CRYPTOLIB_SYMBOL("X509_digest"); - K_EVP_md5 = (EVP_MD *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_md5"); - K_ASN1_INTEGER_free = (void (*)(ASN1_INTEGER *)) GET_CRYPTOLIB_SYMBOL("ASN1_INTEGER_free"); - K_OBJ_obj2nid = (int (*)(ASN1_OBJECT *)) GET_CRYPTOLIB_SYMBOL("OBJ_obj2nid"); - K_OBJ_nid2ln = (const char *(*)(int)) GET_CRYPTOLIB_SYMBOL("OBJ_nid2ln"); - K_X509_get_ext_count = (int (*)(X509*)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_count"); - K_X509_get_ext_by_NID = (int (*)(X509*,int,int)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_by_NID"); - K_X509_get_ext_by_OBJ = (int (*)(X509*,ASN1_OBJECT*,int)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_by_OBJ"); - K_X509_get_ext = (X509_EXTENSION* (*)(X509*,int)) GET_CRYPTOLIB_SYMBOL("X509_get_ext"); - K_X509_delete_ext = (X509_EXTENSION* (*)(X509*,int)) GET_CRYPTOLIB_SYMBOL("X509_delete_ext"); - K_X509_add_ext = (int (*)(X509*,X509_EXTENSION*,int)) GET_CRYPTOLIB_SYMBOL("X509_add_ext"); - K_X509_get_ext_d2i = (void* (*)(X509*,int,int*,int*)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_d2i"); - K_i2s_ASN1_OCTET_STRING = (char *(*)(X509V3_EXT_METHOD*,ASN1_OCTET_STRING*)) GET_CRYPTOLIB_SYMBOL("i2s_ASN1_OCTET_STRING"); - K_ASN1_BIT_STRING_get_bit = (int (*)(ASN1_BIT_STRING*,int)) GET_CRYPTOLIB_SYMBOL("ASN1_BIT_STRING_get_bit"); - K_PKCS7_new = (PKCS7 *(*)()) GET_CRYPTOLIB_SYMBOL("PKCS7_new"); - K_PKCS7_free = (void (*)(PKCS7*)) GET_CRYPTOLIB_SYMBOL("PKCS7_free"); - K_PKCS7_content_free = (void (*)(PKCS7*)) GET_CRYPTOLIB_SYMBOL("PKCS7_content_free"); - K_i2d_PKCS7 = (int (*)(PKCS7*, unsigned char**)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS7"); - K_i2d_PKCS7_fp = (int (*)(FILE*,PKCS7*)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS7_fp"); - K_i2d_PKCS7_bio = (int (*)(BIO *bp,PKCS7 *p7)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS7_bio"); - K_d2i_PKCS7 = (PKCS7* (*)(PKCS7**,unsigned char**,long)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS7"); - K_d2i_PKCS7_fp = (PKCS7 *(*)(FILE *,PKCS7**)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS7_fp"); - K_d2i_PKCS7_bio = (PKCS7 *(*)(BIO *bp,PKCS7 **p7)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS7_bio"); - K_PKCS7_dup = (PKCS7* (*)(PKCS7*)) GET_CRYPTOLIB_SYMBOL("PKCS7_dup"); - K_PKCS7_sign = (PKCS7 *(*)(X509*, EVP_PKEY*, STACK_OF(X509)*, BIO*, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_sign"); - K_PKCS7_verify = (int (*)(PKCS7*,STACK_OF(X509)*,X509_STORE*,BIO*,BIO*,int)) GET_CRYPTOLIB_SYMBOL("PKCS7_verify"); - K_PKCS7_get0_signers = (STACK_OF(X509) *(*)(PKCS7 *, STACK_OF(X509) *, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_get0_signers"); - K_PKCS7_encrypt = (PKCS7* (*)(STACK_OF(X509) *, BIO *, EVP_CIPHER *, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_encrypt"); - K_PKCS7_decrypt = (int (*)(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_decrypt"); - K_PEM_X509_INFO_read = (STACK_OF(X509_INFO) *(*)(FILE*, STACK_OF(X509_INFO)*, pem_password_cb*, void *)) GET_CRYPTOLIB_SYMBOL("PEM_X509_INFO_read"); - K_ASN1_d2i_fp = (char *(*)(char *(*)(),char *(*)(),FILE*,unsigned char**)) GET_CRYPTOLIB_SYMBOL("ASN1_d2i_fp"); - K_X509_new = (X509 *(*)()) GET_CRYPTOLIB_SYMBOL("X509_new"); - K_X509_PURPOSE_get_count = (int (*)()) GET_CRYPTOLIB_SYMBOL("X509_PURPOSE_get_count"); - K_X509_PURPOSE_get_id = (int (*)(X509_PURPOSE *)) GET_CRYPTOLIB_SYMBOL("X509_PURPOSE_get_id"); - K_X509_check_purpose = (int (*)(X509*,int,int)) GET_CRYPTOLIB_SYMBOL("X509_check_purpose"); - K_X509_PURPOSE_get0 = (X509_PURPOSE *(*)(int)) GET_CRYPTOLIB_SYMBOL("X509_PURPOSE_get0"); - K_EVP_PKEY_assign = (int (*)(EVP_PKEY*, int, char*)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_assign"); - K_X509_REQ_set_pubkey = (int (*)(X509_REQ*, EVP_PKEY*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_set_pubkey"); - K_RSA_get0_key = (void (*)(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)) GET_CRYPTOLIB_SYMBOL("RSA_get0_key"); - K_RSA_generate_key = (RSA* (*)(int, unsigned long, void (*)(int,int,void *), void *)) GET_CRYPTOLIB_SYMBOL("RSA_generate_key"); - K_DSA_get0_pqg = (void (*)(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)) GET_CRYPTOLIB_SYMBOL("DSA_get0_pqg"); - K_DSA_get0_key = (void (*)(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)) GET_CRYPTOLIB_SYMBOL("DSA_get0_key"); - K_i2d_X509_REQ_fp = (int (*)(FILE *, X509_REQ *)) GET_CRYPTOLIB_SYMBOL("i2d_X509_REQ_fp"); - K_ERR_clear_error = (void (*)()) GET_CRYPTOLIB_SYMBOL("ERR_clear_error"); - K_ERR_get_error = (unsigned long (*)()) GET_CRYPTOLIB_SYMBOL("ERR_get_error"); - K_ERR_print_errors_fp = (void (*)(FILE*)) GET_CRYPTOLIB_SYMBOL("ERR_print_errors_fp"); - K_X509_get1_email = (STACK *(*)(X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_get1_email"); - K_X509_email_free = (void (*)(STACK *sk)) GET_CRYPTOLIB_SYMBOL("X509_email_free"); - K_EVP_des_ede3_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_des_ede3_cbc"); - K_EVP_des_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_des_cbc"); - K_EVP_rc2_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_rc2_cbc"); - K_EVP_rc2_64_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_rc2_64_cbc"); - K_EVP_rc2_40_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_rc2_40_cbc"); - K_i2d_PrivateKey_fp = (int (*)(FILE*,EVP_PKEY*)) GET_CRYPTOLIB_SYMBOL("i2d_PrivateKey_fp"); - K_i2d_PKCS8PrivateKey_fp = (int (*)(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS8PrivateKey_fp"); - K_RSA_free = (void (*)(RSA*)) GET_CRYPTOLIB_SYMBOL("RSA_free"); - K_EVP_bf_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_bf_cbc"); - K_X509_REQ_sign = (int (*)(X509_REQ*, EVP_PKEY*, const EVP_MD*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_sign"); - K_X509_NAME_add_entry_by_txt = (int (*)(X509_NAME*, char*, int, unsigned char*, int, int, int)) GET_CRYPTOLIB_SYMBOL("X509_NAME_add_entry_by_txt"); - K_X509_NAME_new = (X509_NAME *(*)()) GET_CRYPTOLIB_SYMBOL("X509_NAME_new"); - K_X509_REQ_set_subject_name = (int (*)(X509_REQ*,X509_NAME*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_set_subject_name"); - K_ASN1_STRING_data = (unsigned char *(*)(ASN1_STRING*)) GET_CRYPTOLIB_SYMBOL("ASN1_STRING_data"); - K_ASN1_STRING_length = (int (*)(ASN1_STRING*)) GET_CRYPTOLIB_SYMBOL("ASN1_STRING_length"); - K_X509_CRL_get0_lastUpdate = (const ASN1_TIME* (*)(const X509_CRL *crl)) GET_CRYPTOLIB_SYMBOL("X509_CRL_get0_lastUpdate"); - K_X509_CRL_get0_nextUpdate = (const ASN1_TIME* (*)(const X509_CRL *crl)) GET_CRYPTOLIB_SYMBOL("X509_CRL_get0_nextUpdate"); - K_X509_STORE_CTX_get_current_cert = (X509* (*)(X509_STORE_CTX *ctx)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_get_current_cert"); - K_X509_STORE_CTX_get_error = (int (*)(X509_STORE_CTX *ctx)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_get_error"); - K_X509_STORE_CTX_get_error_depth = (int (*)(X509_STORE_CTX *ctx)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_get_error_depth"); - K_X509_STORE_CTX_set_error = (void (*)(X509_STORE_CTX *ctx, int s)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set_error"); - K_X509_STORE_set_verify_cb = (void (*)(X509_STORE *ctx, - X509_STORE_CTX_verify_cb verify_cb)) GET_CRYPTOLIB_SYMBOL("X509_STORE_set_verify_cb"); - K_X509_STORE_get0_objects = (STACK_OF(X509_OBJECT)* (*)(X509_STORE *v)) GET_CRYPTOLIB_SYMBOL("X509_STORE_get0_objects"); - K_X509_OBJECT_get_type = (X509_LOOKUP_TYPE (*)(const X509_OBJECT *a)) GET_CRYPTOLIB_SYMBOL("X509_OBJECT_get_type"); - K_X509_OBJECT_get0_X509 = (X509* (*)(const X509_OBJECT *a)) GET_CRYPTOLIB_SYMBOL("X509_OBJECT_get0_X509"); - K_X509_getm_notAfter = (ASN1_TIME* (*)(const X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_getm_notAfter"); - K_X509_getm_notBefore = (ASN1_TIME* (*)(const X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_getm_notBefore"); -#endif - } - -#ifdef __OpenBSD__ - { - TQString libname = findMostRecentLib("/usr/lib", "ssl"); - if (!libname.isNull()) - _sslLib = ll->globalLibrary(libname.latin1()); - } -#else - for (TQStringList::Iterator it = libpaths.begin(); - it != libpaths.end(); - ++it) { - for (TQStringList::Iterator shit = libnamess.begin(); - shit != libnamess.end(); - ++shit) { - TQString alib = *it; - if (!alib.isEmpty() && !alib.endsWith("/")) - alib += "/"; - alib += *shit; - TQString tmpStr(alib.latin1()); - tmpStr.replace(TQRegExp("\\(.*\\)"), ""); - if (!access(tmpStr.latin1(), R_OK)) - _sslLib = ll->globalLibrary(alib.latin1()); - if (_sslLib) break; - } - if (_sslLib) break; - } -#endif - - if (_sslLib) { -#ifdef KSSL_HAVE_SSL - // stand back from your monitor and look at this. it's fun! :) - K_SSL_connect = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_connect"); - K_SSL_accept = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_accept"); - K_SSL_read = (int (*)(SSL *, void *, int)) GET_SSLLIB_SYMBOL("SSL_read"); - K_SSL_write = (int (*)(SSL *, const void *, int)) - GET_SSLLIB_SYMBOL("SSL_write"); - K_SSL_new = (SSL* (*)(SSL_CTX *)) GET_SSLLIB_SYMBOL("SSL_new"); - K_SSL_free = (void (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_free"); - K_SSL_shutdown = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_shutdown"); - K_SSL_CTX_new = (SSL_CTX* (*)(SSL_METHOD*)) GET_SSLLIB_SYMBOL("SSL_CTX_new"); - K_SSL_CTX_free = (void (*)(SSL_CTX*)) GET_SSLLIB_SYMBOL("SSL_CTX_free"); - K_SSL_set_fd = (int (*)(SSL *, int)) GET_SSLLIB_SYMBOL("SSL_set_fd"); - K_SSL_pending = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_pending"); - K_SSL_CTX_set_cipher_list = (int (*)(SSL_CTX *, const char *)) - GET_SSLLIB_SYMBOL("SSL_CTX_set_cipher_list"); - K_SSL_CTX_set_verify = (void (*)(SSL_CTX*, int, int (*)(int, X509_STORE_CTX*))) GET_SSLLIB_SYMBOL("SSL_CTX_set_verify"); - K_SSL_use_certificate = (int (*)(SSL*, X509*)) - GET_SSLLIB_SYMBOL("SSL_CTX_use_certificate"); - K_SSL_get_current_cipher = (SSL_CIPHER *(*)(SSL *)) - GET_SSLLIB_SYMBOL("SSL_get_current_cipher"); - K_SSL_set_options = (long (*)(SSL *ssl, long options)) GET_SSLLIB_SYMBOL("SSL_set_options"); - K_SSL_session_reused = (int (*)(SSL *ssl)) GET_SSLLIB_SYMBOL("SSL_session_reused"); - K_SSL_ctrl = (long (*)(SSL * ,int, long, void *)) - GET_SSLLIB_SYMBOL("SSL_ctrl"); - K_TLSv1_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("TLSv1_client_method"); - K_SSLv2_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("SSLv2_client_method"); - K_SSLv3_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("SSLv3_client_method"); - K_TLS_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("TLS_client_method"); - if (!K_TLS_client_method) K_TLS_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("SSLv23_client_method"); - K_SSL_get_peer_certificate = (X509 *(*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_get_peer_certificate"); - K_SSL_CIPHER_get_bits = (int (*)(SSL_CIPHER *,int *)) GET_SSLLIB_SYMBOL("SSL_CIPHER_get_bits"); - K_SSL_CIPHER_get_version = (char * (*)(SSL_CIPHER *)) GET_SSLLIB_SYMBOL("SSL_CIPHER_get_version"); - K_SSL_CIPHER_get_name = (const char * (*)(SSL_CIPHER *)) GET_SSLLIB_SYMBOL("SSL_CIPHER_get_name"); - K_SSL_CIPHER_description = (char * (*)(SSL_CIPHER *, char *, int)) GET_SSLLIB_SYMBOL("SSL_CIPHER_description"); - K_SSL_CTX_use_PrivateKey = (int (*)(SSL_CTX*, EVP_PKEY*)) GET_SSLLIB_SYMBOL("SSL_CTX_use_PrivateKey"); - K_SSL_CTX_use_certificate = (int (*)(SSL_CTX*, X509*)) GET_SSLLIB_SYMBOL("SSL_CTX_use_certificate"); - K_SSL_get_error = (int (*)(SSL*, int)) GET_SSLLIB_SYMBOL("SSL_get_error"); - K_SSL_get_peer_cert_chain = (STACK_OF(X509)* (*)(SSL*)) GET_SSLLIB_SYMBOL("SSL_get_peer_cert_chain"); - K_SSL_load_client_CA_file = (STACK_OF(X509_NAME)* (*)(const char *)) GET_SSLLIB_SYMBOL("SSL_load_client_CA_file"); - K_SSL_peek = (int (*)(SSL*,void*,int)) GET_SSLLIB_SYMBOL("SSL_peek"); - K_SSL_get1_session = (SSL_SESSION* (*)(SSL*)) GET_SSLLIB_SYMBOL("SSL_get1_session"); - K_SSL_SESSION_free = (void (*)(SSL_SESSION*)) GET_SSLLIB_SYMBOL("SSL_SESSION_free"); - K_SSL_set_session = (int (*)(SSL*,SSL_SESSION*)) GET_SSLLIB_SYMBOL("SSL_set_session"); - K_d2i_SSL_SESSION = (SSL_SESSION* (*)(SSL_SESSION**,unsigned char**, long)) GET_SSLLIB_SYMBOL("d2i_SSL_SESSION"); - K_i2d_SSL_SESSION = (int (*)(SSL_SESSION*,unsigned char**)) GET_SSLLIB_SYMBOL("i2d_SSL_SESSION"); - K_SSL_get_ciphers = (STACK_OF(SSL_CIPHER) *(*)(const SSL*)) GET_SSLLIB_SYMBOL("SSL_get_ciphers"); -#endif - - - // Initialize the library (once only!) - void *x; - x = GET_SSLLIB_SYMBOL("OPENSSL_init_ssl"); - if (x) { - // OpenSSL >= 1.1 - if (_cryptoLib) { - ((int (*)(unsigned long long, void*))x)(0, NULL); - x = GET_CRYPTOLIB_SYMBOL("OPENSSL_init_crypto"); - if (x) ((int (*)(unsigned long long, void*))x)(OPENSSL_INIT_ADD_ALL_CIPHERS - | OPENSSL_INIT_ADD_ALL_DIGESTS - | OPENSSL_INIT_LOAD_CONFIG, - NULL); - } - } - else { - // OpenSSL < 1.1 - x = GET_SSLLIB_SYMBOL("SSL_library_init"); - if (_cryptoLib) { - if (x) ((int (*)())x)(); - x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_algorithms"); - if (!x) - x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_algorithms"); - if (x) { - ((void (*)())x)(); - } else { - x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_algorithms_conf"); - if (!x) - x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_algorithms_conf"); - if (x) { - ((void (*)())x)(); - } else { - x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_algorithms_noconf"); - if (!x) - x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_algorithms_noconf"); - if (x) - ((void (*)())x)(); - } - } - x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_ciphers"); - if (!x) - x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_ciphers"); - if (x) ((void (*)())x)(); - x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_digests"); - if (!x) - x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_digests"); - if (x) ((void (*)())x)(); - } - } - } - -} - - -KOpenSSLProxy* KOpenSSLProxy::_me = 0L; -static KStaticDeleter medProxy; - - - -KOpenSSLProxy::~KOpenSSLProxy() { - if (_sslLib) { - _sslLib->unload(); - } - if (_cryptoLib) { - _cryptoLib->unload(); - } - medProxy.setObject(0); -} - - -// FIXME: we should check "ok" and allow this to init the lib if !ok. - -KOpenSSLProxy *KOpenSSLProxy::self() { -#ifdef KSSL_HAVE_SSL - if (!_me) { - _me = medProxy.setObject(_me, new KOpenSSLProxy); - } -#endif - return _me; -} - - - - - - - -#ifdef KSSL_HAVE_SSL - - - -int KOpenSSLProxy::SSL_connect(SSL *ssl) { - if (K_SSL_connect) return (K_SSL_connect)(ssl); - kdWarning() << "SSL_connect not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_accept(SSL *ssl) { - if (K_SSL_accept) return (K_SSL_accept)(ssl); - kdWarning() << "SSL_accept not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_read(SSL *ssl, void *buf, int num) { - if (K_SSL_read) return (K_SSL_read)(ssl, buf, num); - kdWarning() << "SSL_read not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_write(SSL *ssl, const void *buf, int num) { - if (K_SSL_write) return (K_SSL_write)(ssl, buf, num); - kdWarning() << "SSL_write not defined!" << endl; - return -1; -} - - -SSL *KOpenSSLProxy::SSL_new(SSL_CTX *ctx) { - if (K_SSL_new) return (K_SSL_new)(ctx); - kdWarning() << "SSL_new not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::SSL_free(SSL *ssl) { - if (K_SSL_free) (K_SSL_free)(ssl); - else kdWarning() << "SSL_free not defined!" << endl; -} - - -int KOpenSSLProxy::SSL_shutdown(SSL *ssl) { - if (K_SSL_shutdown) return (K_SSL_shutdown)(ssl); - kdWarning() << "SSL_shutdown not defined!" << endl; - return -1; -} - - -SSL_CTX *KOpenSSLProxy::SSL_CTX_new(SSL_METHOD *method) { - if (K_SSL_CTX_new) return (K_SSL_CTX_new)(method); - kdWarning() << "SSL_CTX_new not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::SSL_CTX_free(SSL_CTX *ctx) { - if (K_SSL_CTX_free) (K_SSL_CTX_free)(ctx); - else kdWarning() << "SSL_CTX_free not defined!" << endl; -} - - -int KOpenSSLProxy::SSL_set_fd(SSL *ssl, int fd) { - if (K_SSL_set_fd) return (K_SSL_set_fd)(ssl, fd); - kdWarning() << "SSL_sed_fd not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_pending(SSL *ssl) { - if (K_SSL_pending) return (K_SSL_pending)(ssl); - kdWarning() << "SSL_pending not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { - if (K_SSL_CTX_set_cipher_list) return (K_SSL_CTX_set_cipher_list)(ctx, str); - kdWarning() << "SSL_CTX_set_cipher_list not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::SSL_CTX_set_verify(SSL_CTX *ctx, int mode, - int (*verify_callback)(int, X509_STORE_CTX *)) { - if (K_SSL_CTX_set_verify) (K_SSL_CTX_set_verify)(ctx, mode, verify_callback); - else kdWarning() << "SSL_CTX_set_verify not defined!" << endl; -} - - -int KOpenSSLProxy::SSL_use_certificate(SSL *ssl, X509 *x) { - if (K_SSL_use_certificate) return (K_SSL_use_certificate)(ssl, x); - kdWarning() << "SSL_use_certificate not defined!" << endl; - return -1; -} - - -SSL_CIPHER *KOpenSSLProxy::SSL_get_current_cipher(SSL *ssl) { - if (K_SSL_get_current_cipher) return (K_SSL_get_current_cipher)(ssl); - kdWarning() << "SSL_get_current_cipher not defined!" << endl; - return 0L; -} - - -long KOpenSSLProxy::_SSL_set_options(SSL *ssl, long options) { - if (K_SSL_set_options) return (K_SSL_set_options)(ssl, options); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return this->SSL_set_options(ssl, options); -#endif - kdWarning() << "SSL_set_options not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::_SSL_session_reused(SSL *ssl) { - if (K_SSL_session_reused) return (K_SSL_session_reused)(ssl); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return this->SSL_session_reused(ssl); -#endif - kdWarning() << "SSL_session_reused not defined!" << endl; - return -1; -} - - -long KOpenSSLProxy::SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg) { - if (K_SSL_ctrl) return (K_SSL_ctrl)(ssl, cmd, larg, parg); - kdWarning() << "SSL_ctrl not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::RAND_egd(const char *path) { - if (K_RAND_egd) return (K_RAND_egd)(path); - kdWarning() << "RAND_egd not defined!" << endl; - return -1; -} - - -SSL_METHOD *KOpenSSLProxy::TLSv1_client_method() { - if (K_TLSv1_client_method) return (K_TLSv1_client_method)(); - kdWarning() << "TLSv1_client_method not defined!" << endl; - return 0L; -} - - -SSL_METHOD *KOpenSSLProxy::SSLv2_client_method() { - if (K_SSLv2_client_method) return (K_SSLv2_client_method)(); - kdWarning() << "SSLv2_client_method not defined!" << endl; - return 0L; -} - - -SSL_METHOD *KOpenSSLProxy::SSLv3_client_method() { - if (K_SSLv3_client_method) return (K_SSLv3_client_method)(); - kdWarning() << "SSLv3_client_method not defined!" << endl; - return 0L; -} - - -SSL_METHOD *KOpenSSLProxy::TLS_client_method() { - if (K_TLS_client_method) return (K_TLS_client_method)(); - kdWarning() << "TLS_client_method not defined!" << endl; - return 0L; -} - - -X509 *KOpenSSLProxy::SSL_get_peer_certificate(SSL *s) { - if (K_SSL_get_peer_certificate) return (K_SSL_get_peer_certificate)(s); - kdWarning() << "SSL_get_peer_certificate not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits) { - if (K_SSL_CIPHER_get_bits) return (K_SSL_CIPHER_get_bits)(c, alg_bits); - kdWarning() << "SSL_CIPHER_get_bits not defined!" << endl; - return -1; -} - - -char * KOpenSSLProxy::SSL_CIPHER_get_version(SSL_CIPHER *c) { - if (K_SSL_CIPHER_get_version) return (K_SSL_CIPHER_get_version)(c); - kdWarning() << "SSL_CIPHER_get_version not defined!" << endl; - return 0L; -} - - -const char * KOpenSSLProxy::SSL_CIPHER_get_name(SSL_CIPHER *c) { - if (K_SSL_CIPHER_get_name) return (K_SSL_CIPHER_get_name)(c); - kdWarning() << "SSL_CIPHER_get_name not defined!" << endl; - return 0L; -} - - -char * KOpenSSLProxy::SSL_CIPHER_description(SSL_CIPHER *c,char *buf,int size) { - if (K_SSL_CIPHER_description) return (K_SSL_CIPHER_description)(c,buf,size); - kdWarning() << "SSL_CIPHER_description not defined!" << endl; - return 0L; -} - - -X509 * KOpenSSLProxy::d2i_X509(X509 **a,unsigned char **pp,long length) { - if (K_d2i_X509) return (K_d2i_X509)(a,pp,length); - kdWarning() << "d2i_X509 not defined!" << endl; - return 0L; -} - - -X509_CRL * KOpenSSLProxy::d2i_X509_CRL(X509_CRL **a,unsigned char **pp,long length) { - if (K_d2i_X509_CRL) return (K_d2i_X509_CRL)(a,pp,length); - kdWarning() << "d2i_X509_CRL not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::i2d_X509(X509 *a,unsigned char **pp) { - if (K_i2d_X509) return (K_i2d_X509)(a,pp); - kdWarning() << "i2d_X509 not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_cmp(X509 *a, X509 *b) { - if (K_X509_cmp) return (K_X509_cmp)(a,b); - kdWarning() << "X509_cmp not defined!" << endl; - return 0; -} - - -int KOpenSSLProxy::X509_subject_name_cmp(const X509 *a, const X509 *b) { - if (K_X509_subject_name_cmp) return (K_X509_subject_name_cmp)(a, b); - kdWarning() << "X509_subject_name_cmp not defined!" << endl; - return 0; -} - - -X509_STORE *KOpenSSLProxy::X509_STORE_new(void) { - if (K_X509_STORE_new) return (K_X509_STORE_new)(); - kdWarning() << "X509_STORE_new not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::X509_STORE_free(X509_STORE *v) { - if (K_X509_STORE_free) (K_X509_STORE_free)(v); - else kdWarning() << "X509_STORE_free not defined!" << endl; -} - - -X509_STORE_CTX *KOpenSSLProxy::X509_STORE_CTX_new(void) { - if (K_X509_STORE_CTX_new) return (K_X509_STORE_CTX_new)(); - kdWarning() << "X509_STORE_CTX_new not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::X509_STORE_CTX_free(X509_STORE_CTX *ctx) { - if (K_X509_STORE_CTX_free) (K_X509_STORE_CTX_free)(ctx); - else kdWarning() << "X509_STORE_CTX_free not defined!" << endl; -} - - -int KOpenSSLProxy::X509_verify_cert(X509_STORE_CTX *ctx) { - if (K_X509_verify_cert) return (K_X509_verify_cert)(ctx); - kdWarning() << "X509_verify_cert not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::X509_free(X509 *a) { - if (K_X509_free) (K_X509_free)(a); - else kdWarning() << "X509_free not defined!" << endl; -} - - -void KOpenSSLProxy::X509_CRL_free(X509_CRL *a) { - if (K_X509_CRL_free) (K_X509_CRL_free)(a); - else kdWarning() << "X509_CRL_free not defined!" << endl; -} - - -char *KOpenSSLProxy::X509_NAME_oneline(X509_NAME *a,char *buf,int size) { - if (K_X509_NAME_oneline) return (K_X509_NAME_oneline)(a,buf,size); - kdWarning() << "X509_NAME_online not defined!" << endl; - return 0L; -} - - -X509_NAME *KOpenSSLProxy::X509_get_subject_name(X509 *a) { - if (K_X509_get_subject_name) return (K_X509_get_subject_name)(a); - kdWarning() << "X509_get_subject not defined!" << endl; - return 0L; -} - - -X509_NAME *KOpenSSLProxy::X509_get_issuer_name(X509 *a) { - if (K_X509_get_issuer_name) return (K_X509_get_issuer_name)(a); - kdWarning() << "X509_get_issuer not defined!" << endl; - return 0L; -} - - -X509_LOOKUP *KOpenSSLProxy::X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { - if (K_X509_STORE_add_lookup) return (K_X509_STORE_add_lookup)(v,m); - kdWarning() << "X509_STORE_add_lookup not defined!" << endl; - return 0L; -} - - -X509_LOOKUP_METHOD *KOpenSSLProxy::X509_LOOKUP_file(void) { - if (K_X509_LOOKUP_file) return (K_X509_LOOKUP_file)(); - kdWarning() << "X509_LOOKUP_file not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::X509_LOOKUP_free(X509_LOOKUP *x) { - if (K_X509_LOOKUP_free) (K_X509_LOOKUP_free)(x); - else kdWarning() << "X509_LOOKUP_free not defined!" << endl; -} - - -int KOpenSSLProxy::X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) { - if (K_X509_LOOKUP_ctrl) return (K_X509_LOOKUP_ctrl)(ctx,cmd,argc,argl,ret); - kdWarning() << "X509_LOOKUP_ctrl not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { - if (K_X509_STORE_CTX_init) (K_X509_STORE_CTX_init)(ctx,store,x509,chain); - else kdWarning() << "X509_STORE_CTX_init not defined!" << endl; -} - - -void KOpenSSLProxy::CRYPTO_free(void *x) { - if (K_CRYPTO_free) (K_CRYPTO_free)(x); - else kdWarning() << "CRYPTO_free not defined!" << endl; -} - - -X509 *KOpenSSLProxy::X509_dup(X509 *x509) { - if (K_X509_dup) return (K_X509_dup)(x509); - kdWarning() << "X509_dup not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::X509_get0_signature(const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg, const X509 *x) { - if (K_X509_get0_signature) { - (X509_get0_signature)(psig, palg, x); - return; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (!x) return; - if (psig) *psig = x->signature; - if (palg) *palg = x->sig_alg; - return; -#endif - kdWarning() << "X509_get0_signature not defined!" << endl; -} - - -BIO *KOpenSSLProxy::BIO_new(BIO_METHOD *type) { - if (K_BIO_new) return (K_BIO_new)(type); - kdWarning() << "BIO_new not defined!" << endl; - return 0L; -} - - -BIO_METHOD *KOpenSSLProxy::BIO_s_mem(void) { - if (K_BIO_s_mem) return (K_BIO_s_mem)(); - kdWarning() << "BIO_s_mem not defined!" << endl; - return 0L; -} - - -BIO *KOpenSSLProxy::BIO_new_fp(FILE *stream, int close_flag) { - if (K_BIO_new_fp) return (K_BIO_new_fp)(stream, close_flag); - kdWarning() << "BIO_new_fp not defined!" << endl; - return 0L; -} - - -BIO *KOpenSSLProxy::BIO_new_mem_buf(void *buf, int len) { - if (K_BIO_new_mem_buf) return (K_BIO_new_mem_buf)(buf,len); - kdWarning() << "BIO_new_mem_buf not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::BIO_free(BIO *a) { - if (K_BIO_free) return (K_BIO_free)(a); - kdWarning() << "BIO_free not defined!" << endl; - return -1; -} - - -long KOpenSSLProxy::BIO_ctrl(BIO *bp,int cmd,long larg,void *parg) { - if (K_BIO_ctrl) return (K_BIO_ctrl)(bp,cmd,larg,parg); - kdWarning() << "BIO_ctrl not defined!" << endl; - return 0; // failure return for BIO_ctrl is quite individual, maybe we should abort() instead -} - - -int KOpenSSLProxy::BIO_write(BIO *b, const void *data, int len) { - if (K_BIO_write) return (K_BIO_write)(b, data, len); - kdWarning() << "BIO_write not defined!" << endl; - return -1; -} - - -void *KOpenSSLProxy::BIO_get_data(BIO *a) { - if (K_BIO_get_data) return (K_BIO_get_data)(a); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return a->ptr; -#endif - kdWarning() << "BIO_get_data not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::PEM_write_bio_X509(BIO *bp, X509 *x) { - if (K_PEM_ASN1_write_bio) return (K_PEM_ASN1_write_bio) ((int (*)())K_i2d_X509, PEM_STRING_X509, bp, (char *)x, 0L, 0L, 0, 0L, 0L); - kdWarning() << "PEM_write_bio_X509 not defined!" << endl; - return -1; -} - -#if OPENSSL_VERSION_NUMBER >= 0x10000000L -int KOpenSSLProxy::ASN1_i2d_fp(FILE *out,unsigned char *x) { - if (K_ASN1_item_i2d_fp && K_NETSCAPE_X509_it) - return (K_ASN1_item_i2d_fp)(K_NETSCAPE_X509_it, out, x); - kdWarning() << "ANS1_i2d_fp not defined!" << endl; - return -1; -} -#else -ASN1_METHOD *KOpenSSLProxy::X509_asn1_meth(void) { - if (K_X509_asn1_meth) return (K_X509_asn1_meth)(); - kdWarning() << "X509_ans1_meth not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::ASN1_i2d_fp(FILE *out,unsigned char *x) { - if (K_ASN1_i2d_fp && K_i2d_ASN1_HEADER) - return (K_ASN1_i2d_fp)((int (*)())K_i2d_ASN1_HEADER, out, x); - kdWarning() << "ANS1_i2d_fp not defined!" << endl; - return -1; -} -#endif - -int KOpenSSLProxy::X509_print(FILE *fp, X509 *x) { - if (K_X509_print_fp) return (K_X509_print_fp)(fp, x); - kdWarning() << "X509_print not defined!" << endl; - return -1; -} - - -PKCS12 *KOpenSSLProxy::d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { - if (K_d2i_PKCS12_fp) return (K_d2i_PKCS12_fp)(fp, p12); - kdWarning() << "d2i_PKCS12_fp not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass) { - if (K_PKCS12_newpass) return (K_PKCS12_newpass)(p12, oldpass, newpass); - kdWarning() << "PKCS12_newpass not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::i2d_PKCS12(PKCS12 *p12, unsigned char **p) { - if (K_i2d_PKCS12) return (K_i2d_PKCS12)(p12, p); - kdWarning() << "i2d_PKCS12 not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::i2d_PKCS12_fp(FILE *fp, PKCS12 *p12) { - if (K_i2d_PKCS12_fp) return (K_i2d_PKCS12_fp)(fp, p12); - kdWarning() << "i2d_PKCS12_fp not defined!" << endl; - return -1; -} - - -PKCS12 *KOpenSSLProxy::PKCS12_new(void) { - if (K_PKCS12_new) return (K_PKCS12_new)(); - kdWarning() << "PKCS12_new not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::PKCS12_free(PKCS12 *a) { - if (K_PKCS12_free) (K_PKCS12_free)(a); - else kdWarning() << "PKCS12_free not defined!" << endl; -} - - -int KOpenSSLProxy::PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, - X509 **cert, STACK_OF(X509) **ca) { - if (K_PKCS12_parse) return (K_PKCS12_parse) (p12, pass, pkey, cert, ca); - kdWarning() << "PKCS12_parse not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::EVP_PKEY_free(EVP_PKEY *x) { - if (K_EVP_PKEY_free) (K_EVP_PKEY_free)(x); - else kdWarning() << "EVP_PKEY_free not defined!" << endl; -} - - -EVP_PKEY* KOpenSSLProxy::EVP_PKEY_new() { - if (K_EVP_PKEY_new) return (K_EVP_PKEY_new)(); - kdWarning() << "EVP_PKEY_new not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::EVP_PKEY_base_id(const EVP_PKEY *pkey) { - if (K_EVP_PKEY_base_id) return (K_EVP_PKEY_base_id)(pkey); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return pkey->type; -#endif - kdWarning() << "EVP_PKEY_base_id not defined!" << endl; - return -1; -} - - -RSA* KOpenSSLProxy::EVP_PKEY_get0_RSA(EVP_PKEY *pkey) { - if (K_EVP_PKEY_get0_RSA) return (K_EVP_PKEY_get0_RSA)(pkey); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return pkey->pkey.rsa; -#endif - kdWarning() << "EVP_PKEY_get0_RSA not defined!" << endl; - return 0L; -} - - -DSA* KOpenSSLProxy::EVP_PKEY_get0_DSA(EVP_PKEY *pkey) { - if (K_EVP_PKEY_get0_DSA) return (K_EVP_PKEY_get0_DSA)(pkey); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return pkey->pkey.dsa; -#endif - kdWarning() << "EVP_PKEY_get0_DSA not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::X509_REQ_free(X509_REQ *x) { - if (K_X509_REQ_free) (K_X509_REQ_free)(x); - else kdWarning() << "X509_REQ_free not defined!" << endl; -} - - -X509_REQ* KOpenSSLProxy::X509_REQ_new() { - if (K_X509_REQ_new) return (K_X509_REQ_new)(); - kdWarning() << "X509_REQ_new not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { - if (K_SSL_CTX_use_PrivateKey) return (K_SSL_CTX_use_PrivateKey)(ctx,pkey); - kdWarning() << "SSL_CTX_use_PrivateKey not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { - if (K_SSL_CTX_use_certificate) return (K_SSL_CTX_use_certificate)(ctx,x); - kdWarning() << "SSL_CTX_use_certificate not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::SSL_get_error(SSL *ssl, int rc) { - if (K_SSL_get_error) return (K_SSL_get_error)(ssl,rc); - kdWarning() << "SSL_get_error not defined!" << endl; - return -1; -} - - -STACK_OF(X509) *KOpenSSLProxy::SSL_get_peer_cert_chain(SSL *s) { - if (K_SSL_get_peer_cert_chain) return (K_SSL_get_peer_cert_chain)(s); - kdWarning() << "SSL_get_peer_cert_chain not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::OPENSSL_sk_free(STACK *s) { - if (K_sk_free) (K_sk_free)(s); - else kdWarning() << "OPENSSL_sk_free not defined!" << endl; -} - - -int KOpenSSLProxy::OPENSSL_sk_num(STACK *s) { - if (K_sk_num) return (K_sk_num)(s); - kdWarning() << "OPENSSL_sk_num not defined!" << endl; - return -1; -} - - -char *KOpenSSLProxy::OPENSSL_sk_pop(STACK *s) { - if (K_sk_pop) return (K_sk_pop)(s); - kdWarning() << "OPENSSL_sk_pop not defined!" << endl; - return 0L; -} - - -char *KOpenSSLProxy::OPENSSL_sk_value(STACK *s, int n) { - if (K_sk_value) return (K_sk_value)(s, n); - kdWarning() << "OPENSSL_sk_value not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *v, STACK_OF(X509)* x) { - if (K_X509_STORE_CTX_set0_untrusted) (K_X509_STORE_CTX_set0_untrusted)(v,x); - else kdWarning() << "X509_STORE_CTX_set0_untrusted not defined!" << endl; -} - -void KOpenSSLProxy::X509_STORE_CTX_set_purpose(X509_STORE_CTX *v, int purpose) { - if (K_X509_STORE_CTX_set_purpose) (K_X509_STORE_CTX_set_purpose)(v,purpose); - else kdWarning() << "X509_STORE_CTX_set_purpose not defined!" << endl; -} - - -STACK* KOpenSSLProxy::OPENSSL_sk_dup(const STACK *s) { - if (K_sk_dup) return (K_sk_dup)(s); - kdWarning() << "OPENSSL_sk_dup not defined!" << endl; - return 0L; -} - - -STACK* KOpenSSLProxy::OPENSSL_sk_new(int (*cmp)()) { - if (K_sk_new) return (K_sk_new)(cmp); - kdWarning() << "OPENSSL_sk_new not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::OPENSSL_sk_push(STACK* s, char* d) { - if (K_sk_push) return (K_sk_push)(s,d); - kdWarning() << "OPENSSL_sk_push not defined!" << endl; - return -1; -} - - -char *KOpenSSLProxy::i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint) { - if (K_i2s_ASN1_INTEGER) return (K_i2s_ASN1_INTEGER)(meth, aint); - kdWarning() << "i2s_ANS1_INTEGER not defined!" << endl; - return 0L; -} - - -ASN1_INTEGER *KOpenSSLProxy::X509_get_serialNumber(X509 *x) { - if (K_X509_get_serialNumber) return (K_X509_get_serialNumber)(x); - kdWarning() << "X509_get_serialNumber not defined!" << endl; - return 0L; -} - - -EVP_PKEY *KOpenSSLProxy::X509_get_pubkey(X509 *x) { - if (K_X509_get_pubkey) return (K_X509_get_pubkey)(x); - kdWarning() << "X59_get_pubkey not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) { - if (K_i2d_PublicKey) return (K_i2d_PublicKey)(a,pp); - kdWarning() << "i2d_PublicKey not defined!" << endl; - return 0; -} - - -int KOpenSSLProxy::X509_check_private_key(X509 *x, EVP_PKEY *p) { - if (K_X509_check_private_key) return (K_X509_check_private_key)(x,p); - kdWarning() << "X509_check_private_key not defined!" << endl; - return -1; -} - - -char *KOpenSSLProxy::BN_bn2hex(const BIGNUM *a) { - if (K_BN_bn2hex) return (K_BN_bn2hex)(a); - kdWarning() << "BN_bn2hex not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::X509_digest(const X509 *x,const EVP_MD *t, unsigned char *md, unsigned int *len) { - if (K_X509_digest) return (K_X509_digest)(x, t, md, len); - kdWarning() << "X509_digest not defined!" << endl; - return -1; -} - - -EVP_MD *KOpenSSLProxy::EVP_md5() { - if (K_EVP_md5) return (K_EVP_md5)(); - kdWarning() << "EVP_md5 not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::ASN1_INTEGER_free(ASN1_INTEGER *a) { - if (K_ASN1_INTEGER_free) (K_ASN1_INTEGER_free)(a); - else kdWarning() << "ANS1_INTEGER_free not defined!" << endl; -} - - -int KOpenSSLProxy::OBJ_obj2nid(ASN1_OBJECT *o) { - if (K_OBJ_obj2nid) return (K_OBJ_obj2nid)(o); - kdWarning() << "OBJ_obj2nid not defined!" << endl; - return -1; -} - - -const char * KOpenSSLProxy::OBJ_nid2ln(int n) { - if (K_OBJ_nid2ln) return (K_OBJ_nid2ln)(n); - kdWarning() << "OBJ_nid2ln not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::X509_get_ext_count(X509 *x) { - if (K_X509_get_ext_count) return (K_X509_get_ext_count)(x); - kdWarning() << "X509_get_ext_count not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_get_ext_by_NID(X509 *x, int nid, int lastpos) { - if (K_X509_get_ext_by_NID) return (K_X509_get_ext_by_NID)(x,nid,lastpos); - kdWarning() << "X509_get_ext_by_NID not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos) { - if (K_X509_get_ext_by_OBJ) return (K_X509_get_ext_by_OBJ)(x,obj,lastpos); - kdWarning() << "X509_get_ext_by_OBJ not defined!" << endl; - return -1; -} - - -X509_EXTENSION *KOpenSSLProxy::X509_get_ext(X509 *x, int loc) { - if (K_X509_get_ext) return (K_X509_get_ext)(x,loc); - kdWarning() << "X509_get_ext not defined!" << endl; - return 0L; -} - - -X509_EXTENSION *KOpenSSLProxy::X509_delete_ext(X509 *x, int loc) { - if (K_X509_delete_ext) return (K_X509_delete_ext)(x,loc); - kdWarning() << "X509_delete_ext not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) { - if (K_X509_add_ext) return (K_X509_add_ext)(x,ex,loc); - kdWarning() << "X509_add_ext not defined!" << endl; - return -1; -} - - -void *KOpenSSLProxy::X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) { - if (K_X509_get_ext_d2i) return (K_X509_get_ext_d2i)(x,nid,crit,idx); - kdWarning() << "X509_get_ext_d2i not defined!" << endl; - return 0L; -} - - -char *KOpenSSLProxy::i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5) { - if (K_i2s_ASN1_OCTET_STRING) return (K_i2s_ASN1_OCTET_STRING)(method,ia5); - kdWarning() << "i2s_ANS1_OCTET_STRING not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n) { - if (K_ASN1_BIT_STRING_get_bit) return (K_ASN1_BIT_STRING_get_bit)(a,n); - kdWarning() << "ANS1_BIT_STRING_get_bit not defined!" << endl; - return -1; -} - - -PKCS7 *KOpenSSLProxy::PKCS7_new(void) { - if (K_PKCS7_new) return (K_PKCS7_new)(); - kdWarning() << "PKCS7_new not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::PKCS7_free(PKCS7 *a) { - if (K_PKCS7_free) (K_PKCS7_free)(a); - else kdWarning() << "PKCS7_free not defined!" << endl; -} - - -void KOpenSSLProxy::PKCS7_content_free(PKCS7 *a) { - if (K_PKCS7_content_free) (K_PKCS7_content_free)(a); - else kdWarning() << "PKCS7_content_free not defined!" << endl; -} - - -int KOpenSSLProxy::i2d_PKCS7(PKCS7 *a, unsigned char **pp) { - if (K_i2d_PKCS7) return (K_i2d_PKCS7)(a,pp); - kdWarning() << "i2d_PKCS7 not defined!" << endl; - return -1; -} - - -PKCS7 *KOpenSSLProxy::d2i_PKCS7(PKCS7 **a, unsigned char **pp,long length) { - if (K_d2i_PKCS7) return (K_d2i_PKCS7)(a,pp,length); - kdWarning() << "d2i_PKCS7 not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::i2d_PKCS7_fp(FILE *fp,PKCS7 *p7) { - if (K_i2d_PKCS7_fp) return (K_i2d_PKCS7_fp)(fp,p7); - kdWarning() << "i2d_PKCS7_fd not defined!" << endl; - return -1; -} - - -PKCS7 *KOpenSSLProxy::d2i_PKCS7_fp(FILE *fp,PKCS7 **p7) { - if (K_d2i_PKCS7_fp) return (K_d2i_PKCS7_fp)(fp,p7); - kdWarning() << "d2i_PKCS7_fp not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::i2d_PKCS7_bio(BIO *bp,PKCS7 *p7) { - if (K_i2d_PKCS7_bio) return (K_i2d_PKCS7_bio)(bp, p7); - kdWarning() << "i2d_PKCS7_bio not defined!" << endl; - return -1; -} - - -PKCS7 *KOpenSSLProxy::d2i_PKCS7_bio(BIO *bp,PKCS7 **p7) { - if (K_d2i_PKCS7_bio) return (K_d2i_PKCS7_bio)(bp, p7); - kdWarning() << "d2i_PKCS7_bio not defined!" << endl; - return 0L; -} - - -PKCS7 *KOpenSSLProxy::PKCS7_dup(PKCS7 *p7) { - if (K_PKCS7_dup) return (K_PKCS7_dup)(p7); - kdWarning() << "PKCS7_dup not defined!" << endl; - return 0L; -} - - -PKCS7 *KOpenSSLProxy::PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, - BIO *data, int flags) { - if (K_PKCS7_sign) return (K_PKCS7_sign)(signcert,pkey,certs,data,flags); - kdWarning() << "PKCS7_sign not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::PKCS7_verify(PKCS7* p, STACK_OF(X509)* st, X509_STORE* s, BIO* in, BIO *out, int flags) { - if (K_PKCS7_verify) return (K_PKCS7_verify)(p,st,s,in,out,flags); - kdWarning() << "PKCS7_verify not defined!" << endl; - return 0; -} - - -STACK_OF(X509) *KOpenSSLProxy::PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) { - if (K_PKCS7_get0_signers) return (K_PKCS7_get0_signers)(p7,certs,flags); - kdWarning() << "PKCS7_get0_signers not defined!" << endl; - return 0L; -} - - -PKCS7 *KOpenSSLProxy::PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, - int flags) { - if (K_PKCS7_encrypt) return (K_PKCS7_encrypt)(certs,in,cipher,flags); - kdWarning() << "PKCS7_encrypt not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) { - if (K_PKCS7_decrypt) return (K_PKCS7_decrypt)(p7,pkey,cert,data,flags); - kdWarning() << "PKCS7_decrypt not defined!" << endl; - return 0; -} - - -STACK_OF(X509_NAME) *KOpenSSLProxy::SSL_load_client_CA_file(const char *file) { - if (K_SSL_load_client_CA_file) return (K_SSL_load_client_CA_file)(file); - kdWarning() << "SSL_load_client_CA_file not defined!" << endl; - return 0L; -} - - -STACK_OF(X509_INFO) *KOpenSSLProxy::PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u) { - if (K_PEM_X509_INFO_read) return (K_PEM_X509_INFO_read)(fp,sk,cb,u); - kdWarning() << "PEM_X509_INFO_read not defined!" << endl; - return 0L; -} - - -X509 *KOpenSSLProxy::X509_d2i_fp(FILE *out, X509** buf) { - if (K_ASN1_d2i_fp) return reinterpret_cast((K_ASN1_d2i_fp)(reinterpret_cast(K_X509_new), reinterpret_cast(K_d2i_X509), out, reinterpret_cast(buf))); - kdWarning() << "X509_d2i_fp not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::SSL_peek(SSL *ssl,void *buf,int num) { - if (K_SSL_peek) return (K_SSL_peek)(ssl,buf,num); - kdWarning() << "SSL_peek not defined!" << endl; - return -1; -} - - -const char *KOpenSSLProxy::RAND_file_name(char *buf, size_t num) { - if (K_RAND_file_name) return (K_RAND_file_name)(buf, num); - kdWarning() << "RAND_file_name not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::RAND_load_file(const char *filename, long max_bytes) { - if (K_RAND_load_file) return (K_RAND_load_file)(filename, max_bytes); - kdWarning() << "REND_load_file not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::RAND_write_file(const char *filename) { - if (K_RAND_write_file) return (K_RAND_write_file)(filename); - kdWarning() << "RAND_write_file not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_PURPOSE_get_count() { - if (K_X509_PURPOSE_get_count) return (K_X509_PURPOSE_get_count)(); - kdWarning() << "X509_PURPOSE_get_count not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_PURPOSE_get_id(X509_PURPOSE *p) { - if (K_X509_PURPOSE_get_id) return (K_X509_PURPOSE_get_id)(p); - kdWarning() << "X509_PURPOSE_get_id not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_check_purpose(X509 *x, int id, int ca) { - if (K_X509_check_purpose) return (K_X509_check_purpose)(x, id, ca); - kdWarning() << "X509_check_purpose not defined!" << endl; - return -1; -} - - -X509_PURPOSE *KOpenSSLProxy::X509_PURPOSE_get0(int idx) { - if (K_X509_PURPOSE_get0) return (K_X509_PURPOSE_get0)(idx); - kdWarning() << "X509_PURPOSE_get0 not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key) { - if (K_EVP_PKEY_assign) return (K_EVP_PKEY_assign)(pkey, type, key); - kdWarning() << "EVP_PKEY_assign not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { - if (K_X509_REQ_set_pubkey) return (K_X509_REQ_set_pubkey)(x, pkey); - kdWarning() << "X509_REQ_set_pubkey not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::RSA_get0_key(const RSA *r, - const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { - if (K_RSA_get0_key) { - (K_RSA_get0_key)(r, n, e, d); - return; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (!r) return; - if (n) *n = r->n; - if (e) *e = r->e; - if (d) *d = r->d; - return; -#endif - kdWarning() << "REG_get0_key not defined!" << endl; -} - - -RSA* KOpenSSLProxy::RSA_generate_key(int bits, unsigned long e, void - (*callback)(int,int,void *), void *cb_arg) { - if (K_RSA_generate_key) return (K_RSA_generate_key)(bits, e, callback, cb_arg); - kdWarning() << "RSA_generate_key not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::DSA_get0_pqg(const DSA *d, - const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { - if (K_DSA_get0_pqg) { - (K_DSA_get0_pqg)(d, p, q, g); - return; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (!d) return; - if (p) *p = d->p; - if (q) *q = d->q; - if (g) *g = d->g; - return; -#endif - kdWarning() << "DSA_get0_pqg not defined!" << endl; -} - - -void KOpenSSLProxy::DSA_get0_key(const DSA *d, - const BIGNUM **pub_key, const BIGNUM **priv_key) { - if (K_DSA_get0_key) { - (K_DSA_get0_key)(d, pub_key, priv_key); - return; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (!d) return; - if (pub_key) *pub_key = d->pub_key; - if (priv_key) *priv_key = d->priv_key; - return; -#endif - kdWarning() << "DSA_get0_key not defined!" << endl; -} - - -STACK *KOpenSSLProxy::X509_get1_email(X509 *x) { - if (K_X509_get1_email) return (K_X509_get1_email)(x); - kdWarning() << "X509_get1_email not defined!" << endl; - return 0L; -} - -void KOpenSSLProxy::X509_email_free(STACK *sk) { - if (K_X509_email_free) (K_X509_email_free)(sk); - else kdWarning() << "X509_email_free not defined!" << endl; -} - -EVP_CIPHER *KOpenSSLProxy::EVP_des_ede3_cbc() { - if (K_EVP_des_ede3_cbc) return (K_EVP_des_ede3_cbc)(); - kdWarning() << "EVM_des_ede3_cbc not defined!" << endl; - return 0L; -} - -EVP_CIPHER *KOpenSSLProxy::EVP_des_cbc() { - if (K_EVP_des_cbc) return (K_EVP_des_cbc)(); - kdWarning() << "EVP_des_cbc not defined!" << endl; - return 0L; -} - -EVP_CIPHER *KOpenSSLProxy::EVP_rc2_cbc() { - if (K_EVP_rc2_cbc) return (K_EVP_rc2_cbc)(); - kdWarning() << "EVP_rc2_cbc not defined!" << endl; - return 0L; -} - -EVP_CIPHER *KOpenSSLProxy::EVP_rc2_64_cbc() { - if (K_EVP_rc2_64_cbc) return (K_EVP_rc2_64_cbc)(); - kdWarning() << "EVP_rc2_64_cbc not defined!" << endl; - return 0L; -} - -EVP_CIPHER *KOpenSSLProxy::EVP_rc2_40_cbc() { - if (K_EVP_rc2_40_cbc) return (K_EVP_rc2_40_cbc)(); - kdWarning() << "EVP_rc2_40_cbc not defined!" << endl; - return 0L; -} - -int KOpenSSLProxy::i2d_X509_REQ_fp(FILE *fp, X509_REQ *x) { - if (K_i2d_X509_REQ_fp) return (K_i2d_X509_REQ_fp)(fp,x); - kdWarning() << "i2d_X509_REQ_fp not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::ERR_clear_error() { - if (K_ERR_clear_error) (K_ERR_clear_error)(); - else kdWarning() << "ERR_clear_error not defined!" << endl; -} - - -unsigned long KOpenSSLProxy::ERR_get_error() { - if (K_ERR_get_error) return (K_ERR_get_error)(); - kdWarning() << "ERR_get_error not defined!" << endl; - return 0xffffffff; -} - - -void KOpenSSLProxy::ERR_print_errors_fp(FILE* fp) { - if (K_ERR_print_errors_fp) (K_ERR_print_errors_fp)(fp); - else kdWarning() << "ERR_print_errors_fp not defined!" << endl; -} - - -SSL_SESSION *KOpenSSLProxy::SSL_get1_session(SSL *ssl) { - if (K_SSL_get1_session) return (K_SSL_get1_session)(ssl); - kdWarning() << "SSL_get1_session not defined!" << endl; - return 0L; -} - - -void KOpenSSLProxy::SSL_SESSION_free(SSL_SESSION *session) { - if (K_SSL_SESSION_free) (K_SSL_SESSION_free)(session); - else kdWarning() << "SSL_SESSION_free not defined!" << endl; -} - - -int KOpenSSLProxy::SSL_set_session(SSL *ssl, SSL_SESSION *session) { - if (K_SSL_set_session) return (K_SSL_set_session)(ssl, session); - kdWarning() << "SSL_set_session not defined!" << endl; - return -1; -} - - -SSL_SESSION *KOpenSSLProxy::d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, long length) { - if (K_d2i_SSL_SESSION) return (K_d2i_SSL_SESSION)(a, pp, length); - kdWarning() << "d2i_SSL_SESSION not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) { - if (K_i2d_SSL_SESSION) return (K_i2d_SSL_SESSION)(in, pp); - kdWarning() << "i2d_SSL_SESSION not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *p) { - if (K_i2d_PrivateKey_fp) return (K_i2d_PrivateKey_fp)(fp, p); - kdWarning() << "i2d_PrivateKey not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *p, const EVP_CIPHER *c, char *k, int klen, pem_password_cb *cb, void *u) { - if (K_i2d_PKCS8PrivateKey_fp) return (K_i2d_PKCS8PrivateKey_fp)(fp, p, c, k, klen, cb, u); - kdWarning() << "i2d_PKCS8PrivateKey_fp not defined!" << endl; - return -1; -} - - -void KOpenSSLProxy::RSA_free(RSA *rsa) { - if (K_RSA_free) (K_RSA_free)(rsa); - else kdWarning() << "RSA_free not defined!" << endl; -} - - -EVP_CIPHER *KOpenSSLProxy::EVP_bf_cbc() { - if (K_EVP_bf_cbc) return (K_EVP_bf_cbc)(); - kdWarning() << "EVP_bf_cbc not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { - if (K_X509_REQ_sign) return (K_X509_REQ_sign)(x, pkey, md); - kdWarning() << "X509_REQ_sign not defined!" << endl; - return -1; -} - - -int KOpenSSLProxy::X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, - int type, unsigned char *bytes, int len, int loc, int set) { - if (K_X509_NAME_add_entry_by_txt) return (K_X509_NAME_add_entry_by_txt)(name, field, type, bytes, len, loc, set); - kdWarning() << "X509_NAME_add_entry not defined!" << endl; - return -1; -} - - -X509_NAME *KOpenSSLProxy::X509_NAME_new() { - if (K_X509_NAME_new) return (K_X509_NAME_new)(); - kdWarning() << "X509_NAME_new not defined!" << endl; - return 0L; -} - - -int KOpenSSLProxy::X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name) { - if (K_X509_REQ_set_subject_name) return (K_X509_REQ_set_subject_name)(req, name); - kdWarning() << "X509_REQ_set_subject_name not defined!" << endl; - return -1; -} - - -unsigned char *KOpenSSLProxy::ASN1_STRING_data(ASN1_STRING *x) { - if (K_ASN1_STRING_data) return (K_ASN1_STRING_data)(x); - kdWarning() << "ASN1_STRING_data not defined!" << endl; - return 0L; -} - -int KOpenSSLProxy::ASN1_STRING_length(ASN1_STRING *x) { - if (K_ASN1_STRING_length) return (K_ASN1_STRING_length)(x); - kdWarning() << "ASN1_STRING_length not defined!" << endl; - return 0L; -} - -STACK_OF(SSL_CIPHER) *KOpenSSLProxy::SSL_get_ciphers(const SSL* ssl) { - if (K_SSL_get_ciphers) return (K_SSL_get_ciphers)(ssl); - kdWarning() << "SSL_get_ciphers not defined!" << endl; - return 0L; -} - -const ASN1_TIME* KOpenSSLProxy::X509_CRL_get0_lastUpdate(const X509_CRL *crl) { - if (K_X509_CRL_get0_lastUpdate) return (K_X509_CRL_get0_lastUpdate)(crl); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return X509_CRL_get_lastUpdate(crl); -#endif - kdWarning() << "X509_CRL_get_lastUpdate not defined!" << endl; - return 0L; -} - -const ASN1_TIME* KOpenSSLProxy::X509_CRL_get0_nextUpdate(const X509_CRL *crl) { - if (K_X509_CRL_get0_nextUpdate) return (K_X509_CRL_get0_nextUpdate)(crl); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return X509_CRL_get_nextUpdate(crl); -#endif - kdWarning() << "X509_CRL_get_nextUpdate not defined!" << endl; - return 0L; -} - -X509* KOpenSSLProxy::X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) { - if (K_X509_STORE_CTX_get_current_cert) return (K_X509_STORE_CTX_get_current_cert)(ctx); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return ctx->current_cert; -#endif - kdWarning() << "X509_STORE_CTX_get_current_cert not defined!" << endl; - return 0L; -} - -int KOpenSSLProxy::X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) { - if (K_X509_STORE_CTX_get_error) return (K_X509_STORE_CTX_get_error)(ctx); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return ctx->error; -#endif - kdWarning() << "X509k_STORE_CTX_get_error not defined!" << endl; - return -1; -} - -int KOpenSSLProxy::X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) { - if (K_X509_STORE_CTX_get_error_depth) return (K_X509_STORE_CTX_get_error_depth)(ctx); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return ctx->error_depth; -#endif - kdWarning() << "X509_STORE_CTX_get_error_depth not defined!" << endl; - return -1; -} - -void KOpenSSLProxy::X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) { - if (K_X509_STORE_CTX_set_error) { - (K_X509_STORE_CTX_set_error)(ctx, s); - return; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - ctx->error = s; - return; -#endif - kdWarning() << "X509_STORE_CTX_set_error not defined!" << endl; -} - -void KOpenSSLProxy::X509_STORE_set_verify_cb(X509_STORE *ctx, - X509_STORE_CTX_verify_cb verify_cb) { - if (K_X509_STORE_set_verify_cb) { - (K_X509_STORE_set_verify_cb)(ctx, verify_cb); - return; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - X509_STORE_set_verify_cb_func(ctx, verify_cb); - return; -#endif - kdWarning() << "X590_STORE_set_verify_cb not defined!" << endl; -} - -STACK_OF(X509_OBJECT)* KOpenSSLProxy::X509_STORE_get0_objects(X509_STORE *v) { - if (K_X509_STORE_get0_objects) return (K_X509_STORE_get0_objects)(v); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return v->objs; -#endif - kdWarning() << "X509_STORE_get0_objects not defined!" << endl; - return 0L; -} - -X509_LOOKUP_TYPE KOpenSSLProxy::X509_OBJECT_get_type(const X509_OBJECT *a) { - if (K_X509_OBJECT_get_type) return (K_X509_OBJECT_get_type)(a); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - return a->type; -#endif - kdWarning() << "X509_OBJECT_get_type not defined!" << endl; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) - return X509_LU_NONE; -#else - return 0; -#endif -} - -X509* KOpenSSLProxy::X509_OBJECT_get0_X509(const X509_OBJECT *a) { - if (K_X509_OBJECT_get0_X509) return (K_X509_OBJECT_get0_X509)(a); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return a->data.x509; -#endif - kdWarning() << "X509_OBJECT_get0_X509 not defined!" << endl; - return 0L; -} - - -ASN1_TIME* KOpenSSLProxy::X509_getm_notAfter(const X509 *x) { - if (K_X509_getm_notAfter) return (K_X509_getm_notAfter)(x); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return X509_get_notAfter(x); -#endif - kdWarning() << "X509_get_notAfter not defined!" << endl; - return 0L; -} - -ASN1_TIME* KOpenSSLProxy::X509_getm_notBefore(const X509 *x) { - if (K_X509_getm_notBefore) return (K_X509_getm_notBefore)(x); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return X509_get_notBefore(x); -#endif - kdWarning() << "X509_get_notBefore not defined!" << endl; - return 0L; -} - -/* cover KOpenSSLProxy API compatibility */ -STACK* KOpenSSLProxy::sk_dup(const STACK *s) { - return OPENSSL_sk_dup(s); -} - -void KOpenSSLProxy::sk_free(STACK *s) { - OPENSSL_sk_free(s); -} - -STACK* KOpenSSLProxy::sk_new(int (*cmp)()) { - return OPENSSL_sk_new(cmp); -} - -int KOpenSSLProxy::sk_num(STACK *s) { - return OPENSSL_sk_num(s); -} - -char* KOpenSSLProxy::sk_pop(STACK *s) { - return OPENSSL_sk_pop(s); -} - -int KOpenSSLProxy::sk_push(STACK *s, char *d) { - return OPENSSL_sk_push(s, d); -} - -char* KOpenSSLProxy::sk_value(STACK *s, int n) { - return OPENSSL_sk_value(s, n); -} - -void KOpenSSLProxy::X509_STORE_CTX_set_chain(X509_STORE_CTX *v, STACK_OF(X509)* x) { - X509_STORE_CTX_set0_untrusted(v, x); -} - -SSL_METHOD* KOpenSSLProxy::SSLv23_client_method() { - return TLS_client_method(); -} - -#endif diff --git a/tdeio/kssl/kopenssl.cpp b/tdeio/kssl/kopenssl.cpp new file mode 100644 index 000000000..a009bd7e9 --- /dev/null +++ b/tdeio/kssl/kopenssl.cpp @@ -0,0 +1,2123 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001-2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef KSSL_HAVE_SSL +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include "kopenssl.h" + +#define GET_CRYPTOLIB_SYMBOL(a) ((_cryptoLib->hasSymbol(a)) ? _cryptoLib->symbol(a) : NULL) +#define GET_SSLLIB_SYMBOL(a) ((_sslLib->hasSymbol(a)) ? _sslLib->symbol(a) : NULL) + +// taken from OpenSSL 1.1 header, used to call OPENSSL_init_crypto +#if !defined(OPENSSL_INIT_ADD_ALL_CIPHERS) +# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L +# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L +# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L +#endif + +extern "C" { +#ifdef KSSL_HAVE_SSL +static int (*K_SSL_connect) (SSL *) = 0L; +static int (*K_SSL_accept) (SSL *) = 0L; +static int (*K_SSL_read) (SSL *, void *, int) = 0L; +static int (*K_SSL_write) (SSL *, const void *, int) = 0L; +static SSL *(*K_SSL_new) (SSL_CTX *) = 0L; +static void (*K_SSL_free) (SSL *) = 0L; +static int (*K_SSL_shutdown) (SSL *) = 0L; +static SSL_CTX *(*K_SSL_CTX_new)(SSL_METHOD *) = 0L; +static void (*K_SSL_CTX_free) (SSL_CTX *) = 0L; +static int (*K_SSL_set_fd) (SSL *, int) = 0L; +static int (*K_SSL_pending) (SSL *) = 0L; +static int (*K_SSL_peek) (SSL *, void *, int) = 0L; +static int (*K_SSL_CTX_set_cipher_list)(SSL_CTX *, const char *) = 0L; +static void (*K_SSL_CTX_set_verify)(SSL_CTX *, int, + int (*)(int, X509_STORE_CTX *)) = 0L; +static int (*K_SSL_use_certificate)(SSL *, X509 *) = 0L; +static SSL_CIPHER *(*K_SSL_get_current_cipher)(SSL *) = 0L; +static long (*K_SSL_set_options)(SSL *ssl, long options) = 0L; +static int (*K_SSL_session_reused)(SSL *ssl) = 0L; +static long (*K_SSL_ctrl) (SSL *,int, long, void *) = 0L; +static int (*K_RAND_egd) (const char *) = 0L; +static const char* (*K_RAND_file_name) (char *, size_t) = 0L; +static int (*K_RAND_load_file) (const char *, long) = 0L; +static int (*K_RAND_write_file) (const char *) = 0L; +static SSL_METHOD * (*K_TLSv1_client_method) () = 0L; +static SSL_METHOD * (*K_SSLv2_client_method) () = 0L; +static SSL_METHOD * (*K_SSLv3_client_method) () = 0L; +static SSL_METHOD * (*K_TLS_client_method) () = 0L; +static X509 * (*K_SSL_get_peer_certificate) (SSL *) = 0L; +static int (*K_SSL_CIPHER_get_bits) (SSL_CIPHER *,int *) = 0L; +static char * (*K_SSL_CIPHER_get_version) (SSL_CIPHER *) = 0L; +static const char * (*K_SSL_CIPHER_get_name) (SSL_CIPHER *) = 0L; +static char * (*K_SSL_CIPHER_description) (SSL_CIPHER *, char *, int) = 0L; +static X509 * (*K_d2i_X509) (X509 **,unsigned char **,long) = 0L; +static X509_CRL * (*K_d2i_X509_CRL) (X509_CRL **,unsigned char **,long) = 0L; +static int (*K_i2d_X509) (X509 *,unsigned char **) = 0L; +static int (*K_X509_cmp) (X509 *, X509 *) = 0L; +static int (*K_X509_subject_name_cmp) (const X509 *, const X509 *) = 0L; +static void (*K_X509_STORE_CTX_free) (X509_STORE_CTX *) = 0L; +static int (*K_X509_verify_cert) (X509_STORE_CTX *) = 0L; +static X509_STORE_CTX *(*K_X509_STORE_CTX_new) (void) = 0L; +static void (*K_X509_STORE_free) (X509_STORE *) = 0L; +static X509_STORE *(*K_X509_STORE_new) (void) = 0L; +static void (*K_X509_free) (X509 *) = 0L; +static void (*K_X509_CRL_free) (X509_CRL *) = 0L; +static char *(*K_X509_NAME_oneline) (X509_NAME *,char *,int) = 0L; +static X509_NAME *(*K_X509_get_subject_name) (X509 *) = 0L; +static X509_NAME *(*K_X509_get_issuer_name) (X509 *) = 0L; +static X509_LOOKUP *(*K_X509_STORE_add_lookup) (X509_STORE *, X509_LOOKUP_METHOD *) = 0L; +static X509_LOOKUP_METHOD *(*K_X509_LOOKUP_file)(void) = 0L; +static void (*K_X509_LOOKUP_free)(X509_LOOKUP *) = 0L; +static int (*K_X509_LOOKUP_ctrl)(X509_LOOKUP *, int, const char *, long, char **) = 0L; +static void (*K_X509_STORE_CTX_init)(X509_STORE_CTX *, X509_STORE *, X509 *, STACK_OF(X509) *) = 0L; +static void (*K_CRYPTO_free) (void *) = 0L; +static X509* (*K_X509_dup) (X509 *) = 0L; +static void (*K_X509_get0_signature)(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x) = 0L; +static BIO_METHOD *(*K_BIO_s_mem) (void) = 0L; +static BIO* (*K_BIO_new) (BIO_METHOD *) = 0L; +static BIO* (*K_BIO_new_fp) (FILE *, int) = 0L; +static BIO* (*K_BIO_new_mem_buf) (void *, int) = 0L; +static int (*K_BIO_free) (BIO *) = 0L; +static long (*K_BIO_ctrl) (BIO *,int,long,void *) = 0L; +static int (*K_BIO_write) (BIO *b, const void *data, int len) = 0L; +static void* (*K_BIO_get_data) (BIO *a) = 0L; +static int (*K_PEM_ASN1_write_bio) (int (*)(),const char *,BIO *,char *, + const EVP_CIPHER *,unsigned char *,int , + pem_password_cb *, void *) = 0L; +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +static int (*K_ASN1_item_i2d_fp)(ASN1_ITEM *,FILE *,unsigned char *) = 0L; +static ASN1_ITEM *K_NETSCAPE_X509_it = 0L; +#else +static ASN1_METHOD* (*K_X509_asn1_meth) (void) = 0L; +static int (*K_ASN1_i2d_fp)(int (*)(),FILE *,unsigned char *) = 0L; +static int (*K_i2d_ASN1_HEADER)(ASN1_HEADER *, unsigned char **) = 0L; +#endif +static int (*K_X509_print_fp) (FILE *, X509*) = 0L; +static int (*K_i2d_PKCS12) (PKCS12*, unsigned char**) = 0L; +static int (*K_i2d_PKCS12_fp) (FILE *, PKCS12*) = 0L; +static int (*K_PKCS12_newpass) (PKCS12*, char*, char*) = 0L; +static PKCS12* (*K_d2i_PKCS12_fp) (FILE*, PKCS12**) = 0L; +static PKCS12* (*K_PKCS12_new) (void) = 0L; +static void (*K_PKCS12_free) (PKCS12 *) = 0L; +static int (*K_PKCS12_parse) (PKCS12*, const char *, EVP_PKEY**, + X509**, STACK_OF(X509)**) = 0L; +static void (*K_EVP_PKEY_free) (EVP_PKEY *) = 0L; +static EVP_PKEY* (*K_EVP_PKEY_new) () = 0L; +static int (*K_EVP_PKEY_base_id)(const EVP_PKEY *pkey) = 0L; +static RSA* (*K_EVP_PKEY_get0_RSA)(EVP_PKEY *pkey) = 0L; +static DSA* (*K_EVP_PKEY_get0_DSA)(EVP_PKEY *pkey) = 0L; +static void (*K_X509_REQ_free) (X509_REQ *) = 0L; +static X509_REQ* (*K_X509_REQ_new) () = 0L; +static int (*K_SSL_CTX_use_PrivateKey) (SSL_CTX*, EVP_PKEY*) = 0L; +static int (*K_SSL_CTX_use_certificate) (SSL_CTX*, X509*) = 0L; +static int (*K_SSL_get_error) (SSL*, int) = 0L; +static STACK_OF(X509)* (*K_SSL_get_peer_cert_chain) (SSL*) = 0L; +static void (*K_X509_STORE_CTX_set0_untrusted) (X509_STORE_CTX *, STACK_OF(X509)*) = 0L; +static void (*K_X509_STORE_CTX_set_purpose) (X509_STORE_CTX *, int) = 0L; +static void (*K_sk_free) (STACK*) = 0L; +static int (*K_sk_num) (STACK*) = 0L; +static char* (*K_sk_pop) (STACK*) = 0L; +static char* (*K_sk_value) (STACK*, int) = 0L; +static STACK* (*K_sk_new) (int (*)()) = 0L; +static int (*K_sk_push) (STACK*, char*) = 0L; +static STACK* (*K_sk_dup) (const STACK *) = 0L; +static char * (*K_i2s_ASN1_INTEGER) (X509V3_EXT_METHOD *, ASN1_INTEGER *) =0L; +static ASN1_INTEGER * (*K_X509_get_serialNumber) (X509 *) = 0L; +static EVP_PKEY *(*K_X509_get_pubkey)(X509 *) = 0L; +static int (*K_i2d_PublicKey)(EVP_PKEY *, unsigned char **) = 0L; +static int (*K_X509_check_private_key)(X509 *, EVP_PKEY *) = 0L; +static char * (*K_BN_bn2hex)(const BIGNUM *) = 0L; +static int (*K_X509_digest)(const X509 *,const EVP_MD *, unsigned char *, unsigned int *) = 0L; +static EVP_MD* (*K_EVP_md5)() = 0L; +static void (*K_ASN1_INTEGER_free)(ASN1_INTEGER *) = 0L; +static int (*K_OBJ_obj2nid)(ASN1_OBJECT *) = 0L; +static const char * (*K_OBJ_nid2ln)(int) = 0L; +static int (*K_X509_get_ext_count)(X509*) = 0L; +static int (*K_X509_get_ext_by_NID)(X509*, int, int) = 0L; +static int (*K_X509_get_ext_by_OBJ)(X509*,ASN1_OBJECT*,int) = 0L; +static X509_EXTENSION *(*K_X509_get_ext)(X509*, int loc) = 0L; +static X509_EXTENSION *(*K_X509_delete_ext)(X509*, int) = 0L; +static int (*K_X509_add_ext)(X509*, X509_EXTENSION*, int) = 0L; +static void *(*K_X509_get_ext_d2i)(X509*, int, int*, int*) = 0L; +static char *(*K_i2s_ASN1_OCTET_STRING)(X509V3_EXT_METHOD*, ASN1_OCTET_STRING*) = 0L; +static int (*K_ASN1_BIT_STRING_get_bit)(ASN1_BIT_STRING*, int) = 0L; +static PKCS7 *(*K_PKCS7_new)() = 0L; +static void (*K_PKCS7_free)(PKCS7*) = 0L; +static void (*K_PKCS7_content_free)(PKCS7*) = 0L; +static int (*K_i2d_PKCS7)(PKCS7*, unsigned char**) = 0L; +static PKCS7 *(*K_d2i_PKCS7)(PKCS7**, unsigned char**,long) = 0L; +static int (*K_i2d_PKCS7_fp)(FILE*,PKCS7*) = 0L; +static PKCS7* (*K_d2i_PKCS7_fp)(FILE*,PKCS7**) = 0L; +static int (*K_i2d_PKCS7_bio)(BIO *bp,PKCS7 *p7) = 0L; +static PKCS7 *(*K_d2i_PKCS7_bio)(BIO *bp,PKCS7 **p7) = 0L; +static PKCS7* (*K_PKCS7_dup)(PKCS7*) = 0L; +static STACK_OF(X509_NAME) *(*K_SSL_load_client_CA_file)(const char*) = 0L; +static STACK_OF(X509_INFO) *(*K_PEM_X509_INFO_read)(FILE*, STACK_OF(X509_INFO)*, pem_password_cb*, void*) = 0L; +static char *(*K_ASN1_d2i_fp)(char *(*)(),char *(*)(),FILE*,unsigned char**) = 0L; +static X509 *(*K_X509_new)() = 0L; +static int (*K_X509_PURPOSE_get_count)() = 0L; +static int (*K_X509_PURPOSE_get_id)(X509_PURPOSE *) = 0L; +static int (*K_X509_check_purpose)(X509*,int,int) = 0L; +static X509_PURPOSE* (*K_X509_PURPOSE_get0)(int) = 0L; +static int (*K_EVP_PKEY_assign)(EVP_PKEY*, int, char*) = 0L; +static int (*K_X509_REQ_set_pubkey)(X509_REQ*, EVP_PKEY*) = 0L; +static void (*K_RSA_get0_key)(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) = 0L; +static RSA *(*K_RSA_generate_key)(int, unsigned long, void (*)(int,int,void *), void *) = 0L; +static void (*K_DSA_get0_pqg)(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) = 0L; +static void (*K_DSA_get0_key)(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) = 0L; +static int (*K_i2d_X509_REQ_fp)(FILE*, X509_REQ*) = 0L; +static void (*K_ERR_clear_error)() = 0L; +static unsigned long (*K_ERR_get_error)() = 0L; +static void (*K_ERR_print_errors_fp)(FILE*) = 0L; +static PKCS7 *(*K_PKCS7_sign)(X509*, EVP_PKEY*, STACK_OF(X509)*, BIO*, int) = 0L; +static int (*K_PKCS7_verify)(PKCS7*,STACK_OF(X509)*,X509_STORE*,BIO*,BIO*,int) = 0L; +static STACK_OF(X509) *(*K_PKCS7_get0_signers)(PKCS7 *, STACK_OF(X509) *, int) = 0L; +static PKCS7 *(*K_PKCS7_encrypt)(STACK_OF(X509) *, BIO *, EVP_CIPHER *, int) = 0L; +static int (*K_PKCS7_decrypt)(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int) = 0L; +static SSL_SESSION* (*K_SSL_get1_session)(SSL*) = 0L; +static void (*K_SSL_SESSION_free)(SSL_SESSION*) = 0L; +static int (*K_SSL_set_session)(SSL*,SSL_SESSION*) = 0L; +static SSL_SESSION* (*K_d2i_SSL_SESSION)(SSL_SESSION**,unsigned char**, long) = 0L; +static int (*K_i2d_SSL_SESSION)(SSL_SESSION*,unsigned char**) = 0L; +static STACK *(*K_X509_get1_email)(X509 *x) = 0L; +static void (*K_X509_email_free)(STACK *sk) = 0L; +static EVP_CIPHER *(*K_EVP_des_ede3_cbc)() = 0L; +static EVP_CIPHER *(*K_EVP_des_cbc)() = 0L; +static EVP_CIPHER *(*K_EVP_rc2_cbc)() = 0L; +static EVP_CIPHER *(*K_EVP_rc2_64_cbc)() = 0L; +static EVP_CIPHER *(*K_EVP_rc2_40_cbc)() = 0L; +static int (*K_i2d_PrivateKey_fp)(FILE*,EVP_PKEY*) = 0L; +static int (*K_i2d_PKCS8PrivateKey_fp)(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*) = 0L; +static void (*K_RSA_free)(RSA*) = 0L; +static EVP_CIPHER *(*K_EVP_bf_cbc)() = 0L; +static int (*K_X509_REQ_sign)(X509_REQ*, EVP_PKEY*, const EVP_MD*) = 0L; +static int (*K_X509_NAME_add_entry_by_txt)(X509_NAME*, char*, int, unsigned char*, int, int, int) = 0L; +static X509_NAME *(*K_X509_NAME_new)() = 0L; +static int (*K_X509_REQ_set_subject_name)(X509_REQ*,X509_NAME*) = 0L; +static unsigned char *(*K_ASN1_STRING_data)(ASN1_STRING*) = 0L; +static int (*K_ASN1_STRING_length)(ASN1_STRING*) = 0L; +static STACK_OF(SSL_CIPHER) *(*K_SSL_get_ciphers)(const SSL *ssl) = 0L; +static const ASN1_TIME* (*K_X509_CRL_get0_lastUpdate)(const X509_CRL *crl) = 0L; +static const ASN1_TIME* (*K_X509_CRL_get0_nextUpdate)(const X509_CRL *crl) = 0L; +static X509* (*K_X509_STORE_CTX_get_current_cert)(X509_STORE_CTX *ctx) = 0L; +static int (*K_X509_STORE_CTX_get_error)(X509_STORE_CTX *ctx) = 0L; +static int (*K_X509_STORE_CTX_get_error_depth)(X509_STORE_CTX *ctx) = 0L; +static void (*K_X509_STORE_CTX_set_error)(X509_STORE_CTX *ctx, int s) = 0L; +static void (*K_X509_STORE_set_verify_cb)(X509_STORE *ctx, + X509_STORE_CTX_verify_cb verify_cb) = 0L; +static STACK_OF(X509_OBJECT)* (*K_X509_STORE_get0_objects)(X509_STORE *v) = 0L; +static X509_LOOKUP_TYPE (*K_X509_OBJECT_get_type)(const X509_OBJECT *a) = 0L; +static X509* (*K_X509_OBJECT_get0_X509)(const X509_OBJECT *a) = 0L; +static ASN1_TIME* (*K_X509_getm_notAfter)(const X509 *x) = 0L; +static ASN1_TIME* (*K_X509_getm_notBefore)(const X509 *x) = 0L; +#endif +} + + +bool KOpenSSLProxy::hasLibSSL() const { + return _sslLib != 0L; +} + + +bool KOpenSSLProxy::hasLibCrypto() const { + return _cryptoLib != 0L; +} + + +void KOpenSSLProxy::destroy() { + delete this; + _me = 0L; +} + +#ifdef __OpenBSD__ +#include +#include +#include + +static TQString findMostRecentLib(TQString dir, TQString name) +{ + // Grab all shared libraries in the directory + TQString filter = "lib"+name+".so.*"; + TQDir d(dir, filter); + if (!d.exists()) + return 0L; + TQStringList l = d.entryList(); + + // Find the best one + int bestmaj = -1; + int bestmin = -1; + TQString best = 0L; + // where do we start + uint s = filter.length()-1; + for (TQStringList::Iterator it = l.begin(); it != l.end(); ++it) { + TQString numberpart = (*it).mid(s); + uint endmaj = numberpart.find('.'); + if (endmaj == -1) + continue; + bool ok; + int maj = numberpart.left(endmaj).toInt(&ok); + if (!ok) + continue; + int min = numberpart.mid(endmaj+1).toInt(&ok); + if (!ok) + continue; + if (maj > bestmaj || (maj == bestmaj && min > bestmin)) { + bestmaj = maj; + bestmin = min; + best = (*it); + } + } + if (best.isNull()) + return 0L; + else + return dir+"/"+best; +} +#endif + + +KOpenSSLProxy::KOpenSSLProxy() { +KLibLoader *ll = KLibLoader::self(); +_ok = false; +TQStringList libpaths, libnamesc, libnamess; +TDEConfig *cfg; + + _cryptoLib = 0L; + _sslLib = 0L; + + cfg = new TDEConfig("cryptodefaults", false, false); + cfg->setGroup("OpenSSL"); + TQString upath = cfg->readPathEntry("Path"); + if (!upath.isEmpty()) + libpaths << upath; + + delete cfg; + +#ifdef __OpenBSD__ + { + TQString libname = findMostRecentLib("/usr/" SYSTEM_LIBDIR, "crypto"); + if (!libname.isNull()) + _cryptoLib = ll->globalLibrary(libname.latin1()); + } +#elif defined(__CYGWIN__) + libpaths << "/usr/bin/" + << "/usr/local/bin" + << "/usr/local/openssl/bin" + << "/opt/openssl/bin" + << "/opt/trinity/bin" + << ""; + + libnamess << "cygssl-0.9.7.dll" + << "cygssl.dll" + << "libssl.dll" + << ""; + + libnamesc << "cygcrypto.dll" + << "libcrypto.dll" + << ""; +#else + libpaths + #ifdef _AIX + << "/opt/freeware/lib/" + #endif + << "/usr/" SYSTEM_LIBDIR "/" + << "/usr/ssl/" SYSTEM_LIBDIR "/" + << "/usr/local/" SYSTEM_LIBDIR "/" + << "/usr/local/openssl/" SYSTEM_LIBDIR "/" + << "/usr/local/ssl/" SYSTEM_LIBDIR "/" + << "/opt/openssl/" SYSTEM_LIBDIR "/" + << "/" SYSTEM_LIBDIR "/" + << ""; + +// FIXME: #define here for the various OS types to optimize + libnamess + #ifdef hpux + << "libssl.sl" + #elif defined(_AIX) + << "libssl.a(libssl.so.0)" + #elif defined(__APPLE__) + << "libssl.dylib" + << "libssl.0.9.dylib" + #else + #ifdef SHLIB_VERSION_NUMBER + << "libssl.so." SHLIB_VERSION_NUMBER + #endif + << "libssl.so" + << "libssl.so.0" + #endif + ; + + libnamesc + #ifdef hpux + << "libcrypto.sl" + #elif defined(_AIX) + << "libcrypto.a(libcrypto.so.0)" + #elif defined(__APPLE__) + << "libcrypto.dylib" + << "libcrypto.0.9.dylib" + #else + #ifdef SHLIB_VERSION_NUMBER + << "libcrypto.so." SHLIB_VERSION_NUMBER + #endif + << "libcrypto.so" + << "libcrypto.so.0" + #endif + ; +#endif + + for (TQStringList::Iterator it = libpaths.begin(); + it != libpaths.end(); + ++it) { + for (TQStringList::Iterator shit = libnamesc.begin(); + shit != libnamesc.end(); + ++shit) { + TQString alib = *it; + if (!alib.isEmpty() && !alib.endsWith("/")) + alib += "/"; + alib += *shit; + TQString tmpStr(alib.latin1()); + tmpStr.replace(TQRegExp("\\(.*\\)"), ""); + if (!access(tmpStr.latin1(), R_OK)) + _cryptoLib = ll->globalLibrary(alib.latin1()); + if (_cryptoLib) break; + } + if (_cryptoLib) break; + } + + if (_cryptoLib) { +#ifdef KSSL_HAVE_SSL + K_X509_free = (void (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_free"); + K_X509_CRL_free = (void (*) (X509_CRL *)) GET_CRYPTOLIB_SYMBOL("X509_CRL_free"); + K_RAND_egd = (int (*)(const char *)) GET_CRYPTOLIB_SYMBOL("RAND_egd"); + K_RAND_load_file = (int (*)(const char *, long)) GET_CRYPTOLIB_SYMBOL("RAND_load_file"); + K_RAND_file_name = (const char* (*)(char *, size_t)) GET_CRYPTOLIB_SYMBOL("RAND_file_name"); + K_RAND_write_file = (int (*)(const char *)) GET_CRYPTOLIB_SYMBOL("RAND_write_file"); + K_CRYPTO_free = (void (*) (void *)) GET_CRYPTOLIB_SYMBOL("CRYPTO_free"); + K_d2i_X509 = (X509 * (*)(X509 **,unsigned char **,long)) GET_CRYPTOLIB_SYMBOL("d2i_X509"); + K_d2i_X509_CRL = (X509_CRL * (*)(X509_CRL **,unsigned char **,long)) GET_CRYPTOLIB_SYMBOL("d2i_X509_CRL"); + K_i2d_X509 = (int (*)(X509 *,unsigned char **)) GET_CRYPTOLIB_SYMBOL("i2d_X509"); + K_X509_cmp = (int (*)(X509 *, X509 *)) GET_CRYPTOLIB_SYMBOL("X509_cmp"); + K_X509_subject_name_cmp = (int (*)(const X509 *, const X509 *)) GET_CRYPTOLIB_SYMBOL("X509_subject_name_cmp"); + K_X509_STORE_CTX_new = (X509_STORE_CTX * (*) (void)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_new"); + K_X509_STORE_CTX_free = (void (*) (X509_STORE_CTX *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_free"); + K_X509_verify_cert = (int (*) (X509_STORE_CTX *)) GET_CRYPTOLIB_SYMBOL("X509_verify_cert"); + K_X509_STORE_new = (X509_STORE * (*) (void)) GET_CRYPTOLIB_SYMBOL("X509_STORE_new"); + K_X509_STORE_free = (void (*) (X509_STORE *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_free"); + K_X509_NAME_oneline = (char * (*) (X509_NAME *,char *,int)) GET_CRYPTOLIB_SYMBOL("X509_NAME_oneline"); + K_X509_get_subject_name = (X509_NAME * (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_subject_name"); + K_X509_get_issuer_name = (X509_NAME * (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_issuer_name"); + K_X509_STORE_add_lookup = (X509_LOOKUP *(*) (X509_STORE *, X509_LOOKUP_METHOD *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_add_lookup"); + K_X509_LOOKUP_file = (X509_LOOKUP_METHOD *(*)(void)) GET_CRYPTOLIB_SYMBOL("X509_LOOKUP_file"); + K_X509_LOOKUP_free = (void (*)(X509_LOOKUP *)) GET_CRYPTOLIB_SYMBOL("X509_LOOKUP_free"); + K_X509_LOOKUP_ctrl = (int (*)(X509_LOOKUP *, int, const char *, long, char **)) GET_CRYPTOLIB_SYMBOL("X509_LOOKUP_ctrl"); + K_X509_STORE_CTX_init = (void (*)(X509_STORE_CTX *, X509_STORE *, X509 *, STACK_OF(X509) *)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_init"); + K_X509_dup = (X509* (*)(X509*)) GET_CRYPTOLIB_SYMBOL("X509_dup"); + K_X509_get0_signature = (void (*)(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_get0_signature"); + K_BIO_s_mem = (BIO_METHOD *(*) (void)) GET_CRYPTOLIB_SYMBOL("BIO_s_mem"); + K_BIO_new = (BIO* (*)(BIO_METHOD *)) GET_CRYPTOLIB_SYMBOL("BIO_new"); + K_BIO_new_fp = (BIO* (*)(FILE*, int)) GET_CRYPTOLIB_SYMBOL("BIO_new_fp"); + K_BIO_new_mem_buf = (BIO* (*)(void *, int)) GET_CRYPTOLIB_SYMBOL("BIO_new_mem_buf"); + K_BIO_free = (int (*)(BIO*)) GET_CRYPTOLIB_SYMBOL("BIO_free"); + K_BIO_ctrl = (long (*) (BIO *,int,long,void *)) GET_CRYPTOLIB_SYMBOL("BIO_ctrl"); + K_BIO_write = (int (*) (BIO *b, const void *data, int len)) GET_CRYPTOLIB_SYMBOL("BIO_write"); + K_BIO_get_data = (void* (*)(BIO *a)) GET_CRYPTOLIB_SYMBOL("BIO_get_data"); + K_PEM_ASN1_write_bio = (int (*)(int (*)(), const char *,BIO*, char*, const EVP_CIPHER *, unsigned char *, int, pem_password_cb *, void *)) GET_CRYPTOLIB_SYMBOL("PEM_ASN1_write_bio"); +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + K_ASN1_item_i2d_fp = (int (*)(ASN1_ITEM *, FILE*, unsigned char *)) GET_CRYPTOLIB_SYMBOL("ASN1_item_i2d_fp"); + K_NETSCAPE_X509_it = (ASN1_ITEM *) GET_CRYPTOLIB_SYMBOL("NETSCAPE_X509_it"); +#else + K_X509_asn1_meth = (ASN1_METHOD* (*)(void)) GET_CRYPTOLIB_SYMBOL("X509_asn1_meth"); + K_ASN1_i2d_fp = (int (*)(int (*)(), FILE*, unsigned char *)) GET_CRYPTOLIB_SYMBOL("ASN1_i2d_fp"); + K_i2d_ASN1_HEADER = (int (*)(ASN1_HEADER *, unsigned char **)) GET_CRYPTOLIB_SYMBOL("i2d_ASN1_HEADER"); +#endif + K_X509_print_fp = (int (*)(FILE*, X509*)) GET_CRYPTOLIB_SYMBOL("X509_print_fp"); + K_i2d_PKCS12 = (int (*)(PKCS12*, unsigned char**)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS12"); + K_i2d_PKCS12_fp = (int (*)(FILE *, PKCS12*)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS12_fp"); + K_PKCS12_newpass = (int (*)(PKCS12*, char*, char*)) GET_CRYPTOLIB_SYMBOL("PKCS12_newpass"); + K_d2i_PKCS12_fp = (PKCS12* (*)(FILE*, PKCS12**)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS12_fp"); + K_PKCS12_new = (PKCS12* (*)()) GET_CRYPTOLIB_SYMBOL("PKCS12_new"); + K_PKCS12_free = (void (*)(PKCS12 *)) GET_CRYPTOLIB_SYMBOL("PKCS12_free"); + K_PKCS12_parse = (int (*)(PKCS12*, const char *, EVP_PKEY**, + X509**, STACK_OF(X509)**)) GET_CRYPTOLIB_SYMBOL("PKCS12_parse"); + K_EVP_PKEY_free = (void (*) (EVP_PKEY *)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_free"); + K_EVP_PKEY_new = (EVP_PKEY* (*)()) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_new"); + K_EVP_PKEY_base_id = (int (*)(const EVP_PKEY *pkey)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_base_id"); + K_EVP_PKEY_get0_RSA = (RSA* (*)(EVP_PKEY *pkey)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_get0_RSA"); + K_EVP_PKEY_get0_DSA = (DSA* (*)(EVP_PKEY *pkey)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_get0_DSA"); + K_X509_REQ_free = (void (*)(X509_REQ*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_free"); + K_X509_REQ_new = (X509_REQ* (*)()) GET_CRYPTOLIB_SYMBOL("X509_REQ_new"); + K_X509_STORE_CTX_set0_untrusted = (void (*)(X509_STORE_CTX *, STACK_OF(X509)*)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set0_untrusted"); + if (!K_X509_STORE_CTX_set0_untrusted) K_X509_STORE_CTX_set0_untrusted = (void (*)(X509_STORE_CTX *, STACK_OF(X509)*)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set_chain"); + K_X509_STORE_CTX_set_purpose = (void (*)(X509_STORE_CTX *, int)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set_purpose"); + K_sk_free = (void (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_free"); + if (!K_sk_free) K_sk_free = (void (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("sk_free"); + K_sk_num = (int (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_num"); + if (!K_sk_num) K_sk_num = (int (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("sk_num"); + K_sk_pop = (char* (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_pop"); + if (!K_sk_pop) K_sk_pop = (char* (*) (STACK *)) GET_CRYPTOLIB_SYMBOL("sk_pop"); + K_sk_value = (char* (*) (STACK *, int)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_value"); + if (!K_sk_value) K_sk_value = (char* (*) (STACK *, int)) GET_CRYPTOLIB_SYMBOL("sk_value"); + K_sk_new = (STACK* (*) (int (*)())) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_new"); + if (!K_sk_new) K_sk_new = (STACK* (*) (int (*)())) GET_CRYPTOLIB_SYMBOL("sk_new"); + K_sk_push = (int (*) (STACK*, char*)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_push"); + if (!K_sk_push) K_sk_push = (int (*) (STACK*, char*)) GET_CRYPTOLIB_SYMBOL("sk_push"); + K_sk_dup = (STACK* (*) (const STACK *)) GET_CRYPTOLIB_SYMBOL("OPENSSL_sk_dup"); + if (!K_sk_dup) K_sk_dup = (STACK* (*) (const STACK *)) GET_CRYPTOLIB_SYMBOL("sk_dup"); + K_i2s_ASN1_INTEGER = (char *(*) (X509V3_EXT_METHOD *, ASN1_INTEGER *)) GET_CRYPTOLIB_SYMBOL("i2s_ASN1_INTEGER"); + K_X509_get_serialNumber = (ASN1_INTEGER * (*) (X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_serialNumber"); + K_X509_get_pubkey = (EVP_PKEY *(*)(X509 *)) GET_CRYPTOLIB_SYMBOL("X509_get_pubkey"); + K_i2d_PublicKey = (int (*)(EVP_PKEY *, unsigned char **)) GET_CRYPTOLIB_SYMBOL("i2d_PublicKey"); + K_X509_check_private_key = (int (*)(X509 *, EVP_PKEY *)) GET_CRYPTOLIB_SYMBOL("X509_check_private_key"); + K_BN_bn2hex = (char *(*)(const BIGNUM *)) GET_CRYPTOLIB_SYMBOL("BN_bn2hex"); + K_X509_digest = (int (*)(const X509 *,const EVP_MD *, unsigned char *, unsigned int *)) GET_CRYPTOLIB_SYMBOL("X509_digest"); + K_EVP_md5 = (EVP_MD *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_md5"); + K_ASN1_INTEGER_free = (void (*)(ASN1_INTEGER *)) GET_CRYPTOLIB_SYMBOL("ASN1_INTEGER_free"); + K_OBJ_obj2nid = (int (*)(ASN1_OBJECT *)) GET_CRYPTOLIB_SYMBOL("OBJ_obj2nid"); + K_OBJ_nid2ln = (const char *(*)(int)) GET_CRYPTOLIB_SYMBOL("OBJ_nid2ln"); + K_X509_get_ext_count = (int (*)(X509*)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_count"); + K_X509_get_ext_by_NID = (int (*)(X509*,int,int)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_by_NID"); + K_X509_get_ext_by_OBJ = (int (*)(X509*,ASN1_OBJECT*,int)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_by_OBJ"); + K_X509_get_ext = (X509_EXTENSION* (*)(X509*,int)) GET_CRYPTOLIB_SYMBOL("X509_get_ext"); + K_X509_delete_ext = (X509_EXTENSION* (*)(X509*,int)) GET_CRYPTOLIB_SYMBOL("X509_delete_ext"); + K_X509_add_ext = (int (*)(X509*,X509_EXTENSION*,int)) GET_CRYPTOLIB_SYMBOL("X509_add_ext"); + K_X509_get_ext_d2i = (void* (*)(X509*,int,int*,int*)) GET_CRYPTOLIB_SYMBOL("X509_get_ext_d2i"); + K_i2s_ASN1_OCTET_STRING = (char *(*)(X509V3_EXT_METHOD*,ASN1_OCTET_STRING*)) GET_CRYPTOLIB_SYMBOL("i2s_ASN1_OCTET_STRING"); + K_ASN1_BIT_STRING_get_bit = (int (*)(ASN1_BIT_STRING*,int)) GET_CRYPTOLIB_SYMBOL("ASN1_BIT_STRING_get_bit"); + K_PKCS7_new = (PKCS7 *(*)()) GET_CRYPTOLIB_SYMBOL("PKCS7_new"); + K_PKCS7_free = (void (*)(PKCS7*)) GET_CRYPTOLIB_SYMBOL("PKCS7_free"); + K_PKCS7_content_free = (void (*)(PKCS7*)) GET_CRYPTOLIB_SYMBOL("PKCS7_content_free"); + K_i2d_PKCS7 = (int (*)(PKCS7*, unsigned char**)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS7"); + K_i2d_PKCS7_fp = (int (*)(FILE*,PKCS7*)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS7_fp"); + K_i2d_PKCS7_bio = (int (*)(BIO *bp,PKCS7 *p7)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS7_bio"); + K_d2i_PKCS7 = (PKCS7* (*)(PKCS7**,unsigned char**,long)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS7"); + K_d2i_PKCS7_fp = (PKCS7 *(*)(FILE *,PKCS7**)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS7_fp"); + K_d2i_PKCS7_bio = (PKCS7 *(*)(BIO *bp,PKCS7 **p7)) GET_CRYPTOLIB_SYMBOL("d2i_PKCS7_bio"); + K_PKCS7_dup = (PKCS7* (*)(PKCS7*)) GET_CRYPTOLIB_SYMBOL("PKCS7_dup"); + K_PKCS7_sign = (PKCS7 *(*)(X509*, EVP_PKEY*, STACK_OF(X509)*, BIO*, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_sign"); + K_PKCS7_verify = (int (*)(PKCS7*,STACK_OF(X509)*,X509_STORE*,BIO*,BIO*,int)) GET_CRYPTOLIB_SYMBOL("PKCS7_verify"); + K_PKCS7_get0_signers = (STACK_OF(X509) *(*)(PKCS7 *, STACK_OF(X509) *, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_get0_signers"); + K_PKCS7_encrypt = (PKCS7* (*)(STACK_OF(X509) *, BIO *, EVP_CIPHER *, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_encrypt"); + K_PKCS7_decrypt = (int (*)(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int)) GET_CRYPTOLIB_SYMBOL("PKCS7_decrypt"); + K_PEM_X509_INFO_read = (STACK_OF(X509_INFO) *(*)(FILE*, STACK_OF(X509_INFO)*, pem_password_cb*, void *)) GET_CRYPTOLIB_SYMBOL("PEM_X509_INFO_read"); + K_ASN1_d2i_fp = (char *(*)(char *(*)(),char *(*)(),FILE*,unsigned char**)) GET_CRYPTOLIB_SYMBOL("ASN1_d2i_fp"); + K_X509_new = (X509 *(*)()) GET_CRYPTOLIB_SYMBOL("X509_new"); + K_X509_PURPOSE_get_count = (int (*)()) GET_CRYPTOLIB_SYMBOL("X509_PURPOSE_get_count"); + K_X509_PURPOSE_get_id = (int (*)(X509_PURPOSE *)) GET_CRYPTOLIB_SYMBOL("X509_PURPOSE_get_id"); + K_X509_check_purpose = (int (*)(X509*,int,int)) GET_CRYPTOLIB_SYMBOL("X509_check_purpose"); + K_X509_PURPOSE_get0 = (X509_PURPOSE *(*)(int)) GET_CRYPTOLIB_SYMBOL("X509_PURPOSE_get0"); + K_EVP_PKEY_assign = (int (*)(EVP_PKEY*, int, char*)) GET_CRYPTOLIB_SYMBOL("EVP_PKEY_assign"); + K_X509_REQ_set_pubkey = (int (*)(X509_REQ*, EVP_PKEY*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_set_pubkey"); + K_RSA_get0_key = (void (*)(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)) GET_CRYPTOLIB_SYMBOL("RSA_get0_key"); + K_RSA_generate_key = (RSA* (*)(int, unsigned long, void (*)(int,int,void *), void *)) GET_CRYPTOLIB_SYMBOL("RSA_generate_key"); + K_DSA_get0_pqg = (void (*)(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)) GET_CRYPTOLIB_SYMBOL("DSA_get0_pqg"); + K_DSA_get0_key = (void (*)(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)) GET_CRYPTOLIB_SYMBOL("DSA_get0_key"); + K_i2d_X509_REQ_fp = (int (*)(FILE *, X509_REQ *)) GET_CRYPTOLIB_SYMBOL("i2d_X509_REQ_fp"); + K_ERR_clear_error = (void (*)()) GET_CRYPTOLIB_SYMBOL("ERR_clear_error"); + K_ERR_get_error = (unsigned long (*)()) GET_CRYPTOLIB_SYMBOL("ERR_get_error"); + K_ERR_print_errors_fp = (void (*)(FILE*)) GET_CRYPTOLIB_SYMBOL("ERR_print_errors_fp"); + K_X509_get1_email = (STACK *(*)(X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_get1_email"); + K_X509_email_free = (void (*)(STACK *sk)) GET_CRYPTOLIB_SYMBOL("X509_email_free"); + K_EVP_des_ede3_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_des_ede3_cbc"); + K_EVP_des_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_des_cbc"); + K_EVP_rc2_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_rc2_cbc"); + K_EVP_rc2_64_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_rc2_64_cbc"); + K_EVP_rc2_40_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_rc2_40_cbc"); + K_i2d_PrivateKey_fp = (int (*)(FILE*,EVP_PKEY*)) GET_CRYPTOLIB_SYMBOL("i2d_PrivateKey_fp"); + K_i2d_PKCS8PrivateKey_fp = (int (*)(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*)) GET_CRYPTOLIB_SYMBOL("i2d_PKCS8PrivateKey_fp"); + K_RSA_free = (void (*)(RSA*)) GET_CRYPTOLIB_SYMBOL("RSA_free"); + K_EVP_bf_cbc = (EVP_CIPHER *(*)()) GET_CRYPTOLIB_SYMBOL("EVP_bf_cbc"); + K_X509_REQ_sign = (int (*)(X509_REQ*, EVP_PKEY*, const EVP_MD*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_sign"); + K_X509_NAME_add_entry_by_txt = (int (*)(X509_NAME*, char*, int, unsigned char*, int, int, int)) GET_CRYPTOLIB_SYMBOL("X509_NAME_add_entry_by_txt"); + K_X509_NAME_new = (X509_NAME *(*)()) GET_CRYPTOLIB_SYMBOL("X509_NAME_new"); + K_X509_REQ_set_subject_name = (int (*)(X509_REQ*,X509_NAME*)) GET_CRYPTOLIB_SYMBOL("X509_REQ_set_subject_name"); + K_ASN1_STRING_data = (unsigned char *(*)(ASN1_STRING*)) GET_CRYPTOLIB_SYMBOL("ASN1_STRING_data"); + K_ASN1_STRING_length = (int (*)(ASN1_STRING*)) GET_CRYPTOLIB_SYMBOL("ASN1_STRING_length"); + K_X509_CRL_get0_lastUpdate = (const ASN1_TIME* (*)(const X509_CRL *crl)) GET_CRYPTOLIB_SYMBOL("X509_CRL_get0_lastUpdate"); + K_X509_CRL_get0_nextUpdate = (const ASN1_TIME* (*)(const X509_CRL *crl)) GET_CRYPTOLIB_SYMBOL("X509_CRL_get0_nextUpdate"); + K_X509_STORE_CTX_get_current_cert = (X509* (*)(X509_STORE_CTX *ctx)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_get_current_cert"); + K_X509_STORE_CTX_get_error = (int (*)(X509_STORE_CTX *ctx)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_get_error"); + K_X509_STORE_CTX_get_error_depth = (int (*)(X509_STORE_CTX *ctx)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_get_error_depth"); + K_X509_STORE_CTX_set_error = (void (*)(X509_STORE_CTX *ctx, int s)) GET_CRYPTOLIB_SYMBOL("X509_STORE_CTX_set_error"); + K_X509_STORE_set_verify_cb = (void (*)(X509_STORE *ctx, + X509_STORE_CTX_verify_cb verify_cb)) GET_CRYPTOLIB_SYMBOL("X509_STORE_set_verify_cb"); + K_X509_STORE_get0_objects = (STACK_OF(X509_OBJECT)* (*)(X509_STORE *v)) GET_CRYPTOLIB_SYMBOL("X509_STORE_get0_objects"); + K_X509_OBJECT_get_type = (X509_LOOKUP_TYPE (*)(const X509_OBJECT *a)) GET_CRYPTOLIB_SYMBOL("X509_OBJECT_get_type"); + K_X509_OBJECT_get0_X509 = (X509* (*)(const X509_OBJECT *a)) GET_CRYPTOLIB_SYMBOL("X509_OBJECT_get0_X509"); + K_X509_getm_notAfter = (ASN1_TIME* (*)(const X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_getm_notAfter"); + K_X509_getm_notBefore = (ASN1_TIME* (*)(const X509 *x)) GET_CRYPTOLIB_SYMBOL("X509_getm_notBefore"); +#endif + } + +#ifdef __OpenBSD__ + { + TQString libname = findMostRecentLib("/usr/lib", "ssl"); + if (!libname.isNull()) + _sslLib = ll->globalLibrary(libname.latin1()); + } +#else + for (TQStringList::Iterator it = libpaths.begin(); + it != libpaths.end(); + ++it) { + for (TQStringList::Iterator shit = libnamess.begin(); + shit != libnamess.end(); + ++shit) { + TQString alib = *it; + if (!alib.isEmpty() && !alib.endsWith("/")) + alib += "/"; + alib += *shit; + TQString tmpStr(alib.latin1()); + tmpStr.replace(TQRegExp("\\(.*\\)"), ""); + if (!access(tmpStr.latin1(), R_OK)) + _sslLib = ll->globalLibrary(alib.latin1()); + if (_sslLib) break; + } + if (_sslLib) break; + } +#endif + + if (_sslLib) { +#ifdef KSSL_HAVE_SSL + // stand back from your monitor and look at this. it's fun! :) + K_SSL_connect = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_connect"); + K_SSL_accept = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_accept"); + K_SSL_read = (int (*)(SSL *, void *, int)) GET_SSLLIB_SYMBOL("SSL_read"); + K_SSL_write = (int (*)(SSL *, const void *, int)) + GET_SSLLIB_SYMBOL("SSL_write"); + K_SSL_new = (SSL* (*)(SSL_CTX *)) GET_SSLLIB_SYMBOL("SSL_new"); + K_SSL_free = (void (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_free"); + K_SSL_shutdown = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_shutdown"); + K_SSL_CTX_new = (SSL_CTX* (*)(SSL_METHOD*)) GET_SSLLIB_SYMBOL("SSL_CTX_new"); + K_SSL_CTX_free = (void (*)(SSL_CTX*)) GET_SSLLIB_SYMBOL("SSL_CTX_free"); + K_SSL_set_fd = (int (*)(SSL *, int)) GET_SSLLIB_SYMBOL("SSL_set_fd"); + K_SSL_pending = (int (*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_pending"); + K_SSL_CTX_set_cipher_list = (int (*)(SSL_CTX *, const char *)) + GET_SSLLIB_SYMBOL("SSL_CTX_set_cipher_list"); + K_SSL_CTX_set_verify = (void (*)(SSL_CTX*, int, int (*)(int, X509_STORE_CTX*))) GET_SSLLIB_SYMBOL("SSL_CTX_set_verify"); + K_SSL_use_certificate = (int (*)(SSL*, X509*)) + GET_SSLLIB_SYMBOL("SSL_CTX_use_certificate"); + K_SSL_get_current_cipher = (SSL_CIPHER *(*)(SSL *)) + GET_SSLLIB_SYMBOL("SSL_get_current_cipher"); + K_SSL_set_options = (long (*)(SSL *ssl, long options)) GET_SSLLIB_SYMBOL("SSL_set_options"); + K_SSL_session_reused = (int (*)(SSL *ssl)) GET_SSLLIB_SYMBOL("SSL_session_reused"); + K_SSL_ctrl = (long (*)(SSL * ,int, long, void *)) + GET_SSLLIB_SYMBOL("SSL_ctrl"); + K_TLSv1_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("TLSv1_client_method"); + K_SSLv2_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("SSLv2_client_method"); + K_SSLv3_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("SSLv3_client_method"); + K_TLS_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("TLS_client_method"); + if (!K_TLS_client_method) K_TLS_client_method = (SSL_METHOD *(*)()) GET_SSLLIB_SYMBOL("SSLv23_client_method"); + K_SSL_get_peer_certificate = (X509 *(*)(SSL *)) GET_SSLLIB_SYMBOL("SSL_get_peer_certificate"); + K_SSL_CIPHER_get_bits = (int (*)(SSL_CIPHER *,int *)) GET_SSLLIB_SYMBOL("SSL_CIPHER_get_bits"); + K_SSL_CIPHER_get_version = (char * (*)(SSL_CIPHER *)) GET_SSLLIB_SYMBOL("SSL_CIPHER_get_version"); + K_SSL_CIPHER_get_name = (const char * (*)(SSL_CIPHER *)) GET_SSLLIB_SYMBOL("SSL_CIPHER_get_name"); + K_SSL_CIPHER_description = (char * (*)(SSL_CIPHER *, char *, int)) GET_SSLLIB_SYMBOL("SSL_CIPHER_description"); + K_SSL_CTX_use_PrivateKey = (int (*)(SSL_CTX*, EVP_PKEY*)) GET_SSLLIB_SYMBOL("SSL_CTX_use_PrivateKey"); + K_SSL_CTX_use_certificate = (int (*)(SSL_CTX*, X509*)) GET_SSLLIB_SYMBOL("SSL_CTX_use_certificate"); + K_SSL_get_error = (int (*)(SSL*, int)) GET_SSLLIB_SYMBOL("SSL_get_error"); + K_SSL_get_peer_cert_chain = (STACK_OF(X509)* (*)(SSL*)) GET_SSLLIB_SYMBOL("SSL_get_peer_cert_chain"); + K_SSL_load_client_CA_file = (STACK_OF(X509_NAME)* (*)(const char *)) GET_SSLLIB_SYMBOL("SSL_load_client_CA_file"); + K_SSL_peek = (int (*)(SSL*,void*,int)) GET_SSLLIB_SYMBOL("SSL_peek"); + K_SSL_get1_session = (SSL_SESSION* (*)(SSL*)) GET_SSLLIB_SYMBOL("SSL_get1_session"); + K_SSL_SESSION_free = (void (*)(SSL_SESSION*)) GET_SSLLIB_SYMBOL("SSL_SESSION_free"); + K_SSL_set_session = (int (*)(SSL*,SSL_SESSION*)) GET_SSLLIB_SYMBOL("SSL_set_session"); + K_d2i_SSL_SESSION = (SSL_SESSION* (*)(SSL_SESSION**,unsigned char**, long)) GET_SSLLIB_SYMBOL("d2i_SSL_SESSION"); + K_i2d_SSL_SESSION = (int (*)(SSL_SESSION*,unsigned char**)) GET_SSLLIB_SYMBOL("i2d_SSL_SESSION"); + K_SSL_get_ciphers = (STACK_OF(SSL_CIPHER) *(*)(const SSL*)) GET_SSLLIB_SYMBOL("SSL_get_ciphers"); +#endif + + + // Initialize the library (once only!) + void *x; + x = GET_SSLLIB_SYMBOL("OPENSSL_init_ssl"); + if (x) { + // OpenSSL >= 1.1 + if (_cryptoLib) { + ((int (*)(unsigned long long, void*))x)(0, NULL); + x = GET_CRYPTOLIB_SYMBOL("OPENSSL_init_crypto"); + if (x) ((int (*)(unsigned long long, void*))x)(OPENSSL_INIT_ADD_ALL_CIPHERS + | OPENSSL_INIT_ADD_ALL_DIGESTS + | OPENSSL_INIT_LOAD_CONFIG, + NULL); + } + } + else { + // OpenSSL < 1.1 + x = GET_SSLLIB_SYMBOL("SSL_library_init"); + if (_cryptoLib) { + if (x) ((int (*)())x)(); + x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_algorithms"); + if (!x) + x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_algorithms"); + if (x) { + ((void (*)())x)(); + } else { + x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_algorithms_conf"); + if (!x) + x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_algorithms_conf"); + if (x) { + ((void (*)())x)(); + } else { + x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_algorithms_noconf"); + if (!x) + x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_algorithms_noconf"); + if (x) + ((void (*)())x)(); + } + } + x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_ciphers"); + if (!x) + x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_ciphers"); + if (x) ((void (*)())x)(); + x = GET_CRYPTOLIB_SYMBOL("OpenSSL_add_all_digests"); + if (!x) + x = GET_CRYPTOLIB_SYMBOL("OPENSSL_add_all_digests"); + if (x) ((void (*)())x)(); + } + } + } + +} + + +KOpenSSLProxy* KOpenSSLProxy::_me = 0L; +static KStaticDeleter medProxy; + + + +KOpenSSLProxy::~KOpenSSLProxy() { + if (_sslLib) { + _sslLib->unload(); + } + if (_cryptoLib) { + _cryptoLib->unload(); + } + medProxy.setObject(0); +} + + +// FIXME: we should check "ok" and allow this to init the lib if !ok. + +KOpenSSLProxy *KOpenSSLProxy::self() { +#ifdef KSSL_HAVE_SSL + if (!_me) { + _me = medProxy.setObject(_me, new KOpenSSLProxy); + } +#endif + return _me; +} + + + + + + + +#ifdef KSSL_HAVE_SSL + + + +int KOpenSSLProxy::SSL_connect(SSL *ssl) { + if (K_SSL_connect) return (K_SSL_connect)(ssl); + kdWarning() << "SSL_connect not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_accept(SSL *ssl) { + if (K_SSL_accept) return (K_SSL_accept)(ssl); + kdWarning() << "SSL_accept not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_read(SSL *ssl, void *buf, int num) { + if (K_SSL_read) return (K_SSL_read)(ssl, buf, num); + kdWarning() << "SSL_read not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_write(SSL *ssl, const void *buf, int num) { + if (K_SSL_write) return (K_SSL_write)(ssl, buf, num); + kdWarning() << "SSL_write not defined!" << endl; + return -1; +} + + +SSL *KOpenSSLProxy::SSL_new(SSL_CTX *ctx) { + if (K_SSL_new) return (K_SSL_new)(ctx); + kdWarning() << "SSL_new not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::SSL_free(SSL *ssl) { + if (K_SSL_free) (K_SSL_free)(ssl); + else kdWarning() << "SSL_free not defined!" << endl; +} + + +int KOpenSSLProxy::SSL_shutdown(SSL *ssl) { + if (K_SSL_shutdown) return (K_SSL_shutdown)(ssl); + kdWarning() << "SSL_shutdown not defined!" << endl; + return -1; +} + + +SSL_CTX *KOpenSSLProxy::SSL_CTX_new(SSL_METHOD *method) { + if (K_SSL_CTX_new) return (K_SSL_CTX_new)(method); + kdWarning() << "SSL_CTX_new not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::SSL_CTX_free(SSL_CTX *ctx) { + if (K_SSL_CTX_free) (K_SSL_CTX_free)(ctx); + else kdWarning() << "SSL_CTX_free not defined!" << endl; +} + + +int KOpenSSLProxy::SSL_set_fd(SSL *ssl, int fd) { + if (K_SSL_set_fd) return (K_SSL_set_fd)(ssl, fd); + kdWarning() << "SSL_sed_fd not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_pending(SSL *ssl) { + if (K_SSL_pending) return (K_SSL_pending)(ssl); + kdWarning() << "SSL_pending not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { + if (K_SSL_CTX_set_cipher_list) return (K_SSL_CTX_set_cipher_list)(ctx, str); + kdWarning() << "SSL_CTX_set_cipher_list not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*verify_callback)(int, X509_STORE_CTX *)) { + if (K_SSL_CTX_set_verify) (K_SSL_CTX_set_verify)(ctx, mode, verify_callback); + else kdWarning() << "SSL_CTX_set_verify not defined!" << endl; +} + + +int KOpenSSLProxy::SSL_use_certificate(SSL *ssl, X509 *x) { + if (K_SSL_use_certificate) return (K_SSL_use_certificate)(ssl, x); + kdWarning() << "SSL_use_certificate not defined!" << endl; + return -1; +} + + +SSL_CIPHER *KOpenSSLProxy::SSL_get_current_cipher(SSL *ssl) { + if (K_SSL_get_current_cipher) return (K_SSL_get_current_cipher)(ssl); + kdWarning() << "SSL_get_current_cipher not defined!" << endl; + return 0L; +} + + +long KOpenSSLProxy::_SSL_set_options(SSL *ssl, long options) { + if (K_SSL_set_options) return (K_SSL_set_options)(ssl, options); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return this->SSL_set_options(ssl, options); +#endif + kdWarning() << "SSL_set_options not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::_SSL_session_reused(SSL *ssl) { + if (K_SSL_session_reused) return (K_SSL_session_reused)(ssl); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return this->SSL_session_reused(ssl); +#endif + kdWarning() << "SSL_session_reused not defined!" << endl; + return -1; +} + + +long KOpenSSLProxy::SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg) { + if (K_SSL_ctrl) return (K_SSL_ctrl)(ssl, cmd, larg, parg); + kdWarning() << "SSL_ctrl not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::RAND_egd(const char *path) { + if (K_RAND_egd) return (K_RAND_egd)(path); + kdWarning() << "RAND_egd not defined!" << endl; + return -1; +} + + +SSL_METHOD *KOpenSSLProxy::TLSv1_client_method() { + if (K_TLSv1_client_method) return (K_TLSv1_client_method)(); + kdWarning() << "TLSv1_client_method not defined!" << endl; + return 0L; +} + + +SSL_METHOD *KOpenSSLProxy::SSLv2_client_method() { + if (K_SSLv2_client_method) return (K_SSLv2_client_method)(); + kdWarning() << "SSLv2_client_method not defined!" << endl; + return 0L; +} + + +SSL_METHOD *KOpenSSLProxy::SSLv3_client_method() { + if (K_SSLv3_client_method) return (K_SSLv3_client_method)(); + kdWarning() << "SSLv3_client_method not defined!" << endl; + return 0L; +} + + +SSL_METHOD *KOpenSSLProxy::TLS_client_method() { + if (K_TLS_client_method) return (K_TLS_client_method)(); + kdWarning() << "TLS_client_method not defined!" << endl; + return 0L; +} + + +X509 *KOpenSSLProxy::SSL_get_peer_certificate(SSL *s) { + if (K_SSL_get_peer_certificate) return (K_SSL_get_peer_certificate)(s); + kdWarning() << "SSL_get_peer_certificate not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits) { + if (K_SSL_CIPHER_get_bits) return (K_SSL_CIPHER_get_bits)(c, alg_bits); + kdWarning() << "SSL_CIPHER_get_bits not defined!" << endl; + return -1; +} + + +char * KOpenSSLProxy::SSL_CIPHER_get_version(SSL_CIPHER *c) { + if (K_SSL_CIPHER_get_version) return (K_SSL_CIPHER_get_version)(c); + kdWarning() << "SSL_CIPHER_get_version not defined!" << endl; + return 0L; +} + + +const char * KOpenSSLProxy::SSL_CIPHER_get_name(SSL_CIPHER *c) { + if (K_SSL_CIPHER_get_name) return (K_SSL_CIPHER_get_name)(c); + kdWarning() << "SSL_CIPHER_get_name not defined!" << endl; + return 0L; +} + + +char * KOpenSSLProxy::SSL_CIPHER_description(SSL_CIPHER *c,char *buf,int size) { + if (K_SSL_CIPHER_description) return (K_SSL_CIPHER_description)(c,buf,size); + kdWarning() << "SSL_CIPHER_description not defined!" << endl; + return 0L; +} + + +X509 * KOpenSSLProxy::d2i_X509(X509 **a,unsigned char **pp,long length) { + if (K_d2i_X509) return (K_d2i_X509)(a,pp,length); + kdWarning() << "d2i_X509 not defined!" << endl; + return 0L; +} + + +X509_CRL * KOpenSSLProxy::d2i_X509_CRL(X509_CRL **a,unsigned char **pp,long length) { + if (K_d2i_X509_CRL) return (K_d2i_X509_CRL)(a,pp,length); + kdWarning() << "d2i_X509_CRL not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::i2d_X509(X509 *a,unsigned char **pp) { + if (K_i2d_X509) return (K_i2d_X509)(a,pp); + kdWarning() << "i2d_X509 not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_cmp(X509 *a, X509 *b) { + if (K_X509_cmp) return (K_X509_cmp)(a,b); + kdWarning() << "X509_cmp not defined!" << endl; + return 0; +} + + +int KOpenSSLProxy::X509_subject_name_cmp(const X509 *a, const X509 *b) { + if (K_X509_subject_name_cmp) return (K_X509_subject_name_cmp)(a, b); + kdWarning() << "X509_subject_name_cmp not defined!" << endl; + return 0; +} + + +X509_STORE *KOpenSSLProxy::X509_STORE_new(void) { + if (K_X509_STORE_new) return (K_X509_STORE_new)(); + kdWarning() << "X509_STORE_new not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::X509_STORE_free(X509_STORE *v) { + if (K_X509_STORE_free) (K_X509_STORE_free)(v); + else kdWarning() << "X509_STORE_free not defined!" << endl; +} + + +X509_STORE_CTX *KOpenSSLProxy::X509_STORE_CTX_new(void) { + if (K_X509_STORE_CTX_new) return (K_X509_STORE_CTX_new)(); + kdWarning() << "X509_STORE_CTX_new not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::X509_STORE_CTX_free(X509_STORE_CTX *ctx) { + if (K_X509_STORE_CTX_free) (K_X509_STORE_CTX_free)(ctx); + else kdWarning() << "X509_STORE_CTX_free not defined!" << endl; +} + + +int KOpenSSLProxy::X509_verify_cert(X509_STORE_CTX *ctx) { + if (K_X509_verify_cert) return (K_X509_verify_cert)(ctx); + kdWarning() << "X509_verify_cert not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::X509_free(X509 *a) { + if (K_X509_free) (K_X509_free)(a); + else kdWarning() << "X509_free not defined!" << endl; +} + + +void KOpenSSLProxy::X509_CRL_free(X509_CRL *a) { + if (K_X509_CRL_free) (K_X509_CRL_free)(a); + else kdWarning() << "X509_CRL_free not defined!" << endl; +} + + +char *KOpenSSLProxy::X509_NAME_oneline(X509_NAME *a,char *buf,int size) { + if (K_X509_NAME_oneline) return (K_X509_NAME_oneline)(a,buf,size); + kdWarning() << "X509_NAME_online not defined!" << endl; + return 0L; +} + + +X509_NAME *KOpenSSLProxy::X509_get_subject_name(X509 *a) { + if (K_X509_get_subject_name) return (K_X509_get_subject_name)(a); + kdWarning() << "X509_get_subject not defined!" << endl; + return 0L; +} + + +X509_NAME *KOpenSSLProxy::X509_get_issuer_name(X509 *a) { + if (K_X509_get_issuer_name) return (K_X509_get_issuer_name)(a); + kdWarning() << "X509_get_issuer not defined!" << endl; + return 0L; +} + + +X509_LOOKUP *KOpenSSLProxy::X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { + if (K_X509_STORE_add_lookup) return (K_X509_STORE_add_lookup)(v,m); + kdWarning() << "X509_STORE_add_lookup not defined!" << endl; + return 0L; +} + + +X509_LOOKUP_METHOD *KOpenSSLProxy::X509_LOOKUP_file(void) { + if (K_X509_LOOKUP_file) return (K_X509_LOOKUP_file)(); + kdWarning() << "X509_LOOKUP_file not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::X509_LOOKUP_free(X509_LOOKUP *x) { + if (K_X509_LOOKUP_free) (K_X509_LOOKUP_free)(x); + else kdWarning() << "X509_LOOKUP_free not defined!" << endl; +} + + +int KOpenSSLProxy::X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) { + if (K_X509_LOOKUP_ctrl) return (K_X509_LOOKUP_ctrl)(ctx,cmd,argc,argl,ret); + kdWarning() << "X509_LOOKUP_ctrl not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { + if (K_X509_STORE_CTX_init) (K_X509_STORE_CTX_init)(ctx,store,x509,chain); + else kdWarning() << "X509_STORE_CTX_init not defined!" << endl; +} + + +void KOpenSSLProxy::CRYPTO_free(void *x) { + if (K_CRYPTO_free) (K_CRYPTO_free)(x); + else kdWarning() << "CRYPTO_free not defined!" << endl; +} + + +X509 *KOpenSSLProxy::X509_dup(X509 *x509) { + if (K_X509_dup) return (K_X509_dup)(x509); + kdWarning() << "X509_dup not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x) { + if (K_X509_get0_signature) { + (X509_get0_signature)(psig, palg, x); + return; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (!x) return; + if (psig) *psig = x->signature; + if (palg) *palg = x->sig_alg; + return; +#endif + kdWarning() << "X509_get0_signature not defined!" << endl; +} + + +BIO *KOpenSSLProxy::BIO_new(BIO_METHOD *type) { + if (K_BIO_new) return (K_BIO_new)(type); + kdWarning() << "BIO_new not defined!" << endl; + return 0L; +} + + +BIO_METHOD *KOpenSSLProxy::BIO_s_mem(void) { + if (K_BIO_s_mem) return (K_BIO_s_mem)(); + kdWarning() << "BIO_s_mem not defined!" << endl; + return 0L; +} + + +BIO *KOpenSSLProxy::BIO_new_fp(FILE *stream, int close_flag) { + if (K_BIO_new_fp) return (K_BIO_new_fp)(stream, close_flag); + kdWarning() << "BIO_new_fp not defined!" << endl; + return 0L; +} + + +BIO *KOpenSSLProxy::BIO_new_mem_buf(void *buf, int len) { + if (K_BIO_new_mem_buf) return (K_BIO_new_mem_buf)(buf,len); + kdWarning() << "BIO_new_mem_buf not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::BIO_free(BIO *a) { + if (K_BIO_free) return (K_BIO_free)(a); + kdWarning() << "BIO_free not defined!" << endl; + return -1; +} + + +long KOpenSSLProxy::BIO_ctrl(BIO *bp,int cmd,long larg,void *parg) { + if (K_BIO_ctrl) return (K_BIO_ctrl)(bp,cmd,larg,parg); + kdWarning() << "BIO_ctrl not defined!" << endl; + return 0; // failure return for BIO_ctrl is quite individual, maybe we should abort() instead +} + + +int KOpenSSLProxy::BIO_write(BIO *b, const void *data, int len) { + if (K_BIO_write) return (K_BIO_write)(b, data, len); + kdWarning() << "BIO_write not defined!" << endl; + return -1; +} + + +void *KOpenSSLProxy::BIO_get_data(BIO *a) { + if (K_BIO_get_data) return (K_BIO_get_data)(a); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return a->ptr; +#endif + kdWarning() << "BIO_get_data not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::PEM_write_bio_X509(BIO *bp, X509 *x) { + if (K_PEM_ASN1_write_bio) return (K_PEM_ASN1_write_bio) ((int (*)())K_i2d_X509, PEM_STRING_X509, bp, (char *)x, 0L, 0L, 0, 0L, 0L); + kdWarning() << "PEM_write_bio_X509 not defined!" << endl; + return -1; +} + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +int KOpenSSLProxy::ASN1_i2d_fp(FILE *out,unsigned char *x) { + if (K_ASN1_item_i2d_fp && K_NETSCAPE_X509_it) + return (K_ASN1_item_i2d_fp)(K_NETSCAPE_X509_it, out, x); + kdWarning() << "ANS1_i2d_fp not defined!" << endl; + return -1; +} +#else +ASN1_METHOD *KOpenSSLProxy::X509_asn1_meth(void) { + if (K_X509_asn1_meth) return (K_X509_asn1_meth)(); + kdWarning() << "X509_ans1_meth not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::ASN1_i2d_fp(FILE *out,unsigned char *x) { + if (K_ASN1_i2d_fp && K_i2d_ASN1_HEADER) + return (K_ASN1_i2d_fp)((int (*)())K_i2d_ASN1_HEADER, out, x); + kdWarning() << "ANS1_i2d_fp not defined!" << endl; + return -1; +} +#endif + +int KOpenSSLProxy::X509_print(FILE *fp, X509 *x) { + if (K_X509_print_fp) return (K_X509_print_fp)(fp, x); + kdWarning() << "X509_print not defined!" << endl; + return -1; +} + + +PKCS12 *KOpenSSLProxy::d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { + if (K_d2i_PKCS12_fp) return (K_d2i_PKCS12_fp)(fp, p12); + kdWarning() << "d2i_PKCS12_fp not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass) { + if (K_PKCS12_newpass) return (K_PKCS12_newpass)(p12, oldpass, newpass); + kdWarning() << "PKCS12_newpass not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::i2d_PKCS12(PKCS12 *p12, unsigned char **p) { + if (K_i2d_PKCS12) return (K_i2d_PKCS12)(p12, p); + kdWarning() << "i2d_PKCS12 not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::i2d_PKCS12_fp(FILE *fp, PKCS12 *p12) { + if (K_i2d_PKCS12_fp) return (K_i2d_PKCS12_fp)(fp, p12); + kdWarning() << "i2d_PKCS12_fp not defined!" << endl; + return -1; +} + + +PKCS12 *KOpenSSLProxy::PKCS12_new(void) { + if (K_PKCS12_new) return (K_PKCS12_new)(); + kdWarning() << "PKCS12_new not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::PKCS12_free(PKCS12 *a) { + if (K_PKCS12_free) (K_PKCS12_free)(a); + else kdWarning() << "PKCS12_free not defined!" << endl; +} + + +int KOpenSSLProxy::PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, + X509 **cert, STACK_OF(X509) **ca) { + if (K_PKCS12_parse) return (K_PKCS12_parse) (p12, pass, pkey, cert, ca); + kdWarning() << "PKCS12_parse not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::EVP_PKEY_free(EVP_PKEY *x) { + if (K_EVP_PKEY_free) (K_EVP_PKEY_free)(x); + else kdWarning() << "EVP_PKEY_free not defined!" << endl; +} + + +EVP_PKEY* KOpenSSLProxy::EVP_PKEY_new() { + if (K_EVP_PKEY_new) return (K_EVP_PKEY_new)(); + kdWarning() << "EVP_PKEY_new not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::EVP_PKEY_base_id(const EVP_PKEY *pkey) { + if (K_EVP_PKEY_base_id) return (K_EVP_PKEY_base_id)(pkey); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return pkey->type; +#endif + kdWarning() << "EVP_PKEY_base_id not defined!" << endl; + return -1; +} + + +RSA* KOpenSSLProxy::EVP_PKEY_get0_RSA(EVP_PKEY *pkey) { + if (K_EVP_PKEY_get0_RSA) return (K_EVP_PKEY_get0_RSA)(pkey); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return pkey->pkey.rsa; +#endif + kdWarning() << "EVP_PKEY_get0_RSA not defined!" << endl; + return 0L; +} + + +DSA* KOpenSSLProxy::EVP_PKEY_get0_DSA(EVP_PKEY *pkey) { + if (K_EVP_PKEY_get0_DSA) return (K_EVP_PKEY_get0_DSA)(pkey); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return pkey->pkey.dsa; +#endif + kdWarning() << "EVP_PKEY_get0_DSA not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::X509_REQ_free(X509_REQ *x) { + if (K_X509_REQ_free) (K_X509_REQ_free)(x); + else kdWarning() << "X509_REQ_free not defined!" << endl; +} + + +X509_REQ* KOpenSSLProxy::X509_REQ_new() { + if (K_X509_REQ_new) return (K_X509_REQ_new)(); + kdWarning() << "X509_REQ_new not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { + if (K_SSL_CTX_use_PrivateKey) return (K_SSL_CTX_use_PrivateKey)(ctx,pkey); + kdWarning() << "SSL_CTX_use_PrivateKey not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { + if (K_SSL_CTX_use_certificate) return (K_SSL_CTX_use_certificate)(ctx,x); + kdWarning() << "SSL_CTX_use_certificate not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::SSL_get_error(SSL *ssl, int rc) { + if (K_SSL_get_error) return (K_SSL_get_error)(ssl,rc); + kdWarning() << "SSL_get_error not defined!" << endl; + return -1; +} + + +STACK_OF(X509) *KOpenSSLProxy::SSL_get_peer_cert_chain(SSL *s) { + if (K_SSL_get_peer_cert_chain) return (K_SSL_get_peer_cert_chain)(s); + kdWarning() << "SSL_get_peer_cert_chain not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::OPENSSL_sk_free(STACK *s) { + if (K_sk_free) (K_sk_free)(s); + else kdWarning() << "OPENSSL_sk_free not defined!" << endl; +} + + +int KOpenSSLProxy::OPENSSL_sk_num(STACK *s) { + if (K_sk_num) return (K_sk_num)(s); + kdWarning() << "OPENSSL_sk_num not defined!" << endl; + return -1; +} + + +char *KOpenSSLProxy::OPENSSL_sk_pop(STACK *s) { + if (K_sk_pop) return (K_sk_pop)(s); + kdWarning() << "OPENSSL_sk_pop not defined!" << endl; + return 0L; +} + + +char *KOpenSSLProxy::OPENSSL_sk_value(STACK *s, int n) { + if (K_sk_value) return (K_sk_value)(s, n); + kdWarning() << "OPENSSL_sk_value not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *v, STACK_OF(X509)* x) { + if (K_X509_STORE_CTX_set0_untrusted) (K_X509_STORE_CTX_set0_untrusted)(v,x); + else kdWarning() << "X509_STORE_CTX_set0_untrusted not defined!" << endl; +} + +void KOpenSSLProxy::X509_STORE_CTX_set_purpose(X509_STORE_CTX *v, int purpose) { + if (K_X509_STORE_CTX_set_purpose) (K_X509_STORE_CTX_set_purpose)(v,purpose); + else kdWarning() << "X509_STORE_CTX_set_purpose not defined!" << endl; +} + + +STACK* KOpenSSLProxy::OPENSSL_sk_dup(const STACK *s) { + if (K_sk_dup) return (K_sk_dup)(s); + kdWarning() << "OPENSSL_sk_dup not defined!" << endl; + return 0L; +} + + +STACK* KOpenSSLProxy::OPENSSL_sk_new(int (*cmp)()) { + if (K_sk_new) return (K_sk_new)(cmp); + kdWarning() << "OPENSSL_sk_new not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::OPENSSL_sk_push(STACK* s, char* d) { + if (K_sk_push) return (K_sk_push)(s,d); + kdWarning() << "OPENSSL_sk_push not defined!" << endl; + return -1; +} + + +char *KOpenSSLProxy::i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint) { + if (K_i2s_ASN1_INTEGER) return (K_i2s_ASN1_INTEGER)(meth, aint); + kdWarning() << "i2s_ANS1_INTEGER not defined!" << endl; + return 0L; +} + + +ASN1_INTEGER *KOpenSSLProxy::X509_get_serialNumber(X509 *x) { + if (K_X509_get_serialNumber) return (K_X509_get_serialNumber)(x); + kdWarning() << "X509_get_serialNumber not defined!" << endl; + return 0L; +} + + +EVP_PKEY *KOpenSSLProxy::X509_get_pubkey(X509 *x) { + if (K_X509_get_pubkey) return (K_X509_get_pubkey)(x); + kdWarning() << "X59_get_pubkey not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) { + if (K_i2d_PublicKey) return (K_i2d_PublicKey)(a,pp); + kdWarning() << "i2d_PublicKey not defined!" << endl; + return 0; +} + + +int KOpenSSLProxy::X509_check_private_key(X509 *x, EVP_PKEY *p) { + if (K_X509_check_private_key) return (K_X509_check_private_key)(x,p); + kdWarning() << "X509_check_private_key not defined!" << endl; + return -1; +} + + +char *KOpenSSLProxy::BN_bn2hex(const BIGNUM *a) { + if (K_BN_bn2hex) return (K_BN_bn2hex)(a); + kdWarning() << "BN_bn2hex not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::X509_digest(const X509 *x,const EVP_MD *t, unsigned char *md, unsigned int *len) { + if (K_X509_digest) return (K_X509_digest)(x, t, md, len); + kdWarning() << "X509_digest not defined!" << endl; + return -1; +} + + +EVP_MD *KOpenSSLProxy::EVP_md5() { + if (K_EVP_md5) return (K_EVP_md5)(); + kdWarning() << "EVP_md5 not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::ASN1_INTEGER_free(ASN1_INTEGER *a) { + if (K_ASN1_INTEGER_free) (K_ASN1_INTEGER_free)(a); + else kdWarning() << "ANS1_INTEGER_free not defined!" << endl; +} + + +int KOpenSSLProxy::OBJ_obj2nid(ASN1_OBJECT *o) { + if (K_OBJ_obj2nid) return (K_OBJ_obj2nid)(o); + kdWarning() << "OBJ_obj2nid not defined!" << endl; + return -1; +} + + +const char * KOpenSSLProxy::OBJ_nid2ln(int n) { + if (K_OBJ_nid2ln) return (K_OBJ_nid2ln)(n); + kdWarning() << "OBJ_nid2ln not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::X509_get_ext_count(X509 *x) { + if (K_X509_get_ext_count) return (K_X509_get_ext_count)(x); + kdWarning() << "X509_get_ext_count not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_get_ext_by_NID(X509 *x, int nid, int lastpos) { + if (K_X509_get_ext_by_NID) return (K_X509_get_ext_by_NID)(x,nid,lastpos); + kdWarning() << "X509_get_ext_by_NID not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos) { + if (K_X509_get_ext_by_OBJ) return (K_X509_get_ext_by_OBJ)(x,obj,lastpos); + kdWarning() << "X509_get_ext_by_OBJ not defined!" << endl; + return -1; +} + + +X509_EXTENSION *KOpenSSLProxy::X509_get_ext(X509 *x, int loc) { + if (K_X509_get_ext) return (K_X509_get_ext)(x,loc); + kdWarning() << "X509_get_ext not defined!" << endl; + return 0L; +} + + +X509_EXTENSION *KOpenSSLProxy::X509_delete_ext(X509 *x, int loc) { + if (K_X509_delete_ext) return (K_X509_delete_ext)(x,loc); + kdWarning() << "X509_delete_ext not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) { + if (K_X509_add_ext) return (K_X509_add_ext)(x,ex,loc); + kdWarning() << "X509_add_ext not defined!" << endl; + return -1; +} + + +void *KOpenSSLProxy::X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) { + if (K_X509_get_ext_d2i) return (K_X509_get_ext_d2i)(x,nid,crit,idx); + kdWarning() << "X509_get_ext_d2i not defined!" << endl; + return 0L; +} + + +char *KOpenSSLProxy::i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5) { + if (K_i2s_ASN1_OCTET_STRING) return (K_i2s_ASN1_OCTET_STRING)(method,ia5); + kdWarning() << "i2s_ANS1_OCTET_STRING not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n) { + if (K_ASN1_BIT_STRING_get_bit) return (K_ASN1_BIT_STRING_get_bit)(a,n); + kdWarning() << "ANS1_BIT_STRING_get_bit not defined!" << endl; + return -1; +} + + +PKCS7 *KOpenSSLProxy::PKCS7_new(void) { + if (K_PKCS7_new) return (K_PKCS7_new)(); + kdWarning() << "PKCS7_new not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::PKCS7_free(PKCS7 *a) { + if (K_PKCS7_free) (K_PKCS7_free)(a); + else kdWarning() << "PKCS7_free not defined!" << endl; +} + + +void KOpenSSLProxy::PKCS7_content_free(PKCS7 *a) { + if (K_PKCS7_content_free) (K_PKCS7_content_free)(a); + else kdWarning() << "PKCS7_content_free not defined!" << endl; +} + + +int KOpenSSLProxy::i2d_PKCS7(PKCS7 *a, unsigned char **pp) { + if (K_i2d_PKCS7) return (K_i2d_PKCS7)(a,pp); + kdWarning() << "i2d_PKCS7 not defined!" << endl; + return -1; +} + + +PKCS7 *KOpenSSLProxy::d2i_PKCS7(PKCS7 **a, unsigned char **pp,long length) { + if (K_d2i_PKCS7) return (K_d2i_PKCS7)(a,pp,length); + kdWarning() << "d2i_PKCS7 not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::i2d_PKCS7_fp(FILE *fp,PKCS7 *p7) { + if (K_i2d_PKCS7_fp) return (K_i2d_PKCS7_fp)(fp,p7); + kdWarning() << "i2d_PKCS7_fd not defined!" << endl; + return -1; +} + + +PKCS7 *KOpenSSLProxy::d2i_PKCS7_fp(FILE *fp,PKCS7 **p7) { + if (K_d2i_PKCS7_fp) return (K_d2i_PKCS7_fp)(fp,p7); + kdWarning() << "d2i_PKCS7_fp not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::i2d_PKCS7_bio(BIO *bp,PKCS7 *p7) { + if (K_i2d_PKCS7_bio) return (K_i2d_PKCS7_bio)(bp, p7); + kdWarning() << "i2d_PKCS7_bio not defined!" << endl; + return -1; +} + + +PKCS7 *KOpenSSLProxy::d2i_PKCS7_bio(BIO *bp,PKCS7 **p7) { + if (K_d2i_PKCS7_bio) return (K_d2i_PKCS7_bio)(bp, p7); + kdWarning() << "d2i_PKCS7_bio not defined!" << endl; + return 0L; +} + + +PKCS7 *KOpenSSLProxy::PKCS7_dup(PKCS7 *p7) { + if (K_PKCS7_dup) return (K_PKCS7_dup)(p7); + kdWarning() << "PKCS7_dup not defined!" << endl; + return 0L; +} + + +PKCS7 *KOpenSSLProxy::PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags) { + if (K_PKCS7_sign) return (K_PKCS7_sign)(signcert,pkey,certs,data,flags); + kdWarning() << "PKCS7_sign not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::PKCS7_verify(PKCS7* p, STACK_OF(X509)* st, X509_STORE* s, BIO* in, BIO *out, int flags) { + if (K_PKCS7_verify) return (K_PKCS7_verify)(p,st,s,in,out,flags); + kdWarning() << "PKCS7_verify not defined!" << endl; + return 0; +} + + +STACK_OF(X509) *KOpenSSLProxy::PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) { + if (K_PKCS7_get0_signers) return (K_PKCS7_get0_signers)(p7,certs,flags); + kdWarning() << "PKCS7_get0_signers not defined!" << endl; + return 0L; +} + + +PKCS7 *KOpenSSLProxy::PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, + int flags) { + if (K_PKCS7_encrypt) return (K_PKCS7_encrypt)(certs,in,cipher,flags); + kdWarning() << "PKCS7_encrypt not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) { + if (K_PKCS7_decrypt) return (K_PKCS7_decrypt)(p7,pkey,cert,data,flags); + kdWarning() << "PKCS7_decrypt not defined!" << endl; + return 0; +} + + +STACK_OF(X509_NAME) *KOpenSSLProxy::SSL_load_client_CA_file(const char *file) { + if (K_SSL_load_client_CA_file) return (K_SSL_load_client_CA_file)(file); + kdWarning() << "SSL_load_client_CA_file not defined!" << endl; + return 0L; +} + + +STACK_OF(X509_INFO) *KOpenSSLProxy::PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u) { + if (K_PEM_X509_INFO_read) return (K_PEM_X509_INFO_read)(fp,sk,cb,u); + kdWarning() << "PEM_X509_INFO_read not defined!" << endl; + return 0L; +} + + +X509 *KOpenSSLProxy::X509_d2i_fp(FILE *out, X509** buf) { + if (K_ASN1_d2i_fp) return reinterpret_cast((K_ASN1_d2i_fp)(reinterpret_cast(K_X509_new), reinterpret_cast(K_d2i_X509), out, reinterpret_cast(buf))); + kdWarning() << "X509_d2i_fp not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::SSL_peek(SSL *ssl,void *buf,int num) { + if (K_SSL_peek) return (K_SSL_peek)(ssl,buf,num); + kdWarning() << "SSL_peek not defined!" << endl; + return -1; +} + + +const char *KOpenSSLProxy::RAND_file_name(char *buf, size_t num) { + if (K_RAND_file_name) return (K_RAND_file_name)(buf, num); + kdWarning() << "RAND_file_name not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::RAND_load_file(const char *filename, long max_bytes) { + if (K_RAND_load_file) return (K_RAND_load_file)(filename, max_bytes); + kdWarning() << "REND_load_file not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::RAND_write_file(const char *filename) { + if (K_RAND_write_file) return (K_RAND_write_file)(filename); + kdWarning() << "RAND_write_file not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_PURPOSE_get_count() { + if (K_X509_PURPOSE_get_count) return (K_X509_PURPOSE_get_count)(); + kdWarning() << "X509_PURPOSE_get_count not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_PURPOSE_get_id(X509_PURPOSE *p) { + if (K_X509_PURPOSE_get_id) return (K_X509_PURPOSE_get_id)(p); + kdWarning() << "X509_PURPOSE_get_id not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_check_purpose(X509 *x, int id, int ca) { + if (K_X509_check_purpose) return (K_X509_check_purpose)(x, id, ca); + kdWarning() << "X509_check_purpose not defined!" << endl; + return -1; +} + + +X509_PURPOSE *KOpenSSLProxy::X509_PURPOSE_get0(int idx) { + if (K_X509_PURPOSE_get0) return (K_X509_PURPOSE_get0)(idx); + kdWarning() << "X509_PURPOSE_get0 not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key) { + if (K_EVP_PKEY_assign) return (K_EVP_PKEY_assign)(pkey, type, key); + kdWarning() << "EVP_PKEY_assign not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { + if (K_X509_REQ_set_pubkey) return (K_X509_REQ_set_pubkey)(x, pkey); + kdWarning() << "X509_REQ_set_pubkey not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { + if (K_RSA_get0_key) { + (K_RSA_get0_key)(r, n, e, d); + return; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (!r) return; + if (n) *n = r->n; + if (e) *e = r->e; + if (d) *d = r->d; + return; +#endif + kdWarning() << "REG_get0_key not defined!" << endl; +} + + +RSA* KOpenSSLProxy::RSA_generate_key(int bits, unsigned long e, void + (*callback)(int,int,void *), void *cb_arg) { + if (K_RSA_generate_key) return (K_RSA_generate_key)(bits, e, callback, cb_arg); + kdWarning() << "RSA_generate_key not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (K_DSA_get0_pqg) { + (K_DSA_get0_pqg)(d, p, q, g); + return; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (!d) return; + if (p) *p = d->p; + if (q) *q = d->q; + if (g) *g = d->g; + return; +#endif + kdWarning() << "DSA_get0_pqg not defined!" << endl; +} + + +void KOpenSSLProxy::DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (K_DSA_get0_key) { + (K_DSA_get0_key)(d, pub_key, priv_key); + return; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (!d) return; + if (pub_key) *pub_key = d->pub_key; + if (priv_key) *priv_key = d->priv_key; + return; +#endif + kdWarning() << "DSA_get0_key not defined!" << endl; +} + + +STACK *KOpenSSLProxy::X509_get1_email(X509 *x) { + if (K_X509_get1_email) return (K_X509_get1_email)(x); + kdWarning() << "X509_get1_email not defined!" << endl; + return 0L; +} + +void KOpenSSLProxy::X509_email_free(STACK *sk) { + if (K_X509_email_free) (K_X509_email_free)(sk); + else kdWarning() << "X509_email_free not defined!" << endl; +} + +EVP_CIPHER *KOpenSSLProxy::EVP_des_ede3_cbc() { + if (K_EVP_des_ede3_cbc) return (K_EVP_des_ede3_cbc)(); + kdWarning() << "EVM_des_ede3_cbc not defined!" << endl; + return 0L; +} + +EVP_CIPHER *KOpenSSLProxy::EVP_des_cbc() { + if (K_EVP_des_cbc) return (K_EVP_des_cbc)(); + kdWarning() << "EVP_des_cbc not defined!" << endl; + return 0L; +} + +EVP_CIPHER *KOpenSSLProxy::EVP_rc2_cbc() { + if (K_EVP_rc2_cbc) return (K_EVP_rc2_cbc)(); + kdWarning() << "EVP_rc2_cbc not defined!" << endl; + return 0L; +} + +EVP_CIPHER *KOpenSSLProxy::EVP_rc2_64_cbc() { + if (K_EVP_rc2_64_cbc) return (K_EVP_rc2_64_cbc)(); + kdWarning() << "EVP_rc2_64_cbc not defined!" << endl; + return 0L; +} + +EVP_CIPHER *KOpenSSLProxy::EVP_rc2_40_cbc() { + if (K_EVP_rc2_40_cbc) return (K_EVP_rc2_40_cbc)(); + kdWarning() << "EVP_rc2_40_cbc not defined!" << endl; + return 0L; +} + +int KOpenSSLProxy::i2d_X509_REQ_fp(FILE *fp, X509_REQ *x) { + if (K_i2d_X509_REQ_fp) return (K_i2d_X509_REQ_fp)(fp,x); + kdWarning() << "i2d_X509_REQ_fp not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::ERR_clear_error() { + if (K_ERR_clear_error) (K_ERR_clear_error)(); + else kdWarning() << "ERR_clear_error not defined!" << endl; +} + + +unsigned long KOpenSSLProxy::ERR_get_error() { + if (K_ERR_get_error) return (K_ERR_get_error)(); + kdWarning() << "ERR_get_error not defined!" << endl; + return 0xffffffff; +} + + +void KOpenSSLProxy::ERR_print_errors_fp(FILE* fp) { + if (K_ERR_print_errors_fp) (K_ERR_print_errors_fp)(fp); + else kdWarning() << "ERR_print_errors_fp not defined!" << endl; +} + + +SSL_SESSION *KOpenSSLProxy::SSL_get1_session(SSL *ssl) { + if (K_SSL_get1_session) return (K_SSL_get1_session)(ssl); + kdWarning() << "SSL_get1_session not defined!" << endl; + return 0L; +} + + +void KOpenSSLProxy::SSL_SESSION_free(SSL_SESSION *session) { + if (K_SSL_SESSION_free) (K_SSL_SESSION_free)(session); + else kdWarning() << "SSL_SESSION_free not defined!" << endl; +} + + +int KOpenSSLProxy::SSL_set_session(SSL *ssl, SSL_SESSION *session) { + if (K_SSL_set_session) return (K_SSL_set_session)(ssl, session); + kdWarning() << "SSL_set_session not defined!" << endl; + return -1; +} + + +SSL_SESSION *KOpenSSLProxy::d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, long length) { + if (K_d2i_SSL_SESSION) return (K_d2i_SSL_SESSION)(a, pp, length); + kdWarning() << "d2i_SSL_SESSION not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) { + if (K_i2d_SSL_SESSION) return (K_i2d_SSL_SESSION)(in, pp); + kdWarning() << "i2d_SSL_SESSION not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *p) { + if (K_i2d_PrivateKey_fp) return (K_i2d_PrivateKey_fp)(fp, p); + kdWarning() << "i2d_PrivateKey not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *p, const EVP_CIPHER *c, char *k, int klen, pem_password_cb *cb, void *u) { + if (K_i2d_PKCS8PrivateKey_fp) return (K_i2d_PKCS8PrivateKey_fp)(fp, p, c, k, klen, cb, u); + kdWarning() << "i2d_PKCS8PrivateKey_fp not defined!" << endl; + return -1; +} + + +void KOpenSSLProxy::RSA_free(RSA *rsa) { + if (K_RSA_free) (K_RSA_free)(rsa); + else kdWarning() << "RSA_free not defined!" << endl; +} + + +EVP_CIPHER *KOpenSSLProxy::EVP_bf_cbc() { + if (K_EVP_bf_cbc) return (K_EVP_bf_cbc)(); + kdWarning() << "EVP_bf_cbc not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { + if (K_X509_REQ_sign) return (K_X509_REQ_sign)(x, pkey, md); + kdWarning() << "X509_REQ_sign not defined!" << endl; + return -1; +} + + +int KOpenSSLProxy::X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, + int type, unsigned char *bytes, int len, int loc, int set) { + if (K_X509_NAME_add_entry_by_txt) return (K_X509_NAME_add_entry_by_txt)(name, field, type, bytes, len, loc, set); + kdWarning() << "X509_NAME_add_entry not defined!" << endl; + return -1; +} + + +X509_NAME *KOpenSSLProxy::X509_NAME_new() { + if (K_X509_NAME_new) return (K_X509_NAME_new)(); + kdWarning() << "X509_NAME_new not defined!" << endl; + return 0L; +} + + +int KOpenSSLProxy::X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name) { + if (K_X509_REQ_set_subject_name) return (K_X509_REQ_set_subject_name)(req, name); + kdWarning() << "X509_REQ_set_subject_name not defined!" << endl; + return -1; +} + + +unsigned char *KOpenSSLProxy::ASN1_STRING_data(ASN1_STRING *x) { + if (K_ASN1_STRING_data) return (K_ASN1_STRING_data)(x); + kdWarning() << "ASN1_STRING_data not defined!" << endl; + return 0L; +} + +int KOpenSSLProxy::ASN1_STRING_length(ASN1_STRING *x) { + if (K_ASN1_STRING_length) return (K_ASN1_STRING_length)(x); + kdWarning() << "ASN1_STRING_length not defined!" << endl; + return 0L; +} + +STACK_OF(SSL_CIPHER) *KOpenSSLProxy::SSL_get_ciphers(const SSL* ssl) { + if (K_SSL_get_ciphers) return (K_SSL_get_ciphers)(ssl); + kdWarning() << "SSL_get_ciphers not defined!" << endl; + return 0L; +} + +const ASN1_TIME* KOpenSSLProxy::X509_CRL_get0_lastUpdate(const X509_CRL *crl) { + if (K_X509_CRL_get0_lastUpdate) return (K_X509_CRL_get0_lastUpdate)(crl); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return X509_CRL_get_lastUpdate(crl); +#endif + kdWarning() << "X509_CRL_get_lastUpdate not defined!" << endl; + return 0L; +} + +const ASN1_TIME* KOpenSSLProxy::X509_CRL_get0_nextUpdate(const X509_CRL *crl) { + if (K_X509_CRL_get0_nextUpdate) return (K_X509_CRL_get0_nextUpdate)(crl); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return X509_CRL_get_nextUpdate(crl); +#endif + kdWarning() << "X509_CRL_get_nextUpdate not defined!" << endl; + return 0L; +} + +X509* KOpenSSLProxy::X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) { + if (K_X509_STORE_CTX_get_current_cert) return (K_X509_STORE_CTX_get_current_cert)(ctx); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return ctx->current_cert; +#endif + kdWarning() << "X509_STORE_CTX_get_current_cert not defined!" << endl; + return 0L; +} + +int KOpenSSLProxy::X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) { + if (K_X509_STORE_CTX_get_error) return (K_X509_STORE_CTX_get_error)(ctx); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return ctx->error; +#endif + kdWarning() << "X509k_STORE_CTX_get_error not defined!" << endl; + return -1; +} + +int KOpenSSLProxy::X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) { + if (K_X509_STORE_CTX_get_error_depth) return (K_X509_STORE_CTX_get_error_depth)(ctx); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return ctx->error_depth; +#endif + kdWarning() << "X509_STORE_CTX_get_error_depth not defined!" << endl; + return -1; +} + +void KOpenSSLProxy::X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) { + if (K_X509_STORE_CTX_set_error) { + (K_X509_STORE_CTX_set_error)(ctx, s); + return; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + ctx->error = s; + return; +#endif + kdWarning() << "X509_STORE_CTX_set_error not defined!" << endl; +} + +void KOpenSSLProxy::X509_STORE_set_verify_cb(X509_STORE *ctx, + X509_STORE_CTX_verify_cb verify_cb) { + if (K_X509_STORE_set_verify_cb) { + (K_X509_STORE_set_verify_cb)(ctx, verify_cb); + return; + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + X509_STORE_set_verify_cb_func(ctx, verify_cb); + return; +#endif + kdWarning() << "X590_STORE_set_verify_cb not defined!" << endl; +} + +STACK_OF(X509_OBJECT)* KOpenSSLProxy::X509_STORE_get0_objects(X509_STORE *v) { + if (K_X509_STORE_get0_objects) return (K_X509_STORE_get0_objects)(v); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return v->objs; +#endif + kdWarning() << "X509_STORE_get0_objects not defined!" << endl; + return 0L; +} + +X509_LOOKUP_TYPE KOpenSSLProxy::X509_OBJECT_get_type(const X509_OBJECT *a) { + if (K_X509_OBJECT_get_type) return (K_X509_OBJECT_get_type)(a); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return a->type; +#endif + kdWarning() << "X509_OBJECT_get_type not defined!" << endl; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + return X509_LU_NONE; +#else + return 0; +#endif +} + +X509* KOpenSSLProxy::X509_OBJECT_get0_X509(const X509_OBJECT *a) { + if (K_X509_OBJECT_get0_X509) return (K_X509_OBJECT_get0_X509)(a); +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + return a->data.x509; +#endif + kdWarning() << "X509_OBJECT_get0_X509 not defined!" << endl; + return 0L; +} + + +ASN1_TIME* KOpenSSLProxy::X509_getm_notAfter(const X509 *x) { + if (K_X509_getm_notAfter) return (K_X509_getm_notAfter)(x); +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + return X509_get_notAfter(x); +#endif + kdWarning() << "X509_get_notAfter not defined!" << endl; + return 0L; +} + +ASN1_TIME* KOpenSSLProxy::X509_getm_notBefore(const X509 *x) { + if (K_X509_getm_notBefore) return (K_X509_getm_notBefore)(x); +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + return X509_get_notBefore(x); +#endif + kdWarning() << "X509_get_notBefore not defined!" << endl; + return 0L; +} + +/* cover KOpenSSLProxy API compatibility */ +STACK* KOpenSSLProxy::sk_dup(const STACK *s) { + return OPENSSL_sk_dup(s); +} + +void KOpenSSLProxy::sk_free(STACK *s) { + OPENSSL_sk_free(s); +} + +STACK* KOpenSSLProxy::sk_new(int (*cmp)()) { + return OPENSSL_sk_new(cmp); +} + +int KOpenSSLProxy::sk_num(STACK *s) { + return OPENSSL_sk_num(s); +} + +char* KOpenSSLProxy::sk_pop(STACK *s) { + return OPENSSL_sk_pop(s); +} + +int KOpenSSLProxy::sk_push(STACK *s, char *d) { + return OPENSSL_sk_push(s, d); +} + +char* KOpenSSLProxy::sk_value(STACK *s, int n) { + return OPENSSL_sk_value(s, n); +} + +void KOpenSSLProxy::X509_STORE_CTX_set_chain(X509_STORE_CTX *v, STACK_OF(X509)* x) { + X509_STORE_CTX_set0_untrusted(v, x); +} + +SSL_METHOD* KOpenSSLProxy::SSLv23_client_method() { + return TLS_client_method(); +} + +#endif diff --git a/tdeio/kssl/ksmimecrypto.cc b/tdeio/kssl/ksmimecrypto.cc deleted file mode 100644 index 92318b9f0..000000000 --- a/tdeio/kssl/ksmimecrypto.cc +++ /dev/null @@ -1,417 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2003 Stefan Rompf - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include -#include -#include -#include - -#include "kopenssl.h" -#include "ksslcertificate.h" -#include "ksslpkcs12.h" -#include "ksmimecrypto.h" - -// this hack provided by Malte Starostik to avoid glibc/openssl bug -// on some systems -#ifdef KSSL_HAVE_SSL -#define crypt _openssl_crypt -#include -#undef crypt -#endif - - -#ifdef KSSL_HAVE_SSL -static const char eot = 0; - -class KSMIMECryptoPrivate { - KOpenSSLProxy *kossl; - -public: - KSMIMECryptoPrivate(KOpenSSLProxy *kossl); - - - STACK_OF(X509) *certsToX509(TQPtrList &certs); - - KSMIMECrypto::rc signMessage(BIO *clearText, - BIO *cipherText, - KSSLPKCS12 &privKey, TQPtrList &certs, - bool detached); - - KSMIMECrypto::rc encryptMessage(BIO *clearText, - BIO *cipherText, KSMIMECrypto::algo algorithm, - TQPtrList &recip); - - KSMIMECrypto::rc checkSignature(BIO *clearText, - BIO *signature, bool detached, - TQPtrList &recip); - - KSMIMECrypto::rc decryptMessage(BIO *cipherText, - BIO *clearText, - KSSLPKCS12 &privKey); - - void MemBIOToQByteArray(BIO *src, TQByteArray &dest); - - KSMIMECrypto::rc sslErrToRc(void); -}; - - -KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) { -} - - -STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList &certs) { - STACK_OF(X509) *x509 = reinterpret_cast(kossl->OPENSSL_sk_new(NULL)); - KSSLCertificate *cert = certs.first(); - while(cert) { - kossl->OPENSSL_sk_push(x509, cert->getCert()); - cert = certs.next(); - } - return x509; -} - - -KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText, - BIO *cipherText, - KSSLPKCS12 &privKey, TQPtrList &certs, - bool detached) { - - STACK_OF(X509) *other = NULL; - KSMIMECrypto::rc rc; - int flags = detached?PKCS7_DETACHED:0; - - if (certs.count()) other = certsToX509(certs); - - PKCS7 *p7 = kossl->PKCS7_sign(privKey.getCertificate()->getCert(), privKey.getPrivateKey(), - other, clearText, flags); - - if (other) kossl->OPENSSL_sk_free(other); - - if (!p7) return sslErrToRc(); - - if (kossl->i2d_PKCS7_bio(cipherText, p7)) { - rc = KSMIMECrypto::KSC_R_OK; - } else { - rc = sslErrToRc(); - } - - kossl->PKCS7_free(p7); - - return rc; -} - -KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText, - BIO *cipherText, KSMIMECrypto::algo algorithm, - TQPtrList &recip) { - EVP_CIPHER *cipher = NULL; - KSMIMECrypto::rc rc; - switch(algorithm) { - case KSMIMECrypto::KSC_C_DES3_CBC: - cipher = kossl->EVP_des_ede3_cbc(); - break; - case KSMIMECrypto::KSC_C_RC2_CBC_128: - cipher = kossl->EVP_rc2_cbc(); - break; - case KSMIMECrypto::KSC_C_RC2_CBC_64: - cipher = kossl->EVP_rc2_64_cbc(); - break; - case KSMIMECrypto::KSC_C_DES_CBC: - cipher = kossl->EVP_des_cbc(); - break; - case KSMIMECrypto::KSC_C_RC2_CBC_40: - cipher = kossl->EVP_rc2_40_cbc(); - break; - } - if (!cipher) return KSMIMECrypto::KSC_R_NOCIPHER; - - STACK_OF(X509) *certs = certsToX509(recip); - - PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0); - - kossl->OPENSSL_sk_free(certs); - - if (!p7) return sslErrToRc(); - - if (kossl->i2d_PKCS7_bio(cipherText, p7)) { - rc = KSMIMECrypto::KSC_R_OK; - } else { - rc = sslErrToRc(); - } - - kossl->PKCS7_free(p7); - - return rc; -} - - -KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText, - BIO *signature, bool detached, - TQPtrList &recip) { - - PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL); - KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER; - - if (!p7) return sslErrToRc(); - - BIO *in; - BIO *out; - if (detached) { - in = clearText; - out = NULL; - } else { - in = NULL; - out = clearText; - } - - X509_STORE *dummystore = kossl->X509_STORE_new(); - if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) { - STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY); - int num = kossl->OPENSSL_sk_num(signers); - - for(int n=0; n(kossl->OPENSSL_sk_value(signers, n))); - recip.append(signer); - } - - kossl->OPENSSL_sk_free(signers); - rc = KSMIMECrypto::KSC_R_OK; - } else { - rc = sslErrToRc(); - } - - kossl->X509_STORE_free(dummystore); - kossl->PKCS7_free(p7); - - return rc; -} - - -KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText, - BIO *clearText, - KSSLPKCS12 &privKey) { - - PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL); - KSMIMECrypto::rc rc; - - if (!p7) return sslErrToRc(); - - if (kossl->PKCS7_decrypt(p7, privKey.getPrivateKey(), privKey.getCertificate()->getCert(), - clearText, 0)) { - rc = KSMIMECrypto::KSC_R_OK; - } else { - rc = sslErrToRc(); - } - - kossl->PKCS7_free(p7); - - return rc; -} - - -void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) { - char *buf; - long len = kossl->BIO_get_mem_data(src, &buf); - dest.assign(buf, len); - /* Now this goes quite a bit into openssl internals. - We assume that openssl uses malloc() (it does in - default config) and rip out the buffer. - */ - void *ptr = kossl->BIO_get_data(src); - reinterpret_cast(ptr)->data = NULL; -} - - -KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(void) { - unsigned long cerr = kossl->ERR_get_error(); - - // To be completed and possibly fixed - - switch(ERR_GET_REASON(cerr)) { - case ERR_R_MALLOC_FAILURE: - return KSMIMECrypto::KSC_R_NOMEM; - } - - switch(ERR_GET_LIB(cerr)) { - case ERR_LIB_PKCS7: - switch(ERR_GET_REASON(cerr)) { - case PKCS7_R_WRONG_CONTENT_TYPE: - case PKCS7_R_NO_CONTENT: - case PKCS7_R_NO_SIGNATURES_ON_DATA: - return KSMIMECrypto::KSC_R_FORMAT; - break; - case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE: - case PKCS7_R_DECRYPT_ERROR: // Hmm? - return KSMIMECrypto::KSC_R_WRONGKEY; - break; - case PKCS7_R_DIGEST_FAILURE: - return KSMIMECrypto::KSC_R_VERIFY; - default: - break; - } - break; - default: - break; - } - - kdDebug(7029) <<"KSMIMECrypto: uncaught error " <hasLibCrypto()) kossl = 0L; -#else - kossl = 0L; -#endif -} - - -KSMIMECrypto::~KSMIMECrypto() { -#ifdef KSSL_HAVE_SSL - delete priv; -#endif -} - - -KSMIMECrypto::rc KSMIMECrypto::signMessage(const TQCString &clearText, - TQByteArray &cipherText, - const KSSLPKCS12 &privKey, - const TQPtrList &certs, - bool detached) { -#ifdef KSSL_HAVE_SSL - if (!kossl) return KSC_R_NO_SSL; - BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size()); - BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); - - rc rc = priv->signMessage(in, out, - const_cast(privKey), - const_cast &>(certs), - detached); - - if (!rc) priv->MemBIOToQByteArray(out, cipherText); - - kossl->BIO_free(out); - kossl->BIO_free(in); - - return rc; -#else - return KSC_R_NO_SSL; -#endif -} - - -KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(const TQCString &clearText, - const TQByteArray &signature, - TQPtrList &foundCerts) { -#ifdef KSSL_HAVE_SSL - if (!kossl) return KSC_R_NO_SSL; - BIO *txt = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.length()); - BIO *sig = kossl->BIO_new_mem_buf((char *)signature.data(), signature.size()); - - rc rc = priv->checkSignature(txt, sig, true, foundCerts); - - kossl->BIO_free(sig); - kossl->BIO_free(txt); - - return rc; -#else - return KSC_R_NO_SSL; -#endif -} - - -KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(const TQByteArray &signedText, - TQCString &clearText, - TQPtrList &foundCerts) { -#ifdef KSSL_HAVE_SSL - if (!kossl) return KSC_R_NO_SSL; - - BIO *in = kossl->BIO_new_mem_buf((char *)signedText.data(), signedText.size()); - BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); - - rc rc = priv->checkSignature(out, in, false, foundCerts); - - kossl->BIO_write(out, &eot, 1); - priv->MemBIOToQByteArray(out, clearText); - - kossl->BIO_free(out); - kossl->BIO_free(in); - - return rc; -#else - return KSC_R_NO_SSL; -#endif -} - - -KSMIMECrypto::rc KSMIMECrypto::encryptMessage(const TQCString &clearText, - TQByteArray &cipherText, - algo algorithm, - const TQPtrList &recip) { -#ifdef KSSL_HAVE_SSL - if (!kossl) return KSC_R_NO_SSL; - - BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size()); - BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); - - rc rc = priv->encryptMessage(in,out,algorithm, - const_cast< TQPtrList &>(recip)); - - if (!rc) priv->MemBIOToQByteArray(out, cipherText); - - kossl->BIO_free(out); - kossl->BIO_free(in); - - return rc; -#else - return KSC_R_NO_SSL; -#endif -} - - -KSMIMECrypto::rc KSMIMECrypto::decryptMessage(const TQByteArray &cipherText, - TQCString &clearText, - const KSSLPKCS12 &privKey) { -#ifdef KSSL_HAVE_SSL - if (!kossl) return KSC_R_NO_SSL; - - BIO *in = kossl->BIO_new_mem_buf((char *)cipherText.data(), cipherText.size()); - BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); - - rc rc = priv->decryptMessage(in,out, - const_cast(privKey)); - - kossl->BIO_write(out, &eot, 1); - priv->MemBIOToQByteArray(out, clearText); - - kossl->BIO_free(out); - kossl->BIO_free(in); - - return rc; -#else - return KSC_R_NO_SSL; -#endif -} - diff --git a/tdeio/kssl/ksmimecrypto.cpp b/tdeio/kssl/ksmimecrypto.cpp new file mode 100644 index 000000000..92318b9f0 --- /dev/null +++ b/tdeio/kssl/ksmimecrypto.cpp @@ -0,0 +1,417 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2003 Stefan Rompf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include +#include +#include +#include + +#include "kopenssl.h" +#include "ksslcertificate.h" +#include "ksslpkcs12.h" +#include "ksmimecrypto.h" + +// this hack provided by Malte Starostik to avoid glibc/openssl bug +// on some systems +#ifdef KSSL_HAVE_SSL +#define crypt _openssl_crypt +#include +#undef crypt +#endif + + +#ifdef KSSL_HAVE_SSL +static const char eot = 0; + +class KSMIMECryptoPrivate { + KOpenSSLProxy *kossl; + +public: + KSMIMECryptoPrivate(KOpenSSLProxy *kossl); + + + STACK_OF(X509) *certsToX509(TQPtrList &certs); + + KSMIMECrypto::rc signMessage(BIO *clearText, + BIO *cipherText, + KSSLPKCS12 &privKey, TQPtrList &certs, + bool detached); + + KSMIMECrypto::rc encryptMessage(BIO *clearText, + BIO *cipherText, KSMIMECrypto::algo algorithm, + TQPtrList &recip); + + KSMIMECrypto::rc checkSignature(BIO *clearText, + BIO *signature, bool detached, + TQPtrList &recip); + + KSMIMECrypto::rc decryptMessage(BIO *cipherText, + BIO *clearText, + KSSLPKCS12 &privKey); + + void MemBIOToQByteArray(BIO *src, TQByteArray &dest); + + KSMIMECrypto::rc sslErrToRc(void); +}; + + +KSMIMECryptoPrivate::KSMIMECryptoPrivate(KOpenSSLProxy *kossl): kossl(kossl) { +} + + +STACK_OF(X509) *KSMIMECryptoPrivate::certsToX509(TQPtrList &certs) { + STACK_OF(X509) *x509 = reinterpret_cast(kossl->OPENSSL_sk_new(NULL)); + KSSLCertificate *cert = certs.first(); + while(cert) { + kossl->OPENSSL_sk_push(x509, cert->getCert()); + cert = certs.next(); + } + return x509; +} + + +KSMIMECrypto::rc KSMIMECryptoPrivate::signMessage(BIO *clearText, + BIO *cipherText, + KSSLPKCS12 &privKey, TQPtrList &certs, + bool detached) { + + STACK_OF(X509) *other = NULL; + KSMIMECrypto::rc rc; + int flags = detached?PKCS7_DETACHED:0; + + if (certs.count()) other = certsToX509(certs); + + PKCS7 *p7 = kossl->PKCS7_sign(privKey.getCertificate()->getCert(), privKey.getPrivateKey(), + other, clearText, flags); + + if (other) kossl->OPENSSL_sk_free(other); + + if (!p7) return sslErrToRc(); + + if (kossl->i2d_PKCS7_bio(cipherText, p7)) { + rc = KSMIMECrypto::KSC_R_OK; + } else { + rc = sslErrToRc(); + } + + kossl->PKCS7_free(p7); + + return rc; +} + +KSMIMECrypto::rc KSMIMECryptoPrivate::encryptMessage(BIO *clearText, + BIO *cipherText, KSMIMECrypto::algo algorithm, + TQPtrList &recip) { + EVP_CIPHER *cipher = NULL; + KSMIMECrypto::rc rc; + switch(algorithm) { + case KSMIMECrypto::KSC_C_DES3_CBC: + cipher = kossl->EVP_des_ede3_cbc(); + break; + case KSMIMECrypto::KSC_C_RC2_CBC_128: + cipher = kossl->EVP_rc2_cbc(); + break; + case KSMIMECrypto::KSC_C_RC2_CBC_64: + cipher = kossl->EVP_rc2_64_cbc(); + break; + case KSMIMECrypto::KSC_C_DES_CBC: + cipher = kossl->EVP_des_cbc(); + break; + case KSMIMECrypto::KSC_C_RC2_CBC_40: + cipher = kossl->EVP_rc2_40_cbc(); + break; + } + if (!cipher) return KSMIMECrypto::KSC_R_NOCIPHER; + + STACK_OF(X509) *certs = certsToX509(recip); + + PKCS7 *p7 = kossl->PKCS7_encrypt(certs, clearText, cipher, 0); + + kossl->OPENSSL_sk_free(certs); + + if (!p7) return sslErrToRc(); + + if (kossl->i2d_PKCS7_bio(cipherText, p7)) { + rc = KSMIMECrypto::KSC_R_OK; + } else { + rc = sslErrToRc(); + } + + kossl->PKCS7_free(p7); + + return rc; +} + + +KSMIMECrypto::rc KSMIMECryptoPrivate::checkSignature(BIO *clearText, + BIO *signature, bool detached, + TQPtrList &recip) { + + PKCS7 *p7 = kossl->d2i_PKCS7_bio(signature, NULL); + KSMIMECrypto::rc rc = KSMIMECrypto::KSC_R_OTHER; + + if (!p7) return sslErrToRc(); + + BIO *in; + BIO *out; + if (detached) { + in = clearText; + out = NULL; + } else { + in = NULL; + out = clearText; + } + + X509_STORE *dummystore = kossl->X509_STORE_new(); + if (kossl->PKCS7_verify(p7, NULL, dummystore, in, out, PKCS7_NOVERIFY)) { + STACK_OF(X509) *signers = kossl->PKCS7_get0_signers(p7, 0, PKCS7_NOVERIFY); + int num = kossl->OPENSSL_sk_num(signers); + + for(int n=0; n(kossl->OPENSSL_sk_value(signers, n))); + recip.append(signer); + } + + kossl->OPENSSL_sk_free(signers); + rc = KSMIMECrypto::KSC_R_OK; + } else { + rc = sslErrToRc(); + } + + kossl->X509_STORE_free(dummystore); + kossl->PKCS7_free(p7); + + return rc; +} + + +KSMIMECrypto::rc KSMIMECryptoPrivate::decryptMessage(BIO *cipherText, + BIO *clearText, + KSSLPKCS12 &privKey) { + + PKCS7 *p7 = kossl->d2i_PKCS7_bio(cipherText, NULL); + KSMIMECrypto::rc rc; + + if (!p7) return sslErrToRc(); + + if (kossl->PKCS7_decrypt(p7, privKey.getPrivateKey(), privKey.getCertificate()->getCert(), + clearText, 0)) { + rc = KSMIMECrypto::KSC_R_OK; + } else { + rc = sslErrToRc(); + } + + kossl->PKCS7_free(p7); + + return rc; +} + + +void KSMIMECryptoPrivate::MemBIOToQByteArray(BIO *src, TQByteArray &dest) { + char *buf; + long len = kossl->BIO_get_mem_data(src, &buf); + dest.assign(buf, len); + /* Now this goes quite a bit into openssl internals. + We assume that openssl uses malloc() (it does in + default config) and rip out the buffer. + */ + void *ptr = kossl->BIO_get_data(src); + reinterpret_cast(ptr)->data = NULL; +} + + +KSMIMECrypto::rc KSMIMECryptoPrivate::sslErrToRc(void) { + unsigned long cerr = kossl->ERR_get_error(); + + // To be completed and possibly fixed + + switch(ERR_GET_REASON(cerr)) { + case ERR_R_MALLOC_FAILURE: + return KSMIMECrypto::KSC_R_NOMEM; + } + + switch(ERR_GET_LIB(cerr)) { + case ERR_LIB_PKCS7: + switch(ERR_GET_REASON(cerr)) { + case PKCS7_R_WRONG_CONTENT_TYPE: + case PKCS7_R_NO_CONTENT: + case PKCS7_R_NO_SIGNATURES_ON_DATA: + return KSMIMECrypto::KSC_R_FORMAT; + break; + case PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE: + case PKCS7_R_DECRYPT_ERROR: // Hmm? + return KSMIMECrypto::KSC_R_WRONGKEY; + break; + case PKCS7_R_DIGEST_FAILURE: + return KSMIMECrypto::KSC_R_VERIFY; + default: + break; + } + break; + default: + break; + } + + kdDebug(7029) <<"KSMIMECrypto: uncaught error " <hasLibCrypto()) kossl = 0L; +#else + kossl = 0L; +#endif +} + + +KSMIMECrypto::~KSMIMECrypto() { +#ifdef KSSL_HAVE_SSL + delete priv; +#endif +} + + +KSMIMECrypto::rc KSMIMECrypto::signMessage(const TQCString &clearText, + TQByteArray &cipherText, + const KSSLPKCS12 &privKey, + const TQPtrList &certs, + bool detached) { +#ifdef KSSL_HAVE_SSL + if (!kossl) return KSC_R_NO_SSL; + BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size()); + BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); + + rc rc = priv->signMessage(in, out, + const_cast(privKey), + const_cast &>(certs), + detached); + + if (!rc) priv->MemBIOToQByteArray(out, cipherText); + + kossl->BIO_free(out); + kossl->BIO_free(in); + + return rc; +#else + return KSC_R_NO_SSL; +#endif +} + + +KSMIMECrypto::rc KSMIMECrypto::checkDetachedSignature(const TQCString &clearText, + const TQByteArray &signature, + TQPtrList &foundCerts) { +#ifdef KSSL_HAVE_SSL + if (!kossl) return KSC_R_NO_SSL; + BIO *txt = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.length()); + BIO *sig = kossl->BIO_new_mem_buf((char *)signature.data(), signature.size()); + + rc rc = priv->checkSignature(txt, sig, true, foundCerts); + + kossl->BIO_free(sig); + kossl->BIO_free(txt); + + return rc; +#else + return KSC_R_NO_SSL; +#endif +} + + +KSMIMECrypto::rc KSMIMECrypto::checkOpaqueSignature(const TQByteArray &signedText, + TQCString &clearText, + TQPtrList &foundCerts) { +#ifdef KSSL_HAVE_SSL + if (!kossl) return KSC_R_NO_SSL; + + BIO *in = kossl->BIO_new_mem_buf((char *)signedText.data(), signedText.size()); + BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); + + rc rc = priv->checkSignature(out, in, false, foundCerts); + + kossl->BIO_write(out, &eot, 1); + priv->MemBIOToQByteArray(out, clearText); + + kossl->BIO_free(out); + kossl->BIO_free(in); + + return rc; +#else + return KSC_R_NO_SSL; +#endif +} + + +KSMIMECrypto::rc KSMIMECrypto::encryptMessage(const TQCString &clearText, + TQByteArray &cipherText, + algo algorithm, + const TQPtrList &recip) { +#ifdef KSSL_HAVE_SSL + if (!kossl) return KSC_R_NO_SSL; + + BIO *in = kossl->BIO_new_mem_buf((char *)clearText.data(), clearText.size()); + BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); + + rc rc = priv->encryptMessage(in,out,algorithm, + const_cast< TQPtrList &>(recip)); + + if (!rc) priv->MemBIOToQByteArray(out, cipherText); + + kossl->BIO_free(out); + kossl->BIO_free(in); + + return rc; +#else + return KSC_R_NO_SSL; +#endif +} + + +KSMIMECrypto::rc KSMIMECrypto::decryptMessage(const TQByteArray &cipherText, + TQCString &clearText, + const KSSLPKCS12 &privKey) { +#ifdef KSSL_HAVE_SSL + if (!kossl) return KSC_R_NO_SSL; + + BIO *in = kossl->BIO_new_mem_buf((char *)cipherText.data(), cipherText.size()); + BIO *out = kossl->BIO_new(kossl->BIO_s_mem()); + + rc rc = priv->decryptMessage(in,out, + const_cast(privKey)); + + kossl->BIO_write(out, &eot, 1); + priv->MemBIOToQByteArray(out, clearText); + + kossl->BIO_free(out); + kossl->BIO_free(in); + + return rc; +#else + return KSC_R_NO_SSL; +#endif +} + diff --git a/tdeio/kssl/kssl.cc b/tdeio/kssl/kssl.cc deleted file mode 100644 index 0f34a55da..000000000 --- a/tdeio/kssl/kssl.cc +++ /dev/null @@ -1,699 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000-2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -// this hack provided by Malte Starostik to avoid glibc/openssl bug -// on some systems -#ifdef KSSL_HAVE_SSL -#include -#include -#include -#define crypt _openssl_crypt -#include -#include -#include -#include -#include -#undef crypt -#endif - -#include "kssl.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -class KSSLPrivate { -public: - KSSLPrivate() { - lastInitTLS = false; - kossl = KOpenSSLProxy::self(); - session = 0L; - } - - ~KSSLPrivate() { - delete session; - session = 0L; - } - - bool lastInitTLS; - KSSLCertificate::KSSLValidation m_cert_vfy_res; - TQString proxyPeer; - -#ifdef KSSL_HAVE_SSL - SSL *m_ssl; - SSL_CTX *m_ctx; - SSL_METHOD *m_meth; -#endif - KSSLSession *session; - KOSSL *kossl; -}; - - -KSSL::KSSL(bool init) { - d = new KSSLPrivate; - m_bInit = false; - m_bAutoReconfig = true; - m_cfg = new KSSLSettings(); -#ifdef KSSL_HAVE_SSL - d->m_ssl = 0L; -#endif - - if (init) - initialize(); -} - - -KSSL::~KSSL() { - close(); - delete m_cfg; - delete d; -} - - -int KSSL::seedWithEGD() { -int rc = 0; -#ifdef KSSL_HAVE_SSL - if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) { - rc = d->kossl->RAND_egd(m_cfg->getEGDPath().latin1()); - if (rc < 0) - kdDebug(7029) << "KSSL: Error seeding PRNG with the EGD." << endl; - else kdDebug(7029) << "KSSL: PRNG was seeded with " << rc - << " bytes from the EGD." << endl; - } else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { - rc = d->kossl->RAND_load_file(m_cfg->getEGDPath().latin1(), -1); - if (rc < 0) - kdDebug(7029) << "KSSL: Error seeding PRNG with the entropy file." << endl; - else kdDebug(7029) << "KSSL: PRNG was seeded with " << rc - << " bytes from the entropy file." << endl; - } -#endif -return rc; -} - - -bool KSSL::TLSInit() { -#ifdef KSSL_HAVE_SSL -// kdDebug(7029) << "KSSL TLS initialize" << endl; - if (m_bInit) - return false; - - if (m_bAutoReconfig) - m_cfg->load(); - - if (!m_cfg->tlsv1()) - return false; - - seedWithEGD(); - d->m_meth = d->kossl->TLS_client_method(); - d->lastInitTLS = true; - - m_pi.reset(); - - d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth); - if (d->m_ctx == 0L) { - return false; - } - - // set cipher list - TQString clist = m_cfg->getCipherList(); - //kdDebug(7029) << "Cipher list: " << clist << endl; - if (!clist.isEmpty()) - d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast(clist.ascii())); - - m_bInit = true; -return true; -#else -return false; -#endif -} - - -bool KSSL::initialize() { -#ifdef KSSL_HAVE_SSL - kdDebug(7029) << "KSSL initialize" << endl; - if (m_bInit) - return false; - - if (m_bAutoReconfig) - m_cfg->load(); - - seedWithEGD(); - // FIXME: we should be able to force SSL off entirely. - d->lastInitTLS = false; - - m_pi.reset(); - - if (m_cfg->tlsv1() || (m_cfg->sslv3() && m_cfg->sslv2())) { - d->m_meth = d->kossl->TLS_client_method(); - } - else if (m_cfg->sslv3()) { - d->m_meth = d->kossl->SSLv3_client_method(); - } - else if (m_cfg->sslv2()) { - d->m_meth = d->kossl->SSLv2_client_method(); - } - -/* -if (m_cfg->sslv2() && m_cfg->sslv3()) kdDebug(7029) << "Double method" << endl; -else if (m_cfg->sslv2()) kdDebug(7029) << "SSL2 method" << endl; -else if (m_cfg->sslv3()) kdDebug(7029) << "SSL3 method" << endl; -*/ - - d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth); - if (d->m_ctx == 0L) { - return false; - } - - // set cipher list - TQString clist = m_cfg->getCipherList(); - kdDebug(7029) << "Cipher list: " << clist << endl; - if (!clist.isEmpty()) - d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast(clist.ascii())); - - m_bInit = true; -return true; -#else -return false; -#endif -} - - -bool KSSL::takeSession(KSSLSession *session) { -#ifdef KSSL_HAVE_SSL - if (!session) { - delete d->session; - d->session = 0L; - return true; - } - - // Take session reference - d->session = new KSSLSession; - d->session->_session = session->_session; - session->_session = 0L; - - return true; -#else - return false; -#endif -} - - -void KSSL::close() { -#ifdef KSSL_HAVE_SSL -//kdDebug(7029) << "KSSL close" << endl; - if (!m_bInit) - return; - - delete d->session; - d->session = 0L; - - if (d->m_ssl) { - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0L; - } - - d->kossl->SSL_CTX_free(d->m_ctx); - if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { - d->kossl->RAND_write_file(m_cfg->getEGDPath().latin1()); - } - - m_bInit = false; -#endif -} - - -bool KSSL::reInitialize() { - close(); -return initialize(); -} - -// get the callback file - it's hidden away in here -//#include "ksslcallback.c" - - -bool KSSL::setVerificationLogic() { -#if 0 -#ifdef KSSL_HAVE_SSL - // SSL_set_verify_result(d->m_ssl, X509_V_OK); - // SSL_CTX_set_verify(d->m_ctx, SSL_VERIFY_PEER, X509Callback); -#endif -#endif -return true; -} - - -int KSSL::accept(int sock) { -#ifdef KSSL_HAVE_SSL -// kdDebug(7029) << "KSSL accept" << endl; -int rc; - if (!m_bInit) - return -1; - d->m_ssl = d->kossl->SSL_new(d->m_ctx); - if (!d->m_ssl) - return -1; - - if (d->session) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (static_cast(d->session->_session)->sess_cert == 0) - { - kdDebug(7029) << "Can't reuse session, no certificate." << endl; - delete d->session; - d->session = 0; - } - else -#endif - if (1 == d->kossl->SSL_set_session(d->m_ssl, - static_cast(d->session->_session))) { - kdDebug(7029) << "Session ID is being reused." << endl; - } else { - kdDebug(7029) << "Error attempting to reuse session." << endl; - delete d->session; - d->session = 0; - } - } - -/* - if (!setVerificationLogic()) { - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0; - return -1; - } -*/ - - int off = SSL_OP_ALL; - if (!d->lastInitTLS && !m_cfg->tlsv1()) - off |= SSL_OP_NO_TLSv1; - if (!m_cfg->sslv3()) - off |= SSL_OP_NO_SSLv3; - if (!m_cfg->sslv2()) - off |= SSL_OP_NO_SSLv2; - - d->kossl->_SSL_set_options(d->m_ssl, off); - - rc = d->kossl->SSL_set_fd(d->m_ssl, sock); - if (rc == 0) { - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0; - return rc; - } -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii()); -#endif - - rc = d->kossl->SSL_accept(d->m_ssl); - if (rc == 1) { - setConnectionInfo(); - setPeerInfo(); - kdDebug(7029) << "KSSL connected OK" << endl; - } else { - kdDebug(7029) << "KSSL accept failed - rc = " << rc << endl; - kdDebug(7029) << " ERROR = " - << d->kossl->SSL_get_error(d->m_ssl, rc) << endl; - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0; - return -1; - } - - if (!d->kossl->_SSL_session_reused(d->m_ssl)) { - if (d->session) { - kdDebug(7029) << "Session reuse failed. New session used instead." << endl; - delete d->session; - d->session = 0L; - } - } - - if (!d->session) { - SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl); - if (sess) { - d->session = new KSSLSession; - d->session->_session = sess; - } - } - -return rc; -#else -return -1; -#endif -} - - -int KSSL::connect(int sock) { -#ifdef KSSL_HAVE_SSL -// kdDebug(7029) << "KSSL connect" << endl; -int rc; - if (!m_bInit) - return -1; - d->m_ssl = d->kossl->SSL_new(d->m_ctx); - if (!d->m_ssl) - return -1; - - if (d->session) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (static_cast(d->session->_session)->sess_cert == 0) - { - kdDebug(7029) << "Can't reuse session, no certificate." << endl; - delete d->session; - d->session = 0; - } - else -#endif - if (1 == d->kossl->SSL_set_session(d->m_ssl, - static_cast(d->session->_session))) { - kdDebug(7029) << "Session ID is being reused." << endl; - } else { - kdDebug(7029) << "Error attempting to reuse session." << endl; - delete d->session; - d->session = 0; - } - } - -/* - if (!setVerificationLogic()) { - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0; - return -1; - } -*/ - - int off = SSL_OP_ALL; - if (!d->lastInitTLS && !m_cfg->tlsv1()) - off |= SSL_OP_NO_TLSv1; - if (!m_cfg->sslv3()) - off |= SSL_OP_NO_SSLv3; - if (!m_cfg->sslv2()) - off |= SSL_OP_NO_SSLv2; - - d->kossl->_SSL_set_options(d->m_ssl, off); - - rc = d->kossl->SSL_set_fd(d->m_ssl, sock); - if (rc == 0) { - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0; - return rc; - } -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii()); -#endif - -connect_again: - rc = d->kossl->SSL_connect(d->m_ssl); - if (rc == 1) { - setConnectionInfo(); - setPeerInfo(); - kdDebug(7029) << "KSSL connected OK" << endl; - } else { - int err = d->kossl->SSL_get_error(d->m_ssl, rc); - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - // nonblocking - but we block anyways in connect() :) - goto connect_again; - } else { - kdDebug(7029) << "KSSL connect failed - rc = " - << rc << endl; - kdDebug(7029) << " ERROR = " - << err << endl; - d->kossl->ERR_print_errors_fp(stderr); - d->kossl->SSL_shutdown(d->m_ssl); - d->kossl->SSL_free(d->m_ssl); - d->m_ssl = 0; - return -1; - } - } - - if (!d->kossl->_SSL_session_reused(d->m_ssl)) { - if (d->session) { - kdDebug(7029) << "Session reuse failed. New session used instead." << endl; - delete d->session; - d->session = 0L; - } - } - - if (!d->session) { - SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl); - if (sess) { - d->session = new KSSLSession; - d->session->_session = sess; - } - } - -return rc; -#else -return -1; -#endif -} - - -int KSSL::pending() { -#ifdef KSSL_HAVE_SSL - if (!m_bInit) - return -1; -return d->kossl->SSL_pending(d->m_ssl); -#else -return -1; -#endif -} - - -int KSSL::peek(void *buf, int len) { -#ifdef KSSL_HAVE_SSL - if (!m_bInit) - return -1; - // FIXME: enhance to work the way read() does below, handling errors -return d->kossl->SSL_peek(d->m_ssl, buf, len); -#else -return -1; -#endif -} - - -int KSSL::read(void *buf, int len) { -#ifdef KSSL_HAVE_SSL - int rc = 0; - int maxIters = 10; - - if (!m_bInit) - return -1; - -read_again: - rc = d->kossl->SSL_read(d->m_ssl, (char *)buf, len); - if (rc <= 0) { - int err = d->kossl->SSL_get_error(d->m_ssl, rc); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - kdDebug(7029) << "SSL read() returning 0: " << err << endl; - if (maxIters-- > 0) { - ::usleep(20000); // 20ms sleep - goto read_again; - } - return 0; - } - - kdDebug(7029) << "SSL READ ERROR: " << err << endl; - if (err != SSL_ERROR_NONE && - err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) { - rc = -1; // OpenSSL returns 0 on error too - d->kossl->ERR_print_errors_fp(stderr); - } - -// else if (err == SSL_ERROR_ZERO_RETURN) -// rc = 0; - } -return rc; -#else -return -1; -#endif -} - - -int KSSL::write(const void *buf, int len) { -#ifdef KSSL_HAVE_SSL - if (!m_bInit) - return -1; - -write_again: - int rc = d->kossl->SSL_write(d->m_ssl, (const char *)buf, len); - if (rc <= 0) { // OpenSSL returns 0 on error too - int err = d->kossl->SSL_get_error(d->m_ssl, rc); - - if (err == SSL_ERROR_WANT_WRITE) { - ::usleep(20000); // 20ms sleep - goto write_again; - } - - kdDebug(7029) << "SSL WRITE ERROR: " << err << endl; - if (err != SSL_ERROR_NONE && - err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) - rc = -1; - } - -return rc; -#else -return -1; -#endif -} - - -bool KSSL::reconfig() { - return reInitialize(); -} - - -void KSSL::setAutoReconfig(bool ar) { - m_bAutoReconfig = ar; -} - - -bool KSSL::setSettings(KSSLSettings *settings) { - delete m_cfg; - m_cfg = settings; - return reconfig(); -} - - -#ifdef KSSL_HAVE_SSL -bool KSSL::m_bSSLWorks = true; -#else -bool KSSL::m_bSSLWorks = false; -#endif - -bool KSSL::doesSSLWork() { - return m_bSSLWorks; -} - - -void KSSL::setConnectionInfo() { -#ifdef KSSL_HAVE_SSL -SSL_CIPHER *sc; -char buf[1024]; - - buf[0] = 0; // for safety. - sc = d->kossl->SSL_get_current_cipher(d->m_ssl); - if (!sc) { - kdDebug(7029) << "KSSL get current cipher failed - we're probably gonna crash!" << endl; - return; - } - - // set the number of bits, bits used - m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits)); - // set the cipher version - m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc); - // set the cipher name - m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc); - // set the cipher description - m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023); - -#endif -} - - -void KSSL::setPeerInfo() { -#ifdef KSSL_HAVE_SSL - m_pi.setPeerHost(d->proxyPeer); - m_pi.m_cert.setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl)); - STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl); - if (xs) - xs = reinterpret_cast(d->kossl->OPENSSL_sk_dup(xs)); // Leak? - m_pi.m_cert.setChain((void *)xs); -#endif -} - - -KSSLConnectionInfo& KSSL::connectionInfo() { - return m_ci; -} - - -// KDE 4: Make it const TQString & -void KSSL::setPeerHost(TQString realHost) { - d->proxyPeer = realHost; -} - -// deprecated -void KSSL::setProxyUse(bool, TQString, int, TQString) { -} - - -KSSLPeerInfo& KSSL::peerInfo() { - return m_pi; -} - - -bool KSSL::setClientCertificate(KSSLPKCS12 *pkcs) { -#ifdef KSSL_HAVE_SSL - if (!pkcs || !pkcs->getCertificate()) - return false; - -int rc; -X509 *x = pkcs->getCertificate()->getCert(); -EVP_PKEY *k = pkcs->getPrivateKey(); - - if (!x || !k) return false; - - if (!pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient()) - return false; - - rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x); - if (rc <= 0) { - kdDebug(7029) << "KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl; - return false; - } - - rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k); - if (rc <= 0) { - kdDebug(7029) << "KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl; - return false; - } - - return true; -#else - return false; -#endif -} - -const KSSLSession* KSSL::session() const { - return d->session; -} - -bool KSSL::reusingSession() const { -#ifdef KSSL_HAVE_SSL - return (d->m_ssl && d->kossl->_SSL_session_reused(d->m_ssl)); -#else - return false; -#endif -} - diff --git a/tdeio/kssl/kssl.cpp b/tdeio/kssl/kssl.cpp new file mode 100644 index 000000000..0f34a55da --- /dev/null +++ b/tdeio/kssl/kssl.cpp @@ -0,0 +1,699 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000-2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +// this hack provided by Malte Starostik to avoid glibc/openssl bug +// on some systems +#ifdef KSSL_HAVE_SSL +#include +#include +#include +#define crypt _openssl_crypt +#include +#include +#include +#include +#include +#undef crypt +#endif + +#include "kssl.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +class KSSLPrivate { +public: + KSSLPrivate() { + lastInitTLS = false; + kossl = KOpenSSLProxy::self(); + session = 0L; + } + + ~KSSLPrivate() { + delete session; + session = 0L; + } + + bool lastInitTLS; + KSSLCertificate::KSSLValidation m_cert_vfy_res; + TQString proxyPeer; + +#ifdef KSSL_HAVE_SSL + SSL *m_ssl; + SSL_CTX *m_ctx; + SSL_METHOD *m_meth; +#endif + KSSLSession *session; + KOSSL *kossl; +}; + + +KSSL::KSSL(bool init) { + d = new KSSLPrivate; + m_bInit = false; + m_bAutoReconfig = true; + m_cfg = new KSSLSettings(); +#ifdef KSSL_HAVE_SSL + d->m_ssl = 0L; +#endif + + if (init) + initialize(); +} + + +KSSL::~KSSL() { + close(); + delete m_cfg; + delete d; +} + + +int KSSL::seedWithEGD() { +int rc = 0; +#ifdef KSSL_HAVE_SSL + if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) { + rc = d->kossl->RAND_egd(m_cfg->getEGDPath().latin1()); + if (rc < 0) + kdDebug(7029) << "KSSL: Error seeding PRNG with the EGD." << endl; + else kdDebug(7029) << "KSSL: PRNG was seeded with " << rc + << " bytes from the EGD." << endl; + } else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { + rc = d->kossl->RAND_load_file(m_cfg->getEGDPath().latin1(), -1); + if (rc < 0) + kdDebug(7029) << "KSSL: Error seeding PRNG with the entropy file." << endl; + else kdDebug(7029) << "KSSL: PRNG was seeded with " << rc + << " bytes from the entropy file." << endl; + } +#endif +return rc; +} + + +bool KSSL::TLSInit() { +#ifdef KSSL_HAVE_SSL +// kdDebug(7029) << "KSSL TLS initialize" << endl; + if (m_bInit) + return false; + + if (m_bAutoReconfig) + m_cfg->load(); + + if (!m_cfg->tlsv1()) + return false; + + seedWithEGD(); + d->m_meth = d->kossl->TLS_client_method(); + d->lastInitTLS = true; + + m_pi.reset(); + + d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth); + if (d->m_ctx == 0L) { + return false; + } + + // set cipher list + TQString clist = m_cfg->getCipherList(); + //kdDebug(7029) << "Cipher list: " << clist << endl; + if (!clist.isEmpty()) + d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast(clist.ascii())); + + m_bInit = true; +return true; +#else +return false; +#endif +} + + +bool KSSL::initialize() { +#ifdef KSSL_HAVE_SSL + kdDebug(7029) << "KSSL initialize" << endl; + if (m_bInit) + return false; + + if (m_bAutoReconfig) + m_cfg->load(); + + seedWithEGD(); + // FIXME: we should be able to force SSL off entirely. + d->lastInitTLS = false; + + m_pi.reset(); + + if (m_cfg->tlsv1() || (m_cfg->sslv3() && m_cfg->sslv2())) { + d->m_meth = d->kossl->TLS_client_method(); + } + else if (m_cfg->sslv3()) { + d->m_meth = d->kossl->SSLv3_client_method(); + } + else if (m_cfg->sslv2()) { + d->m_meth = d->kossl->SSLv2_client_method(); + } + +/* +if (m_cfg->sslv2() && m_cfg->sslv3()) kdDebug(7029) << "Double method" << endl; +else if (m_cfg->sslv2()) kdDebug(7029) << "SSL2 method" << endl; +else if (m_cfg->sslv3()) kdDebug(7029) << "SSL3 method" << endl; +*/ + + d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth); + if (d->m_ctx == 0L) { + return false; + } + + // set cipher list + TQString clist = m_cfg->getCipherList(); + kdDebug(7029) << "Cipher list: " << clist << endl; + if (!clist.isEmpty()) + d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast(clist.ascii())); + + m_bInit = true; +return true; +#else +return false; +#endif +} + + +bool KSSL::takeSession(KSSLSession *session) { +#ifdef KSSL_HAVE_SSL + if (!session) { + delete d->session; + d->session = 0L; + return true; + } + + // Take session reference + d->session = new KSSLSession; + d->session->_session = session->_session; + session->_session = 0L; + + return true; +#else + return false; +#endif +} + + +void KSSL::close() { +#ifdef KSSL_HAVE_SSL +//kdDebug(7029) << "KSSL close" << endl; + if (!m_bInit) + return; + + delete d->session; + d->session = 0L; + + if (d->m_ssl) { + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0L; + } + + d->kossl->SSL_CTX_free(d->m_ctx); + if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { + d->kossl->RAND_write_file(m_cfg->getEGDPath().latin1()); + } + + m_bInit = false; +#endif +} + + +bool KSSL::reInitialize() { + close(); +return initialize(); +} + +// get the callback file - it's hidden away in here +//#include "ksslcallback.c" + + +bool KSSL::setVerificationLogic() { +#if 0 +#ifdef KSSL_HAVE_SSL + // SSL_set_verify_result(d->m_ssl, X509_V_OK); + // SSL_CTX_set_verify(d->m_ctx, SSL_VERIFY_PEER, X509Callback); +#endif +#endif +return true; +} + + +int KSSL::accept(int sock) { +#ifdef KSSL_HAVE_SSL +// kdDebug(7029) << "KSSL accept" << endl; +int rc; + if (!m_bInit) + return -1; + d->m_ssl = d->kossl->SSL_new(d->m_ctx); + if (!d->m_ssl) + return -1; + + if (d->session) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (static_cast(d->session->_session)->sess_cert == 0) + { + kdDebug(7029) << "Can't reuse session, no certificate." << endl; + delete d->session; + d->session = 0; + } + else +#endif + if (1 == d->kossl->SSL_set_session(d->m_ssl, + static_cast(d->session->_session))) { + kdDebug(7029) << "Session ID is being reused." << endl; + } else { + kdDebug(7029) << "Error attempting to reuse session." << endl; + delete d->session; + d->session = 0; + } + } + +/* + if (!setVerificationLogic()) { + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0; + return -1; + } +*/ + + int off = SSL_OP_ALL; + if (!d->lastInitTLS && !m_cfg->tlsv1()) + off |= SSL_OP_NO_TLSv1; + if (!m_cfg->sslv3()) + off |= SSL_OP_NO_SSLv3; + if (!m_cfg->sslv2()) + off |= SSL_OP_NO_SSLv2; + + d->kossl->_SSL_set_options(d->m_ssl, off); + + rc = d->kossl->SSL_set_fd(d->m_ssl, sock); + if (rc == 0) { + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0; + return rc; + } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii()); +#endif + + rc = d->kossl->SSL_accept(d->m_ssl); + if (rc == 1) { + setConnectionInfo(); + setPeerInfo(); + kdDebug(7029) << "KSSL connected OK" << endl; + } else { + kdDebug(7029) << "KSSL accept failed - rc = " << rc << endl; + kdDebug(7029) << " ERROR = " + << d->kossl->SSL_get_error(d->m_ssl, rc) << endl; + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0; + return -1; + } + + if (!d->kossl->_SSL_session_reused(d->m_ssl)) { + if (d->session) { + kdDebug(7029) << "Session reuse failed. New session used instead." << endl; + delete d->session; + d->session = 0L; + } + } + + if (!d->session) { + SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl); + if (sess) { + d->session = new KSSLSession; + d->session->_session = sess; + } + } + +return rc; +#else +return -1; +#endif +} + + +int KSSL::connect(int sock) { +#ifdef KSSL_HAVE_SSL +// kdDebug(7029) << "KSSL connect" << endl; +int rc; + if (!m_bInit) + return -1; + d->m_ssl = d->kossl->SSL_new(d->m_ctx); + if (!d->m_ssl) + return -1; + + if (d->session) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (static_cast(d->session->_session)->sess_cert == 0) + { + kdDebug(7029) << "Can't reuse session, no certificate." << endl; + delete d->session; + d->session = 0; + } + else +#endif + if (1 == d->kossl->SSL_set_session(d->m_ssl, + static_cast(d->session->_session))) { + kdDebug(7029) << "Session ID is being reused." << endl; + } else { + kdDebug(7029) << "Error attempting to reuse session." << endl; + delete d->session; + d->session = 0; + } + } + +/* + if (!setVerificationLogic()) { + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0; + return -1; + } +*/ + + int off = SSL_OP_ALL; + if (!d->lastInitTLS && !m_cfg->tlsv1()) + off |= SSL_OP_NO_TLSv1; + if (!m_cfg->sslv3()) + off |= SSL_OP_NO_SSLv3; + if (!m_cfg->sslv2()) + off |= SSL_OP_NO_SSLv2; + + d->kossl->_SSL_set_options(d->m_ssl, off); + + rc = d->kossl->SSL_set_fd(d->m_ssl, sock); + if (rc == 0) { + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0; + return rc; + } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + d->kossl->SSL_set_tlsext_host_name(d->m_ssl, d->proxyPeer.ascii()); +#endif + +connect_again: + rc = d->kossl->SSL_connect(d->m_ssl); + if (rc == 1) { + setConnectionInfo(); + setPeerInfo(); + kdDebug(7029) << "KSSL connected OK" << endl; + } else { + int err = d->kossl->SSL_get_error(d->m_ssl, rc); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + // nonblocking - but we block anyways in connect() :) + goto connect_again; + } else { + kdDebug(7029) << "KSSL connect failed - rc = " + << rc << endl; + kdDebug(7029) << " ERROR = " + << err << endl; + d->kossl->ERR_print_errors_fp(stderr); + d->kossl->SSL_shutdown(d->m_ssl); + d->kossl->SSL_free(d->m_ssl); + d->m_ssl = 0; + return -1; + } + } + + if (!d->kossl->_SSL_session_reused(d->m_ssl)) { + if (d->session) { + kdDebug(7029) << "Session reuse failed. New session used instead." << endl; + delete d->session; + d->session = 0L; + } + } + + if (!d->session) { + SSL_SESSION *sess = d->kossl->SSL_get1_session(d->m_ssl); + if (sess) { + d->session = new KSSLSession; + d->session->_session = sess; + } + } + +return rc; +#else +return -1; +#endif +} + + +int KSSL::pending() { +#ifdef KSSL_HAVE_SSL + if (!m_bInit) + return -1; +return d->kossl->SSL_pending(d->m_ssl); +#else +return -1; +#endif +} + + +int KSSL::peek(void *buf, int len) { +#ifdef KSSL_HAVE_SSL + if (!m_bInit) + return -1; + // FIXME: enhance to work the way read() does below, handling errors +return d->kossl->SSL_peek(d->m_ssl, buf, len); +#else +return -1; +#endif +} + + +int KSSL::read(void *buf, int len) { +#ifdef KSSL_HAVE_SSL + int rc = 0; + int maxIters = 10; + + if (!m_bInit) + return -1; + +read_again: + rc = d->kossl->SSL_read(d->m_ssl, (char *)buf, len); + if (rc <= 0) { + int err = d->kossl->SSL_get_error(d->m_ssl, rc); + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + kdDebug(7029) << "SSL read() returning 0: " << err << endl; + if (maxIters-- > 0) { + ::usleep(20000); // 20ms sleep + goto read_again; + } + return 0; + } + + kdDebug(7029) << "SSL READ ERROR: " << err << endl; + if (err != SSL_ERROR_NONE && + err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) { + rc = -1; // OpenSSL returns 0 on error too + d->kossl->ERR_print_errors_fp(stderr); + } + +// else if (err == SSL_ERROR_ZERO_RETURN) +// rc = 0; + } +return rc; +#else +return -1; +#endif +} + + +int KSSL::write(const void *buf, int len) { +#ifdef KSSL_HAVE_SSL + if (!m_bInit) + return -1; + +write_again: + int rc = d->kossl->SSL_write(d->m_ssl, (const char *)buf, len); + if (rc <= 0) { // OpenSSL returns 0 on error too + int err = d->kossl->SSL_get_error(d->m_ssl, rc); + + if (err == SSL_ERROR_WANT_WRITE) { + ::usleep(20000); // 20ms sleep + goto write_again; + } + + kdDebug(7029) << "SSL WRITE ERROR: " << err << endl; + if (err != SSL_ERROR_NONE && + err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_SYSCALL) + rc = -1; + } + +return rc; +#else +return -1; +#endif +} + + +bool KSSL::reconfig() { + return reInitialize(); +} + + +void KSSL::setAutoReconfig(bool ar) { + m_bAutoReconfig = ar; +} + + +bool KSSL::setSettings(KSSLSettings *settings) { + delete m_cfg; + m_cfg = settings; + return reconfig(); +} + + +#ifdef KSSL_HAVE_SSL +bool KSSL::m_bSSLWorks = true; +#else +bool KSSL::m_bSSLWorks = false; +#endif + +bool KSSL::doesSSLWork() { + return m_bSSLWorks; +} + + +void KSSL::setConnectionInfo() { +#ifdef KSSL_HAVE_SSL +SSL_CIPHER *sc; +char buf[1024]; + + buf[0] = 0; // for safety. + sc = d->kossl->SSL_get_current_cipher(d->m_ssl); + if (!sc) { + kdDebug(7029) << "KSSL get current cipher failed - we're probably gonna crash!" << endl; + return; + } + + // set the number of bits, bits used + m_ci.m_iCipherUsedBits = d->kossl->SSL_CIPHER_get_bits(sc, &(m_ci.m_iCipherBits)); + // set the cipher version + m_ci.m_cipherVersion = d->kossl->SSL_CIPHER_get_version(sc); + // set the cipher name + m_ci.m_cipherName = d->kossl->SSL_CIPHER_get_name(sc); + // set the cipher description + m_ci.m_cipherDescription = d->kossl->SSL_CIPHER_description(sc, buf, 1023); + +#endif +} + + +void KSSL::setPeerInfo() { +#ifdef KSSL_HAVE_SSL + m_pi.setPeerHost(d->proxyPeer); + m_pi.m_cert.setCert(d->kossl->SSL_get_peer_certificate(d->m_ssl)); + STACK_OF(X509) *xs = d->kossl->SSL_get_peer_cert_chain(d->m_ssl); + if (xs) + xs = reinterpret_cast(d->kossl->OPENSSL_sk_dup(xs)); // Leak? + m_pi.m_cert.setChain((void *)xs); +#endif +} + + +KSSLConnectionInfo& KSSL::connectionInfo() { + return m_ci; +} + + +// KDE 4: Make it const TQString & +void KSSL::setPeerHost(TQString realHost) { + d->proxyPeer = realHost; +} + +// deprecated +void KSSL::setProxyUse(bool, TQString, int, TQString) { +} + + +KSSLPeerInfo& KSSL::peerInfo() { + return m_pi; +} + + +bool KSSL::setClientCertificate(KSSLPKCS12 *pkcs) { +#ifdef KSSL_HAVE_SSL + if (!pkcs || !pkcs->getCertificate()) + return false; + +int rc; +X509 *x = pkcs->getCertificate()->getCert(); +EVP_PKEY *k = pkcs->getPrivateKey(); + + if (!x || !k) return false; + + if (!pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient()) + return false; + + rc = d->kossl->SSL_CTX_use_certificate(d->m_ctx, x); + if (rc <= 0) { + kdDebug(7029) << "KSSL - SSL_CTX_use_certificate failed. rc = " << rc << endl; + return false; + } + + rc = d->kossl->SSL_CTX_use_PrivateKey(d->m_ctx, k); + if (rc <= 0) { + kdDebug(7029) << "KSSL - SSL_CTX_use_PrivateKey failed. rc = " << rc << endl; + return false; + } + + return true; +#else + return false; +#endif +} + +const KSSLSession* KSSL::session() const { + return d->session; +} + +bool KSSL::reusingSession() const { +#ifdef KSSL_HAVE_SSL + return (d->m_ssl && d->kossl->_SSL_session_reused(d->m_ssl)); +#else + return false; +#endif +} + diff --git a/tdeio/kssl/ksslcertchain.cc b/tdeio/kssl/ksslcertchain.cc deleted file mode 100644 index 4f14e4be1..000000000 --- a/tdeio/kssl/ksslcertchain.cc +++ /dev/null @@ -1,194 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "kssldefs.h" -#include "ksslcertificate.h" -#include "ksslcertchain.h" - -// this hack provided by Malte Starostik to avoid glibc/openssl bug -// on some systems -#ifdef KSSL_HAVE_SSL -#define crypt _openssl_crypt -#include -#include -#include -#include -#include -#include -#include -#undef crypt -#endif - -#include -#include -#include - - -class KSSLCertChainPrivate { -public: - KSSLCertChainPrivate() { - kossl = KOSSL::self(); - } - - ~KSSLCertChainPrivate() { - } - - KOSSL *kossl; -}; - -KSSLCertChain::KSSLCertChain() { - d = new KSSLCertChainPrivate; - _chain = NULL; -} - - -KSSLCertChain::~KSSLCertChain() { -#ifdef KSSL_HAVE_SSL - if (_chain) { - STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; - - for (;;) { - X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(x)); - if (!x5) break; - d->kossl->X509_free(x5); - } - d->kossl->OPENSSL_sk_free(x); - } -#endif - delete d; -} - - -bool KSSLCertChain::isValid() { - return (_chain && depth() > 0); -} - - -KSSLCertChain *KSSLCertChain::replicate() { -KSSLCertChain *x = new KSSLCertChain; -TQPtrList ch = getChain(); - - x->setChain(ch); // this will do a deep copy for us - ch.setAutoDelete(true); -return x; -} - - -int KSSLCertChain::depth() { -#ifdef KSSL_HAVE_SSL - return d->kossl->OPENSSL_sk_num((STACK_OF(X509)*)_chain); -#endif -return 0; -} - - -TQPtrList KSSLCertChain::getChain() { -TQPtrList cl; -if (!_chain) return cl; -#ifdef KSSL_HAVE_SSL -STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; - - for (int i = 0; i < d->kossl->OPENSSL_sk_num(x); i++) { - X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_value(x, i)); - if (!x5) continue; - KSSLCertificate *nc = new KSSLCertificate; - nc->setCert(d->kossl->X509_dup(x5)); - cl.append(nc); - } - -#endif -return cl; -} - - -void KSSLCertChain::setChain(TQPtrList& chain) { -#ifdef KSSL_HAVE_SSL -if (_chain) { - STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; - - for (;;) { - X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(x)); - if (!x5) break; - d->kossl->X509_free(x5); - } - d->kossl->OPENSSL_sk_free(x); - _chain = NULL; -} - - if (chain.count() == 0) return; - _chain = reinterpret_cast(d->kossl->OPENSSL_sk_new(NULL)); - for (KSSLCertificate *x = chain.first(); x != 0; x = chain.next()) { - d->kossl->OPENSSL_sk_push((STACK_OF(X509) *)_chain, d->kossl->X509_dup(x->getCert())); - } - -#endif -} - - -void KSSLCertChain::setChain(void *stack_of_x509) { -#ifdef KSSL_HAVE_SSL - if (_chain) { - STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; - - for (;;) { - X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(x)); - if (!x5) break; - d->kossl->X509_free(x5); - } - d->kossl->OPENSSL_sk_free(x); - _chain = NULL; - } - - if (!stack_of_x509) return; - - _chain = reinterpret_cast(d->kossl->OPENSSL_sk_new(NULL)); - STACK_OF(X509) *x = (STACK_OF(X509) *)stack_of_x509; - - for (int i = 0; i < d->kossl->OPENSSL_sk_num(x); i++) { - X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_value(x, i)); - if (!x5) continue; - d->kossl->OPENSSL_sk_push((STACK_OF(X509)*)_chain,d->kossl->X509_dup(x5)); - } - -#else - _chain = NULL; -#endif -} - - -void KSSLCertChain::setChain(TQStringList chain) { - setCertChain(chain); -} - -void KSSLCertChain::setCertChain(const TQStringList& chain) { - TQPtrList cl; - cl.setAutoDelete(true); - for (TQStringList::ConstIterator s = chain.begin(); s != chain.end(); ++s) { - KSSLCertificate *c = KSSLCertificate::fromString((*s).local8Bit()); - if (c) { - cl.append(c); - } - } - setChain(cl); -} - diff --git a/tdeio/kssl/ksslcertchain.cpp b/tdeio/kssl/ksslcertchain.cpp new file mode 100644 index 000000000..4f14e4be1 --- /dev/null +++ b/tdeio/kssl/ksslcertchain.cpp @@ -0,0 +1,194 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "kssldefs.h" +#include "ksslcertificate.h" +#include "ksslcertchain.h" + +// this hack provided by Malte Starostik to avoid glibc/openssl bug +// on some systems +#ifdef KSSL_HAVE_SSL +#define crypt _openssl_crypt +#include +#include +#include +#include +#include +#include +#include +#undef crypt +#endif + +#include +#include +#include + + +class KSSLCertChainPrivate { +public: + KSSLCertChainPrivate() { + kossl = KOSSL::self(); + } + + ~KSSLCertChainPrivate() { + } + + KOSSL *kossl; +}; + +KSSLCertChain::KSSLCertChain() { + d = new KSSLCertChainPrivate; + _chain = NULL; +} + + +KSSLCertChain::~KSSLCertChain() { +#ifdef KSSL_HAVE_SSL + if (_chain) { + STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; + + for (;;) { + X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(x)); + if (!x5) break; + d->kossl->X509_free(x5); + } + d->kossl->OPENSSL_sk_free(x); + } +#endif + delete d; +} + + +bool KSSLCertChain::isValid() { + return (_chain && depth() > 0); +} + + +KSSLCertChain *KSSLCertChain::replicate() { +KSSLCertChain *x = new KSSLCertChain; +TQPtrList ch = getChain(); + + x->setChain(ch); // this will do a deep copy for us + ch.setAutoDelete(true); +return x; +} + + +int KSSLCertChain::depth() { +#ifdef KSSL_HAVE_SSL + return d->kossl->OPENSSL_sk_num((STACK_OF(X509)*)_chain); +#endif +return 0; +} + + +TQPtrList KSSLCertChain::getChain() { +TQPtrList cl; +if (!_chain) return cl; +#ifdef KSSL_HAVE_SSL +STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; + + for (int i = 0; i < d->kossl->OPENSSL_sk_num(x); i++) { + X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_value(x, i)); + if (!x5) continue; + KSSLCertificate *nc = new KSSLCertificate; + nc->setCert(d->kossl->X509_dup(x5)); + cl.append(nc); + } + +#endif +return cl; +} + + +void KSSLCertChain::setChain(TQPtrList& chain) { +#ifdef KSSL_HAVE_SSL +if (_chain) { + STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; + + for (;;) { + X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(x)); + if (!x5) break; + d->kossl->X509_free(x5); + } + d->kossl->OPENSSL_sk_free(x); + _chain = NULL; +} + + if (chain.count() == 0) return; + _chain = reinterpret_cast(d->kossl->OPENSSL_sk_new(NULL)); + for (KSSLCertificate *x = chain.first(); x != 0; x = chain.next()) { + d->kossl->OPENSSL_sk_push((STACK_OF(X509) *)_chain, d->kossl->X509_dup(x->getCert())); + } + +#endif +} + + +void KSSLCertChain::setChain(void *stack_of_x509) { +#ifdef KSSL_HAVE_SSL + if (_chain) { + STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; + + for (;;) { + X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(x)); + if (!x5) break; + d->kossl->X509_free(x5); + } + d->kossl->OPENSSL_sk_free(x); + _chain = NULL; + } + + if (!stack_of_x509) return; + + _chain = reinterpret_cast(d->kossl->OPENSSL_sk_new(NULL)); + STACK_OF(X509) *x = (STACK_OF(X509) *)stack_of_x509; + + for (int i = 0; i < d->kossl->OPENSSL_sk_num(x); i++) { + X509* x5 = reinterpret_cast(d->kossl->OPENSSL_sk_value(x, i)); + if (!x5) continue; + d->kossl->OPENSSL_sk_push((STACK_OF(X509)*)_chain,d->kossl->X509_dup(x5)); + } + +#else + _chain = NULL; +#endif +} + + +void KSSLCertChain::setChain(TQStringList chain) { + setCertChain(chain); +} + +void KSSLCertChain::setCertChain(const TQStringList& chain) { + TQPtrList cl; + cl.setAutoDelete(true); + for (TQStringList::ConstIterator s = chain.begin(); s != chain.end(); ++s) { + KSSLCertificate *c = KSSLCertificate::fromString((*s).local8Bit()); + if (c) { + cl.append(c); + } + } + setChain(cl); +} + diff --git a/tdeio/kssl/ksslcertdlg.cc b/tdeio/kssl/ksslcertdlg.cc deleted file mode 100644 index 7431d4c0a..000000000 --- a/tdeio/kssl/ksslcertdlg.cc +++ /dev/null @@ -1,174 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001-2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ksslcertdlg.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -class KSSLCertDlg::KSSLCertDlgPrivate { -private: - friend class KSSLCertDlg; - TQLabel *p_message; - TQPushButton *p_pb_dontsend; - bool p_send_flag; -}; - -KSSLCertDlg::KSSLCertDlg(TQWidget *parent, const char *name, bool modal) - : KDialog(parent, name, modal), d(new KSSLCertDlgPrivate) { - - TQBoxLayout * grid = new TQVBoxLayout( this, KDialog::marginHint(), - KDialog::spacingHint() ); - - d->p_message = new TQLabel(TQString::null, this); - grid->addWidget(d->p_message); - setHost(_host); - - _certs = new TQListView(this); - _certs->addColumn(i18n("Certificate")); - _certs->setResizeMode(TQListView::LastColumn); - TQFontMetrics fm( TDEGlobalSettings::generalFont() ); - _certs->setMinimumHeight(4*fm.height()); - grid->addWidget(_certs); - - _save = new TQCheckBox(i18n("Save selection for this host."), this); - grid->addWidget(_save); - - grid->addWidget(new KSeparator(KSeparator::HLine, this)); - - TQBoxLayout * h = new TQHBoxLayout( grid ); - h->insertStretch(0); - - _ok = new KPushButton(i18n("Send certificate"), this); - h->addWidget(_ok); - connect(_ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotSend())); - - d->p_pb_dontsend = new KPushButton(i18n("Do not send a certificate"), this); - h->addWidget(d->p_pb_dontsend); - connect(d->p_pb_dontsend, TQT_SIGNAL(clicked()), TQT_SLOT(slotDont())); - -#ifndef TQT_NO_WIDGET_TOPEXTRA - setCaption(i18n("TDE SSL Certificate Dialog")); -#endif -} - - -KSSLCertDlg::~KSSLCertDlg() { - delete d; -} - - -void KSSLCertDlg::setup(TQStringList certs, bool saveChecked, bool sendChecked) { - setupDialog(certs, saveChecked, sendChecked); -} - -void KSSLCertDlg::setupDialog(const TQStringList& certs, bool saveChecked, bool sendChecked) { - _save->setChecked(saveChecked); - d->p_send_flag = sendChecked; - - if (sendChecked) - _ok->setDefault(true); // "do send" is the "default action". - else - d->p_pb_dontsend->setDefault(true); // "do not send" is the "default action". - - for (TQStringList::ConstIterator i = certs.begin(); i != certs.end(); ++i) { - if ((*i).isEmpty()) - continue; - - new TQListViewItem(_certs, *i); - } - - _certs->setSelected(_certs->firstChild(), true); -} - - -bool KSSLCertDlg::saveChoice() { - return _save->isChecked(); -} - - -bool KSSLCertDlg::wantsToSend() { - return d->p_send_flag; -} - - -TQString KSSLCertDlg::getChoice() { - TQListViewItem *selected = _certs->selectedItem(); - if (selected && d->p_send_flag) - return selected->text(0); - else - return TQString::null; -} - - -void KSSLCertDlg::setHost(const TQString& host) { - _host = host; - d->p_message->setText(i18n("The server %1 requests a certificate.

" - "Select a certificate to use from the list below:") - .arg(_host)); -} - - -void KSSLCertDlg::slotSend() { - d->p_send_flag = true; - accept(); -} - - -void KSSLCertDlg::slotDont() { - d->p_send_flag = false; - reject(); -} - - -TQDataStream& operator<<(TQDataStream& s, const KSSLCertDlgRet& r) { - s << TQ_INT8(r.ok?1:0) << r.choice << TQ_INT8(r.save?1:0) << TQ_INT8(r.send?1:0); - return s; -} - - -TQDataStream& operator>>(TQDataStream& s, KSSLCertDlgRet& r) { -TQ_INT8 tmp; - s >> tmp; r.ok = (tmp == 1); - s >> r.choice; - s >> tmp; r.save = (tmp == 1); - s >> tmp; r.send = (tmp == 1); - return s; -} - - -#include "ksslcertdlg.moc" - diff --git a/tdeio/kssl/ksslcertdlg.cpp b/tdeio/kssl/ksslcertdlg.cpp new file mode 100644 index 000000000..7431d4c0a --- /dev/null +++ b/tdeio/kssl/ksslcertdlg.cpp @@ -0,0 +1,174 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001-2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "ksslcertdlg.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +class KSSLCertDlg::KSSLCertDlgPrivate { +private: + friend class KSSLCertDlg; + TQLabel *p_message; + TQPushButton *p_pb_dontsend; + bool p_send_flag; +}; + +KSSLCertDlg::KSSLCertDlg(TQWidget *parent, const char *name, bool modal) + : KDialog(parent, name, modal), d(new KSSLCertDlgPrivate) { + + TQBoxLayout * grid = new TQVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + d->p_message = new TQLabel(TQString::null, this); + grid->addWidget(d->p_message); + setHost(_host); + + _certs = new TQListView(this); + _certs->addColumn(i18n("Certificate")); + _certs->setResizeMode(TQListView::LastColumn); + TQFontMetrics fm( TDEGlobalSettings::generalFont() ); + _certs->setMinimumHeight(4*fm.height()); + grid->addWidget(_certs); + + _save = new TQCheckBox(i18n("Save selection for this host."), this); + grid->addWidget(_save); + + grid->addWidget(new KSeparator(KSeparator::HLine, this)); + + TQBoxLayout * h = new TQHBoxLayout( grid ); + h->insertStretch(0); + + _ok = new KPushButton(i18n("Send certificate"), this); + h->addWidget(_ok); + connect(_ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotSend())); + + d->p_pb_dontsend = new KPushButton(i18n("Do not send a certificate"), this); + h->addWidget(d->p_pb_dontsend); + connect(d->p_pb_dontsend, TQT_SIGNAL(clicked()), TQT_SLOT(slotDont())); + +#ifndef TQT_NO_WIDGET_TOPEXTRA + setCaption(i18n("TDE SSL Certificate Dialog")); +#endif +} + + +KSSLCertDlg::~KSSLCertDlg() { + delete d; +} + + +void KSSLCertDlg::setup(TQStringList certs, bool saveChecked, bool sendChecked) { + setupDialog(certs, saveChecked, sendChecked); +} + +void KSSLCertDlg::setupDialog(const TQStringList& certs, bool saveChecked, bool sendChecked) { + _save->setChecked(saveChecked); + d->p_send_flag = sendChecked; + + if (sendChecked) + _ok->setDefault(true); // "do send" is the "default action". + else + d->p_pb_dontsend->setDefault(true); // "do not send" is the "default action". + + for (TQStringList::ConstIterator i = certs.begin(); i != certs.end(); ++i) { + if ((*i).isEmpty()) + continue; + + new TQListViewItem(_certs, *i); + } + + _certs->setSelected(_certs->firstChild(), true); +} + + +bool KSSLCertDlg::saveChoice() { + return _save->isChecked(); +} + + +bool KSSLCertDlg::wantsToSend() { + return d->p_send_flag; +} + + +TQString KSSLCertDlg::getChoice() { + TQListViewItem *selected = _certs->selectedItem(); + if (selected && d->p_send_flag) + return selected->text(0); + else + return TQString::null; +} + + +void KSSLCertDlg::setHost(const TQString& host) { + _host = host; + d->p_message->setText(i18n("The server %1 requests a certificate.

" + "Select a certificate to use from the list below:") + .arg(_host)); +} + + +void KSSLCertDlg::slotSend() { + d->p_send_flag = true; + accept(); +} + + +void KSSLCertDlg::slotDont() { + d->p_send_flag = false; + reject(); +} + + +TQDataStream& operator<<(TQDataStream& s, const KSSLCertDlgRet& r) { + s << TQ_INT8(r.ok?1:0) << r.choice << TQ_INT8(r.save?1:0) << TQ_INT8(r.send?1:0); + return s; +} + + +TQDataStream& operator>>(TQDataStream& s, KSSLCertDlgRet& r) { +TQ_INT8 tmp; + s >> tmp; r.ok = (tmp == 1); + s >> r.choice; + s >> tmp; r.save = (tmp == 1); + s >> tmp; r.send = (tmp == 1); + return s; +} + + +#include "ksslcertdlg.moc" + diff --git a/tdeio/kssl/ksslcertificate.cc b/tdeio/kssl/ksslcertificate.cc deleted file mode 100644 index edf877496..000000000 --- a/tdeio/kssl/ksslcertificate.cc +++ /dev/null @@ -1,1236 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000-2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - - - -#include -#include -#include -#include - -#include "kssldefs.h" -#include "ksslcertificate.h" -#include "ksslcertchain.h" -#include "ksslutils.h" - -#include -#include -#include -#include -#include - -#include - -#ifdef HAVE_SYS_STAT_H -#include -#endif - -// this hack provided by Malte Starostik to avoid glibc/openssl bug -// on some systems -#ifdef KSSL_HAVE_SSL -#define crypt _openssl_crypt -#include -#include -#include -#include -#include -#undef crypt -#endif - -#include -#include -#include -#include "ksslx509v3.h" - - - -static char hv[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - - -class KSSLCertificatePrivate { -public: - KSSLCertificatePrivate() { - kossl = KOSSL::self(); - _lastPurpose = KSSLCertificate::None; - } - - ~KSSLCertificatePrivate() { - } - - KSSLCertificate::KSSLValidation m_stateCache; - bool m_stateCached; - #ifdef KSSL_HAVE_SSL - X509 *m_cert; - X509_CRL *m_cert_crl; - #endif - KOSSL *kossl; - KSSLCertChain _chain; - KSSLX509V3 _extensions; - KSSLCertificate::KSSLPurpose _lastPurpose; -}; - -KSSLCertificate::KSSLCertificate() { - d = new KSSLCertificatePrivate; - d->m_stateCached = false; - TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl"); - #ifdef KSSL_HAVE_SSL - d->m_cert = NULL; - d->m_cert_crl = NULL; - #endif -} - - -KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) { - d = new KSSLCertificatePrivate; - d->m_stateCached = false; - TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl"); - #ifdef KSSL_HAVE_SSL - d->m_cert = NULL; - d->m_cert_crl = NULL; - setCert(KOSSL::self()->X509_dup(const_cast(x).getCert())); - KSSLCertChain *c = x.d->_chain.replicate(); - setChain(c->rawChain()); - delete c; - #endif -} - - - -KSSLCertificate::~KSSLCertificate() { -#ifdef KSSL_HAVE_SSL - if (d->m_cert) { - d->kossl->X509_free(d->m_cert); - } - if (d->m_cert_crl) { - d->kossl->X509_CRL_free(d->m_cert_crl); - } -#endif - delete d; -} - - -KSSLCertChain& KSSLCertificate::chain() { - return d->_chain; -} - - -KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) { -KSSLCertificate *n = NULL; -#ifdef KSSL_HAVE_SSL - if (x5) { - n = new KSSLCertificate; - n->setCert(KOSSL::self()->X509_dup(x5)); - } -#endif -return n; -} - - -KSSLCertificate *KSSLCertificate::fromString(TQCString cert) { -KSSLCertificate *n = NULL; -#ifdef KSSL_HAVE_SSL - if (cert.length() == 0) - return NULL; - - TQByteArray qba, qbb = cert.copy(); - KCodecs::base64Decode(qbb, qba); - unsigned char *qbap = reinterpret_cast(qba.data()); - X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); - if (!x5c) { - return NULL; - } - - n = new KSSLCertificate; - n->setCert(x5c); -#endif -return n; -} - -KSSLCertificate *KSSLCertificate::crlFromString(TQCString cert) { -KSSLCertificate *n = NULL; -#ifdef KSSL_HAVE_SSL - if (cert.length() == 0) - return NULL; - - TQByteArray qba, qbb = cert.copy(); - KCodecs::base64Decode(qbb, qba); - unsigned char *qbap = reinterpret_cast(qba.data()); - X509_CRL *x5c = KOSSL::self()->d2i_X509_CRL(NULL, &qbap, qba.size()); - if (!x5c) { - return NULL; - } - - n = new KSSLCertificate; - n->setCRL(x5c); -#endif -return n; -} - - - -TQString KSSLCertificate::getSubject() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL - char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0); - if (!t) - return rc; - rc = t; - d->kossl->CRYPTO_free(t); -#endif -return rc; -} - - -TQString KSSLCertificate::getSerialNumber() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL - ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert); - if (aint) { - rc = ASN1_INTEGER_QString(aint); - // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail - } -#endif -return rc; -} - - -TQString KSSLCertificate::getSignatureText() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL -char *s; -int n, i; - - const ASN1_BIT_STRING *signature = 0L; - const X509_ALGOR *sig_alg = 0L; - d->kossl->X509_get0_signature(&signature, &sig_alg, d->m_cert); - i = d->kossl->OBJ_obj2nid(sig_alg->algorithm); - rc = i18n("Signature Algorithm: "); - rc += (i == NID_undef)?i18n("Unknown"):TQString(d->kossl->OBJ_nid2ln(i)); - - rc += "\n"; - rc += i18n("Signature Contents:"); - n = signature->length; - s = (char *)signature->data; - for (i = 0; i < n; i++) { - if (i%20 != 0) rc += ":"; - else rc += "\n"; - rc.append(hv[(s[i]&0xf0)>>4]); - rc.append(hv[s[i]&0x0f]); - } - -#endif - -return rc; -} - - -void KSSLCertificate::getEmails(TQStringList &to) const { - to.clear(); -#ifdef KSSL_HAVE_SSL - if (!d->m_cert) - return; - - STACK *s = d->kossl->X509_get1_email(d->m_cert); - if (s) { - for(int n=0; n < d->kossl->OPENSSL_sk_num(s); n++) { - to.append(d->kossl->OPENSSL_sk_value(s,n)); - } - d->kossl->X509_email_free(s); - } -#endif -} - - -TQString KSSLCertificate::getKDEKey() const { - return getSubject() + " (" + getMD5DigestText() + ")"; -} - - -TQString KSSLCertificate::getMD5DigestFromKDEKey(const TQString &k) { - TQString rc; - int pos = k.findRev('('); - if (pos != -1) { - unsigned int len = k.length(); - if (k.at(len-1) == ')') { - rc = k.mid(pos+1, len-pos-2); - } - } - return rc; -} - - -TQString KSSLCertificate::getMD5DigestText() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL - unsigned int n; - unsigned char md[EVP_MAX_MD_SIZE]; - - if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { - return rc; - } - - for (unsigned int j = 0; j < n; j++) { - if (j > 0) - rc += ":"; - rc.append(hv[(md[j]&0xf0)>>4]); - rc.append(hv[md[j]&0x0f]); - } - -#endif - -return rc; -} - - - -TQString KSSLCertificate::getMD5Digest() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL - unsigned int n; - unsigned char md[EVP_MAX_MD_SIZE]; - - if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { - return rc; - } - - for (unsigned int j = 0; j < n; j++) { - rc.append(hv[(md[j]&0xf0)>>4]); - rc.append(hv[md[j]&0x0f]); - } - -#endif - -return rc; -} - - - -TQString KSSLCertificate::getKeyType() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL - EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); - if (pkey) { - #ifndef NO_RSA - if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) - rc = "RSA"; - else - #endif - #ifndef NO_DSA - if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) - rc = "DSA"; - else - #endif - rc = "Unknown"; - d->kossl->EVP_PKEY_free(pkey); - } -#endif - -return rc; -} - - - -TQString KSSLCertificate::getPublicKeyText() const { -TQString rc = ""; -char *x = NULL; - -#ifdef KSSL_HAVE_SSL - EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); - if (pkey) { - rc = i18n("Unknown", "Unknown key algorithm"); - #ifndef NO_RSA - if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) { - rc = i18n("Key type: RSA (%1 bit)") + "\n"; - - RSA *pkey_rsa = d->kossl->EVP_PKEY_get0_RSA(pkey); - const BIGNUM *bn_n = 0L; - const BIGNUM *bn_e = 0L; - d->kossl->RSA_get0_key(pkey_rsa, &bn_n, &bn_e, NULL); - x = d->kossl->BN_bn2hex(bn_n); - rc += i18n("Modulus: "); - rc = rc.arg(strlen(x)*4); - for (unsigned int i = 0; i < strlen(x); i++) { - if (i%40 != 0 && i%2 == 0) - rc += ":"; - else if (i%40 == 0) - rc += "\n"; - rc += x[i]; - } - rc += "\n"; - d->kossl->CRYPTO_free(x); - - x = d->kossl->BN_bn2hex(bn_e); - rc += i18n("Exponent: 0x") + x + "\n"; - d->kossl->CRYPTO_free(x); - } - #endif - #ifndef NO_DSA - if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) { - rc = i18n("Key type: DSA (%1 bit)") + "\n"; - - DSA *pkey_dsa = d->kossl->EVP_PKEY_get0_DSA(pkey); - const BIGNUM *bn_p = 0L; - const BIGNUM *bn_q = 0L; - const BIGNUM *bn_g = 0L; - const BIGNUM *bn_pub_key = 0L; - d->kossl->DSA_get0_pqg(pkey_dsa, &bn_p, &bn_q, &bn_g); - d->kossl->DSA_get0_key(pkey_dsa, &bn_pub_key, NULL); - - x = d->kossl->BN_bn2hex(bn_p); - rc += i18n("Prime: "); - // hack - this may not be always accurate - rc = rc.arg(strlen(x)*4) ; - for (unsigned int i = 0; i < strlen(x); i++) { - if (i%40 != 0 && i%2 == 0) - rc += ":"; - else if (i%40 == 0) - rc += "\n"; - rc += x[i]; - } - rc += "\n"; - d->kossl->CRYPTO_free(x); - - x = d->kossl->BN_bn2hex(bn_q); - rc += i18n("160 bit prime factor: "); - for (unsigned int i = 0; i < strlen(x); i++) { - if (i%40 != 0 && i%2 == 0) - rc += ":"; - else if (i%40 == 0) - rc += "\n"; - rc += x[i]; - } - rc += "\n"; - d->kossl->CRYPTO_free(x); - - x = d->kossl->BN_bn2hex(bn_g); - rc += TQString("g: "); - for (unsigned int i = 0; i < strlen(x); i++) { - if (i%40 != 0 && i%2 == 0) - rc += ":"; - else if (i%40 == 0) - rc += "\n"; - rc += x[i]; - } - rc += "\n"; - d->kossl->CRYPTO_free(x); - - x = d->kossl->BN_bn2hex(bn_pub_key); - rc += i18n("Public key: "); - for (unsigned int i = 0; i < strlen(x); i++) { - if (i%40 != 0 && i%2 == 0) - rc += ":"; - else if (i%40 == 0) - rc += "\n"; - rc += x[i]; - } - rc += "\n"; - d->kossl->CRYPTO_free(x); - } - #endif - d->kossl->EVP_PKEY_free(pkey); - } -#endif - -return rc; -} - - - -TQString KSSLCertificate::getIssuer() const { -TQString rc = ""; - -#ifdef KSSL_HAVE_SSL - char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0); - - if (!t) - return rc; - - rc = t; - d->kossl->CRYPTO_free(t); -#endif - -return rc; -} - -void KSSLCertificate::setChain(void *c) { -#ifdef KSSL_HAVE_SSL - d->_chain.setChain(c); -#endif - d->m_stateCached = false; - d->m_stateCache = KSSLCertificate::Unknown; -} - -void KSSLCertificate::setCert(X509 *c) { -#ifdef KSSL_HAVE_SSL -d->m_cert = c; -if (c) { - d->_extensions.flags = 0; - d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!) - -#if 0 - kdDebug(7029) << "---------------- Certificate ------------------" - << endl; - kdDebug(7029) << getSubject() << endl; -#endif - - for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) { - X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j); - int id = d->kossl->X509_PURPOSE_get_id(ptmp); - for (int ca = 0; ca < 2; ca++) { - int idret = d->kossl->X509_check_purpose(c, id, ca); - if (idret == 1 || idret == 2) { // have it -// kdDebug() << "PURPOSE: " << id << (ca?" CA":"") << endl; - if (!ca) - d->_extensions.flags |= (1L <<(id-1)); - else d->_extensions.flags |= (1L <<(16+id-1)); - } else { - if (!ca) - d->_extensions.flags &= ~(1L <<(id-1)); - else d->_extensions.flags &= ~(1L <<(16+id-1)); - } - } - } - -#if 0 - kdDebug(7029) << "flags: " << TQString::number(c->ex_flags, 2) - << "\nkeyusage: " << TQString::number(c->ex_kusage, 2) - << "\nxkeyusage: " << TQString::number(c->ex_xkusage, 2) - << "\nnscert: " << TQString::number(c->ex_nscert, 2) - << endl; - if (c->ex_flags & EXFLAG_KUSAGE) - kdDebug(7029) << " --- Key Usage extensions found" << endl; - else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl; - - if (c->ex_flags & EXFLAG_XKUSAGE) - kdDebug(7029) << " --- Extended key usage extensions found" << endl; - else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl; - - if (c->ex_flags & EXFLAG_NSCERT) - kdDebug(7029) << " --- NS extensions found" << endl; - else kdDebug(7029) << " --- NS extensions NOT found" << endl; - - if (d->_extensions.certTypeSSLCA()) - kdDebug(7029) << "NOTE: this is an SSL CA file." << endl; - else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl; - - if (d->_extensions.certTypeEmailCA()) - kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl; - else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl; - - if (d->_extensions.certTypeCodeCA()) - kdDebug(7029) << "NOTE: this is a CODE CA file." << endl; - else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl; - - if (d->_extensions.certTypeSSLClient()) - kdDebug(7029) << "NOTE: this is an SSL client." << endl; - else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl; - - if (d->_extensions.certTypeSSLServer()) - kdDebug(7029) << "NOTE: this is an SSL server." << endl; - else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl; - - if (d->_extensions.certTypeNSSSLServer()) - kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl; - else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl; - - if (d->_extensions.certTypeSMIME()) - kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl; - else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl; - - if (d->_extensions.certTypeSMIMEEncrypt()) - kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl; - else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl; - - if (d->_extensions.certTypeSMIMESign()) - kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl; - else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl; - - if (d->_extensions.certTypeCRLSign()) - kdDebug(7029) << "NOTE: this is a CRL signer." << endl; - else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl; - - kdDebug(7029) << "-----------------------------------------------" - << endl; -#endif -} -#endif -d->m_stateCached = false; -d->m_stateCache = KSSLCertificate::Unknown; -} - -void KSSLCertificate::setCRL(X509_CRL *c) { -#ifdef KSSL_HAVE_SSL -d->m_cert_crl = c; -if (c) { - d->_extensions.flags = 0; -} -#endif -d->m_stateCached = false; -d->m_stateCache = KSSLCertificate::Unknown; -} - -X509 *KSSLCertificate::getCert() { -#ifdef KSSL_HAVE_SSL - return d->m_cert; -#endif -return 0; -} - -// pull in the callback. It's common across multiple files but we want -// it to be hidden. - -#include "ksslcallback.c" - - -bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) { - return (validate(p) == KSSLCertificate::Ok); -} - - -bool KSSLCertificate::isValid() { - return isValid(KSSLCertificate::SSLServer); -} - - -int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const { -int rc = 0; -#ifdef KSSL_HAVE_SSL - if (p == KSSLCertificate::SSLServer) { - rc = X509_PURPOSE_SSL_SERVER; - } else if (p == KSSLCertificate::SSLClient) { - rc = X509_PURPOSE_SSL_CLIENT; - } else if (p == KSSLCertificate::SMIMEEncrypt) { - rc = X509_PURPOSE_SMIME_ENCRYPT; - } else if (p == KSSLCertificate::SMIMESign) { - rc = X509_PURPOSE_SMIME_SIGN; - } else if (p == KSSLCertificate::Any) { - rc = X509_PURPOSE_ANY; - } -#endif -return rc; -} - - -// For backward compatibility -KSSLCertificate::KSSLValidation KSSLCertificate::validate() { - return validate(KSSLCertificate::SSLServer); -} - -KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose) -{ - KSSLValidationList result = validateVerbose(purpose); - if (result.isEmpty()) - return KSSLCertificate::Ok; - else - return result.first(); -} - -// -// See apps/verify.c in OpenSSL for the source of most of this logic. -// - -// CRL files? we don't do that yet -KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose) -{ - return validateVerbose(purpose, 0); -} - -KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca) -{ - KSSLValidationList errors; - if (ca || (d->_lastPurpose != purpose)) { - d->m_stateCached = false; - } - - if (!d->m_stateCached) - d->_lastPurpose = purpose; - -#ifdef KSSL_HAVE_SSL - X509_STORE *certStore; - X509_LOOKUP *certLookup; - X509_STORE_CTX *certStoreCTX; - - if (!d->m_cert) - { - errors << KSSLCertificate::Unknown; - return errors; - } - - if (d->m_stateCached) { - errors << d->m_stateCache; - return errors; - } - - TQStringList qsl = TDEGlobal::dirs()->resourceDirs("kssl"); - - if (qsl.isEmpty()) { - errors << KSSLCertificate::NoCARoot; - return errors; - } - - KSSLCertificate::KSSLValidation ksslv = Unknown; - - for (TQStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) { - struct stat sb; - TQString _j = (*j) + "ca-bundle.crt"; - if (-1 == stat(_j.ascii(), &sb)) { - continue; - } - - certStore = d->kossl->X509_STORE_new(); - if (!certStore) { - errors << KSSLCertificate::Unknown; - return errors; - } - - d->kossl->X509_STORE_set_verify_cb(certStore, X509Callback); - - certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file()); - if (!certLookup) { - ksslv = KSSLCertificate::Unknown; - d->kossl->X509_STORE_free(certStore); - continue; - } - - if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) { - // error accessing directory and loading pems - kdDebug(7029) << "KSSL couldn't read CA root: " - << _j << endl; - ksslv = KSSLCertificate::ErrorReadingRoot; - d->kossl->X509_STORE_free(certStore); - continue; - } - - // This is the checking code - certStoreCTX = d->kossl->X509_STORE_CTX_new(); - - // this is a bad error - could mean no free memory. - // This may be the wrong thing to do here - if (!certStoreCTX) { - kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl; - d->kossl->X509_STORE_free(certStore); - continue; - } - - d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL); - if (d->_chain.isValid()) { - d->kossl->X509_STORE_CTX_set0_untrusted(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain()); - } - - //kdDebug(7029) << "KSSL setting CRL.............." << endl; - // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); - - d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose)); - - KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0; - KSSL_X509CallBack_ca_found = false; - - d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); - d->kossl->X509_verify_cert(certStoreCTX); - int errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); - if (ca && !KSSL_X509CallBack_ca_found) { - ksslv = KSSLCertificate::Irrelevant; - } else { - ksslv = processError(errcode); - } - // For servers, we can try NS_SSL_SERVER too - if ( (ksslv != KSSLCertificate::Ok) && - (ksslv != KSSLCertificate::Irrelevant) && - purpose == KSSLCertificate::SSLServer) { - d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, - X509_PURPOSE_NS_SSL_SERVER); - - d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); - d->kossl->X509_verify_cert(certStoreCTX); - errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); - ksslv = processError(errcode); - } - d->kossl->X509_STORE_CTX_free(certStoreCTX); - d->kossl->X509_STORE_free(certStore); - // end of checking code - // - - //kdDebug(7029) << "KSSL Validation procedure RC: " - // << rc << endl; - //kdDebug(7029) << "KSSL Validation procedure errcode: " - // << errcode << endl; - //kdDebug(7029) << "KSSL Validation procedure RESULTS: " - // << ksslv << endl; - - if (ksslv != NoCARoot && ksslv != InvalidCA) { - d->m_stateCached = true; - d->m_stateCache = ksslv; - } - break; - } - - if (ksslv != KSSLCertificate::Ok) - errors << ksslv; -#else - errors << KSSLCertificate::NoSSL; -#endif - return errors; -} - - - -KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() { - return revalidate(KSSLCertificate::SSLServer); -} - - -KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) { - d->m_stateCached = false; - return validate(p); -} - - -KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) { -KSSLCertificate::KSSLValidation rc; - -rc = KSSLCertificate::Unknown; -#ifdef KSSL_HAVE_SSL - switch (ec) { - case X509_V_OK: // OK - rc = KSSLCertificate::Ok; - break; - - - case X509_V_ERR_CERT_REJECTED: - rc = KSSLCertificate::Rejected; - break; - - - case X509_V_ERR_CERT_UNTRUSTED: - rc = KSSLCertificate::Untrusted; - break; - - - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_CRL_SIGNATURE_FAILURE: - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - rc = KSSLCertificate::SignatureFailed; - break; - - case X509_V_ERR_INVALID_CA: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - rc = KSSLCertificate::InvalidCA; - break; - - - case X509_V_ERR_INVALID_PURPOSE: - rc = KSSLCertificate::InvalidPurpose; - break; - - - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - rc = KSSLCertificate::SelfSigned; - break; - - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - rc = KSSLCertificate::SelfSignedChain; - break; - - case X509_V_ERR_CERT_REVOKED: - rc = KSSLCertificate::Revoked; - break; - - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - rc = KSSLCertificate::PathLengthExceeded; - break; - - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_CRL_NOT_YET_VALID: - case X509_V_ERR_CRL_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - rc = KSSLCertificate::Expired; - kdDebug(7029) << "KSSL apparently this is expired. Not after: " - << getNotAfter() << endl; - break; - - //case 1: - case X509_V_ERR_APPLICATION_VERIFICATION: - case X509_V_ERR_OUT_OF_MEM: - case X509_V_ERR_UNABLE_TO_GET_CRL: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - default: - rc = KSSLCertificate::Unknown; - break; -} - -d->m_stateCache = rc; -d->m_stateCached = true; -#endif -return rc; -} - - -TQString KSSLCertificate::getNotBefore() const { -#ifdef KSSL_HAVE_SSL -return ASN1_UTCTIME_QString(d->kossl->X509_getm_notBefore(d->m_cert)); -#else -return TQString::null; -#endif -} - - -TQString KSSLCertificate::getNotAfter() const { -#ifdef KSSL_HAVE_SSL -return ASN1_UTCTIME_QString(d->kossl->X509_getm_notAfter(d->m_cert)); -#else -return TQString::null; -#endif -} - - -TQDateTime KSSLCertificate::getQDTNotBefore() const { -#ifdef KSSL_HAVE_SSL -return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notBefore(d->m_cert), NULL); -#else -return TQDateTime::currentDateTime(); -#endif -} - - -TQDateTime KSSLCertificate::getQDTNotAfter() const { -#ifdef KSSL_HAVE_SSL -return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notAfter(d->m_cert), NULL); -#else -return TQDateTime::currentDateTime(); -#endif -} - - -TQDateTime KSSLCertificate::getQDTLastUpdate() const { -#ifdef KSSL_HAVE_SSL -return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_lastUpdate(d->m_cert_crl), NULL); -#else -return TQDateTime::currentDateTime(); -#endif -} - - -TQDateTime KSSLCertificate::getQDTNextUpdate() const { -#ifdef KSSL_HAVE_SSL -return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_nextUpdate(d->m_cert_crl), NULL); -#else -return TQDateTime::currentDateTime(); -#endif -} - - -int operator==(KSSLCertificate &x, KSSLCertificate &y) { -#ifndef KSSL_HAVE_SSL - return 1; -#else - if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1; - return 0; -#endif -} - - -KSSLCertificate *KSSLCertificate::replicate() { -// The new certificate doesn't have the cached value. It's probably -// better this way. We can't anticipate every reason for doing this. -KSSLCertificate *newOne = new KSSLCertificate(); -#ifdef KSSL_HAVE_SSL - newOne->setCert(d->kossl->X509_dup(getCert())); - KSSLCertChain *c = d->_chain.replicate(); - newOne->setChain(c->rawChain()); - delete c; -#endif -return newOne; -} - - -TQString KSSLCertificate::toString() { -return KCodecs::base64Encode(toDer()); -} - - -TQString KSSLCertificate::verifyText(KSSLValidation x) { -switch (x) { -case KSSLCertificate::Ok: - return i18n("The certificate is valid."); -case KSSLCertificate::PathLengthExceeded: -case KSSLCertificate::ErrorReadingRoot: -case KSSLCertificate::NoCARoot: - return i18n("Certificate signing authority root files could not be found so the certificate is not verified."); -case KSSLCertificate::SelfSignedChain: -case KSSLCertificate::InvalidCA: - return i18n("Certificate signing authority is unknown or invalid."); -case KSSLCertificate::SelfSigned: - return i18n("Certificate is self-signed and thus may not be trustworthy."); -case KSSLCertificate::Expired: - return i18n("Certificate has expired."); -case KSSLCertificate::Revoked: - return i18n("Certificate has been revoked."); -case KSSLCertificate::NoSSL: - return i18n("SSL support was not found."); -case KSSLCertificate::Untrusted: - return i18n("Signature is untrusted."); -case KSSLCertificate::SignatureFailed: - return i18n("Signature test failed."); -case KSSLCertificate::Rejected: -case KSSLCertificate::InvalidPurpose: - return i18n("Rejected, possibly due to an invalid purpose."); -case KSSLCertificate::PrivateKeyFailed: - return i18n("Private key test failed."); -case KSSLCertificate::InvalidHost: - return i18n("The certificate has not been issued for this host."); -case KSSLCertificate::Irrelevant: - return i18n("This certificate is not relevant."); -default: -break; -} - -return i18n("The certificate is invalid."); -} - - -TQByteArray KSSLCertificate::toDer() { -TQByteArray qba; -#ifdef KSSL_HAVE_SSL -unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL); -unsigned char *cert = new unsigned char[certlen]; -unsigned char *p = cert; - // FIXME: return code! - d->kossl->i2d_X509(getCert(), &p); - - // encode it into a QString - qba.duplicate((const char*)cert, certlen); - delete[] cert; -#endif -return qba; -} - - - -TQByteArray KSSLCertificate::toPem() { -TQByteArray qba; -TQString thecert = toString(); -const char *header = "-----BEGIN CERTIFICATE-----\n"; -const char *footer = "-----END CERTIFICATE-----\n"; - - // We just do base64 on the ASN1 - // 64 character lines (unpadded) - unsigned int xx = thecert.length() - 1; - for (unsigned int i = 0; i < xx/64; i++) { - thecert.insert(64*(i+1)+i, '\n'); - } - - thecert.prepend(header); - - if (thecert[thecert.length()-1] != '\n') - thecert += "\n"; - - thecert.append(footer); - - qba.duplicate(thecert.local8Bit(), thecert.length()); -return qba; -} - - -#define NETSCAPE_CERT_HDR "certificate" -#ifdef KSSL_HAVE_SSL -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) -typedef struct NETSCAPE_X509_st -{ - ASN1_OCTET_STRING *header; - X509 *cert; -} NETSCAPE_X509; -#endif -#endif - -// what a piece of crap this is -TQByteArray KSSLCertificate::toNetscape() { -TQByteArray qba; -#ifdef KSSL_HAVE_SSL -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - NETSCAPE_X509 nx; - ASN1_OCTET_STRING hdr; -#else - ASN1_HEADER ah; - ASN1_OCTET_STRING os; -#endif - KTempFile ktf; - -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; - hdr.length = strlen(NETSCAPE_CERT_HDR); - nx.header = &hdr; - nx.cert = getCert(); - - d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&nx); -#else - os.data = (unsigned char *)NETSCAPE_CERT_HDR; - os.length = strlen(NETSCAPE_CERT_HDR); - ah.header = &os; - ah.data = (char *)getCert(); - ah.meth = d->kossl->X509_asn1_meth(); - - d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah); -#endif - - ktf.close(); - - TQFile qf(ktf.name()); - qf.open(IO_ReadOnly); - char *buf = new char[qf.size()]; - qf.readBlock(buf, qf.size()); - qba.duplicate(buf, qf.size()); - qf.close(); - delete[] buf; - - ktf.unlink(); - -#endif -return qba; -} - - - -TQString KSSLCertificate::toText() { -TQString text; -#ifdef KSSL_HAVE_SSL -KTempFile ktf; - - d->kossl->X509_print(ktf.fstream(), getCert()); - ktf.close(); - - TQFile qf(ktf.name()); - qf.open(IO_ReadOnly); - char *buf = new char[qf.size()+1]; - qf.readBlock(buf, qf.size()); - buf[qf.size()] = 0; - text = buf; - delete[] buf; - qf.close(); - ktf.unlink(); -#endif -return text; -} - -// KDE 4: Make it const TQString & -bool KSSLCertificate::setCert(TQString& cert) { -#ifdef KSSL_HAVE_SSL -TQByteArray qba, qbb = cert.local8Bit().copy(); - KCodecs::base64Decode(qbb, qba); - unsigned char *qbap = reinterpret_cast(qba.data()); - X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); - if (x5c) { - setCert(x5c); - return true; - } -#endif -return false; -} - - -KSSLX509V3& KSSLCertificate::x509V3Extensions() { -return d->_extensions; -} - - -bool KSSLCertificate::isSigner() { -return d->_extensions.certTypeCA(); -} - - -TQStringList KSSLCertificate::subjAltNames() const { - TQStringList rc; -#ifdef KSSL_HAVE_SSL - STACK_OF(GENERAL_NAME) *names; - names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0); - - if (!names) { - return rc; - } - - int cnt = d->kossl->OPENSSL_sk_num(names); - - for (int i = 0; i < cnt; i++) { - const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->OPENSSL_sk_value(names, i); - if (val->type != GEN_DNS) { - continue; - } - - TQString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5); - if (!s.isEmpty() && - /* skip subjectAltNames with embedded NULs */ - s.length() == (unsigned int)d->kossl->ASN1_STRING_length(val->d.ia5)) { - rc += s; - } - } - d->kossl->OPENSSL_sk_free(names); -#endif - return rc; -} - - -TQDataStream& operator<<(TQDataStream& s, const KSSLCertificate& r) { -TQStringList qsl; -TQPtrList cl = const_cast(r).chain().getChain(); - - for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { - qsl << c->toString(); - } - - cl.setAutoDelete(true); - - s << const_cast(r).toString() << qsl; - -return s; -} - - -TQDataStream& operator>>(TQDataStream& s, KSSLCertificate& r) { -TQStringList qsl; -TQString cert; - -s >> cert >> qsl; - - if (r.setCert(cert) && !qsl.isEmpty()) - r.chain().setCertChain(qsl); - -return s; -} - - - diff --git a/tdeio/kssl/ksslcertificate.cpp b/tdeio/kssl/ksslcertificate.cpp new file mode 100644 index 000000000..edf877496 --- /dev/null +++ b/tdeio/kssl/ksslcertificate.cpp @@ -0,0 +1,1236 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000-2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + + + +#include +#include +#include +#include + +#include "kssldefs.h" +#include "ksslcertificate.h" +#include "ksslcertchain.h" +#include "ksslutils.h" + +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +// this hack provided by Malte Starostik to avoid glibc/openssl bug +// on some systems +#ifdef KSSL_HAVE_SSL +#define crypt _openssl_crypt +#include +#include +#include +#include +#include +#undef crypt +#endif + +#include +#include +#include +#include "ksslx509v3.h" + + + +static char hv[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + + +class KSSLCertificatePrivate { +public: + KSSLCertificatePrivate() { + kossl = KOSSL::self(); + _lastPurpose = KSSLCertificate::None; + } + + ~KSSLCertificatePrivate() { + } + + KSSLCertificate::KSSLValidation m_stateCache; + bool m_stateCached; + #ifdef KSSL_HAVE_SSL + X509 *m_cert; + X509_CRL *m_cert_crl; + #endif + KOSSL *kossl; + KSSLCertChain _chain; + KSSLX509V3 _extensions; + KSSLCertificate::KSSLPurpose _lastPurpose; +}; + +KSSLCertificate::KSSLCertificate() { + d = new KSSLCertificatePrivate; + d->m_stateCached = false; + TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl"); + #ifdef KSSL_HAVE_SSL + d->m_cert = NULL; + d->m_cert_crl = NULL; + #endif +} + + +KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) { + d = new KSSLCertificatePrivate; + d->m_stateCached = false; + TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl"); + #ifdef KSSL_HAVE_SSL + d->m_cert = NULL; + d->m_cert_crl = NULL; + setCert(KOSSL::self()->X509_dup(const_cast(x).getCert())); + KSSLCertChain *c = x.d->_chain.replicate(); + setChain(c->rawChain()); + delete c; + #endif +} + + + +KSSLCertificate::~KSSLCertificate() { +#ifdef KSSL_HAVE_SSL + if (d->m_cert) { + d->kossl->X509_free(d->m_cert); + } + if (d->m_cert_crl) { + d->kossl->X509_CRL_free(d->m_cert_crl); + } +#endif + delete d; +} + + +KSSLCertChain& KSSLCertificate::chain() { + return d->_chain; +} + + +KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) { +KSSLCertificate *n = NULL; +#ifdef KSSL_HAVE_SSL + if (x5) { + n = new KSSLCertificate; + n->setCert(KOSSL::self()->X509_dup(x5)); + } +#endif +return n; +} + + +KSSLCertificate *KSSLCertificate::fromString(TQCString cert) { +KSSLCertificate *n = NULL; +#ifdef KSSL_HAVE_SSL + if (cert.length() == 0) + return NULL; + + TQByteArray qba, qbb = cert.copy(); + KCodecs::base64Decode(qbb, qba); + unsigned char *qbap = reinterpret_cast(qba.data()); + X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); + if (!x5c) { + return NULL; + } + + n = new KSSLCertificate; + n->setCert(x5c); +#endif +return n; +} + +KSSLCertificate *KSSLCertificate::crlFromString(TQCString cert) { +KSSLCertificate *n = NULL; +#ifdef KSSL_HAVE_SSL + if (cert.length() == 0) + return NULL; + + TQByteArray qba, qbb = cert.copy(); + KCodecs::base64Decode(qbb, qba); + unsigned char *qbap = reinterpret_cast(qba.data()); + X509_CRL *x5c = KOSSL::self()->d2i_X509_CRL(NULL, &qbap, qba.size()); + if (!x5c) { + return NULL; + } + + n = new KSSLCertificate; + n->setCRL(x5c); +#endif +return n; +} + + + +TQString KSSLCertificate::getSubject() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL + char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0); + if (!t) + return rc; + rc = t; + d->kossl->CRYPTO_free(t); +#endif +return rc; +} + + +TQString KSSLCertificate::getSerialNumber() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL + ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert); + if (aint) { + rc = ASN1_INTEGER_QString(aint); + // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail + } +#endif +return rc; +} + + +TQString KSSLCertificate::getSignatureText() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL +char *s; +int n, i; + + const ASN1_BIT_STRING *signature = 0L; + const X509_ALGOR *sig_alg = 0L; + d->kossl->X509_get0_signature(&signature, &sig_alg, d->m_cert); + i = d->kossl->OBJ_obj2nid(sig_alg->algorithm); + rc = i18n("Signature Algorithm: "); + rc += (i == NID_undef)?i18n("Unknown"):TQString(d->kossl->OBJ_nid2ln(i)); + + rc += "\n"; + rc += i18n("Signature Contents:"); + n = signature->length; + s = (char *)signature->data; + for (i = 0; i < n; i++) { + if (i%20 != 0) rc += ":"; + else rc += "\n"; + rc.append(hv[(s[i]&0xf0)>>4]); + rc.append(hv[s[i]&0x0f]); + } + +#endif + +return rc; +} + + +void KSSLCertificate::getEmails(TQStringList &to) const { + to.clear(); +#ifdef KSSL_HAVE_SSL + if (!d->m_cert) + return; + + STACK *s = d->kossl->X509_get1_email(d->m_cert); + if (s) { + for(int n=0; n < d->kossl->OPENSSL_sk_num(s); n++) { + to.append(d->kossl->OPENSSL_sk_value(s,n)); + } + d->kossl->X509_email_free(s); + } +#endif +} + + +TQString KSSLCertificate::getKDEKey() const { + return getSubject() + " (" + getMD5DigestText() + ")"; +} + + +TQString KSSLCertificate::getMD5DigestFromKDEKey(const TQString &k) { + TQString rc; + int pos = k.findRev('('); + if (pos != -1) { + unsigned int len = k.length(); + if (k.at(len-1) == ')') { + rc = k.mid(pos+1, len-pos-2); + } + } + return rc; +} + + +TQString KSSLCertificate::getMD5DigestText() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + + if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { + return rc; + } + + for (unsigned int j = 0; j < n; j++) { + if (j > 0) + rc += ":"; + rc.append(hv[(md[j]&0xf0)>>4]); + rc.append(hv[md[j]&0x0f]); + } + +#endif + +return rc; +} + + + +TQString KSSLCertificate::getMD5Digest() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + + if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { + return rc; + } + + for (unsigned int j = 0; j < n; j++) { + rc.append(hv[(md[j]&0xf0)>>4]); + rc.append(hv[md[j]&0x0f]); + } + +#endif + +return rc; +} + + + +TQString KSSLCertificate::getKeyType() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL + EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); + if (pkey) { + #ifndef NO_RSA + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) + rc = "RSA"; + else + #endif + #ifndef NO_DSA + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) + rc = "DSA"; + else + #endif + rc = "Unknown"; + d->kossl->EVP_PKEY_free(pkey); + } +#endif + +return rc; +} + + + +TQString KSSLCertificate::getPublicKeyText() const { +TQString rc = ""; +char *x = NULL; + +#ifdef KSSL_HAVE_SSL + EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); + if (pkey) { + rc = i18n("Unknown", "Unknown key algorithm"); + #ifndef NO_RSA + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) { + rc = i18n("Key type: RSA (%1 bit)") + "\n"; + + RSA *pkey_rsa = d->kossl->EVP_PKEY_get0_RSA(pkey); + const BIGNUM *bn_n = 0L; + const BIGNUM *bn_e = 0L; + d->kossl->RSA_get0_key(pkey_rsa, &bn_n, &bn_e, NULL); + x = d->kossl->BN_bn2hex(bn_n); + rc += i18n("Modulus: "); + rc = rc.arg(strlen(x)*4); + for (unsigned int i = 0; i < strlen(x); i++) { + if (i%40 != 0 && i%2 == 0) + rc += ":"; + else if (i%40 == 0) + rc += "\n"; + rc += x[i]; + } + rc += "\n"; + d->kossl->CRYPTO_free(x); + + x = d->kossl->BN_bn2hex(bn_e); + rc += i18n("Exponent: 0x") + x + "\n"; + d->kossl->CRYPTO_free(x); + } + #endif + #ifndef NO_DSA + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) { + rc = i18n("Key type: DSA (%1 bit)") + "\n"; + + DSA *pkey_dsa = d->kossl->EVP_PKEY_get0_DSA(pkey); + const BIGNUM *bn_p = 0L; + const BIGNUM *bn_q = 0L; + const BIGNUM *bn_g = 0L; + const BIGNUM *bn_pub_key = 0L; + d->kossl->DSA_get0_pqg(pkey_dsa, &bn_p, &bn_q, &bn_g); + d->kossl->DSA_get0_key(pkey_dsa, &bn_pub_key, NULL); + + x = d->kossl->BN_bn2hex(bn_p); + rc += i18n("Prime: "); + // hack - this may not be always accurate + rc = rc.arg(strlen(x)*4) ; + for (unsigned int i = 0; i < strlen(x); i++) { + if (i%40 != 0 && i%2 == 0) + rc += ":"; + else if (i%40 == 0) + rc += "\n"; + rc += x[i]; + } + rc += "\n"; + d->kossl->CRYPTO_free(x); + + x = d->kossl->BN_bn2hex(bn_q); + rc += i18n("160 bit prime factor: "); + for (unsigned int i = 0; i < strlen(x); i++) { + if (i%40 != 0 && i%2 == 0) + rc += ":"; + else if (i%40 == 0) + rc += "\n"; + rc += x[i]; + } + rc += "\n"; + d->kossl->CRYPTO_free(x); + + x = d->kossl->BN_bn2hex(bn_g); + rc += TQString("g: "); + for (unsigned int i = 0; i < strlen(x); i++) { + if (i%40 != 0 && i%2 == 0) + rc += ":"; + else if (i%40 == 0) + rc += "\n"; + rc += x[i]; + } + rc += "\n"; + d->kossl->CRYPTO_free(x); + + x = d->kossl->BN_bn2hex(bn_pub_key); + rc += i18n("Public key: "); + for (unsigned int i = 0; i < strlen(x); i++) { + if (i%40 != 0 && i%2 == 0) + rc += ":"; + else if (i%40 == 0) + rc += "\n"; + rc += x[i]; + } + rc += "\n"; + d->kossl->CRYPTO_free(x); + } + #endif + d->kossl->EVP_PKEY_free(pkey); + } +#endif + +return rc; +} + + + +TQString KSSLCertificate::getIssuer() const { +TQString rc = ""; + +#ifdef KSSL_HAVE_SSL + char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0); + + if (!t) + return rc; + + rc = t; + d->kossl->CRYPTO_free(t); +#endif + +return rc; +} + +void KSSLCertificate::setChain(void *c) { +#ifdef KSSL_HAVE_SSL + d->_chain.setChain(c); +#endif + d->m_stateCached = false; + d->m_stateCache = KSSLCertificate::Unknown; +} + +void KSSLCertificate::setCert(X509 *c) { +#ifdef KSSL_HAVE_SSL +d->m_cert = c; +if (c) { + d->_extensions.flags = 0; + d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!) + +#if 0 + kdDebug(7029) << "---------------- Certificate ------------------" + << endl; + kdDebug(7029) << getSubject() << endl; +#endif + + for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) { + X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j); + int id = d->kossl->X509_PURPOSE_get_id(ptmp); + for (int ca = 0; ca < 2; ca++) { + int idret = d->kossl->X509_check_purpose(c, id, ca); + if (idret == 1 || idret == 2) { // have it +// kdDebug() << "PURPOSE: " << id << (ca?" CA":"") << endl; + if (!ca) + d->_extensions.flags |= (1L <<(id-1)); + else d->_extensions.flags |= (1L <<(16+id-1)); + } else { + if (!ca) + d->_extensions.flags &= ~(1L <<(id-1)); + else d->_extensions.flags &= ~(1L <<(16+id-1)); + } + } + } + +#if 0 + kdDebug(7029) << "flags: " << TQString::number(c->ex_flags, 2) + << "\nkeyusage: " << TQString::number(c->ex_kusage, 2) + << "\nxkeyusage: " << TQString::number(c->ex_xkusage, 2) + << "\nnscert: " << TQString::number(c->ex_nscert, 2) + << endl; + if (c->ex_flags & EXFLAG_KUSAGE) + kdDebug(7029) << " --- Key Usage extensions found" << endl; + else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl; + + if (c->ex_flags & EXFLAG_XKUSAGE) + kdDebug(7029) << " --- Extended key usage extensions found" << endl; + else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl; + + if (c->ex_flags & EXFLAG_NSCERT) + kdDebug(7029) << " --- NS extensions found" << endl; + else kdDebug(7029) << " --- NS extensions NOT found" << endl; + + if (d->_extensions.certTypeSSLCA()) + kdDebug(7029) << "NOTE: this is an SSL CA file." << endl; + else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl; + + if (d->_extensions.certTypeEmailCA()) + kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl; + else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl; + + if (d->_extensions.certTypeCodeCA()) + kdDebug(7029) << "NOTE: this is a CODE CA file." << endl; + else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl; + + if (d->_extensions.certTypeSSLClient()) + kdDebug(7029) << "NOTE: this is an SSL client." << endl; + else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl; + + if (d->_extensions.certTypeSSLServer()) + kdDebug(7029) << "NOTE: this is an SSL server." << endl; + else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl; + + if (d->_extensions.certTypeNSSSLServer()) + kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl; + else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl; + + if (d->_extensions.certTypeSMIME()) + kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl; + else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl; + + if (d->_extensions.certTypeSMIMEEncrypt()) + kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl; + else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl; + + if (d->_extensions.certTypeSMIMESign()) + kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl; + else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl; + + if (d->_extensions.certTypeCRLSign()) + kdDebug(7029) << "NOTE: this is a CRL signer." << endl; + else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl; + + kdDebug(7029) << "-----------------------------------------------" + << endl; +#endif +} +#endif +d->m_stateCached = false; +d->m_stateCache = KSSLCertificate::Unknown; +} + +void KSSLCertificate::setCRL(X509_CRL *c) { +#ifdef KSSL_HAVE_SSL +d->m_cert_crl = c; +if (c) { + d->_extensions.flags = 0; +} +#endif +d->m_stateCached = false; +d->m_stateCache = KSSLCertificate::Unknown; +} + +X509 *KSSLCertificate::getCert() { +#ifdef KSSL_HAVE_SSL + return d->m_cert; +#endif +return 0; +} + +// pull in the callback. It's common across multiple files but we want +// it to be hidden. + +#include "ksslcallback.c" + + +bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) { + return (validate(p) == KSSLCertificate::Ok); +} + + +bool KSSLCertificate::isValid() { + return isValid(KSSLCertificate::SSLServer); +} + + +int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const { +int rc = 0; +#ifdef KSSL_HAVE_SSL + if (p == KSSLCertificate::SSLServer) { + rc = X509_PURPOSE_SSL_SERVER; + } else if (p == KSSLCertificate::SSLClient) { + rc = X509_PURPOSE_SSL_CLIENT; + } else if (p == KSSLCertificate::SMIMEEncrypt) { + rc = X509_PURPOSE_SMIME_ENCRYPT; + } else if (p == KSSLCertificate::SMIMESign) { + rc = X509_PURPOSE_SMIME_SIGN; + } else if (p == KSSLCertificate::Any) { + rc = X509_PURPOSE_ANY; + } +#endif +return rc; +} + + +// For backward compatibility +KSSLCertificate::KSSLValidation KSSLCertificate::validate() { + return validate(KSSLCertificate::SSLServer); +} + +KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose) +{ + KSSLValidationList result = validateVerbose(purpose); + if (result.isEmpty()) + return KSSLCertificate::Ok; + else + return result.first(); +} + +// +// See apps/verify.c in OpenSSL for the source of most of this logic. +// + +// CRL files? we don't do that yet +KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose) +{ + return validateVerbose(purpose, 0); +} + +KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca) +{ + KSSLValidationList errors; + if (ca || (d->_lastPurpose != purpose)) { + d->m_stateCached = false; + } + + if (!d->m_stateCached) + d->_lastPurpose = purpose; + +#ifdef KSSL_HAVE_SSL + X509_STORE *certStore; + X509_LOOKUP *certLookup; + X509_STORE_CTX *certStoreCTX; + + if (!d->m_cert) + { + errors << KSSLCertificate::Unknown; + return errors; + } + + if (d->m_stateCached) { + errors << d->m_stateCache; + return errors; + } + + TQStringList qsl = TDEGlobal::dirs()->resourceDirs("kssl"); + + if (qsl.isEmpty()) { + errors << KSSLCertificate::NoCARoot; + return errors; + } + + KSSLCertificate::KSSLValidation ksslv = Unknown; + + for (TQStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) { + struct stat sb; + TQString _j = (*j) + "ca-bundle.crt"; + if (-1 == stat(_j.ascii(), &sb)) { + continue; + } + + certStore = d->kossl->X509_STORE_new(); + if (!certStore) { + errors << KSSLCertificate::Unknown; + return errors; + } + + d->kossl->X509_STORE_set_verify_cb(certStore, X509Callback); + + certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file()); + if (!certLookup) { + ksslv = KSSLCertificate::Unknown; + d->kossl->X509_STORE_free(certStore); + continue; + } + + if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) { + // error accessing directory and loading pems + kdDebug(7029) << "KSSL couldn't read CA root: " + << _j << endl; + ksslv = KSSLCertificate::ErrorReadingRoot; + d->kossl->X509_STORE_free(certStore); + continue; + } + + // This is the checking code + certStoreCTX = d->kossl->X509_STORE_CTX_new(); + + // this is a bad error - could mean no free memory. + // This may be the wrong thing to do here + if (!certStoreCTX) { + kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl; + d->kossl->X509_STORE_free(certStore); + continue; + } + + d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL); + if (d->_chain.isValid()) { + d->kossl->X509_STORE_CTX_set0_untrusted(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain()); + } + + //kdDebug(7029) << "KSSL setting CRL.............." << endl; + // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + + d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose)); + + KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0; + KSSL_X509CallBack_ca_found = false; + + d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); + d->kossl->X509_verify_cert(certStoreCTX); + int errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); + if (ca && !KSSL_X509CallBack_ca_found) { + ksslv = KSSLCertificate::Irrelevant; + } else { + ksslv = processError(errcode); + } + // For servers, we can try NS_SSL_SERVER too + if ( (ksslv != KSSLCertificate::Ok) && + (ksslv != KSSLCertificate::Irrelevant) && + purpose == KSSLCertificate::SSLServer) { + d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, + X509_PURPOSE_NS_SSL_SERVER); + + d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); + d->kossl->X509_verify_cert(certStoreCTX); + errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); + ksslv = processError(errcode); + } + d->kossl->X509_STORE_CTX_free(certStoreCTX); + d->kossl->X509_STORE_free(certStore); + // end of checking code + // + + //kdDebug(7029) << "KSSL Validation procedure RC: " + // << rc << endl; + //kdDebug(7029) << "KSSL Validation procedure errcode: " + // << errcode << endl; + //kdDebug(7029) << "KSSL Validation procedure RESULTS: " + // << ksslv << endl; + + if (ksslv != NoCARoot && ksslv != InvalidCA) { + d->m_stateCached = true; + d->m_stateCache = ksslv; + } + break; + } + + if (ksslv != KSSLCertificate::Ok) + errors << ksslv; +#else + errors << KSSLCertificate::NoSSL; +#endif + return errors; +} + + + +KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() { + return revalidate(KSSLCertificate::SSLServer); +} + + +KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) { + d->m_stateCached = false; + return validate(p); +} + + +KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) { +KSSLCertificate::KSSLValidation rc; + +rc = KSSLCertificate::Unknown; +#ifdef KSSL_HAVE_SSL + switch (ec) { + case X509_V_OK: // OK + rc = KSSLCertificate::Ok; + break; + + + case X509_V_ERR_CERT_REJECTED: + rc = KSSLCertificate::Rejected; + break; + + + case X509_V_ERR_CERT_UNTRUSTED: + rc = KSSLCertificate::Untrusted; + break; + + + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + rc = KSSLCertificate::SignatureFailed; + break; + + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + rc = KSSLCertificate::InvalidCA; + break; + + + case X509_V_ERR_INVALID_PURPOSE: + rc = KSSLCertificate::InvalidPurpose; + break; + + + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + rc = KSSLCertificate::SelfSigned; + break; + + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + rc = KSSLCertificate::SelfSignedChain; + break; + + case X509_V_ERR_CERT_REVOKED: + rc = KSSLCertificate::Revoked; + break; + + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + rc = KSSLCertificate::PathLengthExceeded; + break; + + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + rc = KSSLCertificate::Expired; + kdDebug(7029) << "KSSL apparently this is expired. Not after: " + << getNotAfter() << endl; + break; + + //case 1: + case X509_V_ERR_APPLICATION_VERIFICATION: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + default: + rc = KSSLCertificate::Unknown; + break; +} + +d->m_stateCache = rc; +d->m_stateCached = true; +#endif +return rc; +} + + +TQString KSSLCertificate::getNotBefore() const { +#ifdef KSSL_HAVE_SSL +return ASN1_UTCTIME_QString(d->kossl->X509_getm_notBefore(d->m_cert)); +#else +return TQString::null; +#endif +} + + +TQString KSSLCertificate::getNotAfter() const { +#ifdef KSSL_HAVE_SSL +return ASN1_UTCTIME_QString(d->kossl->X509_getm_notAfter(d->m_cert)); +#else +return TQString::null; +#endif +} + + +TQDateTime KSSLCertificate::getQDTNotBefore() const { +#ifdef KSSL_HAVE_SSL +return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notBefore(d->m_cert), NULL); +#else +return TQDateTime::currentDateTime(); +#endif +} + + +TQDateTime KSSLCertificate::getQDTNotAfter() const { +#ifdef KSSL_HAVE_SSL +return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notAfter(d->m_cert), NULL); +#else +return TQDateTime::currentDateTime(); +#endif +} + + +TQDateTime KSSLCertificate::getQDTLastUpdate() const { +#ifdef KSSL_HAVE_SSL +return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_lastUpdate(d->m_cert_crl), NULL); +#else +return TQDateTime::currentDateTime(); +#endif +} + + +TQDateTime KSSLCertificate::getQDTNextUpdate() const { +#ifdef KSSL_HAVE_SSL +return ASN1_UTCTIME_QDateTime((ASN1_UTCTIME*)d->kossl->X509_CRL_get0_nextUpdate(d->m_cert_crl), NULL); +#else +return TQDateTime::currentDateTime(); +#endif +} + + +int operator==(KSSLCertificate &x, KSSLCertificate &y) { +#ifndef KSSL_HAVE_SSL + return 1; +#else + if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1; + return 0; +#endif +} + + +KSSLCertificate *KSSLCertificate::replicate() { +// The new certificate doesn't have the cached value. It's probably +// better this way. We can't anticipate every reason for doing this. +KSSLCertificate *newOne = new KSSLCertificate(); +#ifdef KSSL_HAVE_SSL + newOne->setCert(d->kossl->X509_dup(getCert())); + KSSLCertChain *c = d->_chain.replicate(); + newOne->setChain(c->rawChain()); + delete c; +#endif +return newOne; +} + + +TQString KSSLCertificate::toString() { +return KCodecs::base64Encode(toDer()); +} + + +TQString KSSLCertificate::verifyText(KSSLValidation x) { +switch (x) { +case KSSLCertificate::Ok: + return i18n("The certificate is valid."); +case KSSLCertificate::PathLengthExceeded: +case KSSLCertificate::ErrorReadingRoot: +case KSSLCertificate::NoCARoot: + return i18n("Certificate signing authority root files could not be found so the certificate is not verified."); +case KSSLCertificate::SelfSignedChain: +case KSSLCertificate::InvalidCA: + return i18n("Certificate signing authority is unknown or invalid."); +case KSSLCertificate::SelfSigned: + return i18n("Certificate is self-signed and thus may not be trustworthy."); +case KSSLCertificate::Expired: + return i18n("Certificate has expired."); +case KSSLCertificate::Revoked: + return i18n("Certificate has been revoked."); +case KSSLCertificate::NoSSL: + return i18n("SSL support was not found."); +case KSSLCertificate::Untrusted: + return i18n("Signature is untrusted."); +case KSSLCertificate::SignatureFailed: + return i18n("Signature test failed."); +case KSSLCertificate::Rejected: +case KSSLCertificate::InvalidPurpose: + return i18n("Rejected, possibly due to an invalid purpose."); +case KSSLCertificate::PrivateKeyFailed: + return i18n("Private key test failed."); +case KSSLCertificate::InvalidHost: + return i18n("The certificate has not been issued for this host."); +case KSSLCertificate::Irrelevant: + return i18n("This certificate is not relevant."); +default: +break; +} + +return i18n("The certificate is invalid."); +} + + +TQByteArray KSSLCertificate::toDer() { +TQByteArray qba; +#ifdef KSSL_HAVE_SSL +unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL); +unsigned char *cert = new unsigned char[certlen]; +unsigned char *p = cert; + // FIXME: return code! + d->kossl->i2d_X509(getCert(), &p); + + // encode it into a QString + qba.duplicate((const char*)cert, certlen); + delete[] cert; +#endif +return qba; +} + + + +TQByteArray KSSLCertificate::toPem() { +TQByteArray qba; +TQString thecert = toString(); +const char *header = "-----BEGIN CERTIFICATE-----\n"; +const char *footer = "-----END CERTIFICATE-----\n"; + + // We just do base64 on the ASN1 + // 64 character lines (unpadded) + unsigned int xx = thecert.length() - 1; + for (unsigned int i = 0; i < xx/64; i++) { + thecert.insert(64*(i+1)+i, '\n'); + } + + thecert.prepend(header); + + if (thecert[thecert.length()-1] != '\n') + thecert += "\n"; + + thecert.append(footer); + + qba.duplicate(thecert.local8Bit(), thecert.length()); +return qba; +} + + +#define NETSCAPE_CERT_HDR "certificate" +#ifdef KSSL_HAVE_SSL +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +typedef struct NETSCAPE_X509_st +{ + ASN1_OCTET_STRING *header; + X509 *cert; +} NETSCAPE_X509; +#endif +#endif + +// what a piece of crap this is +TQByteArray KSSLCertificate::toNetscape() { +TQByteArray qba; +#ifdef KSSL_HAVE_SSL +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + NETSCAPE_X509 nx; + ASN1_OCTET_STRING hdr; +#else + ASN1_HEADER ah; + ASN1_OCTET_STRING os; +#endif + KTempFile ktf; + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; + hdr.length = strlen(NETSCAPE_CERT_HDR); + nx.header = &hdr; + nx.cert = getCert(); + + d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&nx); +#else + os.data = (unsigned char *)NETSCAPE_CERT_HDR; + os.length = strlen(NETSCAPE_CERT_HDR); + ah.header = &os; + ah.data = (char *)getCert(); + ah.meth = d->kossl->X509_asn1_meth(); + + d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah); +#endif + + ktf.close(); + + TQFile qf(ktf.name()); + qf.open(IO_ReadOnly); + char *buf = new char[qf.size()]; + qf.readBlock(buf, qf.size()); + qba.duplicate(buf, qf.size()); + qf.close(); + delete[] buf; + + ktf.unlink(); + +#endif +return qba; +} + + + +TQString KSSLCertificate::toText() { +TQString text; +#ifdef KSSL_HAVE_SSL +KTempFile ktf; + + d->kossl->X509_print(ktf.fstream(), getCert()); + ktf.close(); + + TQFile qf(ktf.name()); + qf.open(IO_ReadOnly); + char *buf = new char[qf.size()+1]; + qf.readBlock(buf, qf.size()); + buf[qf.size()] = 0; + text = buf; + delete[] buf; + qf.close(); + ktf.unlink(); +#endif +return text; +} + +// KDE 4: Make it const TQString & +bool KSSLCertificate::setCert(TQString& cert) { +#ifdef KSSL_HAVE_SSL +TQByteArray qba, qbb = cert.local8Bit().copy(); + KCodecs::base64Decode(qbb, qba); + unsigned char *qbap = reinterpret_cast(qba.data()); + X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); + if (x5c) { + setCert(x5c); + return true; + } +#endif +return false; +} + + +KSSLX509V3& KSSLCertificate::x509V3Extensions() { +return d->_extensions; +} + + +bool KSSLCertificate::isSigner() { +return d->_extensions.certTypeCA(); +} + + +TQStringList KSSLCertificate::subjAltNames() const { + TQStringList rc; +#ifdef KSSL_HAVE_SSL + STACK_OF(GENERAL_NAME) *names; + names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0); + + if (!names) { + return rc; + } + + int cnt = d->kossl->OPENSSL_sk_num(names); + + for (int i = 0; i < cnt; i++) { + const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->OPENSSL_sk_value(names, i); + if (val->type != GEN_DNS) { + continue; + } + + TQString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5); + if (!s.isEmpty() && + /* skip subjectAltNames with embedded NULs */ + s.length() == (unsigned int)d->kossl->ASN1_STRING_length(val->d.ia5)) { + rc += s; + } + } + d->kossl->OPENSSL_sk_free(names); +#endif + return rc; +} + + +TQDataStream& operator<<(TQDataStream& s, const KSSLCertificate& r) { +TQStringList qsl; +TQPtrList cl = const_cast(r).chain().getChain(); + + for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { + qsl << c->toString(); + } + + cl.setAutoDelete(true); + + s << const_cast(r).toString() << qsl; + +return s; +} + + +TQDataStream& operator>>(TQDataStream& s, KSSLCertificate& r) { +TQStringList qsl; +TQString cert; + +s >> cert >> qsl; + + if (r.setCert(cert) && !qsl.isEmpty()) + r.chain().setCertChain(qsl); + +return s; +} + + + diff --git a/tdeio/kssl/ksslcertificatecache.cc b/tdeio/kssl/ksslcertificatecache.cc deleted file mode 100644 index 2eecd66d6..000000000 --- a/tdeio/kssl/ksslcertificatecache.cc +++ /dev/null @@ -1,399 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000, 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include "ksslcertificatecache.h" -#include "ksslcertchain.h" -#include "ksslcertificate.h" - -#include -#include -#include -#include - - -class KSSLCertificateCache::KSSLCertificateCachePrivate { - public: - DCOPClient *dcc; - - KSSLCertificateCachePrivate() { dcc = new DCOPClient; dcc->attach(); } - ~KSSLCertificateCachePrivate() { delete dcc;} - -}; - - - -KSSLCertificateCache::KSSLCertificateCache() { - d = new KSSLCertificateCachePrivate; -} - - -KSSLCertificateCache::~KSSLCertificateCache() { - delete d; -} - - -void KSSLCertificateCache::saveToDisk() { - kdDebug() << "Deprecated function KSSLCertificateCache::saveToDisk() called" << endl; -} - - -void KSSLCertificateCache::clearList() { - kdDebug() << "Deprecated function KSSLCertificateCache::clearList() called" << endl; -} - - -void KSSLCertificateCache::loadDefaultPolicies() { - kdDebug() << "Deprecated function KSSLCertificateCache::loadDefaultPolicies() called" << endl; -} - - -void KSSLCertificateCache::reload() { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - d->dcc->call("kded", "kssld", - "cacheReload()", - data, rettype, retval); -} - - -void KSSLCertificateCache::addCertificate(KSSLCertificate& cert, - KSSLCertificatePolicy policy, bool permanent) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - arg << policy; - arg << permanent; - d->dcc->call("kded", "kssld", - "cacheAddCertificate(KSSLCertificate,KSSLCertificateCache::KSSLCertificatePolicy,bool)", - data, rettype, retval); -} - - -// KDE 4: Make it const TQString & -KSSLCertificateCache::KSSLCertificatePolicy KSSLCertificateCache::getPolicyByCN(TQString& cn) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cn; - bool rc = d->dcc->call("kded", "kssld", - "cacheGetPolicyByCN(TQString)", - data, rettype, retval); - - if (rc && rettype == "KSSLCertificateCache::KSSLCertificatePolicy") { - TQDataStream retStream(retval, IO_ReadOnly); - KSSLCertificateCache::KSSLCertificatePolicy drc; - retStream >> drc; - return drc; - } -return KSSLCertificateCache::Ambiguous; -} - - -KSSLCertificateCache::KSSLCertificatePolicy KSSLCertificateCache::getPolicyByCertificate(KSSLCertificate& cert) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - bool rc = d->dcc->call("kded", "kssld", - "cacheGetPolicyByCertificate(KSSLCertificate)", - data, rettype, retval); - - if (rc && rettype == "KSSLCertificateCache::KSSLCertificatePolicy") { - TQDataStream retStream(retval, IO_ReadOnly); - KSSLCertificateCache::KSSLCertificatePolicy drc; - retStream >> drc; - return drc; - } -return KSSLCertificateCache::Ambiguous; -} - - -// KDE 4: Make it const TQString & -bool KSSLCertificateCache::seenCN(TQString& cn) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cn; - bool rc = d->dcc->call("kded", "kssld", - "cacheSeenCN(TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLCertificateCache::seenCertificate(KSSLCertificate& cert) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - bool rc = d->dcc->call("kded", "kssld", - "cacheSeenCertificate(KSSLCertificate)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLCertificateCache::isPermanent(KSSLCertificate& cert) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - bool rc = d->dcc->call("kded", "kssld", - "cacheIsPermanent(KSSLCertificate)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -// KDE 4: Make it const TQString & -bool KSSLCertificateCache::removeByCN(TQString& cn) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cn; - bool rc = d->dcc->call("kded", "kssld", - "cacheRemoveByCN(TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLCertificateCache::removeByCertificate(KSSLCertificate& cert) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - bool rc = d->dcc->call("kded", "kssld", - "cacheRemoveByCertificate(KSSLCertificate)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -// KDE 4: Make it const TQString & -bool KSSLCertificateCache::modifyByCN(TQString& cn, - KSSLCertificateCache::KSSLCertificatePolicy policy, - bool permanent, - TQDateTime& expires) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cn << policy << permanent << expires; - bool rc = d->dcc->call("kded", "kssld", - "cacheModifyByCN(TQString,KSSLCertificateCache::KSSLCertificatePolicy,bool,TQDateTime)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLCertificateCache::modifyByCertificate(KSSLCertificate& cert, - KSSLCertificateCache::KSSLCertificatePolicy policy, - bool permanent, - TQDateTime& expires) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert << policy << permanent << expires; - bool rc = d->dcc->call("kded", "kssld", - "cacheModifyByCertificate(KSSLCertificate,KSSLCertificateCache::KSSLCertificatePolicy,bool,TQDateTime)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -TQStringList KSSLCertificateCache::getHostList(KSSLCertificate& cert) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - bool rc = d->dcc->call("kded", "kssld", - "cacheGetHostList(KSSLCertificate)", - data, rettype, retval); - - if (rc && rettype == TQSTRINGLIST_OBJECT_NAME_STRING) { - TQDataStream retStream(retval, IO_ReadOnly); - TQStringList drc; - retStream >> drc; - return drc; - } -return TQStringList(); -} - - -// KDE 4: Make it const TQString & -bool KSSLCertificateCache::addHost(KSSLCertificate& cert, TQString& host) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert << host; - bool rc = d->dcc->call("kded", "kssld", - "cacheAddHost(KSSLCertificate,TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -// KDE 4: Make it const TQString & -bool KSSLCertificateCache::removeHost(KSSLCertificate& cert, TQString& host) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert << host; - bool rc = d->dcc->call("kded", "kssld", - "cacheRemoveHost(KSSLCertificate,TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -TQStringList KSSLCertificateCache::getKDEKeyByEmail(const TQString &email) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << email; - bool rc = d->dcc->call("kded", "kssld", - "getKDEKeyByEmail(TQString)", - data, rettype, retval); - - if (rc && rettype == TQSTRINGLIST_OBJECT_NAME_STRING) { - TQDataStream retStream(retval, IO_ReadOnly); - TQStringList drc; - retStream >> drc; - return drc; - } - - return TQStringList(); -} - - -KSSLCertificate *KSSLCertificateCache::getCertByMD5Digest(const TQString &key) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << key; - bool rc = d->dcc->call("kded", "kssld", - "getCertByMD5Digest(TQString)", - data, rettype, retval); - - if (rc && rettype == "KSSLCertificate") { - TQDataStream retStream(retval, IO_ReadOnly); - KSSLCertificate *drc = new KSSLCertificate; - retStream >> *drc; - if (drc->getCert()) - return drc; - delete drc; // should not happen too often if used in conjunction with getKDEKeyByEmail - } - - return 0L; -} - - -TQDataStream& operator<<(TQDataStream& s, const KSSLCertificateCache::KSSLCertificatePolicy& p) { - s << (TQ_UINT32)p; -return s; -} - - -TQDataStream& operator>>(TQDataStream& s, KSSLCertificateCache::KSSLCertificatePolicy& p) { - TQ_UINT32 pd; - s >> pd; - p = (KSSLCertificateCache::KSSLCertificatePolicy) pd; - return s; -} - - - - - diff --git a/tdeio/kssl/ksslcertificatecache.cpp b/tdeio/kssl/ksslcertificatecache.cpp new file mode 100644 index 000000000..2eecd66d6 --- /dev/null +++ b/tdeio/kssl/ksslcertificatecache.cpp @@ -0,0 +1,399 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000, 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include "ksslcertificatecache.h" +#include "ksslcertchain.h" +#include "ksslcertificate.h" + +#include +#include +#include +#include + + +class KSSLCertificateCache::KSSLCertificateCachePrivate { + public: + DCOPClient *dcc; + + KSSLCertificateCachePrivate() { dcc = new DCOPClient; dcc->attach(); } + ~KSSLCertificateCachePrivate() { delete dcc;} + +}; + + + +KSSLCertificateCache::KSSLCertificateCache() { + d = new KSSLCertificateCachePrivate; +} + + +KSSLCertificateCache::~KSSLCertificateCache() { + delete d; +} + + +void KSSLCertificateCache::saveToDisk() { + kdDebug() << "Deprecated function KSSLCertificateCache::saveToDisk() called" << endl; +} + + +void KSSLCertificateCache::clearList() { + kdDebug() << "Deprecated function KSSLCertificateCache::clearList() called" << endl; +} + + +void KSSLCertificateCache::loadDefaultPolicies() { + kdDebug() << "Deprecated function KSSLCertificateCache::loadDefaultPolicies() called" << endl; +} + + +void KSSLCertificateCache::reload() { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + d->dcc->call("kded", "kssld", + "cacheReload()", + data, rettype, retval); +} + + +void KSSLCertificateCache::addCertificate(KSSLCertificate& cert, + KSSLCertificatePolicy policy, bool permanent) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + arg << policy; + arg << permanent; + d->dcc->call("kded", "kssld", + "cacheAddCertificate(KSSLCertificate,KSSLCertificateCache::KSSLCertificatePolicy,bool)", + data, rettype, retval); +} + + +// KDE 4: Make it const TQString & +KSSLCertificateCache::KSSLCertificatePolicy KSSLCertificateCache::getPolicyByCN(TQString& cn) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cn; + bool rc = d->dcc->call("kded", "kssld", + "cacheGetPolicyByCN(TQString)", + data, rettype, retval); + + if (rc && rettype == "KSSLCertificateCache::KSSLCertificatePolicy") { + TQDataStream retStream(retval, IO_ReadOnly); + KSSLCertificateCache::KSSLCertificatePolicy drc; + retStream >> drc; + return drc; + } +return KSSLCertificateCache::Ambiguous; +} + + +KSSLCertificateCache::KSSLCertificatePolicy KSSLCertificateCache::getPolicyByCertificate(KSSLCertificate& cert) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + bool rc = d->dcc->call("kded", "kssld", + "cacheGetPolicyByCertificate(KSSLCertificate)", + data, rettype, retval); + + if (rc && rettype == "KSSLCertificateCache::KSSLCertificatePolicy") { + TQDataStream retStream(retval, IO_ReadOnly); + KSSLCertificateCache::KSSLCertificatePolicy drc; + retStream >> drc; + return drc; + } +return KSSLCertificateCache::Ambiguous; +} + + +// KDE 4: Make it const TQString & +bool KSSLCertificateCache::seenCN(TQString& cn) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cn; + bool rc = d->dcc->call("kded", "kssld", + "cacheSeenCN(TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLCertificateCache::seenCertificate(KSSLCertificate& cert) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + bool rc = d->dcc->call("kded", "kssld", + "cacheSeenCertificate(KSSLCertificate)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLCertificateCache::isPermanent(KSSLCertificate& cert) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + bool rc = d->dcc->call("kded", "kssld", + "cacheIsPermanent(KSSLCertificate)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +// KDE 4: Make it const TQString & +bool KSSLCertificateCache::removeByCN(TQString& cn) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cn; + bool rc = d->dcc->call("kded", "kssld", + "cacheRemoveByCN(TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLCertificateCache::removeByCertificate(KSSLCertificate& cert) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + bool rc = d->dcc->call("kded", "kssld", + "cacheRemoveByCertificate(KSSLCertificate)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +// KDE 4: Make it const TQString & +bool KSSLCertificateCache::modifyByCN(TQString& cn, + KSSLCertificateCache::KSSLCertificatePolicy policy, + bool permanent, + TQDateTime& expires) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cn << policy << permanent << expires; + bool rc = d->dcc->call("kded", "kssld", + "cacheModifyByCN(TQString,KSSLCertificateCache::KSSLCertificatePolicy,bool,TQDateTime)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLCertificateCache::modifyByCertificate(KSSLCertificate& cert, + KSSLCertificateCache::KSSLCertificatePolicy policy, + bool permanent, + TQDateTime& expires) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert << policy << permanent << expires; + bool rc = d->dcc->call("kded", "kssld", + "cacheModifyByCertificate(KSSLCertificate,KSSLCertificateCache::KSSLCertificatePolicy,bool,TQDateTime)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +TQStringList KSSLCertificateCache::getHostList(KSSLCertificate& cert) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + bool rc = d->dcc->call("kded", "kssld", + "cacheGetHostList(KSSLCertificate)", + data, rettype, retval); + + if (rc && rettype == TQSTRINGLIST_OBJECT_NAME_STRING) { + TQDataStream retStream(retval, IO_ReadOnly); + TQStringList drc; + retStream >> drc; + return drc; + } +return TQStringList(); +} + + +// KDE 4: Make it const TQString & +bool KSSLCertificateCache::addHost(KSSLCertificate& cert, TQString& host) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert << host; + bool rc = d->dcc->call("kded", "kssld", + "cacheAddHost(KSSLCertificate,TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +// KDE 4: Make it const TQString & +bool KSSLCertificateCache::removeHost(KSSLCertificate& cert, TQString& host) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert << host; + bool rc = d->dcc->call("kded", "kssld", + "cacheRemoveHost(KSSLCertificate,TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +TQStringList KSSLCertificateCache::getKDEKeyByEmail(const TQString &email) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << email; + bool rc = d->dcc->call("kded", "kssld", + "getKDEKeyByEmail(TQString)", + data, rettype, retval); + + if (rc && rettype == TQSTRINGLIST_OBJECT_NAME_STRING) { + TQDataStream retStream(retval, IO_ReadOnly); + TQStringList drc; + retStream >> drc; + return drc; + } + + return TQStringList(); +} + + +KSSLCertificate *KSSLCertificateCache::getCertByMD5Digest(const TQString &key) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << key; + bool rc = d->dcc->call("kded", "kssld", + "getCertByMD5Digest(TQString)", + data, rettype, retval); + + if (rc && rettype == "KSSLCertificate") { + TQDataStream retStream(retval, IO_ReadOnly); + KSSLCertificate *drc = new KSSLCertificate; + retStream >> *drc; + if (drc->getCert()) + return drc; + delete drc; // should not happen too often if used in conjunction with getKDEKeyByEmail + } + + return 0L; +} + + +TQDataStream& operator<<(TQDataStream& s, const KSSLCertificateCache::KSSLCertificatePolicy& p) { + s << (TQ_UINT32)p; +return s; +} + + +TQDataStream& operator>>(TQDataStream& s, KSSLCertificateCache::KSSLCertificatePolicy& p) { + TQ_UINT32 pd; + s >> pd; + p = (KSSLCertificateCache::KSSLCertificatePolicy) pd; + return s; +} + + + + + diff --git a/tdeio/kssl/ksslcertificatefactory.cc b/tdeio/kssl/ksslcertificatefactory.cc deleted file mode 100644 index 66e272ced..000000000 --- a/tdeio/kssl/ksslcertificatefactory.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include - -//#include - -KSSLCertificate* -KSSLCertificateFactory::generateSelfSigned(KSSLKeyType /*keytype*/) { -#if 0 - //#ifdef KSSL_HAVE_SSL - X509_NAME *x509name = X509_NAME_new(); - X509 *x509; - ASN1_UTCTIME *beforeafter; - KSSLCertificate *newcert; - int rc; - - // FIXME: generate the private key - if (keytype == KEYTYPE_UNKNOWN || (key=EVP_PKEY_new()) == NULL) { - X509_NAME_free(x509name); - return NULL; - } - - switch(keytype) { - case KEYTYPE_RSA: - if (!EVP_PKEY_assign_RSA(key, RSA_generate_key(newkey,0x10001, - req_cb,bio_err))) { - - } - break; - case KEYTYPE_DSA: - if (!DSA_generate_key(dsa_params)) goto end; - if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end; - dsa_params=NULL; - if (pkey->type == EVP_PKEY_DSA) - digest=EVP_dss1(); - break; - } - - // FIXME: dn doesn't exist - // FIXME: allow the notAfter value to be parameterized - // FIXME: allow a password to lock the key with - - // Fill in the certificate - X509_NAME_add_entry_by_NID(x509name, OBJ_txt2nid("CN"), 0x1001, - (unsigned char *) dn, -1, -1, 0); - - x509 = X509_new(); - rc = X509_set_issuer_name(x509, x509name); - if (rc != 0) { - X509_free(x509); - X509_NAME_free(x509name); - return NULL; - } - rc = X509_set_subject_name(x509, x509name); - if (rc != 0) { - X509_free(x509); - X509_NAME_free(x509name); - return NULL; - } - ASN1_INTEGER_set(X509_get_serialNumber(*x509), 0); - - X509_NAME_free(x509name); - - // Make it a 1 year certificate - beforeafter = ASN1_UTCTIME_new(); - if (!X509_gmtime_adj(beforeafter, -60*60*24)) { // yesterday - X509_free(x509); - return NULL; - } - if (!X509_set_notBefore(x509, beforeafter)) { - X509_free(x509); - return NULL; - } - if (!X509_gmtime_adj(beforeafter, 60*60*24*364)) { // a year from yesterday - X509_free(x509); - return NULL; - } - if (!X509_set_notAfter(x509, beforeafter)) { - X509_free(x509); - return NULL; - } - ASN1_UTCTIME_free(beforeafter); - - if (!X509_set_pubkey(x509, key)) { - X509_free(x509); - return NULL; - } - - rc = X509_sign(x509, key, EVP_sha1()); - if (rc != 0) { - X509_free(x509); - return NULL; - } - - newCert = new KSSLCertificate; - newCert->setCert(x509); - return newCert; -#else - return NULL; -#endif -} - diff --git a/tdeio/kssl/ksslcertificatefactory.cpp b/tdeio/kssl/ksslcertificatefactory.cpp new file mode 100644 index 000000000..66e272ced --- /dev/null +++ b/tdeio/kssl/ksslcertificatefactory.cpp @@ -0,0 +1,122 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +//#include + +KSSLCertificate* +KSSLCertificateFactory::generateSelfSigned(KSSLKeyType /*keytype*/) { +#if 0 + //#ifdef KSSL_HAVE_SSL + X509_NAME *x509name = X509_NAME_new(); + X509 *x509; + ASN1_UTCTIME *beforeafter; + KSSLCertificate *newcert; + int rc; + + // FIXME: generate the private key + if (keytype == KEYTYPE_UNKNOWN || (key=EVP_PKEY_new()) == NULL) { + X509_NAME_free(x509name); + return NULL; + } + + switch(keytype) { + case KEYTYPE_RSA: + if (!EVP_PKEY_assign_RSA(key, RSA_generate_key(newkey,0x10001, + req_cb,bio_err))) { + + } + break; + case KEYTYPE_DSA: + if (!DSA_generate_key(dsa_params)) goto end; + if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end; + dsa_params=NULL; + if (pkey->type == EVP_PKEY_DSA) + digest=EVP_dss1(); + break; + } + + // FIXME: dn doesn't exist + // FIXME: allow the notAfter value to be parameterized + // FIXME: allow a password to lock the key with + + // Fill in the certificate + X509_NAME_add_entry_by_NID(x509name, OBJ_txt2nid("CN"), 0x1001, + (unsigned char *) dn, -1, -1, 0); + + x509 = X509_new(); + rc = X509_set_issuer_name(x509, x509name); + if (rc != 0) { + X509_free(x509); + X509_NAME_free(x509name); + return NULL; + } + rc = X509_set_subject_name(x509, x509name); + if (rc != 0) { + X509_free(x509); + X509_NAME_free(x509name); + return NULL; + } + ASN1_INTEGER_set(X509_get_serialNumber(*x509), 0); + + X509_NAME_free(x509name); + + // Make it a 1 year certificate + beforeafter = ASN1_UTCTIME_new(); + if (!X509_gmtime_adj(beforeafter, -60*60*24)) { // yesterday + X509_free(x509); + return NULL; + } + if (!X509_set_notBefore(x509, beforeafter)) { + X509_free(x509); + return NULL; + } + if (!X509_gmtime_adj(beforeafter, 60*60*24*364)) { // a year from yesterday + X509_free(x509); + return NULL; + } + if (!X509_set_notAfter(x509, beforeafter)) { + X509_free(x509); + return NULL; + } + ASN1_UTCTIME_free(beforeafter); + + if (!X509_set_pubkey(x509, key)) { + X509_free(x509); + return NULL; + } + + rc = X509_sign(x509, key, EVP_sha1()); + if (rc != 0) { + X509_free(x509); + return NULL; + } + + newCert = new KSSLCertificate; + newCert->setCert(x509); + return newCert; +#else + return NULL; +#endif +} + diff --git a/tdeio/kssl/ksslcertificatehome.cc b/tdeio/kssl/ksslcertificatehome.cc deleted file mode 100644 index 39470c5ab..000000000 --- a/tdeio/kssl/ksslcertificatehome.cc +++ /dev/null @@ -1,246 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000-2005 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include - -#include -#include - -using namespace KNetwork; - -TQStringList KSSLCertificateHome::getCertificateList() { -KSimpleConfig cfg("ksslcertificates", false); -TQStringList list = cfg.groupList(); -TQString defaultstr(""); -TQString blankstr(""); - -list.remove(defaultstr); -list.remove(blankstr); - -return list; -} - - -// KDE 4: make it const TQString & -void KSSLCertificateHome::setDefaultCertificate(TQString name, TQString host, bool send, bool prompt) { -KSimpleConfig cfg("ksslauthmap", false); - -#ifdef Q_WS_WIN //temporary - cfg.setGroup(host); -#else - cfg.setGroup(KResolver::domainToAscii(host)); -#endif - cfg.writeEntry("certificate", name); - cfg.writeEntry("send", send); - cfg.writeEntry("prompt", prompt); - cfg.sync(); -} - - -// KDE 4: make it const TQString & -void KSSLCertificateHome::setDefaultCertificate(KSSLPKCS12 *cert, TQString host, bool send, bool prompt) { - if (cert) - KSSLCertificateHome::setDefaultCertificate(cert->name(), host, send, prompt); -} - - -// KDE 4: make it const TQString & -bool KSSLCertificateHome::addCertificate(TQString filename, TQString password, bool storePass) { -KSSLPKCS12 *pkcs = KSSLPKCS12::loadCertFile(filename, password); - - if (!pkcs) return false; - - KSSLCertificateHome::addCertificate(pkcs, storePass?password:TQString("")); - delete pkcs; - -return true; -} - - -// KDE 4: make it const TQString & -bool KSSLCertificateHome::addCertificate(KSSLPKCS12 *cert, TQString passToStore) { - if (!cert) return false; - -KSimpleConfig cfg("ksslcertificates", false); - - cfg.setGroup(cert->name()); - cfg.writeEntry("PKCS12Base64", cert->toString()); - cfg.writeEntry("Password", passToStore); - cfg.sync(); -return true; -} - -bool KSSLCertificateHome::deleteCertificate(const TQString &filename, const TQString &password) { -KSSLPKCS12 *pkcs = KSSLPKCS12::loadCertFile(filename, password); - - if (!pkcs) return false; - - bool ok = deleteCertificate(pkcs); - delete pkcs; - -return ok; -} - -bool KSSLCertificateHome::deleteCertificate(KSSLPKCS12 *cert) { - if (!cert) return false; - - return deleteCertificateByName(cert->name()); -} - -bool KSSLCertificateHome::deleteCertificateByName(const TQString &name) { - if (name.isEmpty()) return false; - -KSimpleConfig cfg("ksslcertificates", false); - - bool ok = cfg.deleteGroup(name); - cfg.sync(); - -return ok; -} - -// KDE 4: make it const TQString & -KSSLPKCS12* KSSLCertificateHome::getCertificateByName(TQString name, TQString password) { -KSimpleConfig cfg("ksslcertificates", false); - if (!cfg.hasGroup(name)) return NULL; - - cfg.setGroup(name); - - return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), password); -} - - -// KDE 4: make it const TQString & -KSSLPKCS12* KSSLCertificateHome::getCertificateByName(TQString name) { -KSimpleConfig cfg("ksslcertificates", false); - if (!cfg.hasGroup(name)) return NULL; - - cfg.setGroup(name); - - return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), cfg.readEntry("Password", "")); -} - - -// KDE 4: make it const TQString & -bool KSSLCertificateHome::hasCertificateByName(TQString name) { -KSimpleConfig cfg("ksslcertificates", false); - if (!cfg.hasGroup(name)) return false; - return true; -} - -// KDE 4: make it const TQString & -KSSLPKCS12* KSSLCertificateHome::getCertificateByHost(TQString host, TQString password, KSSLAuthAction *aa) { - return KSSLCertificateHome::getCertificateByName(KSSLCertificateHome::getDefaultCertificateName(host, aa), password); -} - - -// KDE 4: make it const TQString & -TQString KSSLCertificateHome::getDefaultCertificateName(TQString host, KSSLAuthAction *aa) { -KSimpleConfig cfg("ksslauthmap", false); - -#ifdef Q_WS_WIN //temporary - if (!cfg.hasGroup(host)) { -#else - if (!cfg.hasGroup(KResolver::domainToAscii(host))) { -#endif - if (aa) *aa = AuthNone; - return TQString::null; - } else { -#ifdef Q_WS_WIN //temporary - cfg.setGroup(host); -#else - cfg.setGroup(KResolver::domainToAscii(host)); -#endif - if (aa) { - bool tmp = cfg.readBoolEntry("send", false); - *aa = AuthSend; - if (!tmp) { - tmp = cfg.readBoolEntry("prompt", false); - *aa = AuthPrompt; - if (!tmp) { - *aa = AuthDont; - } - } - } - return cfg.readEntry("certificate", ""); - } -} - - -TQString KSSLCertificateHome::getDefaultCertificateName(KSSLAuthAction *aa) { -TDEConfig cfg("cryptodefaults", false); - - cfg.setGroup("Auth"); - if (aa) { - TQString am = cfg.readEntry("AuthMethod", ""); - if (am == "send") - *aa = AuthSend; - else if (am == "prompt") - *aa = AuthPrompt; - else - *aa = AuthDont; - } - -return cfg.readEntry("DefaultCert", ""); -} - - -// KDE 4: make it const TQString & -KSSLPKCS12* KSSLCertificateHome::getDefaultCertificate(TQString password, KSSLAuthAction *aa) { -TQString name = KSSLCertificateHome::getDefaultCertificateName(aa); -KSimpleConfig cfg("ksslcertificates", false); - - if (name.isEmpty()) return NULL; - - cfg.setGroup(name); - return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), password); -} - - - -KSSLPKCS12* KSSLCertificateHome::getDefaultCertificate(KSSLAuthAction *aa) { -TQString name = KSSLCertificateHome::getDefaultCertificateName(aa); -KSimpleConfig cfg("ksslcertificates", false); - - if (name.isEmpty()) return NULL; - - cfg.setGroup(name); - return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), - cfg.readEntry("Password", "")); -} - - -// KDE 4: make it const TQString & -void KSSLCertificateHome::setDefaultCertificate(TQString name, bool send, bool prompt) { -KSimpleConfig cfg("ksslauthmap", false); - - cfg.setGroup(""); - cfg.writeEntry("defaultCertificate", name); - cfg.writeEntry("send", send); - cfg.writeEntry("prompt", prompt); -} - - -void KSSLCertificateHome::setDefaultCertificate(KSSLPKCS12 *cert, bool send, bool prompt) { - if (cert) - KSSLCertificateHome::setDefaultCertificate(cert->name(), send, prompt); -} - diff --git a/tdeio/kssl/ksslcertificatehome.cpp b/tdeio/kssl/ksslcertificatehome.cpp new file mode 100644 index 000000000..39470c5ab --- /dev/null +++ b/tdeio/kssl/ksslcertificatehome.cpp @@ -0,0 +1,246 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000-2005 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include + +using namespace KNetwork; + +TQStringList KSSLCertificateHome::getCertificateList() { +KSimpleConfig cfg("ksslcertificates", false); +TQStringList list = cfg.groupList(); +TQString defaultstr(""); +TQString blankstr(""); + +list.remove(defaultstr); +list.remove(blankstr); + +return list; +} + + +// KDE 4: make it const TQString & +void KSSLCertificateHome::setDefaultCertificate(TQString name, TQString host, bool send, bool prompt) { +KSimpleConfig cfg("ksslauthmap", false); + +#ifdef Q_WS_WIN //temporary + cfg.setGroup(host); +#else + cfg.setGroup(KResolver::domainToAscii(host)); +#endif + cfg.writeEntry("certificate", name); + cfg.writeEntry("send", send); + cfg.writeEntry("prompt", prompt); + cfg.sync(); +} + + +// KDE 4: make it const TQString & +void KSSLCertificateHome::setDefaultCertificate(KSSLPKCS12 *cert, TQString host, bool send, bool prompt) { + if (cert) + KSSLCertificateHome::setDefaultCertificate(cert->name(), host, send, prompt); +} + + +// KDE 4: make it const TQString & +bool KSSLCertificateHome::addCertificate(TQString filename, TQString password, bool storePass) { +KSSLPKCS12 *pkcs = KSSLPKCS12::loadCertFile(filename, password); + + if (!pkcs) return false; + + KSSLCertificateHome::addCertificate(pkcs, storePass?password:TQString("")); + delete pkcs; + +return true; +} + + +// KDE 4: make it const TQString & +bool KSSLCertificateHome::addCertificate(KSSLPKCS12 *cert, TQString passToStore) { + if (!cert) return false; + +KSimpleConfig cfg("ksslcertificates", false); + + cfg.setGroup(cert->name()); + cfg.writeEntry("PKCS12Base64", cert->toString()); + cfg.writeEntry("Password", passToStore); + cfg.sync(); +return true; +} + +bool KSSLCertificateHome::deleteCertificate(const TQString &filename, const TQString &password) { +KSSLPKCS12 *pkcs = KSSLPKCS12::loadCertFile(filename, password); + + if (!pkcs) return false; + + bool ok = deleteCertificate(pkcs); + delete pkcs; + +return ok; +} + +bool KSSLCertificateHome::deleteCertificate(KSSLPKCS12 *cert) { + if (!cert) return false; + + return deleteCertificateByName(cert->name()); +} + +bool KSSLCertificateHome::deleteCertificateByName(const TQString &name) { + if (name.isEmpty()) return false; + +KSimpleConfig cfg("ksslcertificates", false); + + bool ok = cfg.deleteGroup(name); + cfg.sync(); + +return ok; +} + +// KDE 4: make it const TQString & +KSSLPKCS12* KSSLCertificateHome::getCertificateByName(TQString name, TQString password) { +KSimpleConfig cfg("ksslcertificates", false); + if (!cfg.hasGroup(name)) return NULL; + + cfg.setGroup(name); + + return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), password); +} + + +// KDE 4: make it const TQString & +KSSLPKCS12* KSSLCertificateHome::getCertificateByName(TQString name) { +KSimpleConfig cfg("ksslcertificates", false); + if (!cfg.hasGroup(name)) return NULL; + + cfg.setGroup(name); + + return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), cfg.readEntry("Password", "")); +} + + +// KDE 4: make it const TQString & +bool KSSLCertificateHome::hasCertificateByName(TQString name) { +KSimpleConfig cfg("ksslcertificates", false); + if (!cfg.hasGroup(name)) return false; + return true; +} + +// KDE 4: make it const TQString & +KSSLPKCS12* KSSLCertificateHome::getCertificateByHost(TQString host, TQString password, KSSLAuthAction *aa) { + return KSSLCertificateHome::getCertificateByName(KSSLCertificateHome::getDefaultCertificateName(host, aa), password); +} + + +// KDE 4: make it const TQString & +TQString KSSLCertificateHome::getDefaultCertificateName(TQString host, KSSLAuthAction *aa) { +KSimpleConfig cfg("ksslauthmap", false); + +#ifdef Q_WS_WIN //temporary + if (!cfg.hasGroup(host)) { +#else + if (!cfg.hasGroup(KResolver::domainToAscii(host))) { +#endif + if (aa) *aa = AuthNone; + return TQString::null; + } else { +#ifdef Q_WS_WIN //temporary + cfg.setGroup(host); +#else + cfg.setGroup(KResolver::domainToAscii(host)); +#endif + if (aa) { + bool tmp = cfg.readBoolEntry("send", false); + *aa = AuthSend; + if (!tmp) { + tmp = cfg.readBoolEntry("prompt", false); + *aa = AuthPrompt; + if (!tmp) { + *aa = AuthDont; + } + } + } + return cfg.readEntry("certificate", ""); + } +} + + +TQString KSSLCertificateHome::getDefaultCertificateName(KSSLAuthAction *aa) { +TDEConfig cfg("cryptodefaults", false); + + cfg.setGroup("Auth"); + if (aa) { + TQString am = cfg.readEntry("AuthMethod", ""); + if (am == "send") + *aa = AuthSend; + else if (am == "prompt") + *aa = AuthPrompt; + else + *aa = AuthDont; + } + +return cfg.readEntry("DefaultCert", ""); +} + + +// KDE 4: make it const TQString & +KSSLPKCS12* KSSLCertificateHome::getDefaultCertificate(TQString password, KSSLAuthAction *aa) { +TQString name = KSSLCertificateHome::getDefaultCertificateName(aa); +KSimpleConfig cfg("ksslcertificates", false); + + if (name.isEmpty()) return NULL; + + cfg.setGroup(name); + return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), password); +} + + + +KSSLPKCS12* KSSLCertificateHome::getDefaultCertificate(KSSLAuthAction *aa) { +TQString name = KSSLCertificateHome::getDefaultCertificateName(aa); +KSimpleConfig cfg("ksslcertificates", false); + + if (name.isEmpty()) return NULL; + + cfg.setGroup(name); + return KSSLPKCS12::fromString(cfg.readEntry("PKCS12Base64", ""), + cfg.readEntry("Password", "")); +} + + +// KDE 4: make it const TQString & +void KSSLCertificateHome::setDefaultCertificate(TQString name, bool send, bool prompt) { +KSimpleConfig cfg("ksslauthmap", false); + + cfg.setGroup(""); + cfg.writeEntry("defaultCertificate", name); + cfg.writeEntry("send", send); + cfg.writeEntry("prompt", prompt); +} + + +void KSSLCertificateHome::setDefaultCertificate(KSSLPKCS12 *cert, bool send, bool prompt) { + if (cert) + KSSLCertificateHome::setDefaultCertificate(cert->name(), send, prompt); +} + diff --git a/tdeio/kssl/ksslconnectioninfo.cc b/tdeio/kssl/ksslconnectioninfo.cc deleted file mode 100644 index ccc7fc780..000000000 --- a/tdeio/kssl/ksslconnectioninfo.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ksslconnectioninfo.h" - - -KSSLConnectionInfo::KSSLConnectionInfo() { - clean(); -} - - -KSSLConnectionInfo::~KSSLConnectionInfo() { - -} - - -void KSSLConnectionInfo::clean() { - m_iCipherUsedBits = 0; - m_iCipherBits = 0; - m_cipherName = ""; -} - - -const TQString& KSSLConnectionInfo::getCipherVersion() const { - return m_cipherVersion; -} - - -const TQString& KSSLConnectionInfo::getCipherDescription() const { - return m_cipherDescription; -} - - -const TQString& KSSLConnectionInfo::getCipher() const { - return m_cipherName; -} - - -int KSSLConnectionInfo::getCipherUsedBits() const { - return m_iCipherUsedBits; -} - - -int KSSLConnectionInfo::getCipherBits() const { - return m_iCipherBits; -} - - - diff --git a/tdeio/kssl/ksslconnectioninfo.cpp b/tdeio/kssl/ksslconnectioninfo.cpp new file mode 100644 index 000000000..ccc7fc780 --- /dev/null +++ b/tdeio/kssl/ksslconnectioninfo.cpp @@ -0,0 +1,66 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "ksslconnectioninfo.h" + + +KSSLConnectionInfo::KSSLConnectionInfo() { + clean(); +} + + +KSSLConnectionInfo::~KSSLConnectionInfo() { + +} + + +void KSSLConnectionInfo::clean() { + m_iCipherUsedBits = 0; + m_iCipherBits = 0; + m_cipherName = ""; +} + + +const TQString& KSSLConnectionInfo::getCipherVersion() const { + return m_cipherVersion; +} + + +const TQString& KSSLConnectionInfo::getCipherDescription() const { + return m_cipherDescription; +} + + +const TQString& KSSLConnectionInfo::getCipher() const { + return m_cipherName; +} + + +int KSSLConnectionInfo::getCipherUsedBits() const { + return m_iCipherUsedBits; +} + + +int KSSLConnectionInfo::getCipherBits() const { + return m_iCipherBits; +} + + + diff --git a/tdeio/kssl/ksslcsessioncache.cc b/tdeio/kssl/ksslcsessioncache.cc deleted file mode 100644 index d39638717..000000000 --- a/tdeio/kssl/ksslcsessioncache.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2003 Stefan Rompf - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include - -#include -#include -#include - -#ifdef Q_WS_WIN -#include "ksslconfig_win.h" -#else -#include "ksslconfig.h" -#endif - -#include "ksslcsessioncache.h" - -/* - * Operation: - * - * Sessions will be stored per running application, not KDE - * wide, to avoid security problems with hostile programs - * that negotiate sessions with weak cryptographic keys and store - * them for everybody to use - I really don't want that. - * - * Retrieval is organised similiar to George's thoughts in the KSSLD - * certificate cache: The cache is organised as a list, with the - * recently fetched (or stored) session first. - * - * The cache has an artificial limit of 32 sessions (should really - * be enough), and relies on the peer server for timeouts - * - */ -#define MAX_ENTRIES 32 - -#ifdef KSSL_HAVE_SSL - -typedef QPair KSSLCSession; -typedef TQPtrList KSSLCSessions; - -static KSSLCSessions *sessions = 0L; -static KStaticDeleter med; - - -static TQString URLtoKey(const KURL &kurl) { - return kurl.host() + ":" + kurl.protocol() + ":" + TQString::number(kurl.port()); -} - - -static void setup() { - KSSLCSessions *ses = new KSSLCSessions; - ses->setAutoDelete(true); - med.setObject(sessions, ses); -} - -#endif - -TQString KSSLCSessionCache::getSessionForURL(const KURL &kurl) { -#ifdef KSSL_HAVE_SSL - if (!sessions) return TQString::null; - TQString key = URLtoKey(kurl); - - for(KSSLCSession *it = sessions->first(); it; it=sessions->next()) { - if (it->first == key) { - sessions->take(); - sessions->prepend(it); - return it->second; - } - } - - // Negative caching disabled: cache pollution -#if 0 - kdDebug(7029) <<"Negative caching " <count() >= MAX_ENTRIES) sessions->removeLast(); - sessions->prepend(new KSSLCSession(key, TQString::null)); -#endif - -#endif - return TQString::null; -} - - -void KSSLCSessionCache::putSessionForURL(const KURL &kurl, const TQString &session) { -#ifdef KSSL_HAVE_SSL - if (!sessions) setup(); - TQString key = URLtoKey(kurl); - KSSLCSession *it; - - for(it = sessions->first(); it && it->first != key; it=sessions->next()); - - if (it) { - sessions->take(); - it->second = session; - } else { - it = new KSSLCSession(key, session); - if (sessions->count() >= MAX_ENTRIES) sessions->removeLast(); - } - - sessions->prepend(it); -#endif -} diff --git a/tdeio/kssl/ksslcsessioncache.cpp b/tdeio/kssl/ksslcsessioncache.cpp new file mode 100644 index 000000000..d39638717 --- /dev/null +++ b/tdeio/kssl/ksslcsessioncache.cpp @@ -0,0 +1,120 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2003 Stefan Rompf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include +#include + +#ifdef Q_WS_WIN +#include "ksslconfig_win.h" +#else +#include "ksslconfig.h" +#endif + +#include "ksslcsessioncache.h" + +/* + * Operation: + * + * Sessions will be stored per running application, not KDE + * wide, to avoid security problems with hostile programs + * that negotiate sessions with weak cryptographic keys and store + * them for everybody to use - I really don't want that. + * + * Retrieval is organised similiar to George's thoughts in the KSSLD + * certificate cache: The cache is organised as a list, with the + * recently fetched (or stored) session first. + * + * The cache has an artificial limit of 32 sessions (should really + * be enough), and relies on the peer server for timeouts + * + */ +#define MAX_ENTRIES 32 + +#ifdef KSSL_HAVE_SSL + +typedef QPair KSSLCSession; +typedef TQPtrList KSSLCSessions; + +static KSSLCSessions *sessions = 0L; +static KStaticDeleter med; + + +static TQString URLtoKey(const KURL &kurl) { + return kurl.host() + ":" + kurl.protocol() + ":" + TQString::number(kurl.port()); +} + + +static void setup() { + KSSLCSessions *ses = new KSSLCSessions; + ses->setAutoDelete(true); + med.setObject(sessions, ses); +} + +#endif + +TQString KSSLCSessionCache::getSessionForURL(const KURL &kurl) { +#ifdef KSSL_HAVE_SSL + if (!sessions) return TQString::null; + TQString key = URLtoKey(kurl); + + for(KSSLCSession *it = sessions->first(); it; it=sessions->next()) { + if (it->first == key) { + sessions->take(); + sessions->prepend(it); + return it->second; + } + } + + // Negative caching disabled: cache pollution +#if 0 + kdDebug(7029) <<"Negative caching " <count() >= MAX_ENTRIES) sessions->removeLast(); + sessions->prepend(new KSSLCSession(key, TQString::null)); +#endif + +#endif + return TQString::null; +} + + +void KSSLCSessionCache::putSessionForURL(const KURL &kurl, const TQString &session) { +#ifdef KSSL_HAVE_SSL + if (!sessions) setup(); + TQString key = URLtoKey(kurl); + KSSLCSession *it; + + for(it = sessions->first(); it && it->first != key; it=sessions->next()); + + if (it) { + sessions->take(); + it->second = session; + } else { + it = new KSSLCSession(key, session); + if (sessions->count() >= MAX_ENTRIES) sessions->removeLast(); + } + + sessions->prepend(it); +#endif +} diff --git a/tdeio/kssl/ksslinfodlg.cc b/tdeio/kssl/ksslinfodlg.cc deleted file mode 100644 index 37e13854e..000000000 --- a/tdeio/kssl/ksslinfodlg.cc +++ /dev/null @@ -1,475 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000,2001 George Staikos - * Copyright (C) 2000 Malte Starostik - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ksslinfodlg.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -#include -#include "ksslcertificate.h" -#include "ksslcertchain.h" -#include "ksslsigners.h" - - -class KSSLInfoDlg::KSSLInfoDlgPrivate { - private: - friend class KSSLInfoDlg; - bool m_secCon; - TQGridLayout *m_layout; - KComboBox *_chain; - KSSLCertificate *_cert; - KSSLCertificate::KSSLValidationList _cert_ksvl; - - bool inQuestion; - - TQLabel *_serialNum; - TQLabel *_csl; - TQLabel *_validFrom; - TQLabel *_validUntil; - TQLabel *_digest; - - TQLabel *pixmap; - TQLabel *info; - - KSSLCertBox *_subject, *_issuer; -}; - - - -KSSLInfoDlg::KSSLInfoDlg(bool secureConnection, TQWidget *parent, const char *name, bool modal) - : KDialog(parent, name, modal, (WFlags)TQt::WDestructiveClose), d(new KSSLInfoDlgPrivate) { - TQVBoxLayout *topLayout = new TQVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); - d->m_secCon = secureConnection; - d->m_layout = new TQGridLayout(topLayout, 3, 3, KDialog::spacingHint()); - d->m_layout->setColStretch(1, 1); - d->m_layout->setColStretch(2, 1); - - d->pixmap = new TQLabel(this); - d->m_layout->addWidget(d->pixmap, 0, 0); - - d->info = new TQLabel(this); - d->m_layout->addWidget(d->info, 0, 1); - - if (KSSL::doesSSLWork()) { - if (d->m_secCon) { - d->pixmap->setPixmap(BarIcon("encrypted")); - d->info->setText(i18n("Current connection is secured with SSL.")); - } else { - d->pixmap->setPixmap(BarIcon("decrypted")); - d->info->setText(i18n("Current connection is not secured with SSL.")); - } - } else { - d->pixmap->setPixmap(BarIcon("decrypted")); - d->info->setText(i18n("SSL support is not available in this build of TDE.")); - } - d->m_layout->addRowSpacing( 0, 50 ); // give minimum height to look better - - TQHBoxLayout *buttonLayout = new TQHBoxLayout(topLayout, KDialog::spacingHint()); - buttonLayout->addStretch( 1 ); - - KPushButton *button; - - if (KSSL::doesSSLWork()) { - button = new KPushButton(KGuiItem(i18n("C&ryptography Configuration..."),"configure"), this); - connect(button, TQT_SIGNAL(clicked()), TQT_SLOT(launchConfig())); - buttonLayout->addWidget( button ); - } - - button = new KPushButton(KStdGuiItem::close(), this); - connect(button, TQT_SIGNAL(clicked()), TQT_SLOT(close())); - buttonLayout->addWidget( button ); - - button->setFocus(); - - setCaption(i18n("TDE SSL Information")); - d->inQuestion = false; - } - - -KSSLInfoDlg::~KSSLInfoDlg() { - delete d; -} - -void KSSLInfoDlg::launchConfig() { - TDEProcess p; - p << "tdecmshell" << "crypto"; - p.start(TDEProcess::DontCare); -} - - -void KSSLInfoDlg::setSecurityInQuestion(bool isIt) { - d->inQuestion = isIt; - if (KSSL::doesSSLWork()) { - if (isIt) { - d->pixmap->setPixmap(BarIcon("halfencrypted")); - if (d->m_secCon) { - d->info->setText(i18n("The main part of this document is secured with SSL, but some parts are not.")); - } - else { - d->info->setText(i18n("Some of this document is secured with SSL, but the main part is not.")); - } - } - else { - if (d->m_secCon) { - d->pixmap->setPixmap(BarIcon("encrypted")); - d->info->setText(i18n("Current connection is secured with SSL.")); - } - else { - d->pixmap->setPixmap(BarIcon("decrypted")); - d->info->setText(i18n("Current connection is not secured with SSL.")); - } - } - } -} - - -void KSSLInfoDlg::setup( KSSL & ssl, const TQString & ip, const TQString & url ) -{ - setup( - &ssl.peerInfo().getPeerCertificate(), - ip, - url, - ssl.connectionInfo().getCipher(), - ssl.connectionInfo().getCipherDescription(), - ssl.connectionInfo().getCipherVersion(), - ssl.connectionInfo().getCipherUsedBits(), - ssl.connectionInfo().getCipherBits(), - ssl.peerInfo().getPeerCertificate().validate() - ); -} - -void KSSLInfoDlg::setup(KSSLCertificate *cert, - const TQString& ip, const TQString& url, - const TQString& cipher, const TQString& cipherdesc, - const TQString& sslversion, int usedbits, int bits, - KSSLCertificate::KSSLValidation /*certState*/) { - // Needed to put the GUI stuff here to get the layouting right - - d->_cert = cert; - - TQGridLayout *layout = new TQGridLayout(4, 2, KDialog::spacingHint()); - - layout->addWidget(new TQLabel(i18n("Chain:"), this), 0, 0); - d->_chain = new KComboBox(this); - layout->addMultiCellWidget(d->_chain, 1, 1, 0, 1); - connect(d->_chain, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotChain(int))); - - d->_chain->clear(); - - if (cert->chain().isValid() && cert->chain().depth() > 1) { - d->_chain->setEnabled(true); - d->_chain->insertItem(i18n("0 - Site Certificate")); - int cnt = 0; - TQPtrList cl = cert->chain().getChain(); - cl.setAutoDelete(true); - for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { - KSSLX509Map map(c->getSubject()); - TQString id; - id = map.getValue("CN"); - if (id.length() == 0) - id = map.getValue("O"); - if (id.length() == 0) - id = map.getValue("OU"); - d->_chain->insertItem(TQString::number(++cnt)+" - "+id); - } - d->_chain->setCurrentItem(0); - } else d->_chain->setEnabled(false); - - layout->addWidget(new TQLabel(i18n("Peer certificate:"), this), 2, 0); - layout->addWidget(d->_subject = static_cast(buildCertInfo(cert->getSubject())), 3, 0); - layout->addWidget(new TQLabel(i18n("Issuer:"), this), 2, 1); - layout->addWidget(d->_issuer = static_cast(buildCertInfo(cert->getIssuer())), 3, 1); - d->m_layout->addMultiCell(layout, 1, 1, 0, 2); - - layout = new TQGridLayout(11, 2, KDialog::spacingHint()); - layout->setColStretch(1, 1); - TQLabel *ipl = new TQLabel(i18n("IP address:"), this); - layout->addWidget(ipl, 0, 0); - if (ip.isEmpty()) { - ipl->hide(); - } - layout->addWidget(ipl = new TQLabel(ip, this), 0, 1); - if (ip.isEmpty()) { - ipl->hide(); - } - layout->addWidget(new TQLabel(i18n("URL:"), this), 1, 0); - KSqueezedTextLabel *urlLabel = new KSqueezedTextLabel(url, this); - layout->addWidget(urlLabel, 1, 1); - layout->addWidget(new TQLabel(i18n("Certificate state:"), this), 2, 0); - - layout->addWidget(d->_csl = new TQLabel("", this), 2, 1); - - update(); - - layout->addWidget(new TQLabel(i18n("Valid from:"), this), 3, 0); - layout->addWidget(d->_validFrom = new TQLabel("", this), 3, 1); - layout->addWidget(new TQLabel(i18n("Valid until:"), this), 4, 0); - layout->addWidget(d->_validUntil = new TQLabel("", this), 4, 1); - - layout->addWidget(new TQLabel(i18n("Serial number:"), this), 5, 0); - layout->addWidget(d->_serialNum = new TQLabel("", this), 5, 1); - layout->addWidget(new TQLabel(i18n("MD5 digest:"), this), 6, 0); - layout->addWidget(d->_digest = new TQLabel("", this), 6, 1); - - layout->addWidget(new TQLabel(i18n("Cipher in use:"), this), 7, 0); - layout->addWidget(new TQLabel(cipher, this), 7, 1); - layout->addWidget(new TQLabel(i18n("Details:"), this), 8, 0); - layout->addWidget(new TQLabel(cipherdesc.simplifyWhiteSpace(), this), 8, 1); - layout->addWidget(new TQLabel(i18n("SSL version:"), this), 9, 0); - layout->addWidget(new TQLabel(sslversion, this), 9, 1); - layout->addWidget(new TQLabel(i18n("Cipher strength:"), this), 10, 0); - layout->addWidget(new TQLabel(i18n("%1 bits used of a %2 bit cipher").arg(usedbits).arg(bits), this), 10, 1); - d->m_layout->addMultiCell(layout, 2, 2, 0, 2); - - ipl->setTextFormat(TQt::PlainText); - urlLabel->setTextFormat(TQt::PlainText); - d->_serialNum->setTextFormat(TQt::PlainText); - d->_csl->setTextFormat(TQt::PlainText); - d->_validFrom->setTextFormat(TQt::PlainText); - d->_validUntil->setTextFormat(TQt::PlainText); - d->_digest->setTextFormat(TQt::PlainText); - - displayCert(cert); -} - -void KSSLInfoDlg::setCertState(const TQString &errorNrs) -{ - d->_cert_ksvl.clear(); - TQStringList errors = TQStringList::split(':', errorNrs); - for(TQStringList::ConstIterator it = errors.begin(); - it != errors.end(); ++it) - { - d->_cert_ksvl << (KSSLCertificate::KSSLValidation) (*it).toInt(); - } -} - -void KSSLInfoDlg::displayCert(KSSLCertificate *x) { - TQPalette cspl; - - d->_serialNum->setText(x->getSerialNumber()); - - cspl = d->_validFrom->palette(); - if (x->getQDTNotBefore() > TQDateTime::currentDateTime(Qt::UTC)) - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - else cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - d->_validFrom->setPalette(cspl); - d->_validFrom->setText(x->getNotBefore()); - - cspl = d->_validUntil->palette(); - if (x->getQDTNotAfter() < TQDateTime::currentDateTime(Qt::UTC)) - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - else cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - d->_validUntil->setPalette(cspl); - d->_validUntil->setText(x->getNotAfter()); - - cspl = palette(); - - KSSLCertificate::KSSLValidation ksv; - KSSLCertificate::KSSLValidationList ksvl; - if ((x == d->_cert) && !d->_cert_ksvl.isEmpty()) { - ksvl = d->_cert_ksvl; - ksv = ksvl.first(); - } else { - if (x == d->_cert) - ksvl = d->_cert->validateVerbose(KSSLCertificate::SSLServer); - else - ksvl = d->_cert->validateVerbose(KSSLCertificate::SSLServer, x); - - if (ksvl.isEmpty()) - ksvl << KSSLCertificate::Ok; - - ksv = ksvl.first(); - - if (ksv == KSSLCertificate::SelfSigned) { - if (x->getQDTNotAfter() > TQDateTime::currentDateTime(Qt::UTC) && - x->getQDTNotBefore() < TQDateTime::currentDateTime(Qt::UTC)) { - if (KSSLSigners().useForSSL(*x)) - ksv = KSSLCertificate::Ok; - } else { - ksv = KSSLCertificate::Expired; - } - } - } - - if (ksv == KSSLCertificate::Ok) { - cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); - } else if (ksv != KSSLCertificate::Irrelevant) { - cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); - } - d->_csl->setPalette(cspl); - - TQString errorStr; - for(KSSLCertificate::KSSLValidationList::ConstIterator it = ksvl.begin(); - it != ksvl.end(); ++it) { - if (!errorStr.isEmpty()) - errorStr.append('\n'); - errorStr += KSSLCertificate::verifyText(*it); - } - - d->_csl->setText(errorStr); - d->_csl->setMinimumSize(d->_csl->sizeHint()); - - d->_subject->setValues(x->getSubject()); - d->_issuer->setValues(x->getIssuer()); - - d->_digest->setText(x->getMD5DigestText()); -} - - -void KSSLInfoDlg::slotChain(int x) { - if (x == 0) { - displayCert(d->_cert); - } else { - TQPtrList cl = d->_cert->chain().getChain(); - cl.setAutoDelete(true); - for (int i = 0; i < x-1; i++) - cl.remove((unsigned int)0); - KSSLCertificate thisCert = *(cl.at(0)); - cl.remove((unsigned int)0); - thisCert.chain().setChain(cl); - displayCert(&thisCert); - } -} - - -KSSLCertBox *KSSLInfoDlg::certInfoWidget(TQWidget *parent, const TQString &certName, TQWidget *mailCatcher) { - KSSLCertBox *result = new KSSLCertBox(parent); - if (!certName.isEmpty()) { - result->setValues(certName, mailCatcher); - } - return result; -} - - -KSSLCertBox::KSSLCertBox(TQWidget *parent, const char *name, WFlags f) -: TQScrollView(parent, name, f) -{ - _frame = 0L; - setBackgroundMode(TQWidget::PaletteButton); - setValues(TQString::null, 0L); -} - - -void KSSLCertBox::setValues(TQString certName, TQWidget *mailCatcher) { - if (_frame) { - removeChild(_frame); - delete _frame; - } - - if (certName.isEmpty()) { - _frame = new TQFrame(this); - addChild(_frame); - viewport()->setBackgroundMode(_frame->backgroundMode()); - _frame->show(); - updateScrollBars(); - show(); - return; - } - - KSSLX509Map cert(certName); - TQString tmp; - viewport()->setBackgroundMode(TQWidget::PaletteButton); - _frame = new TQFrame(this); - TQGridLayout *grid = new TQGridLayout(_frame, 1, 2, KDialog::marginHint(), KDialog::spacingHint()); - grid->setAutoAdd(true); - TQLabel *label = 0L; - if (!(tmp = cert.getValue("O")).isEmpty()) { - label = new TQLabel(i18n("Organization:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); - } - if (!(tmp = cert.getValue("OU")).isEmpty()) { - label = new TQLabel(i18n("Organizational unit:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); - } - if (!(tmp = cert.getValue("L")).isEmpty()) { - label = new TQLabel(i18n("Locality:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); - } - if (!(tmp = cert.getValue("ST")).isEmpty()) { - label = new TQLabel(i18n("Federal State","State:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); - } - if (!(tmp = cert.getValue("C")).isEmpty()) { - label = new TQLabel(i18n("Country:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); - } - if (!(tmp = cert.getValue("CN")).isEmpty()) { - label = new TQLabel(i18n("Common name:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); - } - if (!(tmp = cert.getValue("Email")).isEmpty()) { - label = new TQLabel(i18n("Email:"), _frame); - label->setAlignment(Qt::AlignLeft | Qt::AlignTop); - if (mailCatcher) { - KURLLabel *mail = new KURLLabel(tmp, tmp, _frame); - connect(mail, TQT_SIGNAL(leftClickedURL(const TQString &)), mailCatcher, TQT_SLOT(mailClicked(const TQString &))); - } else { - label = new TQLabel(tmp, _frame); - label->setTextFormat(TQt::PlainText); - } - } - if (label && viewport()) { - viewport()->setBackgroundMode(label->backgroundMode()); - } - addChild(_frame); - updateScrollBars(); - _frame->show(); - show(); -} - - -TQScrollView *KSSLInfoDlg::buildCertInfo(const TQString &certName) { - return KSSLInfoDlg::certInfoWidget(this, certName, this); -} - -void KSSLInfoDlg::urlClicked(const TQString &url) { - kapp->invokeBrowser(url); -} - -void KSSLInfoDlg::mailClicked(const TQString &url) { - kapp->invokeMailer(url, TQString::null); -} - -#include "ksslinfodlg.moc" diff --git a/tdeio/kssl/ksslinfodlg.cpp b/tdeio/kssl/ksslinfodlg.cpp new file mode 100644 index 000000000..37e13854e --- /dev/null +++ b/tdeio/kssl/ksslinfodlg.cpp @@ -0,0 +1,475 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000,2001 George Staikos + * Copyright (C) 2000 Malte Starostik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "ksslinfodlg.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include "ksslcertificate.h" +#include "ksslcertchain.h" +#include "ksslsigners.h" + + +class KSSLInfoDlg::KSSLInfoDlgPrivate { + private: + friend class KSSLInfoDlg; + bool m_secCon; + TQGridLayout *m_layout; + KComboBox *_chain; + KSSLCertificate *_cert; + KSSLCertificate::KSSLValidationList _cert_ksvl; + + bool inQuestion; + + TQLabel *_serialNum; + TQLabel *_csl; + TQLabel *_validFrom; + TQLabel *_validUntil; + TQLabel *_digest; + + TQLabel *pixmap; + TQLabel *info; + + KSSLCertBox *_subject, *_issuer; +}; + + + +KSSLInfoDlg::KSSLInfoDlg(bool secureConnection, TQWidget *parent, const char *name, bool modal) + : KDialog(parent, name, modal, (WFlags)TQt::WDestructiveClose), d(new KSSLInfoDlgPrivate) { + TQVBoxLayout *topLayout = new TQVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); + d->m_secCon = secureConnection; + d->m_layout = new TQGridLayout(topLayout, 3, 3, KDialog::spacingHint()); + d->m_layout->setColStretch(1, 1); + d->m_layout->setColStretch(2, 1); + + d->pixmap = new TQLabel(this); + d->m_layout->addWidget(d->pixmap, 0, 0); + + d->info = new TQLabel(this); + d->m_layout->addWidget(d->info, 0, 1); + + if (KSSL::doesSSLWork()) { + if (d->m_secCon) { + d->pixmap->setPixmap(BarIcon("encrypted")); + d->info->setText(i18n("Current connection is secured with SSL.")); + } else { + d->pixmap->setPixmap(BarIcon("decrypted")); + d->info->setText(i18n("Current connection is not secured with SSL.")); + } + } else { + d->pixmap->setPixmap(BarIcon("decrypted")); + d->info->setText(i18n("SSL support is not available in this build of TDE.")); + } + d->m_layout->addRowSpacing( 0, 50 ); // give minimum height to look better + + TQHBoxLayout *buttonLayout = new TQHBoxLayout(topLayout, KDialog::spacingHint()); + buttonLayout->addStretch( 1 ); + + KPushButton *button; + + if (KSSL::doesSSLWork()) { + button = new KPushButton(KGuiItem(i18n("C&ryptography Configuration..."),"configure"), this); + connect(button, TQT_SIGNAL(clicked()), TQT_SLOT(launchConfig())); + buttonLayout->addWidget( button ); + } + + button = new KPushButton(KStdGuiItem::close(), this); + connect(button, TQT_SIGNAL(clicked()), TQT_SLOT(close())); + buttonLayout->addWidget( button ); + + button->setFocus(); + + setCaption(i18n("TDE SSL Information")); + d->inQuestion = false; + } + + +KSSLInfoDlg::~KSSLInfoDlg() { + delete d; +} + +void KSSLInfoDlg::launchConfig() { + TDEProcess p; + p << "tdecmshell" << "crypto"; + p.start(TDEProcess::DontCare); +} + + +void KSSLInfoDlg::setSecurityInQuestion(bool isIt) { + d->inQuestion = isIt; + if (KSSL::doesSSLWork()) { + if (isIt) { + d->pixmap->setPixmap(BarIcon("halfencrypted")); + if (d->m_secCon) { + d->info->setText(i18n("The main part of this document is secured with SSL, but some parts are not.")); + } + else { + d->info->setText(i18n("Some of this document is secured with SSL, but the main part is not.")); + } + } + else { + if (d->m_secCon) { + d->pixmap->setPixmap(BarIcon("encrypted")); + d->info->setText(i18n("Current connection is secured with SSL.")); + } + else { + d->pixmap->setPixmap(BarIcon("decrypted")); + d->info->setText(i18n("Current connection is not secured with SSL.")); + } + } + } +} + + +void KSSLInfoDlg::setup( KSSL & ssl, const TQString & ip, const TQString & url ) +{ + setup( + &ssl.peerInfo().getPeerCertificate(), + ip, + url, + ssl.connectionInfo().getCipher(), + ssl.connectionInfo().getCipherDescription(), + ssl.connectionInfo().getCipherVersion(), + ssl.connectionInfo().getCipherUsedBits(), + ssl.connectionInfo().getCipherBits(), + ssl.peerInfo().getPeerCertificate().validate() + ); +} + +void KSSLInfoDlg::setup(KSSLCertificate *cert, + const TQString& ip, const TQString& url, + const TQString& cipher, const TQString& cipherdesc, + const TQString& sslversion, int usedbits, int bits, + KSSLCertificate::KSSLValidation /*certState*/) { + // Needed to put the GUI stuff here to get the layouting right + + d->_cert = cert; + + TQGridLayout *layout = new TQGridLayout(4, 2, KDialog::spacingHint()); + + layout->addWidget(new TQLabel(i18n("Chain:"), this), 0, 0); + d->_chain = new KComboBox(this); + layout->addMultiCellWidget(d->_chain, 1, 1, 0, 1); + connect(d->_chain, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotChain(int))); + + d->_chain->clear(); + + if (cert->chain().isValid() && cert->chain().depth() > 1) { + d->_chain->setEnabled(true); + d->_chain->insertItem(i18n("0 - Site Certificate")); + int cnt = 0; + TQPtrList cl = cert->chain().getChain(); + cl.setAutoDelete(true); + for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) { + KSSLX509Map map(c->getSubject()); + TQString id; + id = map.getValue("CN"); + if (id.length() == 0) + id = map.getValue("O"); + if (id.length() == 0) + id = map.getValue("OU"); + d->_chain->insertItem(TQString::number(++cnt)+" - "+id); + } + d->_chain->setCurrentItem(0); + } else d->_chain->setEnabled(false); + + layout->addWidget(new TQLabel(i18n("Peer certificate:"), this), 2, 0); + layout->addWidget(d->_subject = static_cast(buildCertInfo(cert->getSubject())), 3, 0); + layout->addWidget(new TQLabel(i18n("Issuer:"), this), 2, 1); + layout->addWidget(d->_issuer = static_cast(buildCertInfo(cert->getIssuer())), 3, 1); + d->m_layout->addMultiCell(layout, 1, 1, 0, 2); + + layout = new TQGridLayout(11, 2, KDialog::spacingHint()); + layout->setColStretch(1, 1); + TQLabel *ipl = new TQLabel(i18n("IP address:"), this); + layout->addWidget(ipl, 0, 0); + if (ip.isEmpty()) { + ipl->hide(); + } + layout->addWidget(ipl = new TQLabel(ip, this), 0, 1); + if (ip.isEmpty()) { + ipl->hide(); + } + layout->addWidget(new TQLabel(i18n("URL:"), this), 1, 0); + KSqueezedTextLabel *urlLabel = new KSqueezedTextLabel(url, this); + layout->addWidget(urlLabel, 1, 1); + layout->addWidget(new TQLabel(i18n("Certificate state:"), this), 2, 0); + + layout->addWidget(d->_csl = new TQLabel("", this), 2, 1); + + update(); + + layout->addWidget(new TQLabel(i18n("Valid from:"), this), 3, 0); + layout->addWidget(d->_validFrom = new TQLabel("", this), 3, 1); + layout->addWidget(new TQLabel(i18n("Valid until:"), this), 4, 0); + layout->addWidget(d->_validUntil = new TQLabel("", this), 4, 1); + + layout->addWidget(new TQLabel(i18n("Serial number:"), this), 5, 0); + layout->addWidget(d->_serialNum = new TQLabel("", this), 5, 1); + layout->addWidget(new TQLabel(i18n("MD5 digest:"), this), 6, 0); + layout->addWidget(d->_digest = new TQLabel("", this), 6, 1); + + layout->addWidget(new TQLabel(i18n("Cipher in use:"), this), 7, 0); + layout->addWidget(new TQLabel(cipher, this), 7, 1); + layout->addWidget(new TQLabel(i18n("Details:"), this), 8, 0); + layout->addWidget(new TQLabel(cipherdesc.simplifyWhiteSpace(), this), 8, 1); + layout->addWidget(new TQLabel(i18n("SSL version:"), this), 9, 0); + layout->addWidget(new TQLabel(sslversion, this), 9, 1); + layout->addWidget(new TQLabel(i18n("Cipher strength:"), this), 10, 0); + layout->addWidget(new TQLabel(i18n("%1 bits used of a %2 bit cipher").arg(usedbits).arg(bits), this), 10, 1); + d->m_layout->addMultiCell(layout, 2, 2, 0, 2); + + ipl->setTextFormat(TQt::PlainText); + urlLabel->setTextFormat(TQt::PlainText); + d->_serialNum->setTextFormat(TQt::PlainText); + d->_csl->setTextFormat(TQt::PlainText); + d->_validFrom->setTextFormat(TQt::PlainText); + d->_validUntil->setTextFormat(TQt::PlainText); + d->_digest->setTextFormat(TQt::PlainText); + + displayCert(cert); +} + +void KSSLInfoDlg::setCertState(const TQString &errorNrs) +{ + d->_cert_ksvl.clear(); + TQStringList errors = TQStringList::split(':', errorNrs); + for(TQStringList::ConstIterator it = errors.begin(); + it != errors.end(); ++it) + { + d->_cert_ksvl << (KSSLCertificate::KSSLValidation) (*it).toInt(); + } +} + +void KSSLInfoDlg::displayCert(KSSLCertificate *x) { + TQPalette cspl; + + d->_serialNum->setText(x->getSerialNumber()); + + cspl = d->_validFrom->palette(); + if (x->getQDTNotBefore() > TQDateTime::currentDateTime(Qt::UTC)) + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + else cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + d->_validFrom->setPalette(cspl); + d->_validFrom->setText(x->getNotBefore()); + + cspl = d->_validUntil->palette(); + if (x->getQDTNotAfter() < TQDateTime::currentDateTime(Qt::UTC)) + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + else cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + d->_validUntil->setPalette(cspl); + d->_validUntil->setText(x->getNotAfter()); + + cspl = palette(); + + KSSLCertificate::KSSLValidation ksv; + KSSLCertificate::KSSLValidationList ksvl; + if ((x == d->_cert) && !d->_cert_ksvl.isEmpty()) { + ksvl = d->_cert_ksvl; + ksv = ksvl.first(); + } else { + if (x == d->_cert) + ksvl = d->_cert->validateVerbose(KSSLCertificate::SSLServer); + else + ksvl = d->_cert->validateVerbose(KSSLCertificate::SSLServer, x); + + if (ksvl.isEmpty()) + ksvl << KSSLCertificate::Ok; + + ksv = ksvl.first(); + + if (ksv == KSSLCertificate::SelfSigned) { + if (x->getQDTNotAfter() > TQDateTime::currentDateTime(Qt::UTC) && + x->getQDTNotBefore() < TQDateTime::currentDateTime(Qt::UTC)) { + if (KSSLSigners().useForSSL(*x)) + ksv = KSSLCertificate::Ok; + } else { + ksv = KSSLCertificate::Expired; + } + } + } + + if (ksv == KSSLCertificate::Ok) { + cspl.setColor(TQColorGroup::Foreground, TQColor(42,153,59)); + } else if (ksv != KSSLCertificate::Irrelevant) { + cspl.setColor(TQColorGroup::Foreground, TQColor(196,33,21)); + } + d->_csl->setPalette(cspl); + + TQString errorStr; + for(KSSLCertificate::KSSLValidationList::ConstIterator it = ksvl.begin(); + it != ksvl.end(); ++it) { + if (!errorStr.isEmpty()) + errorStr.append('\n'); + errorStr += KSSLCertificate::verifyText(*it); + } + + d->_csl->setText(errorStr); + d->_csl->setMinimumSize(d->_csl->sizeHint()); + + d->_subject->setValues(x->getSubject()); + d->_issuer->setValues(x->getIssuer()); + + d->_digest->setText(x->getMD5DigestText()); +} + + +void KSSLInfoDlg::slotChain(int x) { + if (x == 0) { + displayCert(d->_cert); + } else { + TQPtrList cl = d->_cert->chain().getChain(); + cl.setAutoDelete(true); + for (int i = 0; i < x-1; i++) + cl.remove((unsigned int)0); + KSSLCertificate thisCert = *(cl.at(0)); + cl.remove((unsigned int)0); + thisCert.chain().setChain(cl); + displayCert(&thisCert); + } +} + + +KSSLCertBox *KSSLInfoDlg::certInfoWidget(TQWidget *parent, const TQString &certName, TQWidget *mailCatcher) { + KSSLCertBox *result = new KSSLCertBox(parent); + if (!certName.isEmpty()) { + result->setValues(certName, mailCatcher); + } + return result; +} + + +KSSLCertBox::KSSLCertBox(TQWidget *parent, const char *name, WFlags f) +: TQScrollView(parent, name, f) +{ + _frame = 0L; + setBackgroundMode(TQWidget::PaletteButton); + setValues(TQString::null, 0L); +} + + +void KSSLCertBox::setValues(TQString certName, TQWidget *mailCatcher) { + if (_frame) { + removeChild(_frame); + delete _frame; + } + + if (certName.isEmpty()) { + _frame = new TQFrame(this); + addChild(_frame); + viewport()->setBackgroundMode(_frame->backgroundMode()); + _frame->show(); + updateScrollBars(); + show(); + return; + } + + KSSLX509Map cert(certName); + TQString tmp; + viewport()->setBackgroundMode(TQWidget::PaletteButton); + _frame = new TQFrame(this); + TQGridLayout *grid = new TQGridLayout(_frame, 1, 2, KDialog::marginHint(), KDialog::spacingHint()); + grid->setAutoAdd(true); + TQLabel *label = 0L; + if (!(tmp = cert.getValue("O")).isEmpty()) { + label = new TQLabel(i18n("Organization:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); + } + if (!(tmp = cert.getValue("OU")).isEmpty()) { + label = new TQLabel(i18n("Organizational unit:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); + } + if (!(tmp = cert.getValue("L")).isEmpty()) { + label = new TQLabel(i18n("Locality:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); + } + if (!(tmp = cert.getValue("ST")).isEmpty()) { + label = new TQLabel(i18n("Federal State","State:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); + } + if (!(tmp = cert.getValue("C")).isEmpty()) { + label = new TQLabel(i18n("Country:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); + } + if (!(tmp = cert.getValue("CN")).isEmpty()) { + label = new TQLabel(i18n("Common name:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + (new TQLabel(tmp, _frame))->setTextFormat(TQt::PlainText); + } + if (!(tmp = cert.getValue("Email")).isEmpty()) { + label = new TQLabel(i18n("Email:"), _frame); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + if (mailCatcher) { + KURLLabel *mail = new KURLLabel(tmp, tmp, _frame); + connect(mail, TQT_SIGNAL(leftClickedURL(const TQString &)), mailCatcher, TQT_SLOT(mailClicked(const TQString &))); + } else { + label = new TQLabel(tmp, _frame); + label->setTextFormat(TQt::PlainText); + } + } + if (label && viewport()) { + viewport()->setBackgroundMode(label->backgroundMode()); + } + addChild(_frame); + updateScrollBars(); + _frame->show(); + show(); +} + + +TQScrollView *KSSLInfoDlg::buildCertInfo(const TQString &certName) { + return KSSLInfoDlg::certInfoWidget(this, certName, this); +} + +void KSSLInfoDlg::urlClicked(const TQString &url) { + kapp->invokeBrowser(url); +} + +void KSSLInfoDlg::mailClicked(const TQString &url) { + kapp->invokeMailer(url, TQString::null); +} + +#include "ksslinfodlg.moc" diff --git a/tdeio/kssl/ksslkeygen.cc b/tdeio/kssl/ksslkeygen.cc deleted file mode 100644 index 86fe4717d..000000000 --- a/tdeio/kssl/ksslkeygen.cc +++ /dev/null @@ -1,222 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include "ksslkeygen.h" -#include "keygenwizard.h" -#include "keygenwizard2.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - -KSSLKeyGen::KSSLKeyGen(TQWidget *parent, const char *name, bool modal) -:KWizard(parent,name,modal) { - _idx = -1; - -#ifdef KSSL_HAVE_SSL - page1 = new KGWizardPage1(this, "Wizard Page 1"); - addPage(page1, i18n("TDE Certificate Request")); - page2 = new KGWizardPage2(this, "Wizard Page 2"); - addPage(page2, i18n("TDE Certificate Request - Password")); - setHelpEnabled(page1, false); - setHelpEnabled(page2, false); - setFinishEnabled(page2, false); - connect(page2->_password1, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotPassChanged())); - connect(page2->_password2, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotPassChanged())); - connect(finishButton(), TQT_SIGNAL(clicked()), TQT_SLOT(slotGenerate())); -#else - // tell him he doesn't have SSL -#endif -} - - -KSSLKeyGen::~KSSLKeyGen() { - -} - - -void KSSLKeyGen::slotPassChanged() { - setFinishEnabled(page2, page2->_password1->text() == page2->_password2->text() && page2->_password1->text().length() >= 4); -} - - -void KSSLKeyGen::slotGenerate() { - assert(_idx >= 0 && _idx <= 3); // for now - - - // Generate the CSR - int bits; - switch (_idx) { - case 0: - bits = 2048; - break; - case 1: - bits = 1024; - break; - case 2: - bits = 768; - break; - case 3: - bits = 512; - break; - default: - KMessageBox::sorry(NULL, i18n("Unsupported key size."), i18n("TDE SSL Information")); - return; - } - - KProgressDialog *kpd = new KProgressDialog(this, "progress dialog", i18n("TDE"), i18n("Please wait while the encryption keys are generated...")); - kpd->progressBar()->setProgress(0); - kpd->show(); - // FIXME - progress dialog won't show this way - - int rc = generateCSR("This CSR" /*FIXME */, page2->_password1->text(), bits, 0x10001 /* This is the traditional exponent used */); - kpd->progressBar()->setProgress(100); - -#ifndef Q_OS_WIN //TODO: reenable for WIN32 - if (rc == 0 && TDEWallet::Wallet::isEnabled()) { - rc = KMessageBox::questionYesNo(this, i18n("Do you wish to store the passphrase in your wallet file?"), TQString::null, i18n("Store"), i18n("Do Not Store")); - if (rc == KMessageBox::Yes) { - TDEWallet::Wallet *w = TDEWallet::Wallet::openWallet(TDEWallet::Wallet::LocalWallet(), winId()); - if (w) { - // FIXME: store passphrase in wallet - delete w; - } - } - } -#endif - - kpd->deleteLater(); -} - - -int KSSLKeyGen::generateCSR(const TQString& name, const TQString& pass, int bits, int e) { -#ifdef KSSL_HAVE_SSL - KOSSL *kossl = KOSSL::self(); - - X509_REQ *req = kossl->X509_REQ_new(); - if (!req) { - return -2; - } - - EVP_PKEY *pkey = kossl->EVP_PKEY_new(); - if (!pkey) { - kossl->X509_REQ_free(req); - return -4; - } - - RSA *rsakey = kossl->RSA_generate_key(bits, e, NULL, NULL); - if (!rsakey) { - kossl->X509_REQ_free(req); - kossl->EVP_PKEY_free(pkey); - return -3; - } - - kossl->EVP_PKEY_assign(pkey, EVP_PKEY_RSA, (char *)rsakey); - - kossl->X509_REQ_set_pubkey(req, pkey); - - // Set the subject - X509_NAME *n = kossl->X509_NAME_new(); - - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_countryName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationalUnitName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_localityName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_stateOrProvinceName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_commonName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_pkcs9_emailAddress, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); - - kossl->X509_REQ_set_subject_name(req, n); - - - kossl->X509_REQ_sign(req, pkey, kossl->EVP_md5()); - - // We write it to the database and then the caller can obtain it - // back from there. Yes it's inefficient, but it doesn't happen - // often and this way things are uniform. - - TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl"); - - TQString path = TDEGlobal::dirs()->saveLocation("kssl"); - KTempFile csrFile(path + "csr_", ".der"); - - if (!csrFile.fstream()) { - kossl->X509_REQ_free(req); - kossl->EVP_PKEY_free(pkey); - return -5; - } - - KTempFile p8File(path + "pkey_", ".p8"); - - if (!p8File.fstream()) { - kossl->X509_REQ_free(req); - kossl->EVP_PKEY_free(pkey); - return -5; - } - - kossl->i2d_X509_REQ_fp(csrFile.fstream(), req); - - kossl->i2d_PKCS8PrivateKey_fp(p8File.fstream(), pkey, - kossl->EVP_bf_cbc(), pass.local8Bit().data(), - pass.length(), 0L, 0L); - - // FIXME Write tdeconfig entry to store the filenames under the md5 hash - - kossl->X509_REQ_free(req); - kossl->EVP_PKEY_free(pkey); - - return 0; -#else - return -1; -#endif -} - - -TQStringList KSSLKeyGen::supportedKeySizes() { - TQStringList x; - -#ifdef KSSL_HAVE_SSL - x << i18n("2048 (High Grade)") - << i18n("1024 (Medium Grade)") - << i18n("768 (Low Grade)") - << i18n("512 (Low Grade)"); -#else - x << i18n("No SSL support."); -#endif - - return x; -} - - -#include "ksslkeygen.moc" - diff --git a/tdeio/kssl/ksslkeygen.cpp b/tdeio/kssl/ksslkeygen.cpp new file mode 100644 index 000000000..86fe4717d --- /dev/null +++ b/tdeio/kssl/ksslkeygen.cpp @@ -0,0 +1,222 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include "ksslkeygen.h" +#include "keygenwizard.h" +#include "keygenwizard2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +KSSLKeyGen::KSSLKeyGen(TQWidget *parent, const char *name, bool modal) +:KWizard(parent,name,modal) { + _idx = -1; + +#ifdef KSSL_HAVE_SSL + page1 = new KGWizardPage1(this, "Wizard Page 1"); + addPage(page1, i18n("TDE Certificate Request")); + page2 = new KGWizardPage2(this, "Wizard Page 2"); + addPage(page2, i18n("TDE Certificate Request - Password")); + setHelpEnabled(page1, false); + setHelpEnabled(page2, false); + setFinishEnabled(page2, false); + connect(page2->_password1, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotPassChanged())); + connect(page2->_password2, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotPassChanged())); + connect(finishButton(), TQT_SIGNAL(clicked()), TQT_SLOT(slotGenerate())); +#else + // tell him he doesn't have SSL +#endif +} + + +KSSLKeyGen::~KSSLKeyGen() { + +} + + +void KSSLKeyGen::slotPassChanged() { + setFinishEnabled(page2, page2->_password1->text() == page2->_password2->text() && page2->_password1->text().length() >= 4); +} + + +void KSSLKeyGen::slotGenerate() { + assert(_idx >= 0 && _idx <= 3); // for now + + + // Generate the CSR + int bits; + switch (_idx) { + case 0: + bits = 2048; + break; + case 1: + bits = 1024; + break; + case 2: + bits = 768; + break; + case 3: + bits = 512; + break; + default: + KMessageBox::sorry(NULL, i18n("Unsupported key size."), i18n("TDE SSL Information")); + return; + } + + KProgressDialog *kpd = new KProgressDialog(this, "progress dialog", i18n("TDE"), i18n("Please wait while the encryption keys are generated...")); + kpd->progressBar()->setProgress(0); + kpd->show(); + // FIXME - progress dialog won't show this way + + int rc = generateCSR("This CSR" /*FIXME */, page2->_password1->text(), bits, 0x10001 /* This is the traditional exponent used */); + kpd->progressBar()->setProgress(100); + +#ifndef Q_OS_WIN //TODO: reenable for WIN32 + if (rc == 0 && TDEWallet::Wallet::isEnabled()) { + rc = KMessageBox::questionYesNo(this, i18n("Do you wish to store the passphrase in your wallet file?"), TQString::null, i18n("Store"), i18n("Do Not Store")); + if (rc == KMessageBox::Yes) { + TDEWallet::Wallet *w = TDEWallet::Wallet::openWallet(TDEWallet::Wallet::LocalWallet(), winId()); + if (w) { + // FIXME: store passphrase in wallet + delete w; + } + } + } +#endif + + kpd->deleteLater(); +} + + +int KSSLKeyGen::generateCSR(const TQString& name, const TQString& pass, int bits, int e) { +#ifdef KSSL_HAVE_SSL + KOSSL *kossl = KOSSL::self(); + + X509_REQ *req = kossl->X509_REQ_new(); + if (!req) { + return -2; + } + + EVP_PKEY *pkey = kossl->EVP_PKEY_new(); + if (!pkey) { + kossl->X509_REQ_free(req); + return -4; + } + + RSA *rsakey = kossl->RSA_generate_key(bits, e, NULL, NULL); + if (!rsakey) { + kossl->X509_REQ_free(req); + kossl->EVP_PKEY_free(pkey); + return -3; + } + + kossl->EVP_PKEY_assign(pkey, EVP_PKEY_RSA, (char *)rsakey); + + kossl->X509_REQ_set_pubkey(req, pkey); + + // Set the subject + X509_NAME *n = kossl->X509_NAME_new(); + + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_countryName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationalUnitName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_localityName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_stateOrProvinceName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_commonName, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_pkcs9_emailAddress, MBSTRING_UTF8, (unsigned char*)name.local8Bit().data(), -1, -1, 0); + + kossl->X509_REQ_set_subject_name(req, n); + + + kossl->X509_REQ_sign(req, pkey, kossl->EVP_md5()); + + // We write it to the database and then the caller can obtain it + // back from there. Yes it's inefficient, but it doesn't happen + // often and this way things are uniform. + + TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl"); + + TQString path = TDEGlobal::dirs()->saveLocation("kssl"); + KTempFile csrFile(path + "csr_", ".der"); + + if (!csrFile.fstream()) { + kossl->X509_REQ_free(req); + kossl->EVP_PKEY_free(pkey); + return -5; + } + + KTempFile p8File(path + "pkey_", ".p8"); + + if (!p8File.fstream()) { + kossl->X509_REQ_free(req); + kossl->EVP_PKEY_free(pkey); + return -5; + } + + kossl->i2d_X509_REQ_fp(csrFile.fstream(), req); + + kossl->i2d_PKCS8PrivateKey_fp(p8File.fstream(), pkey, + kossl->EVP_bf_cbc(), pass.local8Bit().data(), + pass.length(), 0L, 0L); + + // FIXME Write tdeconfig entry to store the filenames under the md5 hash + + kossl->X509_REQ_free(req); + kossl->EVP_PKEY_free(pkey); + + return 0; +#else + return -1; +#endif +} + + +TQStringList KSSLKeyGen::supportedKeySizes() { + TQStringList x; + +#ifdef KSSL_HAVE_SSL + x << i18n("2048 (High Grade)") + << i18n("1024 (Medium Grade)") + << i18n("768 (Low Grade)") + << i18n("512 (Low Grade)"); +#else + x << i18n("No SSL support."); +#endif + + return x; +} + + +#include "ksslkeygen.moc" + diff --git a/tdeio/kssl/ksslpeerinfo.cc b/tdeio/kssl/ksslpeerinfo.cc deleted file mode 100644 index d1c2d00fc..000000000 --- a/tdeio/kssl/ksslpeerinfo.cc +++ /dev/null @@ -1,171 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000-2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "ksslpeerinfo.h" -#include - -#include -#include -#include -#ifndef Q_WS_WIN //TODO kresolver not ported -#include "kresolver.h" -#endif - -#include "ksslx509map.h" - -class KSSLPeerInfoPrivate { -public: - KSSLPeerInfoPrivate() {} - ~KSSLPeerInfoPrivate() { } - TQString peerHost; -}; - - - -KSSLPeerInfo::KSSLPeerInfo() { - d = new KSSLPeerInfoPrivate; -} - -KSSLPeerInfo::~KSSLPeerInfo() { - delete d; -} - -KSSLCertificate& KSSLPeerInfo::getPeerCertificate() { - return m_cert; -} - -void KSSLPeerInfo::setPeerHost(TQString realHost) { - d->peerHost = realHost.stripWhiteSpace(); - while(d->peerHost.endsWith(".")) - d->peerHost.truncate(d->peerHost.length()-1); - -#ifdef Q_WS_WIN //TODO kresolver not ported - d->peerHost = d->peerHost.lower(); -#else - d->peerHost = TQString::fromLatin1(KNetwork::KResolver::domainToAscii(d->peerHost)); -#endif -} - -bool KSSLPeerInfo::certMatchesAddress() { -#ifdef KSSL_HAVE_SSL - KSSLX509Map certinfo(m_cert.getSubject()); - TQStringList cns = TQStringList::split(TQRegExp("[ \n\r]"), certinfo.getValue("CN")); - cns += m_cert.subjAltNames(); - - for (TQStringList::Iterator cn = cns.begin(); cn != cns.end(); ++cn) { - if (cnMatchesAddress((*cn).stripWhiteSpace().lower())) - return true; - } - -#endif - - return false; -} - - -bool KSSLPeerInfo::cnMatchesAddress(TQString cn) { -#ifdef KSSL_HAVE_SSL - TQRegExp rx; - - kdDebug(7029) << "Matching CN=[" << cn << "] to [" - << d->peerHost << "]" << endl; - - // Check for invalid characters - if (TQRegExp("[^a-zA-Z0-9\\.\\*\\-]").search(cn) >= 0) { - kdDebug(7029) << "CN contains invalid characters! Failing." << endl; - return false; - } - - // Domains can legally end with '.'s. We don't need them though. - while(cn.endsWith(".")) - cn.truncate(cn.length()-1); - - // Do not let empty CN's get by!! - if (cn.isEmpty()) - return false; - - // Check for IPv4 address - rx.setPattern("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); - if (rx.exactMatch(d->peerHost)) - return d->peerHost == cn; - - // Check for IPv6 address here... - rx.setPattern("^\\[.*\\]$"); - if (rx.exactMatch(d->peerHost)) - return d->peerHost == cn; - - if (cn.contains('*')) { - // First make sure that there are at least two valid parts - // after the wildcard (*). - TQStringList parts = TQStringList::split('.', cn, false); - - while (parts.count() > 2) - parts.remove(parts.begin()); - - if (parts.count() != 2) { - return false; // we don't allow *.root - that's bad - } - - if (parts[0].contains('*') || parts[1].contains('*')) { - return false; - } - - // RFC2818 says that *.example.com should match against - // foo.example.com but not bar.foo.example.com - // (ie. they must have the same number of parts) - if (TQRegExp(cn, false, true).exactMatch(d->peerHost) && - TQStringList::split('.', cn, false).count() == - TQStringList::split('.', d->peerHost, false).count()) - return true; - - // *.example.com must match example.com also. Sigh.. - if (cn.startsWith("*.")) { - TQString chopped = cn.mid(2); - if (chopped == d->peerHost) { - return true; - } - } - return false; - } - - // We must have an exact match in this case (insensitive though) - // (note we already did .lower()) - if (cn == d->peerHost) - return true; -#endif - return false; -} - - -void KSSLPeerInfo::reset() { - d->peerHost = TQString::null; -} - - -const TQString& KSSLPeerInfo::peerHost() const { - return d->peerHost; -} - diff --git a/tdeio/kssl/ksslpeerinfo.cpp b/tdeio/kssl/ksslpeerinfo.cpp new file mode 100644 index 000000000..d1c2d00fc --- /dev/null +++ b/tdeio/kssl/ksslpeerinfo.cpp @@ -0,0 +1,171 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000-2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "ksslpeerinfo.h" +#include + +#include +#include +#include +#ifndef Q_WS_WIN //TODO kresolver not ported +#include "kresolver.h" +#endif + +#include "ksslx509map.h" + +class KSSLPeerInfoPrivate { +public: + KSSLPeerInfoPrivate() {} + ~KSSLPeerInfoPrivate() { } + TQString peerHost; +}; + + + +KSSLPeerInfo::KSSLPeerInfo() { + d = new KSSLPeerInfoPrivate; +} + +KSSLPeerInfo::~KSSLPeerInfo() { + delete d; +} + +KSSLCertificate& KSSLPeerInfo::getPeerCertificate() { + return m_cert; +} + +void KSSLPeerInfo::setPeerHost(TQString realHost) { + d->peerHost = realHost.stripWhiteSpace(); + while(d->peerHost.endsWith(".")) + d->peerHost.truncate(d->peerHost.length()-1); + +#ifdef Q_WS_WIN //TODO kresolver not ported + d->peerHost = d->peerHost.lower(); +#else + d->peerHost = TQString::fromLatin1(KNetwork::KResolver::domainToAscii(d->peerHost)); +#endif +} + +bool KSSLPeerInfo::certMatchesAddress() { +#ifdef KSSL_HAVE_SSL + KSSLX509Map certinfo(m_cert.getSubject()); + TQStringList cns = TQStringList::split(TQRegExp("[ \n\r]"), certinfo.getValue("CN")); + cns += m_cert.subjAltNames(); + + for (TQStringList::Iterator cn = cns.begin(); cn != cns.end(); ++cn) { + if (cnMatchesAddress((*cn).stripWhiteSpace().lower())) + return true; + } + +#endif + + return false; +} + + +bool KSSLPeerInfo::cnMatchesAddress(TQString cn) { +#ifdef KSSL_HAVE_SSL + TQRegExp rx; + + kdDebug(7029) << "Matching CN=[" << cn << "] to [" + << d->peerHost << "]" << endl; + + // Check for invalid characters + if (TQRegExp("[^a-zA-Z0-9\\.\\*\\-]").search(cn) >= 0) { + kdDebug(7029) << "CN contains invalid characters! Failing." << endl; + return false; + } + + // Domains can legally end with '.'s. We don't need them though. + while(cn.endsWith(".")) + cn.truncate(cn.length()-1); + + // Do not let empty CN's get by!! + if (cn.isEmpty()) + return false; + + // Check for IPv4 address + rx.setPattern("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); + if (rx.exactMatch(d->peerHost)) + return d->peerHost == cn; + + // Check for IPv6 address here... + rx.setPattern("^\\[.*\\]$"); + if (rx.exactMatch(d->peerHost)) + return d->peerHost == cn; + + if (cn.contains('*')) { + // First make sure that there are at least two valid parts + // after the wildcard (*). + TQStringList parts = TQStringList::split('.', cn, false); + + while (parts.count() > 2) + parts.remove(parts.begin()); + + if (parts.count() != 2) { + return false; // we don't allow *.root - that's bad + } + + if (parts[0].contains('*') || parts[1].contains('*')) { + return false; + } + + // RFC2818 says that *.example.com should match against + // foo.example.com but not bar.foo.example.com + // (ie. they must have the same number of parts) + if (TQRegExp(cn, false, true).exactMatch(d->peerHost) && + TQStringList::split('.', cn, false).count() == + TQStringList::split('.', d->peerHost, false).count()) + return true; + + // *.example.com must match example.com also. Sigh.. + if (cn.startsWith("*.")) { + TQString chopped = cn.mid(2); + if (chopped == d->peerHost) { + return true; + } + } + return false; + } + + // We must have an exact match in this case (insensitive though) + // (note we already did .lower()) + if (cn == d->peerHost) + return true; +#endif + return false; +} + + +void KSSLPeerInfo::reset() { + d->peerHost = TQString::null; +} + + +const TQString& KSSLPeerInfo::peerHost() const { + return d->peerHost; +} + diff --git a/tdeio/kssl/ksslpemcallback.cc b/tdeio/kssl/ksslpemcallback.cc deleted file mode 100644 index 584020c0f..000000000 --- a/tdeio/kssl/ksslpemcallback.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include "ksslpemcallback.h" - -int KSSLPemCallback(char *buf, int size, int rwflag, void *userdata) { -#ifdef KSSL_HAVE_SSL - TQString pass2; - Q_UNUSED(userdata); - Q_UNUSED(rwflag); - - if (!buf) return -1; - int rc = KPasswordDialog::getPassword(pass2, i18n("Certificate password")); - if (rc != KPasswordDialog::Accepted) return -1; - - TQCString pass = pass2.utf8(); // utf8 length may differ from TQString length - const uint passlen = pass.length(); - if (passlen > (unsigned int)size-1) - pass.truncate((unsigned int)size-1); - - tqstrncpy(buf, pass, size-1); - buf[size-1] = 0; - pass.fill(' '); - pass2.fill(' '); - return (int)passlen; -#else - Q_UNUSED(buf); - Q_UNUSED(size); - Q_UNUSED(rwflag); - Q_UNUSED(userdata); - return -1; -#endif -} - - diff --git a/tdeio/kssl/ksslpemcallback.cpp b/tdeio/kssl/ksslpemcallback.cpp new file mode 100644 index 000000000..584020c0f --- /dev/null +++ b/tdeio/kssl/ksslpemcallback.cpp @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "ksslpemcallback.h" + +int KSSLPemCallback(char *buf, int size, int rwflag, void *userdata) { +#ifdef KSSL_HAVE_SSL + TQString pass2; + Q_UNUSED(userdata); + Q_UNUSED(rwflag); + + if (!buf) return -1; + int rc = KPasswordDialog::getPassword(pass2, i18n("Certificate password")); + if (rc != KPasswordDialog::Accepted) return -1; + + TQCString pass = pass2.utf8(); // utf8 length may differ from TQString length + const uint passlen = pass.length(); + if (passlen > (unsigned int)size-1) + pass.truncate((unsigned int)size-1); + + tqstrncpy(buf, pass, size-1); + buf[size-1] = 0; + pass.fill(' '); + pass2.fill(' '); + return (int)passlen; +#else + Q_UNUSED(buf); + Q_UNUSED(size); + Q_UNUSED(rwflag); + Q_UNUSED(userdata); + return -1; +#endif +} + + diff --git a/tdeio/kssl/ksslpkcs12.cc b/tdeio/kssl/ksslpkcs12.cc deleted file mode 100644 index 08bc54a0b..000000000 --- a/tdeio/kssl/ksslpkcs12.cc +++ /dev/null @@ -1,274 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include - -#include - - -KSSLPKCS12::KSSLPKCS12() { - _pkcs = NULL; - _pkey = NULL; - _cert = NULL; - _caStack = NULL; - kossl = KOSSL::self(); -} - - - -KSSLPKCS12::~KSSLPKCS12() { -#ifdef KSSL_HAVE_SSL - if (_pkey) kossl->EVP_PKEY_free(_pkey); - if (_caStack) { - for (;;) { - X509* x5 = reinterpret_cast(kossl->OPENSSL_sk_pop(_caStack)); - if (!x5) break; - kossl->X509_free(x5); - } - kossl->OPENSSL_sk_free(_caStack); - } - if (_pkcs) kossl->PKCS12_free(_pkcs); -#endif - if (_cert) delete _cert; -} - - -KSSLPKCS12* KSSLPKCS12::fromString(TQString base64, TQString password) { -#ifdef KSSL_HAVE_SSL -KTempFile ktf; - - if (base64.isEmpty()) return NULL; - TQByteArray qba, qbb = TQCString(base64.latin1()).copy(); - KCodecs::base64Decode(qbb, qba); - ktf.file()->writeBlock(qba); - ktf.close(); - KSSLPKCS12* rc = loadCertFile(ktf.name(), password); - ktf.unlink(); - return rc; -#endif -return NULL; -} - - - -KSSLPKCS12* KSSLPKCS12::loadCertFile(TQString filename, TQString password) { -#ifdef KSSL_HAVE_SSL -TQFile qf(filename); -PKCS12 *newpkcs = NULL; - - if (!qf.open(IO_ReadOnly)) - return NULL; - - FILE *fp = fdopen(qf.handle(), "r"); - if (!fp) return NULL; - - newpkcs = KOSSL::self()->d2i_PKCS12_fp(fp, &newpkcs); - - fclose(fp); - if (!newpkcs) { - KOSSL::self()->ERR_clear_error(); - return NULL; - } - - KSSLPKCS12 *c = new KSSLPKCS12; - c->setCert(newpkcs); - - // Now we parse it to see if we can decrypt it and interpret it - if (!c->parse(password)) { - delete c; c = NULL; - } - - return c; -#endif -return NULL; -} - - -void KSSLPKCS12::setCert(PKCS12 *c) { -#ifdef KSSL_HAVE_SSL - _pkcs = c; -#endif -} - - -bool KSSLPKCS12::changePassword(TQString pold, TQString pnew) { -#ifdef KSSL_HAVE_SSL - // OpenSSL makes me cast away the const here. argh - return (0 == kossl->PKCS12_newpass(_pkcs, - pold.isNull() ? (char *)"" : (char *)pold.latin1(), - pnew.isNull() ? (char *)"" : (char *)pnew.latin1())); -#endif -return false; -} - - -bool KSSLPKCS12::parse(TQString pass) { -#ifdef KSSL_HAVE_SSL -X509 *x = NULL; - - assert(_pkcs); // if you're calling this before pkcs gets set, it's a BUG! - - if (_cert) delete _cert; - if (_pkey) kossl->EVP_PKEY_free(_pkey); - if (_caStack) { - for (;;) { - X509* x5 = reinterpret_cast(kossl->OPENSSL_sk_pop(_caStack)); - if (!x5) break; - kossl->X509_free(x5); - } - kossl->OPENSSL_sk_free(_caStack); - } - _pkey = NULL; - _caStack = NULL; - _cert = NULL; - - int rc = kossl->PKCS12_parse(_pkcs, pass.latin1(), &_pkey, &x, &_caStack); - - if (rc == 1) { - // kdDebug(7029) << "PKCS12_parse success" << endl; - if (x) { - _cert = new KSSLCertificate; - _cert->setCert(x); - if (_caStack) { - _cert->setChain(_caStack); - } - return true; - } - } else { - _caStack = NULL; - _pkey = NULL; - kossl->ERR_clear_error(); - } -#endif -return false; -} - - -EVP_PKEY *KSSLPKCS12::getPrivateKey() { - return _pkey; -} - - -KSSLCertificate *KSSLPKCS12::getCertificate() { - return _cert; -} - - -TQString KSSLPKCS12::toString() { -TQString base64; -#ifdef KSSL_HAVE_SSL -unsigned char *p; -int len; - - len = kossl->i2d_PKCS12(_pkcs, NULL); - if (len >= 0) { - char *buf = new char[len]; - p = (unsigned char *)buf; - kossl->i2d_PKCS12(_pkcs, &p); - TQByteArray qba; - qba.setRawData(buf, len); - base64 = KCodecs::base64Encode(qba); - qba.resetRawData(buf, len); - delete[] buf; - } -#endif -return base64; -} - - - -bool KSSLPKCS12::toFile(TQString filename) { -#ifdef KSSL_HAVE_SSL -TQFile out(filename); - - if (!out.open(IO_WriteOnly)) return false; - - int fd = out.handle(); - FILE *fp = fdopen(fd, "w"); - - if (!fp) { - unlink(filename.latin1()); - return false; - } - - kossl->i2d_PKCS12_fp(fp, _pkcs); - - fclose(fp); - return true; -#endif -return false; -} - - -KSSLCertificate::KSSLValidation KSSLPKCS12::validate() { - return validate(KSSLCertificate::SSLServer); -} - - -KSSLCertificate::KSSLValidation KSSLPKCS12::validate(KSSLCertificate::KSSLPurpose p) { -#ifdef KSSL_HAVE_SSL -KSSLCertificate::KSSLValidation xx = _cert->validate(p); - if (1 != kossl->X509_check_private_key(_cert->getCert(), _pkey)) { - xx = KSSLCertificate::PrivateKeyFailed; - } - -return xx; -#else -return KSSLCertificate::NoSSL; -#endif -} - - -KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate() { - return revalidate(KSSLCertificate::SSLServer); -} - - -KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate(KSSLCertificate::KSSLPurpose p) { - return _cert->revalidate(p); -} - - -bool KSSLPKCS12::isValid() { -return isValid(KSSLCertificate::SSLServer); -} - - -bool KSSLPKCS12::isValid(KSSLCertificate::KSSLPurpose p) { -return (validate(p) == KSSLCertificate::Ok); -} - - -TQString KSSLPKCS12::name() { - return _cert->getSubject(); -} - diff --git a/tdeio/kssl/ksslpkcs12.cpp b/tdeio/kssl/ksslpkcs12.cpp new file mode 100644 index 000000000..08bc54a0b --- /dev/null +++ b/tdeio/kssl/ksslpkcs12.cpp @@ -0,0 +1,274 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include + + +KSSLPKCS12::KSSLPKCS12() { + _pkcs = NULL; + _pkey = NULL; + _cert = NULL; + _caStack = NULL; + kossl = KOSSL::self(); +} + + + +KSSLPKCS12::~KSSLPKCS12() { +#ifdef KSSL_HAVE_SSL + if (_pkey) kossl->EVP_PKEY_free(_pkey); + if (_caStack) { + for (;;) { + X509* x5 = reinterpret_cast(kossl->OPENSSL_sk_pop(_caStack)); + if (!x5) break; + kossl->X509_free(x5); + } + kossl->OPENSSL_sk_free(_caStack); + } + if (_pkcs) kossl->PKCS12_free(_pkcs); +#endif + if (_cert) delete _cert; +} + + +KSSLPKCS12* KSSLPKCS12::fromString(TQString base64, TQString password) { +#ifdef KSSL_HAVE_SSL +KTempFile ktf; + + if (base64.isEmpty()) return NULL; + TQByteArray qba, qbb = TQCString(base64.latin1()).copy(); + KCodecs::base64Decode(qbb, qba); + ktf.file()->writeBlock(qba); + ktf.close(); + KSSLPKCS12* rc = loadCertFile(ktf.name(), password); + ktf.unlink(); + return rc; +#endif +return NULL; +} + + + +KSSLPKCS12* KSSLPKCS12::loadCertFile(TQString filename, TQString password) { +#ifdef KSSL_HAVE_SSL +TQFile qf(filename); +PKCS12 *newpkcs = NULL; + + if (!qf.open(IO_ReadOnly)) + return NULL; + + FILE *fp = fdopen(qf.handle(), "r"); + if (!fp) return NULL; + + newpkcs = KOSSL::self()->d2i_PKCS12_fp(fp, &newpkcs); + + fclose(fp); + if (!newpkcs) { + KOSSL::self()->ERR_clear_error(); + return NULL; + } + + KSSLPKCS12 *c = new KSSLPKCS12; + c->setCert(newpkcs); + + // Now we parse it to see if we can decrypt it and interpret it + if (!c->parse(password)) { + delete c; c = NULL; + } + + return c; +#endif +return NULL; +} + + +void KSSLPKCS12::setCert(PKCS12 *c) { +#ifdef KSSL_HAVE_SSL + _pkcs = c; +#endif +} + + +bool KSSLPKCS12::changePassword(TQString pold, TQString pnew) { +#ifdef KSSL_HAVE_SSL + // OpenSSL makes me cast away the const here. argh + return (0 == kossl->PKCS12_newpass(_pkcs, + pold.isNull() ? (char *)"" : (char *)pold.latin1(), + pnew.isNull() ? (char *)"" : (char *)pnew.latin1())); +#endif +return false; +} + + +bool KSSLPKCS12::parse(TQString pass) { +#ifdef KSSL_HAVE_SSL +X509 *x = NULL; + + assert(_pkcs); // if you're calling this before pkcs gets set, it's a BUG! + + if (_cert) delete _cert; + if (_pkey) kossl->EVP_PKEY_free(_pkey); + if (_caStack) { + for (;;) { + X509* x5 = reinterpret_cast(kossl->OPENSSL_sk_pop(_caStack)); + if (!x5) break; + kossl->X509_free(x5); + } + kossl->OPENSSL_sk_free(_caStack); + } + _pkey = NULL; + _caStack = NULL; + _cert = NULL; + + int rc = kossl->PKCS12_parse(_pkcs, pass.latin1(), &_pkey, &x, &_caStack); + + if (rc == 1) { + // kdDebug(7029) << "PKCS12_parse success" << endl; + if (x) { + _cert = new KSSLCertificate; + _cert->setCert(x); + if (_caStack) { + _cert->setChain(_caStack); + } + return true; + } + } else { + _caStack = NULL; + _pkey = NULL; + kossl->ERR_clear_error(); + } +#endif +return false; +} + + +EVP_PKEY *KSSLPKCS12::getPrivateKey() { + return _pkey; +} + + +KSSLCertificate *KSSLPKCS12::getCertificate() { + return _cert; +} + + +TQString KSSLPKCS12::toString() { +TQString base64; +#ifdef KSSL_HAVE_SSL +unsigned char *p; +int len; + + len = kossl->i2d_PKCS12(_pkcs, NULL); + if (len >= 0) { + char *buf = new char[len]; + p = (unsigned char *)buf; + kossl->i2d_PKCS12(_pkcs, &p); + TQByteArray qba; + qba.setRawData(buf, len); + base64 = KCodecs::base64Encode(qba); + qba.resetRawData(buf, len); + delete[] buf; + } +#endif +return base64; +} + + + +bool KSSLPKCS12::toFile(TQString filename) { +#ifdef KSSL_HAVE_SSL +TQFile out(filename); + + if (!out.open(IO_WriteOnly)) return false; + + int fd = out.handle(); + FILE *fp = fdopen(fd, "w"); + + if (!fp) { + unlink(filename.latin1()); + return false; + } + + kossl->i2d_PKCS12_fp(fp, _pkcs); + + fclose(fp); + return true; +#endif +return false; +} + + +KSSLCertificate::KSSLValidation KSSLPKCS12::validate() { + return validate(KSSLCertificate::SSLServer); +} + + +KSSLCertificate::KSSLValidation KSSLPKCS12::validate(KSSLCertificate::KSSLPurpose p) { +#ifdef KSSL_HAVE_SSL +KSSLCertificate::KSSLValidation xx = _cert->validate(p); + if (1 != kossl->X509_check_private_key(_cert->getCert(), _pkey)) { + xx = KSSLCertificate::PrivateKeyFailed; + } + +return xx; +#else +return KSSLCertificate::NoSSL; +#endif +} + + +KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate() { + return revalidate(KSSLCertificate::SSLServer); +} + + +KSSLCertificate::KSSLValidation KSSLPKCS12::revalidate(KSSLCertificate::KSSLPurpose p) { + return _cert->revalidate(p); +} + + +bool KSSLPKCS12::isValid() { +return isValid(KSSLCertificate::SSLServer); +} + + +bool KSSLPKCS12::isValid(KSSLCertificate::KSSLPurpose p) { +return (validate(p) == KSSLCertificate::Ok); +} + + +TQString KSSLPKCS12::name() { + return _cert->getSubject(); +} + diff --git a/tdeio/kssl/ksslpkcs7.cc b/tdeio/kssl/ksslpkcs7.cc deleted file mode 100644 index bced75e80..000000000 --- a/tdeio/kssl/ksslpkcs7.cc +++ /dev/null @@ -1,189 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include - -#include - - -KSSLPKCS7::KSSLPKCS7() { - _pkcs = NULL; - _cert = NULL; - kossl = KOSSL::self(); -} - - - -KSSLPKCS7::~KSSLPKCS7() { -#ifdef KSSL_HAVE_SSL - if (_pkcs) kossl->PKCS7_free(_pkcs); -#endif - if (_cert) delete _cert; -} - - -KSSLPKCS7* KSSLPKCS7::fromString(TQString base64) { -#ifdef KSSL_HAVE_SSL -KTempFile ktf; - - if (base64.isEmpty()) return NULL; - TQByteArray qba, qbb = TQCString(base64.latin1()).copy(); - KCodecs::base64Decode(qbb, qba); - ktf.file()->writeBlock(qba); - ktf.close(); - KSSLPKCS7* rc = loadCertFile(ktf.name()); - ktf.unlink(); - return rc; -#endif -return NULL; -} - - - -KSSLPKCS7* KSSLPKCS7::loadCertFile(TQString filename) { -#ifdef KSSL_HAVE_SSL -TQFile qf(filename); -PKCS7 *newpkcs = NULL; - - if (!qf.open(IO_ReadOnly)) - return NULL; - - FILE *fp = fdopen(qf.handle(), "r"); - if (!fp) return NULL; - - newpkcs = KOSSL::self()->d2i_PKCS7_fp(fp, &newpkcs); - - if (!newpkcs) return NULL; - - KSSLPKCS7 *c = new KSSLPKCS7; - c->setCert(newpkcs); - - return c; -#endif -return NULL; -} - - -void KSSLPKCS7::setCert(PKCS7 *c) { -#ifdef KSSL_HAVE_SSL - _pkcs = c; - //STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); - //X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); - // set _chain and _cert here. -#endif -} - - -KSSLCertificate *KSSLPKCS7::getCertificate() { - return _cert; -} - - -KSSLCertChain *KSSLPKCS7::getChain() { - return _chain; -} - - -TQString KSSLPKCS7::toString() { -TQString base64; -#ifdef KSSL_HAVE_SSL -unsigned char *p; -int len; - - len = kossl->i2d_PKCS7(_pkcs, NULL); - if (len >= 0) { - char *buf = new char[len]; - p = (unsigned char *)buf; - kossl->i2d_PKCS7(_pkcs, &p); - TQByteArray qba; - qba.setRawData(buf, len); - base64 = KCodecs::base64Encode(qba); - qba.resetRawData(buf, len); - delete[] buf; - } -#endif -return base64; -} - - - -bool KSSLPKCS7::toFile(TQString filename) { -#ifdef KSSL_HAVE_SSL -TQFile out(filename); - - if (!out.open(IO_WriteOnly)) return false; - - int fd = out.handle(); - FILE *fp = fdopen(fd, "w"); - - if (!fp) { - unlink(filename.latin1()); - return false; - } - - kossl->i2d_PKCS7_fp(fp, _pkcs); - - fclose(fp); - return true; -#endif -return false; -} - - -KSSLCertificate::KSSLValidation KSSLPKCS7::validate() { -#ifdef KSSL_HAVE_SSL -KSSLCertificate::KSSLValidation xx = _cert->validate(); -return xx; -#else -return KSSLCertificate::NoSSL; -#endif -} - - -KSSLCertificate::KSSLValidation KSSLPKCS7::revalidate() { - if (_cert) - return _cert->revalidate(); - return KSSLCertificate::Unknown; -} - - -bool KSSLPKCS7::isValid() { -return (validate() == KSSLCertificate::Ok); -} - - -TQString KSSLPKCS7::name() { - if (_cert) - return _cert->getSubject(); - return TQString(); -} - diff --git a/tdeio/kssl/ksslpkcs7.cpp b/tdeio/kssl/ksslpkcs7.cpp new file mode 100644 index 000000000..bced75e80 --- /dev/null +++ b/tdeio/kssl/ksslpkcs7.cpp @@ -0,0 +1,189 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include + + +KSSLPKCS7::KSSLPKCS7() { + _pkcs = NULL; + _cert = NULL; + kossl = KOSSL::self(); +} + + + +KSSLPKCS7::~KSSLPKCS7() { +#ifdef KSSL_HAVE_SSL + if (_pkcs) kossl->PKCS7_free(_pkcs); +#endif + if (_cert) delete _cert; +} + + +KSSLPKCS7* KSSLPKCS7::fromString(TQString base64) { +#ifdef KSSL_HAVE_SSL +KTempFile ktf; + + if (base64.isEmpty()) return NULL; + TQByteArray qba, qbb = TQCString(base64.latin1()).copy(); + KCodecs::base64Decode(qbb, qba); + ktf.file()->writeBlock(qba); + ktf.close(); + KSSLPKCS7* rc = loadCertFile(ktf.name()); + ktf.unlink(); + return rc; +#endif +return NULL; +} + + + +KSSLPKCS7* KSSLPKCS7::loadCertFile(TQString filename) { +#ifdef KSSL_HAVE_SSL +TQFile qf(filename); +PKCS7 *newpkcs = NULL; + + if (!qf.open(IO_ReadOnly)) + return NULL; + + FILE *fp = fdopen(qf.handle(), "r"); + if (!fp) return NULL; + + newpkcs = KOSSL::self()->d2i_PKCS7_fp(fp, &newpkcs); + + if (!newpkcs) return NULL; + + KSSLPKCS7 *c = new KSSLPKCS7; + c->setCert(newpkcs); + + return c; +#endif +return NULL; +} + + +void KSSLPKCS7::setCert(PKCS7 *c) { +#ifdef KSSL_HAVE_SSL + _pkcs = c; + //STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); + //X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); + // set _chain and _cert here. +#endif +} + + +KSSLCertificate *KSSLPKCS7::getCertificate() { + return _cert; +} + + +KSSLCertChain *KSSLPKCS7::getChain() { + return _chain; +} + + +TQString KSSLPKCS7::toString() { +TQString base64; +#ifdef KSSL_HAVE_SSL +unsigned char *p; +int len; + + len = kossl->i2d_PKCS7(_pkcs, NULL); + if (len >= 0) { + char *buf = new char[len]; + p = (unsigned char *)buf; + kossl->i2d_PKCS7(_pkcs, &p); + TQByteArray qba; + qba.setRawData(buf, len); + base64 = KCodecs::base64Encode(qba); + qba.resetRawData(buf, len); + delete[] buf; + } +#endif +return base64; +} + + + +bool KSSLPKCS7::toFile(TQString filename) { +#ifdef KSSL_HAVE_SSL +TQFile out(filename); + + if (!out.open(IO_WriteOnly)) return false; + + int fd = out.handle(); + FILE *fp = fdopen(fd, "w"); + + if (!fp) { + unlink(filename.latin1()); + return false; + } + + kossl->i2d_PKCS7_fp(fp, _pkcs); + + fclose(fp); + return true; +#endif +return false; +} + + +KSSLCertificate::KSSLValidation KSSLPKCS7::validate() { +#ifdef KSSL_HAVE_SSL +KSSLCertificate::KSSLValidation xx = _cert->validate(); +return xx; +#else +return KSSLCertificate::NoSSL; +#endif +} + + +KSSLCertificate::KSSLValidation KSSLPKCS7::revalidate() { + if (_cert) + return _cert->revalidate(); + return KSSLCertificate::Unknown; +} + + +bool KSSLPKCS7::isValid() { +return (validate() == KSSLCertificate::Ok); +} + + +TQString KSSLPKCS7::name() { + if (_cert) + return _cert->getSubject(); + return TQString(); +} + diff --git a/tdeio/kssl/ksslsession.cc b/tdeio/kssl/ksslsession.cc deleted file mode 100644 index 3c80233f1..000000000 --- a/tdeio/kssl/ksslsession.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ksslsession.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -KSSLSession::KSSLSession() : _session(0L) { -} - - -KSSLSession::~KSSLSession() { -#ifdef KSSL_HAVE_SSL - if (_session) { - KOpenSSLProxy::self()->SSL_SESSION_free(static_cast(_session)); - _session = 0L; - } -#endif -} - - -TQString KSSLSession::toString() const { -TQString rc; -#ifdef KSSL_HAVE_SSL -TQByteArray qba; -SSL_SESSION *session = static_cast(_session); -unsigned int slen = KOpenSSLProxy::self()->i2d_SSL_SESSION(session, 0L); -unsigned char *csess = new unsigned char[slen]; -unsigned char *p = csess; - - if (!KOpenSSLProxy::self()->i2d_SSL_SESSION(session, &p)) { - delete[] csess; - return TQString::null; - } - - // encode it into a QString - qba.duplicate((const char*)csess, slen); - delete[] csess; - rc = KCodecs::base64Encode(qba); -#endif -return rc; -} - - -KSSLSession *KSSLSession::fromString(const TQString& s) { -KSSLSession *session = 0L; -#ifdef KSSL_HAVE_SSL -TQByteArray qba, qbb = s.local8Bit().copy(); - KCodecs::base64Decode(qbb, qba); - unsigned char *qbap = reinterpret_cast(qba.data()); - SSL_SESSION *ss = KOSSL::self()->d2i_SSL_SESSION(0L, &qbap, qba.size()); - if (ss) { - session = new KSSLSession; - session->_session = ss; - } -#endif -return session; -} - - diff --git a/tdeio/kssl/ksslsession.cpp b/tdeio/kssl/ksslsession.cpp new file mode 100644 index 000000000..3c80233f1 --- /dev/null +++ b/tdeio/kssl/ksslsession.cpp @@ -0,0 +1,82 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "ksslsession.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +KSSLSession::KSSLSession() : _session(0L) { +} + + +KSSLSession::~KSSLSession() { +#ifdef KSSL_HAVE_SSL + if (_session) { + KOpenSSLProxy::self()->SSL_SESSION_free(static_cast(_session)); + _session = 0L; + } +#endif +} + + +TQString KSSLSession::toString() const { +TQString rc; +#ifdef KSSL_HAVE_SSL +TQByteArray qba; +SSL_SESSION *session = static_cast(_session); +unsigned int slen = KOpenSSLProxy::self()->i2d_SSL_SESSION(session, 0L); +unsigned char *csess = new unsigned char[slen]; +unsigned char *p = csess; + + if (!KOpenSSLProxy::self()->i2d_SSL_SESSION(session, &p)) { + delete[] csess; + return TQString::null; + } + + // encode it into a QString + qba.duplicate((const char*)csess, slen); + delete[] csess; + rc = KCodecs::base64Encode(qba); +#endif +return rc; +} + + +KSSLSession *KSSLSession::fromString(const TQString& s) { +KSSLSession *session = 0L; +#ifdef KSSL_HAVE_SSL +TQByteArray qba, qbb = s.local8Bit().copy(); + KCodecs::base64Decode(qbb, qba); + unsigned char *qbap = reinterpret_cast(qba.data()); + SSL_SESSION *ss = KOSSL::self()->d2i_SSL_SESSION(0L, &qbap, qba.size()); + if (ss) { + session = new KSSLSession; + session->_session = ss; + } +#endif +return session; +} + + diff --git a/tdeio/kssl/ksslsettings.cc b/tdeio/kssl/ksslsettings.cc deleted file mode 100644 index 090eaef4f..000000000 --- a/tdeio/kssl/ksslsettings.cc +++ /dev/null @@ -1,345 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include -#include -#include - -#include -#include - -#include "ksslsettings.h" -#include -#include -#include - -// this hack provided by Malte Starostik to avoid glibc/openssl bug -// on some systems -#ifdef KSSL_HAVE_SSL -#define crypt _openssl_crypt -#include -#undef crypt -#endif -#include - - -class CipherNode { -public: - CipherNode(const char *_name, int _keylen) : - name(_name), keylen(_keylen) {} - TQString name; - int keylen; - inline int operator==(CipherNode &x) - { return ((x.keylen == keylen) && (x.name == name)); } - inline int operator< (CipherNode &x) { return keylen < x.keylen; } - inline int operator<=(CipherNode &x) { return keylen <= x.keylen; } - inline int operator> (CipherNode &x) { return keylen > x.keylen; } - inline int operator>=(CipherNode &x) { return keylen >= x.keylen; } -}; - - -class KSSLSettingsPrivate { -public: - KSSLSettingsPrivate() { - kossl = NULL; // try to delay this as long as possible - } - ~KSSLSettingsPrivate() { - - } - - KOSSL *kossl; - bool m_bUseEGD; - bool m_bUseEFile; - TQString m_EGDPath; - bool m_bSendX509; - bool m_bPromptX509; -}; - -// -// FIXME -// Implementation note: for now, we only read cipher settings from disk, -// and do not store them in memory. This should change. -// - -KSSLSettings::KSSLSettings(bool readConfig) { - d = new KSSLSettingsPrivate; - m_cfg = new TDEConfig("cryptodefaults", false, false); - - if (!TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl")) { - //kdDebug(7029) << "Error adding (kssl, share/apps/kssl)" << endl; - } - - if (readConfig) load(); -} - - -// we don't save settings incase it was a temporary object -KSSLSettings::~KSSLSettings() { - delete m_cfg; - delete d; -} - - -bool KSSLSettings::sslv2() const { - return m_bUseSSLv2; -} - - -bool KSSLSettings::sslv3() const { - return m_bUseSSLv3; -} - - -bool KSSLSettings::tlsv1() const { - return m_bUseTLSv1; -} - - -// FIXME: we should make a default list available if this fails -// since OpenSSL seems to just choose any old thing if it's given an -// empty list. This behavior is not confirmed though. -TQString KSSLSettings::getCipherList() { - TQString clist; -#ifdef KSSL_HAVE_SSL - TQString tcipher; - bool firstcipher = true; - SSL_METHOD *meth = 0L; - TQPtrList cipherList; - - cipherList.setAutoDelete(true); - - if (!d->kossl) - d->kossl = KOSSL::self(); - - if (m_bUseSSLv3 && m_bUseSSLv2) - meth = d->kossl->TLS_client_method(); - else if(m_bUseSSLv3) - meth = d->kossl->SSLv3_client_method(); - else if (m_bUseSSLv2) - meth = d->kossl->SSLv2_client_method(); - - SSL_CTX *ctx = d->kossl->SSL_CTX_new(meth); - SSL* ssl = d->kossl->SSL_new(ctx); - STACK_OF(SSL_CIPHER)* sk = d->kossl->SSL_get_ciphers(ssl); - int cnt = d->kossl->OPENSSL_sk_num(sk); - for (int i=0; i< cnt; i++) { - SSL_CIPHER *sc = reinterpret_cast(d->kossl->OPENSSL_sk_value(sk,i)); - if (!sc) - break; - - if(!strcmp("SSLv2", d->kossl->SSL_CIPHER_get_version(sc))) - m_cfg->setGroup("SSLv2"); - else - m_cfg->setGroup("SSLv3"); - - tcipher.sprintf("cipher_%s", d->kossl->SSL_CIPHER_get_name(sc)); - int bits = d->kossl->SSL_CIPHER_get_bits(sc, NULL); - if (m_cfg->readBoolEntry(tcipher, bits >= 56)) { - CipherNode *xx = new CipherNode(d->kossl->SSL_CIPHER_get_name(sc),bits); - if (!cipherList.contains(xx)) - cipherList.prepend(xx); - else - delete xx; - } - } - d->kossl->SSL_free(ssl); - d->kossl->SSL_CTX_free(ctx); - - // Remove any ADH ciphers as per RFC2246 - // Also remove NULL ciphers and 168bit ciphers - for (unsigned int i = 0; i < cipherList.count(); i++) { - CipherNode *j = 0L; - while ((j = cipherList.at(i)) != 0L) { - if (j->name.contains("ADH-") || j->name.contains("NULL-") || j->name.contains("DES-CBC3-SHA") || j->name.contains("FZA")) { - cipherList.remove(j); - } else { - break; - } - } - } - - // now assemble the list cipher1:cipher2:cipher3:...:ciphern - while (!cipherList.isEmpty()) { - if (firstcipher) - firstcipher = false; - else clist.append(":"); - clist.append(cipherList.getLast()->name); - cipherList.removeLast(); - } // while - - kdDebug(7029) << "Cipher list is: " << clist << endl; - -#endif - return clist; -} - -// FIXME - sync these up so that we can use them with the control module!! -void KSSLSettings::load() { - m_cfg->reparseConfiguration(); - - m_cfg->setGroup("TLS"); - m_bUseTLSv1 = m_cfg->readBoolEntry("Enabled", true); - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_NO_SSL2) - m_bUseSSLv2 = false; -#else - m_cfg->setGroup("SSLv2"); - m_bUseSSLv2 = m_cfg->readBoolEntry("Enabled", false); -#endif - -#if defined(OPENSSL_NO_SSL3) - m_bUseSSLv3 = false; -#else - m_cfg->setGroup("SSLv3"); - m_bUseSSLv3 = m_cfg->readBoolEntry("Enabled", true); -#endif - - m_cfg->setGroup("Warnings"); - m_bWarnOnEnter = m_cfg->readBoolEntry("OnEnter", false); - m_bWarnOnLeave = m_cfg->readBoolEntry("OnLeave", true); - m_bWarnOnUnencrypted = m_cfg->readBoolEntry("OnUnencrypted", true); - m_bWarnOnMixed = m_cfg->readBoolEntry("OnMixed", true); - - m_cfg->setGroup("Validation"); - m_bWarnSelfSigned = m_cfg->readBoolEntry("WarnSelfSigned", true); - m_bWarnExpired = m_cfg->readBoolEntry("WarnExpired", true); - m_bWarnRevoked = m_cfg->readBoolEntry("WarnRevoked", true); - - m_cfg->setGroup("EGD"); - d->m_bUseEGD = m_cfg->readBoolEntry("UseEGD", false); - d->m_bUseEFile = m_cfg->readBoolEntry("UseEFile", false); - d->m_EGDPath = m_cfg->readPathEntry("EGDPath"); - - m_cfg->setGroup("Auth"); - d->m_bSendX509 = ("send" == m_cfg->readEntry("AuthMethod", "")); - d->m_bPromptX509 = ("prompt" == m_cfg->readEntry("AuthMethod", "")); - - #ifdef KSSL_HAVE_SSL - - - - #endif -} - - -void KSSLSettings::defaults() { - m_bUseTLSv1 = true; - m_bUseSSLv2 = false; - m_bUseSSLv3 = true; - m_bWarnOnEnter = false; - m_bWarnOnLeave = true; - m_bWarnOnUnencrypted = true; - m_bWarnOnMixed = true; - m_bWarnSelfSigned = true; - m_bWarnExpired = true; - m_bWarnRevoked = true; - d->m_bUseEGD = false; - d->m_bUseEFile = false; - d->m_EGDPath = ""; -} - - -void KSSLSettings::save() { - m_cfg->setGroup("TLS"); - m_cfg->writeEntry("Enabled", m_bUseTLSv1); - - m_cfg->setGroup("SSLv2"); - m_cfg->writeEntry("Enabled", m_bUseSSLv2); - - m_cfg->setGroup("SSLv3"); - m_cfg->writeEntry("Enabled", m_bUseSSLv3); - - m_cfg->setGroup("Warnings"); - m_cfg->writeEntry("OnEnter", m_bWarnOnEnter); - m_cfg->writeEntry("OnLeave", m_bWarnOnLeave); - m_cfg->writeEntry("OnUnencrypted", m_bWarnOnUnencrypted); - m_cfg->writeEntry("OnMixed", m_bWarnOnMixed); - - m_cfg->setGroup("Validation"); - m_cfg->writeEntry("WarnSelfSigned", m_bWarnSelfSigned); - m_cfg->writeEntry("WarnExpired", m_bWarnExpired); - m_cfg->writeEntry("WarnRevoked", m_bWarnRevoked); - - m_cfg->setGroup("EGD"); - m_cfg->writeEntry("UseEGD", d->m_bUseEGD); - m_cfg->writeEntry("UseEFile", d->m_bUseEFile); - m_cfg->writePathEntry("EGDPath", d->m_EGDPath); - - m_cfg->sync(); - // FIXME - ciphers -#if 0 -#ifdef KSSL_HAVE_SSL - m_cfg->setGroup("SSLv2"); - for (unsigned int i = 0; i < v2ciphers.count(); i++) { - TQString ciphername; - ciphername.sprintf("cipher_%s", v2ciphers[i].ascii()); - if (v2selectedciphers.contains(v2ciphers[i])) { - m_cfg->writeEntry(ciphername, true); - } else m_cfg->writeEntry(ciphername, false); - } - - m_cfg->setGroup("SSLv3"); - for (unsigned int i = 0; i < v3ciphers.count(); i++) { - TQString ciphername; - ciphername.sprintf("cipher_%s", v3ciphers[i].ascii()); - if (v3selectedciphers.contains(v3ciphers[i])) { - m_cfg->writeEntry(ciphername, true); - } else m_cfg->writeEntry(ciphername, false); - } -#endif - - m_cfg->sync(); - - // insure proper permissions -- contains sensitive data - TQString cfgName(TDEGlobal::dirs()->findResource("config", "cryptodefaults")); - if (!cfgName.isEmpty()) - ::chmod(TQFile::encodeName(cfgName), 0600); -#endif -} - - -bool KSSLSettings::warnOnEnter() const { return m_bWarnOnEnter; } -void KSSLSettings::setWarnOnEnter(bool x) { m_bWarnOnEnter = x; } -bool KSSLSettings::warnOnUnencrypted() const { return m_bWarnOnUnencrypted; } -void KSSLSettings::setWarnOnUnencrypted(bool x) { m_bWarnOnUnencrypted = x; } -bool KSSLSettings::warnOnLeave() const { return m_bWarnOnLeave; } -void KSSLSettings::setWarnOnLeave(bool x) { m_bWarnOnLeave = x; } -bool KSSLSettings::warnOnMixed() const { return m_bWarnOnMixed; } -bool KSSLSettings::warnOnSelfSigned() const { return m_bWarnSelfSigned; } -bool KSSLSettings::warnOnRevoked() const { return m_bWarnRevoked; } -bool KSSLSettings::warnOnExpired() const { return m_bWarnExpired; } -bool KSSLSettings::useEGD() const { return d->m_bUseEGD; } -bool KSSLSettings::useEFile() const { return d->m_bUseEFile; } -bool KSSLSettings::autoSendX509() const { return d->m_bSendX509; } -bool KSSLSettings::promptSendX509() const { return d->m_bPromptX509; } - -void KSSLSettings::setTLSv1(bool enabled) { m_bUseTLSv1 = enabled; } -void KSSLSettings::setSSLv2(bool enabled) { m_bUseSSLv2 = enabled; } -void KSSLSettings::setSSLv3(bool enabled) { m_bUseSSLv3 = enabled; } - -TQString& KSSLSettings::getEGDPath() { return d->m_EGDPath; } - diff --git a/tdeio/kssl/ksslsettings.cpp b/tdeio/kssl/ksslsettings.cpp new file mode 100644 index 000000000..090eaef4f --- /dev/null +++ b/tdeio/kssl/ksslsettings.cpp @@ -0,0 +1,345 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include + +#include +#include + +#include "ksslsettings.h" +#include +#include +#include + +// this hack provided by Malte Starostik to avoid glibc/openssl bug +// on some systems +#ifdef KSSL_HAVE_SSL +#define crypt _openssl_crypt +#include +#undef crypt +#endif +#include + + +class CipherNode { +public: + CipherNode(const char *_name, int _keylen) : + name(_name), keylen(_keylen) {} + TQString name; + int keylen; + inline int operator==(CipherNode &x) + { return ((x.keylen == keylen) && (x.name == name)); } + inline int operator< (CipherNode &x) { return keylen < x.keylen; } + inline int operator<=(CipherNode &x) { return keylen <= x.keylen; } + inline int operator> (CipherNode &x) { return keylen > x.keylen; } + inline int operator>=(CipherNode &x) { return keylen >= x.keylen; } +}; + + +class KSSLSettingsPrivate { +public: + KSSLSettingsPrivate() { + kossl = NULL; // try to delay this as long as possible + } + ~KSSLSettingsPrivate() { + + } + + KOSSL *kossl; + bool m_bUseEGD; + bool m_bUseEFile; + TQString m_EGDPath; + bool m_bSendX509; + bool m_bPromptX509; +}; + +// +// FIXME +// Implementation note: for now, we only read cipher settings from disk, +// and do not store them in memory. This should change. +// + +KSSLSettings::KSSLSettings(bool readConfig) { + d = new KSSLSettingsPrivate; + m_cfg = new TDEConfig("cryptodefaults", false, false); + + if (!TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl")) { + //kdDebug(7029) << "Error adding (kssl, share/apps/kssl)" << endl; + } + + if (readConfig) load(); +} + + +// we don't save settings incase it was a temporary object +KSSLSettings::~KSSLSettings() { + delete m_cfg; + delete d; +} + + +bool KSSLSettings::sslv2() const { + return m_bUseSSLv2; +} + + +bool KSSLSettings::sslv3() const { + return m_bUseSSLv3; +} + + +bool KSSLSettings::tlsv1() const { + return m_bUseTLSv1; +} + + +// FIXME: we should make a default list available if this fails +// since OpenSSL seems to just choose any old thing if it's given an +// empty list. This behavior is not confirmed though. +TQString KSSLSettings::getCipherList() { + TQString clist; +#ifdef KSSL_HAVE_SSL + TQString tcipher; + bool firstcipher = true; + SSL_METHOD *meth = 0L; + TQPtrList cipherList; + + cipherList.setAutoDelete(true); + + if (!d->kossl) + d->kossl = KOSSL::self(); + + if (m_bUseSSLv3 && m_bUseSSLv2) + meth = d->kossl->TLS_client_method(); + else if(m_bUseSSLv3) + meth = d->kossl->SSLv3_client_method(); + else if (m_bUseSSLv2) + meth = d->kossl->SSLv2_client_method(); + + SSL_CTX *ctx = d->kossl->SSL_CTX_new(meth); + SSL* ssl = d->kossl->SSL_new(ctx); + STACK_OF(SSL_CIPHER)* sk = d->kossl->SSL_get_ciphers(ssl); + int cnt = d->kossl->OPENSSL_sk_num(sk); + for (int i=0; i< cnt; i++) { + SSL_CIPHER *sc = reinterpret_cast(d->kossl->OPENSSL_sk_value(sk,i)); + if (!sc) + break; + + if(!strcmp("SSLv2", d->kossl->SSL_CIPHER_get_version(sc))) + m_cfg->setGroup("SSLv2"); + else + m_cfg->setGroup("SSLv3"); + + tcipher.sprintf("cipher_%s", d->kossl->SSL_CIPHER_get_name(sc)); + int bits = d->kossl->SSL_CIPHER_get_bits(sc, NULL); + if (m_cfg->readBoolEntry(tcipher, bits >= 56)) { + CipherNode *xx = new CipherNode(d->kossl->SSL_CIPHER_get_name(sc),bits); + if (!cipherList.contains(xx)) + cipherList.prepend(xx); + else + delete xx; + } + } + d->kossl->SSL_free(ssl); + d->kossl->SSL_CTX_free(ctx); + + // Remove any ADH ciphers as per RFC2246 + // Also remove NULL ciphers and 168bit ciphers + for (unsigned int i = 0; i < cipherList.count(); i++) { + CipherNode *j = 0L; + while ((j = cipherList.at(i)) != 0L) { + if (j->name.contains("ADH-") || j->name.contains("NULL-") || j->name.contains("DES-CBC3-SHA") || j->name.contains("FZA")) { + cipherList.remove(j); + } else { + break; + } + } + } + + // now assemble the list cipher1:cipher2:cipher3:...:ciphern + while (!cipherList.isEmpty()) { + if (firstcipher) + firstcipher = false; + else clist.append(":"); + clist.append(cipherList.getLast()->name); + cipherList.removeLast(); + } // while + + kdDebug(7029) << "Cipher list is: " << clist << endl; + +#endif + return clist; +} + +// FIXME - sync these up so that we can use them with the control module!! +void KSSLSettings::load() { + m_cfg->reparseConfiguration(); + + m_cfg->setGroup("TLS"); + m_bUseTLSv1 = m_cfg->readBoolEntry("Enabled", true); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_NO_SSL2) + m_bUseSSLv2 = false; +#else + m_cfg->setGroup("SSLv2"); + m_bUseSSLv2 = m_cfg->readBoolEntry("Enabled", false); +#endif + +#if defined(OPENSSL_NO_SSL3) + m_bUseSSLv3 = false; +#else + m_cfg->setGroup("SSLv3"); + m_bUseSSLv3 = m_cfg->readBoolEntry("Enabled", true); +#endif + + m_cfg->setGroup("Warnings"); + m_bWarnOnEnter = m_cfg->readBoolEntry("OnEnter", false); + m_bWarnOnLeave = m_cfg->readBoolEntry("OnLeave", true); + m_bWarnOnUnencrypted = m_cfg->readBoolEntry("OnUnencrypted", true); + m_bWarnOnMixed = m_cfg->readBoolEntry("OnMixed", true); + + m_cfg->setGroup("Validation"); + m_bWarnSelfSigned = m_cfg->readBoolEntry("WarnSelfSigned", true); + m_bWarnExpired = m_cfg->readBoolEntry("WarnExpired", true); + m_bWarnRevoked = m_cfg->readBoolEntry("WarnRevoked", true); + + m_cfg->setGroup("EGD"); + d->m_bUseEGD = m_cfg->readBoolEntry("UseEGD", false); + d->m_bUseEFile = m_cfg->readBoolEntry("UseEFile", false); + d->m_EGDPath = m_cfg->readPathEntry("EGDPath"); + + m_cfg->setGroup("Auth"); + d->m_bSendX509 = ("send" == m_cfg->readEntry("AuthMethod", "")); + d->m_bPromptX509 = ("prompt" == m_cfg->readEntry("AuthMethod", "")); + + #ifdef KSSL_HAVE_SSL + + + + #endif +} + + +void KSSLSettings::defaults() { + m_bUseTLSv1 = true; + m_bUseSSLv2 = false; + m_bUseSSLv3 = true; + m_bWarnOnEnter = false; + m_bWarnOnLeave = true; + m_bWarnOnUnencrypted = true; + m_bWarnOnMixed = true; + m_bWarnSelfSigned = true; + m_bWarnExpired = true; + m_bWarnRevoked = true; + d->m_bUseEGD = false; + d->m_bUseEFile = false; + d->m_EGDPath = ""; +} + + +void KSSLSettings::save() { + m_cfg->setGroup("TLS"); + m_cfg->writeEntry("Enabled", m_bUseTLSv1); + + m_cfg->setGroup("SSLv2"); + m_cfg->writeEntry("Enabled", m_bUseSSLv2); + + m_cfg->setGroup("SSLv3"); + m_cfg->writeEntry("Enabled", m_bUseSSLv3); + + m_cfg->setGroup("Warnings"); + m_cfg->writeEntry("OnEnter", m_bWarnOnEnter); + m_cfg->writeEntry("OnLeave", m_bWarnOnLeave); + m_cfg->writeEntry("OnUnencrypted", m_bWarnOnUnencrypted); + m_cfg->writeEntry("OnMixed", m_bWarnOnMixed); + + m_cfg->setGroup("Validation"); + m_cfg->writeEntry("WarnSelfSigned", m_bWarnSelfSigned); + m_cfg->writeEntry("WarnExpired", m_bWarnExpired); + m_cfg->writeEntry("WarnRevoked", m_bWarnRevoked); + + m_cfg->setGroup("EGD"); + m_cfg->writeEntry("UseEGD", d->m_bUseEGD); + m_cfg->writeEntry("UseEFile", d->m_bUseEFile); + m_cfg->writePathEntry("EGDPath", d->m_EGDPath); + + m_cfg->sync(); + // FIXME - ciphers +#if 0 +#ifdef KSSL_HAVE_SSL + m_cfg->setGroup("SSLv2"); + for (unsigned int i = 0; i < v2ciphers.count(); i++) { + TQString ciphername; + ciphername.sprintf("cipher_%s", v2ciphers[i].ascii()); + if (v2selectedciphers.contains(v2ciphers[i])) { + m_cfg->writeEntry(ciphername, true); + } else m_cfg->writeEntry(ciphername, false); + } + + m_cfg->setGroup("SSLv3"); + for (unsigned int i = 0; i < v3ciphers.count(); i++) { + TQString ciphername; + ciphername.sprintf("cipher_%s", v3ciphers[i].ascii()); + if (v3selectedciphers.contains(v3ciphers[i])) { + m_cfg->writeEntry(ciphername, true); + } else m_cfg->writeEntry(ciphername, false); + } +#endif + + m_cfg->sync(); + + // insure proper permissions -- contains sensitive data + TQString cfgName(TDEGlobal::dirs()->findResource("config", "cryptodefaults")); + if (!cfgName.isEmpty()) + ::chmod(TQFile::encodeName(cfgName), 0600); +#endif +} + + +bool KSSLSettings::warnOnEnter() const { return m_bWarnOnEnter; } +void KSSLSettings::setWarnOnEnter(bool x) { m_bWarnOnEnter = x; } +bool KSSLSettings::warnOnUnencrypted() const { return m_bWarnOnUnencrypted; } +void KSSLSettings::setWarnOnUnencrypted(bool x) { m_bWarnOnUnencrypted = x; } +bool KSSLSettings::warnOnLeave() const { return m_bWarnOnLeave; } +void KSSLSettings::setWarnOnLeave(bool x) { m_bWarnOnLeave = x; } +bool KSSLSettings::warnOnMixed() const { return m_bWarnOnMixed; } +bool KSSLSettings::warnOnSelfSigned() const { return m_bWarnSelfSigned; } +bool KSSLSettings::warnOnRevoked() const { return m_bWarnRevoked; } +bool KSSLSettings::warnOnExpired() const { return m_bWarnExpired; } +bool KSSLSettings::useEGD() const { return d->m_bUseEGD; } +bool KSSLSettings::useEFile() const { return d->m_bUseEFile; } +bool KSSLSettings::autoSendX509() const { return d->m_bSendX509; } +bool KSSLSettings::promptSendX509() const { return d->m_bPromptX509; } + +void KSSLSettings::setTLSv1(bool enabled) { m_bUseTLSv1 = enabled; } +void KSSLSettings::setSSLv2(bool enabled) { m_bUseSSLv2 = enabled; } +void KSSLSettings::setSSLv3(bool enabled) { m_bUseSSLv3 = enabled; } + +TQString& KSSLSettings::getEGDPath() { return d->m_EGDPath; } + diff --git a/tdeio/kssl/ksslsigners.cc b/tdeio/kssl/ksslsigners.cc deleted file mode 100644 index 028ddf555..000000000 --- a/tdeio/kssl/ksslsigners.cc +++ /dev/null @@ -1,251 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include -#include -#include "ksslcertificate.h" -#include "ksslsigners.h" -#include -#include -#include -#include - - -KSSLSigners::KSSLSigners() { - dcc = new DCOPClient; - dcc->attach(); -} - - -KSSLSigners::~KSSLSigners() { - delete dcc; -} - -bool KSSLSigners::addCA(KSSLCertificate& cert, - bool ssl, - bool email, - bool code) { - return addCA(cert.toString(), ssl, email, code); -} - - -bool KSSLSigners::addCA(TQString cert, - bool ssl, - bool email, - bool code) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << cert; - arg << ssl << email << code; - bool rc = dcc->call("kded", "kssld", - "caAdd(TQString,bool,bool,bool)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLSigners::regenerate() { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - bool rc = dcc->call("kded", "kssld", - "caRegenerate()", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLSigners::useForSSL(KSSLCertificate& cert) { - return useForSSL(cert.getSubject()); -} - - -bool KSSLSigners::useForSSL(TQString subject) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << subject; - bool rc = dcc->call("kded", "kssld", - "caUseForSSL(TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLSigners::useForEmail(KSSLCertificate& cert) { - return useForEmail(cert.getSubject()); -} - - -bool KSSLSigners::useForEmail(TQString subject) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << subject; - bool rc = dcc->call("kded", "kssld", - "caUseForEmail(TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLSigners::useForCode(KSSLCertificate& cert) { - return useForCode(cert.getSubject()); -} - - -bool KSSLSigners::useForCode(TQString subject) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << subject; - bool rc = dcc->call("kded", "kssld", - "caUseForCode(TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -bool KSSLSigners::remove(KSSLCertificate& cert) { - return remove(cert.getSubject()); -} - - -bool KSSLSigners::remove(TQString subject) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << subject; - bool rc = dcc->call("kded", "kssld", - "caRemove(TQString)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - -TQStringList KSSLSigners::list() { - TQStringList drc; - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - bool rc = dcc->call("kded", "kssld", - "caList()", - data, rettype, retval); - - if (rc && rettype == TQSTRINGLIST_OBJECT_NAME_STRING) { - TQDataStream retStream(retval, IO_ReadOnly); - retStream >> drc; - } - -return drc; -} - - -TQString KSSLSigners::getCert(TQString subject) { - TQString drc; - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << subject; - bool rc = dcc->call("kded", "kssld", - "caGetCert(TQString)", - data, rettype, retval); - - if (rc && rettype == TQSTRING_OBJECT_NAME_STRING) { - TQDataStream retStream(retval, IO_ReadOnly); - retStream >> drc; - } - -return drc; -} - - -bool KSSLSigners::setUse(TQString subject, bool ssl, bool email, bool code) { - TQByteArray data, retval; - TQCString rettype; - TQDataStream arg(data, IO_WriteOnly); - arg << subject << ssl << email << code; - bool rc = dcc->call("kded", "kssld", - "caSetUse(TQString,bool,bool,bool)", - data, rettype, retval); - - if (rc && rettype == "bool") { - TQDataStream retStream(retval, IO_ReadOnly); - bool drc; - retStream >> drc; - return drc; - } - -return false; -} - - - - diff --git a/tdeio/kssl/ksslsigners.cpp b/tdeio/kssl/ksslsigners.cpp new file mode 100644 index 000000000..028ddf555 --- /dev/null +++ b/tdeio/kssl/ksslsigners.cpp @@ -0,0 +1,251 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include +#include +#include "ksslcertificate.h" +#include "ksslsigners.h" +#include +#include +#include +#include + + +KSSLSigners::KSSLSigners() { + dcc = new DCOPClient; + dcc->attach(); +} + + +KSSLSigners::~KSSLSigners() { + delete dcc; +} + +bool KSSLSigners::addCA(KSSLCertificate& cert, + bool ssl, + bool email, + bool code) { + return addCA(cert.toString(), ssl, email, code); +} + + +bool KSSLSigners::addCA(TQString cert, + bool ssl, + bool email, + bool code) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << cert; + arg << ssl << email << code; + bool rc = dcc->call("kded", "kssld", + "caAdd(TQString,bool,bool,bool)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLSigners::regenerate() { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + bool rc = dcc->call("kded", "kssld", + "caRegenerate()", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLSigners::useForSSL(KSSLCertificate& cert) { + return useForSSL(cert.getSubject()); +} + + +bool KSSLSigners::useForSSL(TQString subject) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << subject; + bool rc = dcc->call("kded", "kssld", + "caUseForSSL(TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLSigners::useForEmail(KSSLCertificate& cert) { + return useForEmail(cert.getSubject()); +} + + +bool KSSLSigners::useForEmail(TQString subject) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << subject; + bool rc = dcc->call("kded", "kssld", + "caUseForEmail(TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLSigners::useForCode(KSSLCertificate& cert) { + return useForCode(cert.getSubject()); +} + + +bool KSSLSigners::useForCode(TQString subject) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << subject; + bool rc = dcc->call("kded", "kssld", + "caUseForCode(TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +bool KSSLSigners::remove(KSSLCertificate& cert) { + return remove(cert.getSubject()); +} + + +bool KSSLSigners::remove(TQString subject) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << subject; + bool rc = dcc->call("kded", "kssld", + "caRemove(TQString)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + +TQStringList KSSLSigners::list() { + TQStringList drc; + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + bool rc = dcc->call("kded", "kssld", + "caList()", + data, rettype, retval); + + if (rc && rettype == TQSTRINGLIST_OBJECT_NAME_STRING) { + TQDataStream retStream(retval, IO_ReadOnly); + retStream >> drc; + } + +return drc; +} + + +TQString KSSLSigners::getCert(TQString subject) { + TQString drc; + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << subject; + bool rc = dcc->call("kded", "kssld", + "caGetCert(TQString)", + data, rettype, retval); + + if (rc && rettype == TQSTRING_OBJECT_NAME_STRING) { + TQDataStream retStream(retval, IO_ReadOnly); + retStream >> drc; + } + +return drc; +} + + +bool KSSLSigners::setUse(TQString subject, bool ssl, bool email, bool code) { + TQByteArray data, retval; + TQCString rettype; + TQDataStream arg(data, IO_WriteOnly); + arg << subject << ssl << email << code; + bool rc = dcc->call("kded", "kssld", + "caSetUse(TQString,bool,bool,bool)", + data, rettype, retval); + + if (rc && rettype == "bool") { + TQDataStream retStream(retval, IO_ReadOnly); + bool drc; + retStream >> drc; + return drc; + } + +return false; +} + + + + diff --git a/tdeio/kssl/ksslutils.cc b/tdeio/kssl/ksslutils.cc deleted file mode 100644 index 2e6e3a303..000000000 --- a/tdeio/kssl/ksslutils.cc +++ /dev/null @@ -1,103 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000,2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include "ksslutils.h" - -#include -#include -#include -#include - -#include "kopenssl.h" - -#ifdef KSSL_HAVE_SSL -// This code is mostly taken from OpenSSL v0.9.5a -// by Eric Young -TQDateTime ASN1_UTCTIME_QDateTime(ASN1_UTCTIME *tm, int *isGmt) { -TQDateTime qdt; -char *v; -int gmt=0; -int gentime=0; -int yoffset=0; -int yearbase=1900; -int i; -int y=0,M=0,d=0,h=0,m=0,s=0; -TQDate qdate; -TQTime qtime; - - i = tm->length; - v = (char *)tm->data; - if ((i == 15) || (i == 21)) { - gentime=1; - yoffset=2; - yearbase=0; - } - if (i < 10) goto auq_err; - if (v[i-1] == 'Z') gmt=1; - for (i=0; i<10+yoffset; i++) - if ((v[i] > '9') || (v[i] < '0')) goto auq_err; - y = (v[0+yoffset]-'0')*10+(v[1+yoffset]-'0'); - if (gentime) - y += (v[0]-'0')*1000+(v[1]-'0')*100; - if (y < 50) y+=100; - M = (v[2+yoffset]-'0')*10+(v[3+yoffset]-'0'); - if ((M > 12) || (M < 1)) goto auq_err; - d = (v[4+yoffset]-'0')*10+(v[5+yoffset]-'0'); - h = (v[6+yoffset]-'0')*10+(v[7+yoffset]-'0'); - m = (v[8+yoffset]-'0')*10+(v[9+yoffset]-'0'); - if ( (v[10+yoffset] >= '0') && (v[10+yoffset] <= '9') && - (v[11+yoffset] >= '0') && (v[11+yoffset] <= '9')) - s = (v[10+yoffset]-'0')*10+(v[11+yoffset]-'0'); - - // localize the date and display it. - qdate.setYMD(y+yearbase, M, d); - qtime.setHMS(h,m,s); - qdt.setDate(qdate); qdt.setTime(qtime); - auq_err: - if (isGmt) *isGmt = gmt; -return qdt; -} - - -TQString ASN1_UTCTIME_QString(ASN1_UTCTIME *tm) { - TQString qstr; - int gmt; - TQDateTime qdt = ASN1_UTCTIME_QDateTime(tm, &gmt); - - qstr = TDEGlobal::locale()->formatDateTime(qdt, false, true); - if (gmt) { - qstr += " "; - qstr += i18n("GMT"); - } - return qstr; -} - - -TQString ASN1_INTEGER_QString(ASN1_INTEGER *aint) { - char *rep = KOSSL::self()->i2s_ASN1_INTEGER(NULL, aint); - TQString yy = rep; - KOSSL::self()->CRYPTO_free(rep); - return yy; -} - - -#endif - diff --git a/tdeio/kssl/ksslutils.cpp b/tdeio/kssl/ksslutils.cpp new file mode 100644 index 000000000..2e6e3a303 --- /dev/null +++ b/tdeio/kssl/ksslutils.cpp @@ -0,0 +1,103 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000,2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#include "ksslutils.h" + +#include +#include +#include +#include + +#include "kopenssl.h" + +#ifdef KSSL_HAVE_SSL +// This code is mostly taken from OpenSSL v0.9.5a +// by Eric Young +TQDateTime ASN1_UTCTIME_QDateTime(ASN1_UTCTIME *tm, int *isGmt) { +TQDateTime qdt; +char *v; +int gmt=0; +int gentime=0; +int yoffset=0; +int yearbase=1900; +int i; +int y=0,M=0,d=0,h=0,m=0,s=0; +TQDate qdate; +TQTime qtime; + + i = tm->length; + v = (char *)tm->data; + if ((i == 15) || (i == 21)) { + gentime=1; + yoffset=2; + yearbase=0; + } + if (i < 10) goto auq_err; + if (v[i-1] == 'Z') gmt=1; + for (i=0; i<10+yoffset; i++) + if ((v[i] > '9') || (v[i] < '0')) goto auq_err; + y = (v[0+yoffset]-'0')*10+(v[1+yoffset]-'0'); + if (gentime) + y += (v[0]-'0')*1000+(v[1]-'0')*100; + if (y < 50) y+=100; + M = (v[2+yoffset]-'0')*10+(v[3+yoffset]-'0'); + if ((M > 12) || (M < 1)) goto auq_err; + d = (v[4+yoffset]-'0')*10+(v[5+yoffset]-'0'); + h = (v[6+yoffset]-'0')*10+(v[7+yoffset]-'0'); + m = (v[8+yoffset]-'0')*10+(v[9+yoffset]-'0'); + if ( (v[10+yoffset] >= '0') && (v[10+yoffset] <= '9') && + (v[11+yoffset] >= '0') && (v[11+yoffset] <= '9')) + s = (v[10+yoffset]-'0')*10+(v[11+yoffset]-'0'); + + // localize the date and display it. + qdate.setYMD(y+yearbase, M, d); + qtime.setHMS(h,m,s); + qdt.setDate(qdate); qdt.setTime(qtime); + auq_err: + if (isGmt) *isGmt = gmt; +return qdt; +} + + +TQString ASN1_UTCTIME_QString(ASN1_UTCTIME *tm) { + TQString qstr; + int gmt; + TQDateTime qdt = ASN1_UTCTIME_QDateTime(tm, &gmt); + + qstr = TDEGlobal::locale()->formatDateTime(qdt, false, true); + if (gmt) { + qstr += " "; + qstr += i18n("GMT"); + } + return qstr; +} + + +TQString ASN1_INTEGER_QString(ASN1_INTEGER *aint) { + char *rep = KOSSL::self()->i2s_ASN1_INTEGER(NULL, aint); + TQString yy = rep; + KOSSL::self()->CRYPTO_free(rep); + return yy; +} + + +#endif + diff --git a/tdeio/kssl/ksslx509map.cc b/tdeio/kssl/ksslx509map.cc deleted file mode 100644 index 7896fdfcf..000000000 --- a/tdeio/kssl/ksslx509map.cc +++ /dev/null @@ -1,103 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2000 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ksslx509map.h" -#include -#include - -KSSLX509Map::KSSLX509Map(const TQString& name) { - parse(name); -} - - -KSSLX509Map::~KSSLX509Map() { - -} - - -void KSSLX509Map::setValue(const TQString& key, const TQString& value) { - m_pairs.replace(key, value); -} - - -TQString KSSLX509Map::getValue(const TQString& key) const { - if (!m_pairs.contains(key)) { - return TQString::null; - } - - return m_pairs[key]; -} - -static TQStringList tokenizeBy(const TQString& str, const TQRegExp& tok, bool keepEmpties = false) { -TQStringList tokens; -unsigned int head, tail; -const char *chstr = str.ascii(); -unsigned int length = str.length(); - - if (length < 1) { - return tokens; - } - - if (length == 1) { - tokens.append(str); - return tokens; - } - - for(head = 0, tail = 0; tail < length-1; head = tail+1) { - TQString thisline; - - tail = str.find(tok, head); - - if (tail > length) // last token - none at end - tail = length; - - if (tail-head > 0 || keepEmpties) { // it has to be at least 1 long! - thisline = &(chstr[head]); - thisline.truncate(tail-head); - tokens.append(thisline); - } - } - return tokens; -} - - -void KSSLX509Map::parse(const TQString& name) { -TQStringList vl = tokenizeBy(name, TQRegExp("/[A-Za-z]+="), false); - - m_pairs.clear(); - - for (TQStringList::Iterator j = vl.begin(); j != vl.end(); ++j) { - TQStringList apair = tokenizeBy(*j, TQRegExp("="), false); - if (m_pairs.contains(apair[0])) { - TQString oldValue = m_pairs[apair[0]]; - oldValue += "\n"; - oldValue += apair[1]; - m_pairs.replace(apair[0], oldValue); - } else { - m_pairs.insert(apair[0], apair[1]); - } - } -} - - -void KSSLX509Map::reset(const TQString& name) { - parse(name); -} - diff --git a/tdeio/kssl/ksslx509map.cpp b/tdeio/kssl/ksslx509map.cpp new file mode 100644 index 000000000..7896fdfcf --- /dev/null +++ b/tdeio/kssl/ksslx509map.cpp @@ -0,0 +1,103 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2000 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "ksslx509map.h" +#include +#include + +KSSLX509Map::KSSLX509Map(const TQString& name) { + parse(name); +} + + +KSSLX509Map::~KSSLX509Map() { + +} + + +void KSSLX509Map::setValue(const TQString& key, const TQString& value) { + m_pairs.replace(key, value); +} + + +TQString KSSLX509Map::getValue(const TQString& key) const { + if (!m_pairs.contains(key)) { + return TQString::null; + } + + return m_pairs[key]; +} + +static TQStringList tokenizeBy(const TQString& str, const TQRegExp& tok, bool keepEmpties = false) { +TQStringList tokens; +unsigned int head, tail; +const char *chstr = str.ascii(); +unsigned int length = str.length(); + + if (length < 1) { + return tokens; + } + + if (length == 1) { + tokens.append(str); + return tokens; + } + + for(head = 0, tail = 0; tail < length-1; head = tail+1) { + TQString thisline; + + tail = str.find(tok, head); + + if (tail > length) // last token - none at end + tail = length; + + if (tail-head > 0 || keepEmpties) { // it has to be at least 1 long! + thisline = &(chstr[head]); + thisline.truncate(tail-head); + tokens.append(thisline); + } + } + return tokens; +} + + +void KSSLX509Map::parse(const TQString& name) { +TQStringList vl = tokenizeBy(name, TQRegExp("/[A-Za-z]+="), false); + + m_pairs.clear(); + + for (TQStringList::Iterator j = vl.begin(); j != vl.end(); ++j) { + TQStringList apair = tokenizeBy(*j, TQRegExp("="), false); + if (m_pairs.contains(apair[0])) { + TQString oldValue = m_pairs[apair[0]]; + oldValue += "\n"; + oldValue += apair[1]; + m_pairs.replace(apair[0], oldValue); + } else { + m_pairs.insert(apair[0], apair[1]); + } + } +} + + +void KSSLX509Map::reset(const TQString& name) { + parse(name); +} + diff --git a/tdeio/kssl/ksslx509v3.cc b/tdeio/kssl/ksslx509v3.cc deleted file mode 100644 index a3310b9db..000000000 --- a/tdeio/kssl/ksslx509v3.cc +++ /dev/null @@ -1,143 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "ksslx509v3.h" -#include -#include - - -KSSLX509V3::KSSLX509V3() { - flags = 0; -} - - -KSSLX509V3::~KSSLX509V3() { -} - - -/* When reading this, please remember that - * !A || B is logically equivalent to A => B - */ - -bool KSSLX509V3::certTypeCA() { -#ifdef KSSL_HAVE_SSL - // First try CA without X509_PURPOSE_ANY CA, then just try SSLCA - return (flags & (65471L << 16)) ? true : certTypeSSLCA(); -#endif - return false; -} - - -bool KSSLX509V3::certTypeSSLCA() { -#ifdef KSSL_HAVE_SSL - return (flags & ((1 << (16+X509_PURPOSE_NS_SSL_SERVER-1))| - (1 << (16+X509_PURPOSE_SSL_SERVER-1))| - (1 << (16+X509_PURPOSE_SSL_CLIENT-1)))) ? true : - (false || ((1 << (16+X509_PURPOSE_ANY-1)) && - (certTypeSSLServer() || - certTypeSSLClient() || - certTypeNSSSLServer()))); -#endif - return false; -} - - -bool KSSLX509V3::certTypeEmailCA() { -#ifdef KSSL_HAVE_SSL - return (flags & ((1 << (16+X509_PURPOSE_SMIME_ENCRYPT-1))| - (1 << (16+X509_PURPOSE_SMIME_SIGN-1)))) ? true : - (false || ((1 << (16+X509_PURPOSE_ANY-1)) && - certTypeSMIME())); -#endif - return false; -} - - -bool KSSLX509V3::certTypeCodeCA() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (16+X509_PURPOSE_ANY-1))) ? true : false; -#endif - return false; -} - - -bool KSSLX509V3::certTypeSSLClient() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (X509_PURPOSE_SSL_CLIENT-1))) ? true : false; -#endif - return false; -} - - -bool KSSLX509V3::certTypeSSLServer() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (X509_PURPOSE_SSL_SERVER-1))) ? true : false; -#endif - return false; -} - - -bool KSSLX509V3::certTypeNSSSLServer() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (X509_PURPOSE_NS_SSL_SERVER-1))) ? true : false; -#endif - return false; -} - - -bool KSSLX509V3::certTypeSMIME() { -#ifdef KSSL_HAVE_SSL - return certTypeSMIMEEncrypt()||certTypeSMIMESign(); -#endif - return false; -} - - -bool KSSLX509V3::certTypeSMIMEEncrypt() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (X509_PURPOSE_SMIME_ENCRYPT-1))) ? true : false; -#endif - return false; -} - - -bool KSSLX509V3::certTypeSMIMESign() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (X509_PURPOSE_SMIME_SIGN-1))) ? true : false; -#endif - return false; -} - - -bool KSSLX509V3::certTypeCRLSign() { -#ifdef KSSL_HAVE_SSL - return (flags & (1 << (X509_PURPOSE_CRL_SIGN-1))) ? true : false; -#endif - return false; -} - - - - - diff --git a/tdeio/kssl/ksslx509v3.cpp b/tdeio/kssl/ksslx509v3.cpp new file mode 100644 index 000000000..a3310b9db --- /dev/null +++ b/tdeio/kssl/ksslx509v3.cpp @@ -0,0 +1,143 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ksslx509v3.h" +#include +#include + + +KSSLX509V3::KSSLX509V3() { + flags = 0; +} + + +KSSLX509V3::~KSSLX509V3() { +} + + +/* When reading this, please remember that + * !A || B is logically equivalent to A => B + */ + +bool KSSLX509V3::certTypeCA() { +#ifdef KSSL_HAVE_SSL + // First try CA without X509_PURPOSE_ANY CA, then just try SSLCA + return (flags & (65471L << 16)) ? true : certTypeSSLCA(); +#endif + return false; +} + + +bool KSSLX509V3::certTypeSSLCA() { +#ifdef KSSL_HAVE_SSL + return (flags & ((1 << (16+X509_PURPOSE_NS_SSL_SERVER-1))| + (1 << (16+X509_PURPOSE_SSL_SERVER-1))| + (1 << (16+X509_PURPOSE_SSL_CLIENT-1)))) ? true : + (false || ((1 << (16+X509_PURPOSE_ANY-1)) && + (certTypeSSLServer() || + certTypeSSLClient() || + certTypeNSSSLServer()))); +#endif + return false; +} + + +bool KSSLX509V3::certTypeEmailCA() { +#ifdef KSSL_HAVE_SSL + return (flags & ((1 << (16+X509_PURPOSE_SMIME_ENCRYPT-1))| + (1 << (16+X509_PURPOSE_SMIME_SIGN-1)))) ? true : + (false || ((1 << (16+X509_PURPOSE_ANY-1)) && + certTypeSMIME())); +#endif + return false; +} + + +bool KSSLX509V3::certTypeCodeCA() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (16+X509_PURPOSE_ANY-1))) ? true : false; +#endif + return false; +} + + +bool KSSLX509V3::certTypeSSLClient() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (X509_PURPOSE_SSL_CLIENT-1))) ? true : false; +#endif + return false; +} + + +bool KSSLX509V3::certTypeSSLServer() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (X509_PURPOSE_SSL_SERVER-1))) ? true : false; +#endif + return false; +} + + +bool KSSLX509V3::certTypeNSSSLServer() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (X509_PURPOSE_NS_SSL_SERVER-1))) ? true : false; +#endif + return false; +} + + +bool KSSLX509V3::certTypeSMIME() { +#ifdef KSSL_HAVE_SSL + return certTypeSMIMEEncrypt()||certTypeSMIMESign(); +#endif + return false; +} + + +bool KSSLX509V3::certTypeSMIMEEncrypt() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (X509_PURPOSE_SMIME_ENCRYPT-1))) ? true : false; +#endif + return false; +} + + +bool KSSLX509V3::certTypeSMIMESign() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (X509_PURPOSE_SMIME_SIGN-1))) ? true : false; +#endif + return false; +} + + +bool KSSLX509V3::certTypeCRLSign() { +#ifdef KSSL_HAVE_SSL + return (flags & (1 << (X509_PURPOSE_CRL_SIGN-1))) ? true : false; +#endif + return false; +} + + + + + diff --git a/tdeio/tdefile/tdefiledialog.h b/tdeio/tdefile/tdefiledialog.h index 55980bfb6..cd94ebe51 100644 --- a/tdeio/tdefile/tdefiledialog.h +++ b/tdeio/tdefile/tdefiledialog.h @@ -268,7 +268,7 @@ public: * tdefile->setFilter("*.cpp"); * tdefile->setFilter("*.cpp|Sources (*.cpp)"); * tdefile->setFilter("*.cpp|" + i18n("Sources (*.cpp)")); - * tdefile->setFilter("*.cpp *.cc *.C|C++ Source Files\n*.h *.H|Header files"); + * tdefile->setFilter("*.cpp|C++ Source Files\n*.h|Header files"); * \endcode * * Note: The text to display is not parsed in any way. So, if you @@ -359,7 +359,7 @@ public: * This widget has to inherit TQWidget and it has to implement * a slot showPreview(const KURL &); which is called * every time the file changes. You may want to look at - * koffice/lib/kofficecore/koFilterManager.cc for some hints :) + * koffice/lib/kofficecore/koFilterManager.cpp for some hints :) * * Ownership is transferred to KFileDialog. You need to create the * preview-widget with "new", i.e. on the heap. @@ -811,7 +811,7 @@ signals: * or chose one of the predefined set via setFilter(). * * @param filter contains the new filter (only the extension part, - * not the explanation), i.e. "*.cpp" or "*.cpp *.cc". + * not the explanation), i.e. "*.cpp". * * @see setFilter() * @see currentFilter() diff --git a/tdeio/tdeio/kmimetypechooser.cpp b/tdeio/tdeio/kmimetypechooser.cpp index 72fdf925e..758cd4940 100644 --- a/tdeio/tdeio/kmimetypechooser.cpp +++ b/tdeio/tdeio/kmimetypechooser.cpp @@ -192,7 +192,7 @@ void KMimeTypeChooser::editMimeType() if ( !(d->lvMimeTypes->currentItem() && (d->lvMimeTypes->currentItem())->parent()) ) return; TQString mt = (d->lvMimeTypes->currentItem()->parent())->text( 0 ) + "/" + (d->lvMimeTypes->currentItem())->text( 0 ); - // thanks to libkonq/konq_operations.cc + // thanks to libkonq/konq_operations.cpp connect( KSycoca::self(), TQT_SIGNAL(databaseChanged()), this, TQT_SLOT(slotSycocaDatabaseChanged()) ); TQString keditfiletype = TQString::fromLatin1("keditfiletype"); diff --git a/tdeio/tdeio/tdefileitem.cpp b/tdeio/tdeio/tdefileitem.cpp index 7b4c7ccd3..7af8aae39 100644 --- a/tdeio/tdeio/tdefileitem.cpp +++ b/tdeio/tdeio/tdefileitem.cpp @@ -172,7 +172,7 @@ void KFileItem::init( bool _determineMimeTypeOnDemand ) if ( KDE_stat( path.data(), &buf ) == 0 ) { mode = buf.st_mode; } - else { // link pointing to nowhere (see tdeio/file/file.cc) + else { // link pointing to nowhere (see tdeio/file/file.cpp) mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO; } } diff --git a/tdeio/tdeio/tdefileitem.h b/tdeio/tdeio/tdefileitem.h index b0dd9b4b8..171b611e3 100644 --- a/tdeio/tdeio/tdefileitem.h +++ b/tdeio/tdeio/tdefileitem.h @@ -30,7 +30,7 @@ #include #include -#define TDEFILEITEM_HAS_ISWRITABLE // only used in libkonq/konq_iconviewwidget.cc, will be removed for 3.4 +#define TDEFILEITEM_HAS_ISWRITABLE // only used in libkonq/konq_iconviewwidget.cpp, will be removed for 3.4 /** * A KFileItem is a generic class to handle a file, local or remote. diff --git a/tdeio/tests/kurifiltertest.cpp b/tdeio/tests/kurifiltertest.cpp index dec955156..0b3e6621d 100644 --- a/tdeio/tests/kurifiltertest.cpp +++ b/tdeio/tests/kurifiltertest.cpp @@ -270,7 +270,7 @@ int main(int argc, char **argv) // a search using the default search engine // 'ls' is a bit of a special case though, due to the toplevel domain called 'ls' filter( "cp", "http://www.google.com/search?q=cp&ie=UTF-8&oe=UTF-8", KURIFilterData::NET_PROTOCOL, - TQStringList(), 0, false /* don't check for executables, see konq_misc.cc */ ); + TQStringList(), 0, false /* don't check for executables, see konq_misc.cpp */ ); // Executable tests - No IKWS in minicli filter( "cp", "cp", KURIFilterData::EXECUTABLE, minicliFilters ); diff --git a/tdeioslave/file/CMakeLists.txt b/tdeioslave/file/CMakeLists.txt index 6456e962b..0215e1522 100644 --- a/tdeioslave/file/CMakeLists.txt +++ b/tdeioslave/file/CMakeLists.txt @@ -44,7 +44,7 @@ tde_create_translated_desktop( set( target tdeio_file ) set( ${target}_SRCS - file.cc + file.cpp ) tde_add_kpart( ${target} AUTOMOC diff --git a/tdeioslave/file/Makefile.am b/tdeioslave/file/Makefile.am index c7f35b51f..d31b69b41 100644 --- a/tdeioslave/file/Makefile.am +++ b/tdeioslave/file/Makefile.am @@ -8,7 +8,7 @@ INCLUDES = $(all_includes) kde_module_LTLIBRARIES = tdeio_file.la -tdeio_file_la_SOURCES = file.cc +tdeio_file_la_SOURCES = file.cpp tdeio_file_la_LIBADD = $(LIB_TDEIO) $(LIB_TQT) $(LIB_TDECORE) $(ACL_LIBS) tdeio_file_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(top_builddir)/dcop/libDCOP.la noinst_HEADERS = file.h diff --git a/tdeioslave/file/file.cc b/tdeioslave/file/file.cc deleted file mode 100644 index fda72f2d5..000000000 --- a/tdeioslave/file/file.cc +++ /dev/null @@ -1,1890 +0,0 @@ -/* - Copyright (C) 2000-2002 Stephan Kulow - Copyright (C) 2000-2002 David Faure - Copyright (C) 2000-2002 Waldo Bastian - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License (LGPL) as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later - version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -// $Id$ - -#include - -#include //for Q_OS_XXX -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif - -//sendfile has different semantics in different platforms -#if defined HAVE_SENDFILE && defined Q_OS_LINUX -#define USE_SENDFILE 1 -#endif - -#ifdef USE_SENDFILE -#include -#endif - -#ifdef USE_POSIX_ACL -#include -#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS -#include -#else -#include -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_STRING_H -#include -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "file.h" -#include -#include -#include -#include - -#ifdef HAVE_VOLMGT -#include -#include -#endif - -#include -#include -#include -#include -#include - -using namespace TDEIO; - -#define MAX_IPC_SIZE (1024*32) - -static TQString testLogFile( const char *_filename ); -#ifdef USE_POSIX_ACL -static TQString aclAsString( acl_t p_acl ); -static bool isExtendedACL( acl_t p_acl ); -static void appendACLAtoms( const TQCString & path, UDSEntry& entry, - mode_t type, bool withACL ); -#endif - -extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } - -int kdemain( int argc, char **argv ) -{ - TDELocale::setMainCatalogue("tdelibs"); - TDEInstance instance( "tdeio_file" ); - ( void ) TDEGlobal::locale(); - - kdDebug(7101) << "Starting " << getpid() << endl; - - if (argc != 4) - { - fprintf(stderr, "Usage: tdeio_file protocol domain-socket1 domain-socket2\n"); - exit(-1); - } - - FileProtocol slave(argv[2], argv[3]); - slave.dispatchLoop(); - - kdDebug(7101) << "Done" << endl; - return 0; -} - - -FileProtocol::FileProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "file", pool, app ) -{ - usercache.setAutoDelete( true ); - groupcache.setAutoDelete( true ); -} - - -int FileProtocol::setACL( const char *path, mode_t perm, bool directoryDefault ) -{ - int ret = 0; -#ifdef USE_POSIX_ACL - - const TQString ACLString = metaData( "ACL_STRING" ); - const TQString defaultACLString = metaData( "DEFAULT_ACL_STRING" ); - // Empty strings mean leave as is - if ( !ACLString.isEmpty() ) { - acl_t acl = 0; - if ( ACLString == "ACL_DELETE" ) { - // user told us to delete the extended ACL, so let's write only - // the minimal (UNIX permission bits) part - acl = acl_from_mode( perm ); - } - acl = acl_from_text( ACLString.latin1() ); - if ( acl_valid( acl ) == 0 ) { // let's be safe - ret = acl_set_file( path, ACL_TYPE_ACCESS, acl ); - kdDebug(7101) << "Set ACL on: " << path << " to: " << aclAsString( acl ) << endl; - } - acl_free( acl ); - if ( ret != 0 ) return ret; // better stop trying right away - } - - if ( directoryDefault && !defaultACLString.isEmpty() ) { - if ( defaultACLString == "ACL_DELETE" ) { - // user told us to delete the default ACL, do so - ret += acl_delete_def_file( path ); - } else { - acl_t acl = acl_from_text( defaultACLString.latin1() ); - if ( acl_valid( acl ) == 0 ) { // let's be safe - ret += acl_set_file( path, ACL_TYPE_DEFAULT, acl ); - kdDebug(7101) << "Set Default ACL on: " << path << " to: " << aclAsString( acl ) << endl; - } - acl_free( acl ); - } - } -#endif - return ret; -} - -void FileProtocol::chmod( const KURL& url, int permissions ) -{ - TQCString _path( TQFile::encodeName(url.path()) ); - /* FIXME: Should be atomic */ - if ( ::chmod( _path.data(), permissions ) == -1 || - ( setACL( _path.data(), permissions, false ) == -1 ) || - /* if not a directory, cannot set default ACLs */ - ( setACL( _path.data(), permissions, true ) == -1 && errno != ENOTDIR ) ) { - - switch (errno) { - case EPERM: - case EACCES: - error( TDEIO::ERR_ACCESS_DENIED, url.path() ); - break; - case ENOTSUP: - error( TDEIO::ERR_UNSUPPORTED_ACTION, url.path() ); - break; - case ENOSPC: - error( TDEIO::ERR_DISK_FULL, url.path() ); - break; - default: - error( TDEIO::ERR_CANNOT_CHMOD, url.path() ); - } - } else - finished(); -} - -void FileProtocol::mkdir( const KURL& url, int permissions ) -{ - TQCString _path( TQFile::encodeName(url.path())); - - kdDebug(7101) << "mkdir(): " << _path << ", permission = " << permissions << endl; - - KDE_struct_stat buff; - if ( KDE_stat( _path.data(), &buff ) == -1 ) { - if ( ::mkdir( _path.data(), 0777 /*umask will be applied*/ ) != 0 ) { - if ( errno == EACCES ) { - error( TDEIO::ERR_ACCESS_DENIED, url.path() ); - return; - } else if ( errno == ENOSPC ) { - error( TDEIO::ERR_DISK_FULL, url.path() ); - return; - } else { - error( TDEIO::ERR_COULD_NOT_MKDIR, url.path() ); - return; - } - } else { - if ( permissions != -1 ) - chmod( url, permissions ); - else - finished(); - return; - } - } - - if ( S_ISDIR( buff.st_mode ) ) { - kdDebug(7101) << "ERR_DIR_ALREADY_EXIST" << endl; - error( TDEIO::ERR_DIR_ALREADY_EXIST, url.path() ); - return; - } - error( TDEIO::ERR_FILE_ALREADY_EXIST, url.path() ); - return; -} - -void FileProtocol::get( const KURL& url ) -{ - if (!url.isLocalFile()) { - KURL redir(url); - redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); - redirection(redir); - finished(); - return; - } - - TQCString _path( TQFile::encodeName(url.path())); - KDE_struct_stat buff; - if ( KDE_stat( _path.data(), &buff ) == -1 ) { - if ( errno == EACCES ) - error( TDEIO::ERR_ACCESS_DENIED, url.path() ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); - return; - } - - if ( S_ISDIR( buff.st_mode ) ) { - error( TDEIO::ERR_IS_DIRECTORY, url.path() ); - return; - } - if ( !S_ISREG( buff.st_mode ) ) { - error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); - return; - } - - int fd = KDE_open( _path.data(), O_RDONLY); - if ( fd < 0 ) { - error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); - return; - } - -#ifdef HAVE_FADVISE - posix_fadvise( fd, 0, 0, POSIX_FADV_SEQUENTIAL); -#endif - - // Determine the mimetype of the file to be retrieved, and emit it. - // This is mandatory in all slaves (for KRun/BrowserRun to work). - KMimeType::Ptr mt = KMimeType::findByURL( url, buff.st_mode, true /* local URL */ ); - emit mimeType( mt->name() ); - - TDEIO::filesize_t processed_size = 0; - - TQString resumeOffset = metaData("resume"); - if ( !resumeOffset.isEmpty() ) - { - bool ok; - TDEIO::fileoffset_t offset = resumeOffset.toLongLong(&ok); - if (ok && (offset > 0) && (offset < buff.st_size)) - { - if (KDE_lseek(fd, offset, SEEK_SET) == offset) - { - canResume (); - processed_size = offset; - kdDebug( 7101 ) << "Resume offset: " << TDEIO::number(offset) << endl; - } - } - } - - totalSize( buff.st_size ); - - char buffer[ MAX_IPC_SIZE ]; - TQByteArray array; - - while( 1 ) - { - int n = ::read( fd, buffer, MAX_IPC_SIZE ); - if (n == -1) - { - if (errno == EINTR) - continue; - error( TDEIO::ERR_COULD_NOT_READ, url.path()); - close(fd); - return; - } - if (n == 0) - break; // Finished - - array.setRawData(buffer, n); - data( array ); - array.resetRawData(buffer, n); - - processed_size += n; - processedSize( processed_size ); - - //kdDebug( 7101 ) << "Processed: " << TDEIO::number (processed_size) << endl; - } - - data( TQByteArray() ); - - close( fd ); - - processedSize( buff.st_size ); - finished(); -} - -static int -write_all(int fd, const char *buf, size_t len) -{ - while (len > 0) - { - ssize_t written = write(fd, buf, len); - if (written < 0) - { - if (errno == EINTR) - continue; - return -1; - } - buf += written; - len -= written; - } - return 0; -} - -static bool -same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest) -{ - if (src.st_ino == dest.st_ino && - src.st_dev == dest.st_dev) - return true; - - return false; -} - -void FileProtocol::put( const KURL& url, int _mode, bool _overwrite, bool _resume ) -{ - TQString dest_orig = url.path(); - TQCString _dest_orig( TQFile::encodeName(dest_orig)); - - kdDebug(7101) << "put(): " << dest_orig << ", mode=" << _mode << endl; - - TQString dest_part( dest_orig ); - dest_part += TQString::fromLatin1(".part"); - TQCString _dest_part( TQFile::encodeName(dest_part)); - - KDE_struct_stat buff_orig; - bool bOrigExists = (KDE_lstat( _dest_orig.data(), &buff_orig ) != -1); - bool bPartExists = false; - bool bMarkPartial = config()->readBoolEntry("MarkPartial", true); - - if (bMarkPartial) - { - KDE_struct_stat buff_part; - bPartExists = (KDE_stat( _dest_part.data(), &buff_part ) != -1); - - if (bPartExists && !_resume && !_overwrite && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode)) - { - kdDebug(7101) << "FileProtocol::put : calling canResume with " - << TDEIO::number(buff_part.st_size) << endl; - - // Maybe we can use this partial file for resuming - // Tell about the size we have, and the app will tell us - // if it's ok to resume or not. - _resume = canResume( buff_part.st_size ); - - kdDebug(7101) << "FileProtocol::put got answer " << _resume << endl; - } - } - - if ( bOrigExists && !_overwrite && !_resume) - { - if (S_ISDIR(buff_orig.st_mode)) - error( TDEIO::ERR_DIR_ALREADY_EXIST, dest_orig ); - else - error( TDEIO::ERR_FILE_ALREADY_EXIST, dest_orig ); - return; - } - - int result; - TQString dest; - TQCString _dest; - - int fd = -1; - - // Loop until we got 0 (end of data) - do - { - TQByteArray buffer; - dataReq(); // Request for data - result = readData( buffer ); - - if (result >= 0) - { - if (dest.isEmpty()) - { - if (bMarkPartial) - { - kdDebug(7101) << "Appending .part extension to " << dest_orig << endl; - dest = dest_part; - if ( bPartExists && !_resume ) - { - kdDebug(7101) << "Deleting partial file " << dest_part << endl; - remove( _dest_part.data() ); - // Catch errors when we try to open the file. - } - } - else - { - dest = dest_orig; - if ( bOrigExists && !_resume ) - { - kdDebug(7101) << "Deleting destination file " << dest_orig << endl; - remove( _dest_orig.data() ); - // Catch errors when we try to open the file. - } - } - - _dest = TQFile::encodeName(dest); - - if ( _resume ) - { - fd = KDE_open( _dest.data(), O_RDWR ); // append if resuming - KDE_lseek(fd, 0, SEEK_END); // Seek to end - } - else - { - // WABA: Make sure that we keep writing permissions ourselves, - // otherwise we can be in for a surprise on NFS. - mode_t initialMode; - if (_mode != -1) - initialMode = _mode | S_IWUSR | S_IRUSR; - else - initialMode = 0666; - - fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); - } - - if ( fd < 0 ) - { - kdDebug(7101) << "####################### COULD NOT WRITE " << dest << " _mode=" << _mode << endl; - kdDebug(7101) << "errno==" << errno << "(" << strerror(errno) << ")" << endl; - if ( errno == EACCES ) - error( TDEIO::ERR_WRITE_ACCESS_DENIED, dest ); - else - error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, dest ); - return; - } - } - - if (write_all( fd, buffer.data(), buffer.size())) - { - if ( errno == ENOSPC ) // disk full - { - error( TDEIO::ERR_DISK_FULL, dest_orig); - result = -2; // means: remove dest file - } - else - { - kdWarning(7101) << "Couldn't write. Error:" << strerror(errno) << endl; - error( TDEIO::ERR_COULD_NOT_WRITE, dest_orig); - result = -1; - } - } - } - } - while ( result > 0 ); - - // An error occurred deal with it. - if (result < 0) - { - kdDebug(7101) << "Error during 'put'. Aborting." << endl; - - if (fd != -1) - { - close(fd); - - KDE_struct_stat buff; - if (bMarkPartial && KDE_stat( _dest.data(), &buff ) == 0) - { - int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); - if (buff.st_size < size) - remove(_dest.data()); - } - } - - ::exit(255); - } - - if ( fd == -1 ) // we got nothing to write out, so we never opened the file - { - finished(); - return; - } - - if ( close(fd) ) - { - kdWarning(7101) << "Error when closing file descriptor:" << strerror(errno) << endl; - error( TDEIO::ERR_COULD_NOT_WRITE, dest_orig); - return; - } - - // after full download rename the file back to original name - if ( bMarkPartial ) - { - // If the original URL is a symlink and we were asked to overwrite it, - // remove the symlink first. This ensures that we do not overwrite the - // current source if the symlink points to it. - if( _overwrite && S_ISLNK( buff_orig.st_mode ) ) - remove( _dest_orig.data() ); - - if ( ::rename( _dest.data(), _dest_orig.data() ) ) - { - kdWarning(7101) << " Couldn't rename " << _dest << " to " << _dest_orig << endl; - error( TDEIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig ); - return; - } - } - - // set final permissions - if ( _mode != -1 && !_resume ) - { - if (::chmod(_dest_orig.data(), _mode) != 0) - { - // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. - if ( TDEIO::testFileSystemFlag( _dest_orig, TDEIO::SupportsChmod ) ) - warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) ); - } - } - - // set modification time - const TQString mtimeStr = metaData( "modified" ); - if ( !mtimeStr.isEmpty() ) { - TQDateTime dt = TQT_TQDATETIME_OBJECT(TQDateTime::fromString( mtimeStr, Qt::ISODate )); - if ( dt.isValid() ) { - KDE_struct_stat dest_statbuf; - if (KDE_stat( _dest_orig.data(), &dest_statbuf ) == 0) { - struct utimbuf utbuf; - utbuf.actime = dest_statbuf.st_atime; // access time, unchanged - utbuf.modtime = dt.toTime_t(); // modification time - kdDebug() << k_funcinfo << "setting modtime to " << utbuf.modtime << endl; - utime( _dest_orig.data(), &utbuf ); - } - } - - } - - // We have done our job => finish - finished(); -} - - -void FileProtocol::copy( const KURL &src, const KURL &dest, - int _mode, bool _overwrite ) -{ - kdDebug(7101) << "copy(): " << src << " -> " << dest << ", mode=" << _mode << endl; - - TQCString _src( TQFile::encodeName(src.path())); - TQCString _dest( TQFile::encodeName(dest.path())); - KDE_struct_stat buff_src; -#ifdef USE_POSIX_ACL - acl_t acl; -#endif - - if ( KDE_stat( _src.data(), &buff_src ) == -1 ) { - if ( errno == EACCES ) - error( TDEIO::ERR_ACCESS_DENIED, src.path() ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, src.path() ); - return; - } - - if ( S_ISDIR( buff_src.st_mode ) ) { - error( TDEIO::ERR_IS_DIRECTORY, src.path() ); - return; - } - if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) { - error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, src.path() ); - return; - } - - KDE_struct_stat buff_dest; - bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 ); - if ( dest_exists ) - { - if (S_ISDIR(buff_dest.st_mode)) - { - error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); - return; - } - - if ( same_inode( buff_dest, buff_src) ) - { - error( TDEIO::ERR_IDENTICAL_FILES, dest.path() ); - return; - } - - if (!_overwrite) - { - error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); - return; - } - - // If the destination is a symlink and overwrite is TRUE, - // remove the symlink first to prevent the scenario where - // the symlink actually points to current source! - if (_overwrite && S_ISLNK(buff_dest.st_mode)) - { - kdDebug(7101) << "copy(): LINK DESTINATION" << endl; - remove( _dest.data() ); - } - } - - int src_fd = KDE_open( _src.data(), O_RDONLY); - if ( src_fd < 0 ) { - error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, src.path() ); - return; - } - -#ifdef HAVE_FADVISE - posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL); -#endif - // WABA: Make sure that we keep writing permissions ourselves, - // otherwise we can be in for a surprise on NFS. - mode_t initialMode; - if (_mode != -1) - initialMode = _mode | S_IWUSR; - else - initialMode = 0666; - - int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); - if ( dest_fd < 0 ) { - kdDebug(7101) << "###### COULD NOT WRITE " << dest.url() << endl; - if ( errno == EACCES ) { - error( TDEIO::ERR_WRITE_ACCESS_DENIED, dest.path() ); - } else { - error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.path() ); - } - close(src_fd); - return; - } - -#ifdef HAVE_FADVISE - posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL); -#endif - -#ifdef USE_POSIX_ACL - acl = acl_get_fd(src_fd); - if ( acl && !isExtendedACL( acl ) ) { - kdDebug(7101) << _dest.data() << " doesn't have extended ACL" << endl; - acl_free( acl ); - acl = NULL; - } -#endif - totalSize( buff_src.st_size ); - - TDEIO::filesize_t processed_size = 0; - char buffer[ MAX_IPC_SIZE ]; - int n; -#ifdef USE_SENDFILE - bool use_sendfile=buff_src.st_size < 0x7FFFFFFF; -#endif - while( 1 ) - { -#ifdef USE_SENDFILE - if (use_sendfile) { - off_t sf = processed_size; - n = ::sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE ); - processed_size = sf; - if ( n == -1 && errno == EINVAL ) { //not all filesystems support sendfile() - kdDebug(7101) << "sendfile() not supported, falling back " << endl; - use_sendfile = false; - } - } - if (!use_sendfile) -#endif - n = ::read( src_fd, buffer, MAX_IPC_SIZE ); - - if (n == -1) - { - if (errno == EINTR) - continue; -#ifdef USE_SENDFILE - if ( use_sendfile ) { - kdDebug(7101) << "sendfile() error:" << strerror(errno) << endl; - if ( errno == ENOSPC ) // disk full - { - error( TDEIO::ERR_DISK_FULL, dest.path()); - remove( _dest.data() ); - } - else { - error( TDEIO::ERR_SLAVE_DEFINED, - i18n("Cannot copy file from %1 to %2. (Errno: %3)") - .arg( src.path() ).arg( dest.path() ).arg( errno ) ); - } - } else -#endif - error( TDEIO::ERR_COULD_NOT_READ, src.path()); - close(src_fd); - close(dest_fd); -#ifdef USE_POSIX_ACL - if (acl) acl_free(acl); -#endif - return; - } - if (n == 0) - break; // Finished -#ifdef USE_SENDFILE - if ( !use_sendfile ) { -#endif - if (write_all( dest_fd, buffer, n)) - { - close(src_fd); - close(dest_fd); - - if ( errno == ENOSPC ) // disk full - { - error( TDEIO::ERR_DISK_FULL, dest.path()); - remove( _dest.data() ); - } - else - { - kdWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno) << endl; - error( TDEIO::ERR_COULD_NOT_WRITE, dest.path()); - } -#ifdef USE_POSIX_ACL - if (acl) acl_free(acl); -#endif - return; - } - processed_size += n; -#ifdef USE_SENDFILE - } -#endif - processedSize( processed_size ); - } - - close( src_fd ); - - if (close( dest_fd)) - { - kdWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno) << endl; - error( TDEIO::ERR_COULD_NOT_WRITE, dest.path()); -#ifdef USE_POSIX_ACL - if (acl) acl_free(acl); -#endif - return; - } - - // set final permissions - if ( _mode != -1 ) - { - if ( (::chmod(_dest.data(), _mode) != 0) -#ifdef USE_POSIX_ACL - || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0) -#endif - ) - { - // Eat the error if the filesystem apparently doesn't support chmod. - if ( TDEIO::testFileSystemFlag( _dest, TDEIO::SupportsChmod ) ) - warning( i18n( "Could not change permissions for\n%1" ).arg( dest.path() ) ); - } - } -#ifdef USE_POSIX_ACL - if (acl) acl_free(acl); -#endif - - // copy access and modification time - struct utimbuf ut; - ut.actime = buff_src.st_atime; - ut.modtime = buff_src.st_mtime; - if ( ::utime( _dest.data(), &ut ) != 0 ) - { - kdWarning() << TQString(TQString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg( dest.path() )) << endl; - } - - processedSize( buff_src.st_size ); - finished(); -} - -void FileProtocol::rename( const KURL &src, const KURL &dest, - bool _overwrite ) -{ - TQCString _src( TQFile::encodeName(src.path())); - TQCString _dest( TQFile::encodeName(dest.path())); - KDE_struct_stat buff_src; - if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) { - if ( errno == EACCES ) - error( TDEIO::ERR_ACCESS_DENIED, src.path() ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, src.path() ); - return; - } - - KDE_struct_stat buff_dest; - bool dest_exists = ( KDE_stat( _dest.data(), &buff_dest ) != -1 ); - if ( dest_exists ) - { - if (S_ISDIR(buff_dest.st_mode)) - { - error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); - return; - } - - if ( same_inode( buff_dest, buff_src) ) - { - error( TDEIO::ERR_IDENTICAL_FILES, dest.path() ); - return; - } - - if (!_overwrite) - { - error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); - return; - } - } - - if ( ::rename( _src.data(), _dest.data())) - { - if (( errno == EACCES ) || (errno == EPERM)) { - error( TDEIO::ERR_ACCESS_DENIED, dest.path() ); - } - else if (errno == EXDEV) { - error( TDEIO::ERR_UNSUPPORTED_ACTION, TQString::fromLatin1("rename")); - } - else if (errno == EROFS) { // The file is on a read-only filesystem - error( TDEIO::ERR_CANNOT_DELETE, src.path() ); - } - else { - error( TDEIO::ERR_CANNOT_RENAME, src.path() ); - } - return; - } - - finished(); -} - -void FileProtocol::symlink( const TQString &target, const KURL &dest, bool overwrite ) -{ - // Assume dest is local too (wouldn't be here otherwise) - if ( ::symlink( TQFile::encodeName( target ), TQFile::encodeName( dest.path() ) ) == -1 ) - { - // Does the destination already exist ? - if ( errno == EEXIST ) - { - if ( overwrite ) - { - // Try to delete the destination - if ( unlink( TQFile::encodeName( dest.path() ) ) != 0 ) - { - error( TDEIO::ERR_CANNOT_DELETE, dest.path() ); - return; - } - // Try again - this won't loop forever since unlink succeeded - symlink( target, dest, overwrite ); - } - else - { - KDE_struct_stat buff_dest; - KDE_lstat( TQFile::encodeName( dest.path() ), &buff_dest ); - if (S_ISDIR(buff_dest.st_mode)) - error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); - else - error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); - return; - } - } - else - { - // Some error occurred while we tried to symlink - error( TDEIO::ERR_CANNOT_SYMLINK, dest.path() ); - return; - } - } - finished(); -} - -void FileProtocol::del( const KURL& url, bool isfile) -{ - TQCString _path( TQFile::encodeName(url.path())); - /***** - * Delete files - *****/ - - if (isfile) { - kdDebug( 7101 ) << "Deleting file "<< url.url() << endl; - - // TODO deletingFile( source ); - - if ( unlink( _path.data() ) == -1 ) { - if ((errno == EACCES) || (errno == EPERM)) - error( TDEIO::ERR_ACCESS_DENIED, url.path()); - else if (errno == EISDIR) - error( TDEIO::ERR_IS_DIRECTORY, url.path()); - else - error( TDEIO::ERR_CANNOT_DELETE, url.path() ); - return; - } - } else { - - /***** - * Delete empty directory - *****/ - - kdDebug( 7101 ) << "Deleting directory " << url.url() << endl; - - if ( ::rmdir( _path.data() ) == -1 ) { - if ((errno == EACCES) || (errno == EPERM)) - error( TDEIO::ERR_ACCESS_DENIED, url.path()); - else { - kdDebug( 7101 ) << "could not rmdir " << perror << endl; - error( TDEIO::ERR_COULD_NOT_RMDIR, url.path() ); - return; - } - } - } - - finished(); -} - - -TQString FileProtocol::getUserName( uid_t uid ) -{ - TQString *temp; - temp = usercache.find( uid ); - if ( !temp ) { - struct passwd *user = getpwuid( uid ); - if ( user ) { - usercache.insert( uid, new TQString(TQString::fromLatin1(user->pw_name)) ); - return TQString::fromLatin1( user->pw_name ); - } - else - return TQString::number( uid ); - } - else - return *temp; -} - -TQString FileProtocol::getGroupName( gid_t gid ) -{ - TQString *temp; - temp = groupcache.find( gid ); - if ( !temp ) { - struct group *grp = getgrgid( gid ); - if ( grp ) { - groupcache.insert( gid, new TQString(TQString::fromLatin1(grp->gr_name)) ); - return TQString::fromLatin1( grp->gr_name ); - } - else - return TQString::number( gid ); - } - else - return *temp; -} - - - -bool FileProtocol::createUDSEntry( const TQString & filename, const TQCString & path, UDSEntry & entry, - short int details, bool withACL ) -{ - assert(entry.count() == 0); // by contract :-) - // Note: details = 0 (only "file or directory or symlink or doesn't exist") isn't implemented - // because there's no real performance penalty in tdeio_file for returning the complete - // details. Please consider doing it in your tdeioslave if you're using this one as a model :) - UDSAtom atom; - atom.m_uds = TDEIO::UDS_NAME; - atom.m_str = filename; - entry.append( atom ); - - mode_t type; - mode_t access; - KDE_struct_stat buff; - - if ( KDE_lstat( path.data(), &buff ) == 0 ) { - - if (S_ISLNK(buff.st_mode)) { - - char buffer2[ 1000 ]; - int n = readlink( path.data(), buffer2, 1000 ); - if ( n != -1 ) { - buffer2[ n ] = 0; - } - - atom.m_uds = TDEIO::UDS_LINK_DEST; - atom.m_str = TQFile::decodeName( buffer2 ); - entry.append( atom ); - - // A symlink -> follow it only if details>1 - if ( details > 1 && KDE_stat( path.data(), &buff ) == -1 ) { - // It is a link pointing to nowhere - type = S_IFMT - 1; - access = S_IRWXU | S_IRWXG | S_IRWXO; - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = type; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = access; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = 0L; - entry.append( atom ); - - goto notype; - - } - } - } else { - // kdWarning() << "lstat didn't work on " << path.data() << endl; - return false; - } - - type = buff.st_mode & S_IFMT; // extract file type - access = buff.st_mode & 07777; // extract permissions - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = type; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = access; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = buff.st_size; - entry.append( atom ); - -#ifdef USE_POSIX_ACL - /* Append an atom indicating whether the file has extended acl information - * and if withACL is specified also one with the acl itself. If it's a directory - * and it has a default ACL, also append that. */ - appendACLAtoms( path, entry, type, withACL ); -#endif - - notype: - atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; - atom.m_long = buff.st_mtime; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - atom.m_str = getUserName( buff.st_uid ); - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_GROUP; - atom.m_str = getGroupName( buff.st_gid ); - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS_TIME; - atom.m_long = buff.st_atime; - entry.append( atom ); - - // Note: buff.st_ctime isn't the creation time ! - // We made that mistake for KDE 2.0, but it's in fact the - // "file status" change time, which we don't care about. - - return true; -} - -void FileProtocol::stat( const KURL & url ) -{ - if (!url.isLocalFile()) { - KURL redir(url); - redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); - redirection(redir); - kdDebug(7101) << "redirecting to " << redir.url() << endl; - finished(); - return; - } - - /* directories may not have a slash at the end if - * we want to stat() them; it requires that we - * change into it .. which may not be allowed - * stat("/is/unaccessible") -> rwx------ - * stat("/is/unaccessible/") -> EPERM H.Z. - * This is the reason for the -1 - */ - TQCString _path( TQFile::encodeName(url.path(-1))); - - TQString sDetails = metaData(TQString::fromLatin1("details")); - int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); - kdDebug(7101) << "FileProtocol::stat details=" << details << endl; - - UDSEntry entry; - if ( !createUDSEntry( url.fileName(), _path, entry, details, true /*with acls*/ ) ) - { - error( TDEIO::ERR_DOES_NOT_EXIST, url.path(-1) ); - return; - } -#if 0 -///////// debug code - TDEIO::UDSEntry::ConstIterator it = entry.begin(); - for( ; it != entry.end(); it++ ) { - switch ((*it).m_uds) { - case TDEIO::UDS_FILE_TYPE: - kdDebug(7101) << "File Type : " << (mode_t)((*it).m_long) << endl; - break; - case TDEIO::UDS_ACCESS: - kdDebug(7101) << "Access permissions : " << (mode_t)((*it).m_long) << endl; - break; - case TDEIO::UDS_USER: - kdDebug(7101) << "User : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_GROUP: - kdDebug(7101) << "Group : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_NAME: - kdDebug(7101) << "Name : " << ((*it).m_str.ascii() ) << endl; - //m_strText = decodeFileName( (*it).m_str ); - break; - case TDEIO::UDS_URL: - kdDebug(7101) << "URL : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_MIME_TYPE: - kdDebug(7101) << "MimeType : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_LINK_DEST: - kdDebug(7101) << "LinkDest : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_EXTENDED_ACL: - kdDebug(7101) << "Contains extended ACL " << endl; - break; - } - } - MetaData::iterator it1 = mOutgoingMetaData.begin(); - for ( ; it1 != mOutgoingMetaData.end(); it1++ ) { - kdDebug(7101) << it1.key() << " = " << it1.data() << endl; - } -///////// -#endif - statEntry( entry ); - - finished(); -} - -void FileProtocol::listDir( const KURL& url) -{ - kdDebug(7101) << "========= LIST " << url.url() << " =========" << endl; - if (!url.isLocalFile()) { - KURL redir(url); - redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); - redirection(redir); - kdDebug(7101) << "redirecting to " << redir.url() << endl; - finished(); - return; - } - - TQCString _path( TQFile::encodeName(url.path())); - - KDE_struct_stat buff; - if ( KDE_stat( _path.data(), &buff ) == -1 ) { - error( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); - return; - } - - if ( !S_ISDIR( buff.st_mode ) ) { - error( TDEIO::ERR_IS_FILE, url.path() ); - return; - } - - DIR *dp = 0L; - KDE_struct_dirent *ep; - - dp = opendir( _path.data() ); - if ( dp == 0 ) { - switch (errno) - { -#ifdef ENOMEDIUM - case ENOMEDIUM: - error( ERR_SLAVE_DEFINED, - i18n( "No media in device for %1" ).arg( url.path() ) ); - break; -#endif - default: - error( TDEIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() ); - break; - } - return; - } - - // Don't make this a TQStringList. The locale file name we get here - // should be passed intact to createUDSEntry to avoid problems with - // files where TQFile::encodeName(TQFile::decodeName(a)) != a. - TQStrList entryNames; - - while ( ( ep = KDE_readdir( dp ) ) != 0L ) { - entryNames.append( ep->d_name ); - } - - closedir( dp ); - totalSize( entryNames.count() ); - - /* set the current dir to the path to speed up - in not having to pass an absolute path. - We restore the path later to get out of the - path - the kernel wouldn't unmount or delete - directories we keep as active directory. And - as the slave runs in the background, it's hard - to see for the user what the problem would be */ -#if !defined(PATH_MAX) && defined(__GLIBC__) - char *path_buffer; - path_buffer = getcwd(NULL, 0); -#else - char path_buffer[PATH_MAX]; - (void) getcwd(path_buffer, PATH_MAX - 1); -#endif - if ( chdir( _path.data() ) ) { - if (errno == EACCES) - error(ERR_ACCESS_DENIED, _path); - else - error(ERR_CANNOT_ENTER_DIRECTORY, _path); - finished(); - } - - UDSEntry entry; - TQStrListIterator it(entryNames); - for (; it.current(); ++it) { - entry.clear(); - if ( createUDSEntry( TQFile::decodeName(*it), - *it /* we can use the filename as relative path*/, - entry, 2, true ) ) - listEntry( entry, false); - //else - // ;//Well, this should never happen... but with wrong encoding names - } - - listEntry( entry, true ); // ready - - kdDebug(7101) << "============= COMPLETED LIST ============" << endl; - - chdir(path_buffer); -#if !defined(PATH_MAX) && defined(__GLIBC__) - free(path_buffer); -#endif - - finished(); -} - -/* -void FileProtocol::testDir( const TQString& path ) -{ - TQCString _path( TQFile::encodeName(path)); - KDE_struct_stat buff; - if ( KDE_stat( _path.data(), &buff ) == -1 ) { - error( TDEIO::ERR_DOES_NOT_EXIST, path ); - return; - } - - if ( S_ISDIR( buff.st_mode ) ) - isDirectory(); - else - isFile(); - - finished(); -} -*/ - -void FileProtocol::special( const TQByteArray &data) -{ - int tmp; - TQDataStream stream(data, IO_ReadOnly); - - stream >> tmp; - switch (tmp) { - case 1: - { - TQString fstype, dev, point; - TQ_INT8 iRo; - - stream >> iRo >> fstype >> dev >> point; - - bool ro = ( iRo != 0 ); - - kdDebug(7101) << "MOUNTING fstype=" << fstype << " dev=" << dev << " point=" << point << " ro=" << ro << endl; - bool ok = pmount( dev ); - if (ok) - finished(); - else - mount( ro, fstype.ascii(), dev, point ); - - } - break; - case 2: - { - TQString point; - stream >> point; - bool ok = pumount( point ); - if (ok) - finished(); - else - unmount( point ); - } - break; - - case 3: - { - TQString filename; - stream >> filename; - KShred shred( filename ); - connect( &shred, TQT_SIGNAL( processedSize( TDEIO::filesize_t ) ), - this, TQT_SLOT( slotProcessedSize( TDEIO::filesize_t ) ) ); - connect( &shred, TQT_SIGNAL( infoMessage( const TQString & ) ), - this, TQT_SLOT( slotInfoMessage( const TQString & ) ) ); - if (!shred.shred()) - error( TDEIO::ERR_CANNOT_DELETE, filename ); - else - finished(); - break; - } - default: - break; - } -} - -// Connected to KShred -void FileProtocol::slotProcessedSize( TDEIO::filesize_t bytes ) -{ - kdDebug(7101) << "FileProtocol::slotProcessedSize (" << (unsigned int) bytes << ")" << endl; - processedSize( bytes ); -} - -// Connected to KShred -void FileProtocol::slotInfoMessage( const TQString & msg ) -{ - kdDebug(7101) << "FileProtocol::slotInfoMessage (" << msg << ")" << endl; - infoMessage( msg ); -} - -void FileProtocol::mount( bool _ro, const char *_fstype, const TQString& _dev, const TQString& _point ) -{ - kdDebug(7101) << "FileProtocol::mount _fstype=" << _fstype << endl; - TQCString buffer; - -#ifdef HAVE_VOLMGT - /* - * support for Solaris volume management - */ - TQString err; - TQCString devname = TQFile::encodeName( _dev ); - - if( volmgt_running() ) { -// kdDebug(7101) << "VOLMGT: vold ok." << endl; - if( volmgt_check( devname.data() ) == 0 ) { - kdDebug(7101) << "VOLMGT: no media in " - << devname.data() << endl; - err = i18n("No Media inserted or Media not recognized."); - error( TDEIO::ERR_COULD_NOT_MOUNT, err ); - return; - } else { - kdDebug(7101) << "VOLMGT: " << devname.data() - << ": media ok" << endl; - finished(); - return; - } - } else { - err = i18n("\"vold\" is not running."); - kdDebug(7101) << "VOLMGT: " << err << endl; - error( TDEIO::ERR_COULD_NOT_MOUNT, err ); - return; - } -#else - - - KTempFile tmpFile; - TQCString tmpFileC = TQFile::encodeName(tmpFile.name()); - const char *tmp = tmpFileC.data(); - TQCString dev; - if ( _dev.startsWith( "LABEL=" ) ) { // turn LABEL=foo into -L foo (#71430) - TQString labelName = _dev.mid( 6 ); - dev = "-L "; - dev += TQFile::encodeName( TDEProcess::quote( labelName ) ); // is it correct to assume same encoding as filesystem? - } else if ( _dev.startsWith( "UUID=" ) ) { // and UUID=bar into -U bar - TQString uuidName = _dev.mid( 5 ); - dev = "-U "; - dev += TQFile::encodeName( TDEProcess::quote( uuidName ) ); - } - else - dev = TQFile::encodeName( TDEProcess::quote(_dev) ); // get those ready to be given to a shell - - TQCString point = TQFile::encodeName( TDEProcess::quote(_point) ); - bool fstype_empty = !_fstype || !*_fstype; - TQCString fstype = TDEProcess::quote(_fstype).latin1(); // good guess - TQCString readonly = _ro ? "-r" : ""; - TQString epath = TQString::fromLatin1(getenv("PATH")); - TQString path = TQString::fromLatin1("/sbin:/bin"); - if(!epath.isEmpty()) - path += TQString::fromLatin1(":") + epath; - TQString mountProg = TDEGlobal::dirs()->findExe("mount", path); - if (mountProg.isEmpty()){ - error( TDEIO::ERR_COULD_NOT_MOUNT, i18n("Could not find program \"mount\"")); - return; - } - - // Two steps, in case mount doesn't like it when we pass all options - for ( int step = 0 ; step <= 1 ; step++ ) - { - // Mount using device only if no fstype nor mountpoint (KDE-1.x like) - if ( !_dev.isEmpty() && _point.isEmpty() && fstype_empty ) - buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), dev.data(), tmp ); - else - // Mount using the mountpoint, if no fstype nor device (impossible in first step) - if ( !_point.isEmpty() && _dev.isEmpty() && fstype_empty ) - buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), point.data(), tmp ); - else - // mount giving device + mountpoint but no fstype - if ( !_point.isEmpty() && !_dev.isEmpty() && fstype_empty ) - buffer.sprintf( "%s %s %s %s 2>%s", mountProg.latin1(), readonly.data(), dev.data(), point.data(), tmp ); - else - // mount giving device + mountpoint + fstype -#if defined(__svr4__) && defined(__sun__) // MARCO for Solaris 8 and I - // believe this is true for SVR4 in general - buffer.sprintf( "%s -F %s %s %s %s 2>%s" - mountProg.latin1() - fstype.data() - _ro ? "-oro" : "" - dev.data() - point.data() - tmp ); -#elif defined(__OpenBSD__) - buffer.sprintf( "%s %s %s -t %s %s %s 2>%s", "tdesu", mountProg.latin1(), readonly.data(), - fstype.data(), dev.data(), point.data(), tmp ); -#else - buffer.sprintf( "%s %s -t %s %s %s 2>%s", mountProg.latin1(), readonly.data(), - fstype.data(), dev.data(), point.data(), tmp ); -#endif - - kdDebug(7101) << buffer << endl; - - int mount_ret = system( buffer.data() ); - - TQString err = testLogFile( tmp ); - if ( err.isEmpty() && mount_ret == 0) - { - finished(); - return; - } - else - { - // Didn't work - or maybe we just got a warning - TQString mp = TDEIO::findDeviceMountPoint( _dev ); - // Is the device mounted ? - if ( !mp.isEmpty() && mount_ret == 0) - { - kdDebug(7101) << "mount got a warning: " << err << endl; - warning( err ); - finished(); - return; - } - else - { - if ( (step == 0) && !_point.isEmpty()) - { - kdDebug(7101) << err << endl; - kdDebug(7101) << "Mounting with those options didn't work, trying with only mountpoint" << endl; - fstype = ""; - fstype_empty = true; - dev = ""; - // The reason for trying with only mountpoint (instead of - // only device) is that some people (hi Malte!) have the - // same device associated with two mountpoints - // for different fstypes, like /dev/fd0 /mnt/e2floppy and - // /dev/fd0 /mnt/dosfloppy. - // If the user has the same mountpoint associated with two - // different devices, well they shouldn't specify the - // mountpoint but just the device. - } - else - { - error( TDEIO::ERR_COULD_NOT_MOUNT, err ); - return; - } - } - } - } -#endif /* ! HAVE_VOLMGT */ -} - - -void FileProtocol::unmount( const TQString& _point ) -{ - TQCString buffer; - - KTempFile tmpFile; - TQCString tmpFileC = TQFile::encodeName(tmpFile.name()); - TQString err; - const char *tmp = tmpFileC.data(); - -#ifdef HAVE_VOLMGT - /* - * support for Solaris volume management - */ - char *devname; - char *ptr; - FILE *mnttab; - struct mnttab mnt; - - if( volmgt_running() ) { - kdDebug(7101) << "VOLMGT: looking for " - << _point.local8Bit() << endl; - - if( (mnttab = KDE_fopen( MNTTAB, "r" )) == NULL ) { - err = "couldn't open mnttab"; - kdDebug(7101) << "VOLMGT: " << err << endl; - error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); - return; - } - - /* - * since there's no way to derive the device name from - * the mount point through the volmgt library (and - * media_findname() won't work in this case), we have to - * look ourselves... - */ - devname = NULL; - rewind( mnttab ); - while( getmntent( mnttab, &mnt ) == 0 ) { - if( strcmp( _point.local8Bit(), mnt.mnt_mountp ) == 0 ){ - devname = mnt.mnt_special; - break; - } - } - fclose( mnttab ); - - if( devname == NULL ) { - err = "not in mnttab"; - kdDebug(7101) << "VOLMGT: " - << TQFile::encodeName(_point).data() - << ": " << err << endl; - error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); - return; - } - - /* - * strip off the directory name (volume name) - * the eject(1) command will handle unmounting and - * physically eject the media (if possible) - */ - ptr = strrchr( devname, '/' ); - *ptr = '\0'; - TQCString qdevname(TQFile::encodeName(TDEProcess::quote(TQFile::decodeName(TQCString(devname)))).data()); - buffer.sprintf( "/usr/bin/eject %s 2>%s", qdevname.data(), tmp ); - kdDebug(7101) << "VOLMGT: eject " << qdevname << endl; - - /* - * from eject(1): exit status == 0 => need to manually eject - * exit status == 4 => media was ejected - */ -// if( WEXITSTATUS( system( buffer.local8Bit() )) == 4 ) { - if( WEXITSTATUS( system( buffer.data() )) == 4 ) { // Fix for TQString -> QCString? - /* - * this is not an error, so skip "testLogFile()" - * to avoid wrong/confusing error popup - */ - unlink( tmp ); - finished(); - return; - } - } else { - /* - * eject(1) should do its job without vold(1M) running, - * so we probably could call eject anyway, but since the - * media is mounted now, vold must've died for some reason - * during the user's session, so it should be restarted... - */ - err = i18n("\"vold\" is not running."); - kdDebug(7101) << "VOLMGT: " << err << endl; - error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); - return; - } -#else - TQString epath = getenv("PATH"); - TQString path = TQString::fromLatin1("/sbin:/bin"); - if (!epath.isEmpty()) - path += ":" + epath; - TQString umountProg = TDEGlobal::dirs()->findExe("umount", path); - - if (umountProg.isEmpty()) { - error( TDEIO::ERR_COULD_NOT_UNMOUNT, i18n("Could not find program \"umount\"")); - return; - } -#ifdef __OpenBSD__ - buffer.sprintf( "%s %s %s 2>%s", "tdesu", umountProg.latin1(), TQFile::encodeName(TDEProcess::quote(_point)).data(), tmp ); -#else - buffer.sprintf( "%s %s 2>%s", umountProg.latin1(), TQFile::encodeName(TDEProcess::quote(_point)).data(), tmp ); -#endif - system( buffer.data() ); -#endif /* HAVE_VOLMGT */ - - err = testLogFile( tmp ); - - if (err.contains("fstab") || err.contains("root")) { - TQString olderr; - err = TQString::null; - - DCOPRef d("kded", "mediamanager"); - d.setDCOPClient ( dcopClient() ); - DCOPReply reply = d.call("properties", _point); - TQString udi; - - if ( reply.isValid() ) { - TQStringList list = reply; - if (list.size()) - udi = list[0]; - } - - if (!udi.isEmpty()) - reply = d.call("unmount", udi); - - if (udi.isEmpty() || !reply.isValid()) - err = olderr; - else if (reply.isValid()) { - TQStringVariantMap unmountResult; - reply.get(unmountResult); - if (!unmountResult.contains("result") || !unmountResult["result"].toBool()) { - err = unmountResult.contains("errStr") ? unmountResult["errStr"].toString() : i18n("Unknown unmount error."); - } - } - } - - if ( err.isEmpty() ) - finished(); - else - error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); -} - -/************************************* - * - * pmount handling - * - *************************************/ - -bool FileProtocol::pmount(const TQString &dev) -{ - TQString mountProg = TQString::null; - TQCString buffer; - -#ifdef WITH_UDISKS2 - // Use 'udisksctl' (UDISKS2) if available - mountProg = TDEGlobal::dirs()->findExe("udisksctl"); - if (!mountProg.isEmpty()) { - buffer.sprintf( "%s mount -b %s", TQFile::encodeName(mountProg).data(), - TQFile::encodeName(TDEProcess::quote(dev)).data() ); - } -#endif - -#ifdef WITH_UDISKS - // Use 'udisks' (UDISKS1) if available - if (mountProg.isEmpty()) { - mountProg = TDEGlobal::dirs()->findExe("udisks"); - if (!mountProg.isEmpty()) { - buffer.sprintf( "%s --mount %s", TQFile::encodeName(mountProg).data(), - TQFile::encodeName(TDEProcess::quote(dev)).data() ); - } - } -#endif - - // Use 'pmount', if available - if (mountProg.isEmpty()) { - mountProg = TDEGlobal::dirs()->findExe("pmount"); - if (!mountProg.isEmpty()) { - buffer.sprintf( "%s %s", TQFile::encodeName(mountProg).data(), - TQFile::encodeName(TDEProcess::quote(dev)).data() ); - } - } - - if (mountProg.isEmpty()) { - return false; - } - - int res = system( buffer.data() ); - - return res==0; -} - -bool FileProtocol::pumount(const TQString &point) -{ - TQString real_point = TDEStandardDirs::realPath(point); - - KMountPoint::List mtab = KMountPoint::currentMountPoints(); - - KMountPoint::List::const_iterator it = mtab.begin(); - KMountPoint::List::const_iterator end = mtab.end(); - - TQString dev; - - for (; it!=end; ++it) - { - TQString tmp = (*it)->mountedFrom(); - TQString mp = (*it)->mountPoint(); - mp = TDEStandardDirs::realPath(mp); - - if (mp==real_point) - dev = TDEStandardDirs::realPath(tmp); - } - - if (dev.isEmpty()) return false; - if (dev.endsWith("/")) dev.truncate(dev.length()-1); - - TQString umountProg = TQString::null; - TQCString buffer; - -#ifdef WITH_UDISKS2 - // Use 'udisksctl' (UDISKS2), if available - umountProg = TDEGlobal::dirs()->findExe("udisksctl"); - if (!umountProg.isEmpty()) { - buffer.sprintf( "%s unmount -b %s", TQFile::encodeName(umountProg).data(), - TQFile::encodeName(TDEProcess::quote(dev)).data() ); - } -#endif - -#ifdef WITH_UDISKS - // Use 'udisks' (UDISKS1), if available - if (umountProg.isEmpty()) { - umountProg = TDEGlobal::dirs()->findExe("udisks"); - if (!umountProg.isEmpty()) { - buffer.sprintf( "%s --unmount %s", TQFile::encodeName(umountProg).data(), - TQFile::encodeName(TDEProcess::quote(dev)).data() ); - } - } -#endif - - // Use 'pumount', if available - if (umountProg.isEmpty()) { - umountProg = TDEGlobal::dirs()->findExe("pumount"); - if (!umountProg.isEmpty()) { - buffer.sprintf( "%s %s", TQFile::encodeName(umountProg).data(), - TQFile::encodeName(TDEProcess::quote(dev)).data() ); - } - } - - if (umountProg.isEmpty()) { - return false; - } - - int res = system( buffer.data() ); - - return res==0; -} - -/************************************* - * - * Utilities - * - *************************************/ - -static TQString testLogFile( const char *_filename ) -{ - char buffer[ 1024 ]; - KDE_struct_stat buff; - - TQString result; - - KDE_stat( _filename, &buff ); - int size = buff.st_size; - if ( size == 0 ) { - unlink( _filename ); - return result; - } - - FILE * f = KDE_fopen( _filename, "rb" ); - if ( f == 0L ) { - unlink( _filename ); - result = i18n("Could not read %1").arg(TQFile::decodeName(_filename)); - return result; - } - - result = ""; - const char *p = ""; - while ( p != 0L ) { - p = fgets( buffer, sizeof(buffer)-1, f ); - if ( p != 0L ) - result += TQString::fromLocal8Bit(buffer); - } - - fclose( f ); - - unlink( _filename ); - - return result; -} - -/************************************* - * - * ACL handling helpers - * - *************************************/ -#ifdef USE_POSIX_ACL - -static bool isExtendedACL( acl_t acl ) -{ - return ( acl_equiv_mode( acl, 0 ) != 0 ); -} - -static TQString aclAsString( acl_t acl ) -{ - char *aclString = acl_to_text( acl, 0 ); - TQString ret = TQString::fromLatin1( aclString ); - acl_free( (void*)aclString ); - return ret; -} - -static void appendACLAtoms( const TQCString & path, UDSEntry& entry, mode_t type, bool withACL ) -{ - // first check for a noop -#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS - if ( acl_extended_file( path.data() ) == 0 ) return; -#endif - - acl_t acl = 0; - acl_t defaultAcl = 0; - UDSAtom atom; - bool isDir = S_ISDIR( type ); - // do we have an acl for the file, and/or a default acl for the dir, if it is one? - if ( ( acl = acl_get_file( path.data(), ACL_TYPE_ACCESS ) ) ) { - if ( !isExtendedACL( acl ) ) { - acl_free( acl ); - acl = 0; - } - } - - /* Sadly libacl does not provided a means of checking for extended ACL and default - * ACL separately. Since a directory can have both, we need to check again. */ - if ( isDir ) - defaultAcl = acl_get_file( path.data(), ACL_TYPE_DEFAULT ); - - if ( acl || defaultAcl ) { - kdDebug(7101) << path.data() << " has extended ACL entries " << endl; - atom.m_uds = TDEIO::UDS_EXTENDED_ACL; - atom.m_long = 1; - entry.append( atom ); - } - if ( withACL ) { - if ( acl ) { - atom.m_uds = TDEIO::UDS_ACL_STRING; - atom.m_str = aclAsString( acl ); - entry.append( atom ); - kdDebug(7101) << path.data() << "ACL: " << atom.m_str << endl; - } - if ( defaultAcl ) { - atom.m_uds = TDEIO::UDS_DEFAULT_ACL_STRING; - atom.m_str = aclAsString( defaultAcl ); - entry.append( atom ); - kdDebug(7101) << path.data() << "DEFAULT ACL: " << atom.m_str << endl; - } - } - if ( acl ) acl_free( acl ); - if ( defaultAcl ) acl_free( defaultAcl ); -} -#endif - -#include "file.moc" diff --git a/tdeioslave/file/file.cpp b/tdeioslave/file/file.cpp new file mode 100644 index 000000000..fda72f2d5 --- /dev/null +++ b/tdeioslave/file/file.cpp @@ -0,0 +1,1890 @@ +/* + Copyright (C) 2000-2002 Stephan Kulow + Copyright (C) 2000-2002 David Faure + Copyright (C) 2000-2002 Waldo Bastian + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// $Id$ + +#include + +#include //for Q_OS_XXX +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +//sendfile has different semantics in different platforms +#if defined HAVE_SENDFILE && defined Q_OS_LINUX +#define USE_SENDFILE 1 +#endif + +#ifdef USE_SENDFILE +#include +#endif + +#ifdef USE_POSIX_ACL +#include +#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS +#include +#else +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STRING_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "file.h" +#include +#include +#include +#include + +#ifdef HAVE_VOLMGT +#include +#include +#endif + +#include +#include +#include +#include +#include + +using namespace TDEIO; + +#define MAX_IPC_SIZE (1024*32) + +static TQString testLogFile( const char *_filename ); +#ifdef USE_POSIX_ACL +static TQString aclAsString( acl_t p_acl ); +static bool isExtendedACL( acl_t p_acl ); +static void appendACLAtoms( const TQCString & path, UDSEntry& entry, + mode_t type, bool withACL ); +#endif + +extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } + +int kdemain( int argc, char **argv ) +{ + TDELocale::setMainCatalogue("tdelibs"); + TDEInstance instance( "tdeio_file" ); + ( void ) TDEGlobal::locale(); + + kdDebug(7101) << "Starting " << getpid() << endl; + + if (argc != 4) + { + fprintf(stderr, "Usage: tdeio_file protocol domain-socket1 domain-socket2\n"); + exit(-1); + } + + FileProtocol slave(argv[2], argv[3]); + slave.dispatchLoop(); + + kdDebug(7101) << "Done" << endl; + return 0; +} + + +FileProtocol::FileProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "file", pool, app ) +{ + usercache.setAutoDelete( true ); + groupcache.setAutoDelete( true ); +} + + +int FileProtocol::setACL( const char *path, mode_t perm, bool directoryDefault ) +{ + int ret = 0; +#ifdef USE_POSIX_ACL + + const TQString ACLString = metaData( "ACL_STRING" ); + const TQString defaultACLString = metaData( "DEFAULT_ACL_STRING" ); + // Empty strings mean leave as is + if ( !ACLString.isEmpty() ) { + acl_t acl = 0; + if ( ACLString == "ACL_DELETE" ) { + // user told us to delete the extended ACL, so let's write only + // the minimal (UNIX permission bits) part + acl = acl_from_mode( perm ); + } + acl = acl_from_text( ACLString.latin1() ); + if ( acl_valid( acl ) == 0 ) { // let's be safe + ret = acl_set_file( path, ACL_TYPE_ACCESS, acl ); + kdDebug(7101) << "Set ACL on: " << path << " to: " << aclAsString( acl ) << endl; + } + acl_free( acl ); + if ( ret != 0 ) return ret; // better stop trying right away + } + + if ( directoryDefault && !defaultACLString.isEmpty() ) { + if ( defaultACLString == "ACL_DELETE" ) { + // user told us to delete the default ACL, do so + ret += acl_delete_def_file( path ); + } else { + acl_t acl = acl_from_text( defaultACLString.latin1() ); + if ( acl_valid( acl ) == 0 ) { // let's be safe + ret += acl_set_file( path, ACL_TYPE_DEFAULT, acl ); + kdDebug(7101) << "Set Default ACL on: " << path << " to: " << aclAsString( acl ) << endl; + } + acl_free( acl ); + } + } +#endif + return ret; +} + +void FileProtocol::chmod( const KURL& url, int permissions ) +{ + TQCString _path( TQFile::encodeName(url.path()) ); + /* FIXME: Should be atomic */ + if ( ::chmod( _path.data(), permissions ) == -1 || + ( setACL( _path.data(), permissions, false ) == -1 ) || + /* if not a directory, cannot set default ACLs */ + ( setACL( _path.data(), permissions, true ) == -1 && errno != ENOTDIR ) ) { + + switch (errno) { + case EPERM: + case EACCES: + error( TDEIO::ERR_ACCESS_DENIED, url.path() ); + break; + case ENOTSUP: + error( TDEIO::ERR_UNSUPPORTED_ACTION, url.path() ); + break; + case ENOSPC: + error( TDEIO::ERR_DISK_FULL, url.path() ); + break; + default: + error( TDEIO::ERR_CANNOT_CHMOD, url.path() ); + } + } else + finished(); +} + +void FileProtocol::mkdir( const KURL& url, int permissions ) +{ + TQCString _path( TQFile::encodeName(url.path())); + + kdDebug(7101) << "mkdir(): " << _path << ", permission = " << permissions << endl; + + KDE_struct_stat buff; + if ( KDE_stat( _path.data(), &buff ) == -1 ) { + if ( ::mkdir( _path.data(), 0777 /*umask will be applied*/ ) != 0 ) { + if ( errno == EACCES ) { + error( TDEIO::ERR_ACCESS_DENIED, url.path() ); + return; + } else if ( errno == ENOSPC ) { + error( TDEIO::ERR_DISK_FULL, url.path() ); + return; + } else { + error( TDEIO::ERR_COULD_NOT_MKDIR, url.path() ); + return; + } + } else { + if ( permissions != -1 ) + chmod( url, permissions ); + else + finished(); + return; + } + } + + if ( S_ISDIR( buff.st_mode ) ) { + kdDebug(7101) << "ERR_DIR_ALREADY_EXIST" << endl; + error( TDEIO::ERR_DIR_ALREADY_EXIST, url.path() ); + return; + } + error( TDEIO::ERR_FILE_ALREADY_EXIST, url.path() ); + return; +} + +void FileProtocol::get( const KURL& url ) +{ + if (!url.isLocalFile()) { + KURL redir(url); + redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); + redirection(redir); + finished(); + return; + } + + TQCString _path( TQFile::encodeName(url.path())); + KDE_struct_stat buff; + if ( KDE_stat( _path.data(), &buff ) == -1 ) { + if ( errno == EACCES ) + error( TDEIO::ERR_ACCESS_DENIED, url.path() ); + else + error( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); + return; + } + + if ( S_ISDIR( buff.st_mode ) ) { + error( TDEIO::ERR_IS_DIRECTORY, url.path() ); + return; + } + if ( !S_ISREG( buff.st_mode ) ) { + error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); + return; + } + + int fd = KDE_open( _path.data(), O_RDONLY); + if ( fd < 0 ) { + error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); + return; + } + +#ifdef HAVE_FADVISE + posix_fadvise( fd, 0, 0, POSIX_FADV_SEQUENTIAL); +#endif + + // Determine the mimetype of the file to be retrieved, and emit it. + // This is mandatory in all slaves (for KRun/BrowserRun to work). + KMimeType::Ptr mt = KMimeType::findByURL( url, buff.st_mode, true /* local URL */ ); + emit mimeType( mt->name() ); + + TDEIO::filesize_t processed_size = 0; + + TQString resumeOffset = metaData("resume"); + if ( !resumeOffset.isEmpty() ) + { + bool ok; + TDEIO::fileoffset_t offset = resumeOffset.toLongLong(&ok); + if (ok && (offset > 0) && (offset < buff.st_size)) + { + if (KDE_lseek(fd, offset, SEEK_SET) == offset) + { + canResume (); + processed_size = offset; + kdDebug( 7101 ) << "Resume offset: " << TDEIO::number(offset) << endl; + } + } + } + + totalSize( buff.st_size ); + + char buffer[ MAX_IPC_SIZE ]; + TQByteArray array; + + while( 1 ) + { + int n = ::read( fd, buffer, MAX_IPC_SIZE ); + if (n == -1) + { + if (errno == EINTR) + continue; + error( TDEIO::ERR_COULD_NOT_READ, url.path()); + close(fd); + return; + } + if (n == 0) + break; // Finished + + array.setRawData(buffer, n); + data( array ); + array.resetRawData(buffer, n); + + processed_size += n; + processedSize( processed_size ); + + //kdDebug( 7101 ) << "Processed: " << TDEIO::number (processed_size) << endl; + } + + data( TQByteArray() ); + + close( fd ); + + processedSize( buff.st_size ); + finished(); +} + +static int +write_all(int fd, const char *buf, size_t len) +{ + while (len > 0) + { + ssize_t written = write(fd, buf, len); + if (written < 0) + { + if (errno == EINTR) + continue; + return -1; + } + buf += written; + len -= written; + } + return 0; +} + +static bool +same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest) +{ + if (src.st_ino == dest.st_ino && + src.st_dev == dest.st_dev) + return true; + + return false; +} + +void FileProtocol::put( const KURL& url, int _mode, bool _overwrite, bool _resume ) +{ + TQString dest_orig = url.path(); + TQCString _dest_orig( TQFile::encodeName(dest_orig)); + + kdDebug(7101) << "put(): " << dest_orig << ", mode=" << _mode << endl; + + TQString dest_part( dest_orig ); + dest_part += TQString::fromLatin1(".part"); + TQCString _dest_part( TQFile::encodeName(dest_part)); + + KDE_struct_stat buff_orig; + bool bOrigExists = (KDE_lstat( _dest_orig.data(), &buff_orig ) != -1); + bool bPartExists = false; + bool bMarkPartial = config()->readBoolEntry("MarkPartial", true); + + if (bMarkPartial) + { + KDE_struct_stat buff_part; + bPartExists = (KDE_stat( _dest_part.data(), &buff_part ) != -1); + + if (bPartExists && !_resume && !_overwrite && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode)) + { + kdDebug(7101) << "FileProtocol::put : calling canResume with " + << TDEIO::number(buff_part.st_size) << endl; + + // Maybe we can use this partial file for resuming + // Tell about the size we have, and the app will tell us + // if it's ok to resume or not. + _resume = canResume( buff_part.st_size ); + + kdDebug(7101) << "FileProtocol::put got answer " << _resume << endl; + } + } + + if ( bOrigExists && !_overwrite && !_resume) + { + if (S_ISDIR(buff_orig.st_mode)) + error( TDEIO::ERR_DIR_ALREADY_EXIST, dest_orig ); + else + error( TDEIO::ERR_FILE_ALREADY_EXIST, dest_orig ); + return; + } + + int result; + TQString dest; + TQCString _dest; + + int fd = -1; + + // Loop until we got 0 (end of data) + do + { + TQByteArray buffer; + dataReq(); // Request for data + result = readData( buffer ); + + if (result >= 0) + { + if (dest.isEmpty()) + { + if (bMarkPartial) + { + kdDebug(7101) << "Appending .part extension to " << dest_orig << endl; + dest = dest_part; + if ( bPartExists && !_resume ) + { + kdDebug(7101) << "Deleting partial file " << dest_part << endl; + remove( _dest_part.data() ); + // Catch errors when we try to open the file. + } + } + else + { + dest = dest_orig; + if ( bOrigExists && !_resume ) + { + kdDebug(7101) << "Deleting destination file " << dest_orig << endl; + remove( _dest_orig.data() ); + // Catch errors when we try to open the file. + } + } + + _dest = TQFile::encodeName(dest); + + if ( _resume ) + { + fd = KDE_open( _dest.data(), O_RDWR ); // append if resuming + KDE_lseek(fd, 0, SEEK_END); // Seek to end + } + else + { + // WABA: Make sure that we keep writing permissions ourselves, + // otherwise we can be in for a surprise on NFS. + mode_t initialMode; + if (_mode != -1) + initialMode = _mode | S_IWUSR | S_IRUSR; + else + initialMode = 0666; + + fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); + } + + if ( fd < 0 ) + { + kdDebug(7101) << "####################### COULD NOT WRITE " << dest << " _mode=" << _mode << endl; + kdDebug(7101) << "errno==" << errno << "(" << strerror(errno) << ")" << endl; + if ( errno == EACCES ) + error( TDEIO::ERR_WRITE_ACCESS_DENIED, dest ); + else + error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, dest ); + return; + } + } + + if (write_all( fd, buffer.data(), buffer.size())) + { + if ( errno == ENOSPC ) // disk full + { + error( TDEIO::ERR_DISK_FULL, dest_orig); + result = -2; // means: remove dest file + } + else + { + kdWarning(7101) << "Couldn't write. Error:" << strerror(errno) << endl; + error( TDEIO::ERR_COULD_NOT_WRITE, dest_orig); + result = -1; + } + } + } + } + while ( result > 0 ); + + // An error occurred deal with it. + if (result < 0) + { + kdDebug(7101) << "Error during 'put'. Aborting." << endl; + + if (fd != -1) + { + close(fd); + + KDE_struct_stat buff; + if (bMarkPartial && KDE_stat( _dest.data(), &buff ) == 0) + { + int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); + if (buff.st_size < size) + remove(_dest.data()); + } + } + + ::exit(255); + } + + if ( fd == -1 ) // we got nothing to write out, so we never opened the file + { + finished(); + return; + } + + if ( close(fd) ) + { + kdWarning(7101) << "Error when closing file descriptor:" << strerror(errno) << endl; + error( TDEIO::ERR_COULD_NOT_WRITE, dest_orig); + return; + } + + // after full download rename the file back to original name + if ( bMarkPartial ) + { + // If the original URL is a symlink and we were asked to overwrite it, + // remove the symlink first. This ensures that we do not overwrite the + // current source if the symlink points to it. + if( _overwrite && S_ISLNK( buff_orig.st_mode ) ) + remove( _dest_orig.data() ); + + if ( ::rename( _dest.data(), _dest_orig.data() ) ) + { + kdWarning(7101) << " Couldn't rename " << _dest << " to " << _dest_orig << endl; + error( TDEIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig ); + return; + } + } + + // set final permissions + if ( _mode != -1 && !_resume ) + { + if (::chmod(_dest_orig.data(), _mode) != 0) + { + // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. + if ( TDEIO::testFileSystemFlag( _dest_orig, TDEIO::SupportsChmod ) ) + warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) ); + } + } + + // set modification time + const TQString mtimeStr = metaData( "modified" ); + if ( !mtimeStr.isEmpty() ) { + TQDateTime dt = TQT_TQDATETIME_OBJECT(TQDateTime::fromString( mtimeStr, Qt::ISODate )); + if ( dt.isValid() ) { + KDE_struct_stat dest_statbuf; + if (KDE_stat( _dest_orig.data(), &dest_statbuf ) == 0) { + struct utimbuf utbuf; + utbuf.actime = dest_statbuf.st_atime; // access time, unchanged + utbuf.modtime = dt.toTime_t(); // modification time + kdDebug() << k_funcinfo << "setting modtime to " << utbuf.modtime << endl; + utime( _dest_orig.data(), &utbuf ); + } + } + + } + + // We have done our job => finish + finished(); +} + + +void FileProtocol::copy( const KURL &src, const KURL &dest, + int _mode, bool _overwrite ) +{ + kdDebug(7101) << "copy(): " << src << " -> " << dest << ", mode=" << _mode << endl; + + TQCString _src( TQFile::encodeName(src.path())); + TQCString _dest( TQFile::encodeName(dest.path())); + KDE_struct_stat buff_src; +#ifdef USE_POSIX_ACL + acl_t acl; +#endif + + if ( KDE_stat( _src.data(), &buff_src ) == -1 ) { + if ( errno == EACCES ) + error( TDEIO::ERR_ACCESS_DENIED, src.path() ); + else + error( TDEIO::ERR_DOES_NOT_EXIST, src.path() ); + return; + } + + if ( S_ISDIR( buff_src.st_mode ) ) { + error( TDEIO::ERR_IS_DIRECTORY, src.path() ); + return; + } + if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) { + error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, src.path() ); + return; + } + + KDE_struct_stat buff_dest; + bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 ); + if ( dest_exists ) + { + if (S_ISDIR(buff_dest.st_mode)) + { + error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); + return; + } + + if ( same_inode( buff_dest, buff_src) ) + { + error( TDEIO::ERR_IDENTICAL_FILES, dest.path() ); + return; + } + + if (!_overwrite) + { + error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); + return; + } + + // If the destination is a symlink and overwrite is TRUE, + // remove the symlink first to prevent the scenario where + // the symlink actually points to current source! + if (_overwrite && S_ISLNK(buff_dest.st_mode)) + { + kdDebug(7101) << "copy(): LINK DESTINATION" << endl; + remove( _dest.data() ); + } + } + + int src_fd = KDE_open( _src.data(), O_RDONLY); + if ( src_fd < 0 ) { + error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, src.path() ); + return; + } + +#ifdef HAVE_FADVISE + posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL); +#endif + // WABA: Make sure that we keep writing permissions ourselves, + // otherwise we can be in for a surprise on NFS. + mode_t initialMode; + if (_mode != -1) + initialMode = _mode | S_IWUSR; + else + initialMode = 0666; + + int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); + if ( dest_fd < 0 ) { + kdDebug(7101) << "###### COULD NOT WRITE " << dest.url() << endl; + if ( errno == EACCES ) { + error( TDEIO::ERR_WRITE_ACCESS_DENIED, dest.path() ); + } else { + error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.path() ); + } + close(src_fd); + return; + } + +#ifdef HAVE_FADVISE + posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL); +#endif + +#ifdef USE_POSIX_ACL + acl = acl_get_fd(src_fd); + if ( acl && !isExtendedACL( acl ) ) { + kdDebug(7101) << _dest.data() << " doesn't have extended ACL" << endl; + acl_free( acl ); + acl = NULL; + } +#endif + totalSize( buff_src.st_size ); + + TDEIO::filesize_t processed_size = 0; + char buffer[ MAX_IPC_SIZE ]; + int n; +#ifdef USE_SENDFILE + bool use_sendfile=buff_src.st_size < 0x7FFFFFFF; +#endif + while( 1 ) + { +#ifdef USE_SENDFILE + if (use_sendfile) { + off_t sf = processed_size; + n = ::sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE ); + processed_size = sf; + if ( n == -1 && errno == EINVAL ) { //not all filesystems support sendfile() + kdDebug(7101) << "sendfile() not supported, falling back " << endl; + use_sendfile = false; + } + } + if (!use_sendfile) +#endif + n = ::read( src_fd, buffer, MAX_IPC_SIZE ); + + if (n == -1) + { + if (errno == EINTR) + continue; +#ifdef USE_SENDFILE + if ( use_sendfile ) { + kdDebug(7101) << "sendfile() error:" << strerror(errno) << endl; + if ( errno == ENOSPC ) // disk full + { + error( TDEIO::ERR_DISK_FULL, dest.path()); + remove( _dest.data() ); + } + else { + error( TDEIO::ERR_SLAVE_DEFINED, + i18n("Cannot copy file from %1 to %2. (Errno: %3)") + .arg( src.path() ).arg( dest.path() ).arg( errno ) ); + } + } else +#endif + error( TDEIO::ERR_COULD_NOT_READ, src.path()); + close(src_fd); + close(dest_fd); +#ifdef USE_POSIX_ACL + if (acl) acl_free(acl); +#endif + return; + } + if (n == 0) + break; // Finished +#ifdef USE_SENDFILE + if ( !use_sendfile ) { +#endif + if (write_all( dest_fd, buffer, n)) + { + close(src_fd); + close(dest_fd); + + if ( errno == ENOSPC ) // disk full + { + error( TDEIO::ERR_DISK_FULL, dest.path()); + remove( _dest.data() ); + } + else + { + kdWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno) << endl; + error( TDEIO::ERR_COULD_NOT_WRITE, dest.path()); + } +#ifdef USE_POSIX_ACL + if (acl) acl_free(acl); +#endif + return; + } + processed_size += n; +#ifdef USE_SENDFILE + } +#endif + processedSize( processed_size ); + } + + close( src_fd ); + + if (close( dest_fd)) + { + kdWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno) << endl; + error( TDEIO::ERR_COULD_NOT_WRITE, dest.path()); +#ifdef USE_POSIX_ACL + if (acl) acl_free(acl); +#endif + return; + } + + // set final permissions + if ( _mode != -1 ) + { + if ( (::chmod(_dest.data(), _mode) != 0) +#ifdef USE_POSIX_ACL + || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0) +#endif + ) + { + // Eat the error if the filesystem apparently doesn't support chmod. + if ( TDEIO::testFileSystemFlag( _dest, TDEIO::SupportsChmod ) ) + warning( i18n( "Could not change permissions for\n%1" ).arg( dest.path() ) ); + } + } +#ifdef USE_POSIX_ACL + if (acl) acl_free(acl); +#endif + + // copy access and modification time + struct utimbuf ut; + ut.actime = buff_src.st_atime; + ut.modtime = buff_src.st_mtime; + if ( ::utime( _dest.data(), &ut ) != 0 ) + { + kdWarning() << TQString(TQString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg( dest.path() )) << endl; + } + + processedSize( buff_src.st_size ); + finished(); +} + +void FileProtocol::rename( const KURL &src, const KURL &dest, + bool _overwrite ) +{ + TQCString _src( TQFile::encodeName(src.path())); + TQCString _dest( TQFile::encodeName(dest.path())); + KDE_struct_stat buff_src; + if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) { + if ( errno == EACCES ) + error( TDEIO::ERR_ACCESS_DENIED, src.path() ); + else + error( TDEIO::ERR_DOES_NOT_EXIST, src.path() ); + return; + } + + KDE_struct_stat buff_dest; + bool dest_exists = ( KDE_stat( _dest.data(), &buff_dest ) != -1 ); + if ( dest_exists ) + { + if (S_ISDIR(buff_dest.st_mode)) + { + error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); + return; + } + + if ( same_inode( buff_dest, buff_src) ) + { + error( TDEIO::ERR_IDENTICAL_FILES, dest.path() ); + return; + } + + if (!_overwrite) + { + error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); + return; + } + } + + if ( ::rename( _src.data(), _dest.data())) + { + if (( errno == EACCES ) || (errno == EPERM)) { + error( TDEIO::ERR_ACCESS_DENIED, dest.path() ); + } + else if (errno == EXDEV) { + error( TDEIO::ERR_UNSUPPORTED_ACTION, TQString::fromLatin1("rename")); + } + else if (errno == EROFS) { // The file is on a read-only filesystem + error( TDEIO::ERR_CANNOT_DELETE, src.path() ); + } + else { + error( TDEIO::ERR_CANNOT_RENAME, src.path() ); + } + return; + } + + finished(); +} + +void FileProtocol::symlink( const TQString &target, const KURL &dest, bool overwrite ) +{ + // Assume dest is local too (wouldn't be here otherwise) + if ( ::symlink( TQFile::encodeName( target ), TQFile::encodeName( dest.path() ) ) == -1 ) + { + // Does the destination already exist ? + if ( errno == EEXIST ) + { + if ( overwrite ) + { + // Try to delete the destination + if ( unlink( TQFile::encodeName( dest.path() ) ) != 0 ) + { + error( TDEIO::ERR_CANNOT_DELETE, dest.path() ); + return; + } + // Try again - this won't loop forever since unlink succeeded + symlink( target, dest, overwrite ); + } + else + { + KDE_struct_stat buff_dest; + KDE_lstat( TQFile::encodeName( dest.path() ), &buff_dest ); + if (S_ISDIR(buff_dest.st_mode)) + error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); + else + error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); + return; + } + } + else + { + // Some error occurred while we tried to symlink + error( TDEIO::ERR_CANNOT_SYMLINK, dest.path() ); + return; + } + } + finished(); +} + +void FileProtocol::del( const KURL& url, bool isfile) +{ + TQCString _path( TQFile::encodeName(url.path())); + /***** + * Delete files + *****/ + + if (isfile) { + kdDebug( 7101 ) << "Deleting file "<< url.url() << endl; + + // TODO deletingFile( source ); + + if ( unlink( _path.data() ) == -1 ) { + if ((errno == EACCES) || (errno == EPERM)) + error( TDEIO::ERR_ACCESS_DENIED, url.path()); + else if (errno == EISDIR) + error( TDEIO::ERR_IS_DIRECTORY, url.path()); + else + error( TDEIO::ERR_CANNOT_DELETE, url.path() ); + return; + } + } else { + + /***** + * Delete empty directory + *****/ + + kdDebug( 7101 ) << "Deleting directory " << url.url() << endl; + + if ( ::rmdir( _path.data() ) == -1 ) { + if ((errno == EACCES) || (errno == EPERM)) + error( TDEIO::ERR_ACCESS_DENIED, url.path()); + else { + kdDebug( 7101 ) << "could not rmdir " << perror << endl; + error( TDEIO::ERR_COULD_NOT_RMDIR, url.path() ); + return; + } + } + } + + finished(); +} + + +TQString FileProtocol::getUserName( uid_t uid ) +{ + TQString *temp; + temp = usercache.find( uid ); + if ( !temp ) { + struct passwd *user = getpwuid( uid ); + if ( user ) { + usercache.insert( uid, new TQString(TQString::fromLatin1(user->pw_name)) ); + return TQString::fromLatin1( user->pw_name ); + } + else + return TQString::number( uid ); + } + else + return *temp; +} + +TQString FileProtocol::getGroupName( gid_t gid ) +{ + TQString *temp; + temp = groupcache.find( gid ); + if ( !temp ) { + struct group *grp = getgrgid( gid ); + if ( grp ) { + groupcache.insert( gid, new TQString(TQString::fromLatin1(grp->gr_name)) ); + return TQString::fromLatin1( grp->gr_name ); + } + else + return TQString::number( gid ); + } + else + return *temp; +} + + + +bool FileProtocol::createUDSEntry( const TQString & filename, const TQCString & path, UDSEntry & entry, + short int details, bool withACL ) +{ + assert(entry.count() == 0); // by contract :-) + // Note: details = 0 (only "file or directory or symlink or doesn't exist") isn't implemented + // because there's no real performance penalty in tdeio_file for returning the complete + // details. Please consider doing it in your tdeioslave if you're using this one as a model :) + UDSAtom atom; + atom.m_uds = TDEIO::UDS_NAME; + atom.m_str = filename; + entry.append( atom ); + + mode_t type; + mode_t access; + KDE_struct_stat buff; + + if ( KDE_lstat( path.data(), &buff ) == 0 ) { + + if (S_ISLNK(buff.st_mode)) { + + char buffer2[ 1000 ]; + int n = readlink( path.data(), buffer2, 1000 ); + if ( n != -1 ) { + buffer2[ n ] = 0; + } + + atom.m_uds = TDEIO::UDS_LINK_DEST; + atom.m_str = TQFile::decodeName( buffer2 ); + entry.append( atom ); + + // A symlink -> follow it only if details>1 + if ( details > 1 && KDE_stat( path.data(), &buff ) == -1 ) { + // It is a link pointing to nowhere + type = S_IFMT - 1; + access = S_IRWXU | S_IRWXG | S_IRWXO; + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long = type; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = access; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_SIZE; + atom.m_long = 0L; + entry.append( atom ); + + goto notype; + + } + } + } else { + // kdWarning() << "lstat didn't work on " << path.data() << endl; + return false; + } + + type = buff.st_mode & S_IFMT; // extract file type + access = buff.st_mode & 07777; // extract permissions + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long = type; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = access; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_SIZE; + atom.m_long = buff.st_size; + entry.append( atom ); + +#ifdef USE_POSIX_ACL + /* Append an atom indicating whether the file has extended acl information + * and if withACL is specified also one with the acl itself. If it's a directory + * and it has a default ACL, also append that. */ + appendACLAtoms( path, entry, type, withACL ); +#endif + + notype: + atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; + atom.m_long = buff.st_mtime; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_USER; + atom.m_str = getUserName( buff.st_uid ); + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_GROUP; + atom.m_str = getGroupName( buff.st_gid ); + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS_TIME; + atom.m_long = buff.st_atime; + entry.append( atom ); + + // Note: buff.st_ctime isn't the creation time ! + // We made that mistake for KDE 2.0, but it's in fact the + // "file status" change time, which we don't care about. + + return true; +} + +void FileProtocol::stat( const KURL & url ) +{ + if (!url.isLocalFile()) { + KURL redir(url); + redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); + redirection(redir); + kdDebug(7101) << "redirecting to " << redir.url() << endl; + finished(); + return; + } + + /* directories may not have a slash at the end if + * we want to stat() them; it requires that we + * change into it .. which may not be allowed + * stat("/is/unaccessible") -> rwx------ + * stat("/is/unaccessible/") -> EPERM H.Z. + * This is the reason for the -1 + */ + TQCString _path( TQFile::encodeName(url.path(-1))); + + TQString sDetails = metaData(TQString::fromLatin1("details")); + int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); + kdDebug(7101) << "FileProtocol::stat details=" << details << endl; + + UDSEntry entry; + if ( !createUDSEntry( url.fileName(), _path, entry, details, true /*with acls*/ ) ) + { + error( TDEIO::ERR_DOES_NOT_EXIST, url.path(-1) ); + return; + } +#if 0 +///////// debug code + TDEIO::UDSEntry::ConstIterator it = entry.begin(); + for( ; it != entry.end(); it++ ) { + switch ((*it).m_uds) { + case TDEIO::UDS_FILE_TYPE: + kdDebug(7101) << "File Type : " << (mode_t)((*it).m_long) << endl; + break; + case TDEIO::UDS_ACCESS: + kdDebug(7101) << "Access permissions : " << (mode_t)((*it).m_long) << endl; + break; + case TDEIO::UDS_USER: + kdDebug(7101) << "User : " << ((*it).m_str.ascii() ) << endl; + break; + case TDEIO::UDS_GROUP: + kdDebug(7101) << "Group : " << ((*it).m_str.ascii() ) << endl; + break; + case TDEIO::UDS_NAME: + kdDebug(7101) << "Name : " << ((*it).m_str.ascii() ) << endl; + //m_strText = decodeFileName( (*it).m_str ); + break; + case TDEIO::UDS_URL: + kdDebug(7101) << "URL : " << ((*it).m_str.ascii() ) << endl; + break; + case TDEIO::UDS_MIME_TYPE: + kdDebug(7101) << "MimeType : " << ((*it).m_str.ascii() ) << endl; + break; + case TDEIO::UDS_LINK_DEST: + kdDebug(7101) << "LinkDest : " << ((*it).m_str.ascii() ) << endl; + break; + case TDEIO::UDS_EXTENDED_ACL: + kdDebug(7101) << "Contains extended ACL " << endl; + break; + } + } + MetaData::iterator it1 = mOutgoingMetaData.begin(); + for ( ; it1 != mOutgoingMetaData.end(); it1++ ) { + kdDebug(7101) << it1.key() << " = " << it1.data() << endl; + } +///////// +#endif + statEntry( entry ); + + finished(); +} + +void FileProtocol::listDir( const KURL& url) +{ + kdDebug(7101) << "========= LIST " << url.url() << " =========" << endl; + if (!url.isLocalFile()) { + KURL redir(url); + redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb")); + redirection(redir); + kdDebug(7101) << "redirecting to " << redir.url() << endl; + finished(); + return; + } + + TQCString _path( TQFile::encodeName(url.path())); + + KDE_struct_stat buff; + if ( KDE_stat( _path.data(), &buff ) == -1 ) { + error( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); + return; + } + + if ( !S_ISDIR( buff.st_mode ) ) { + error( TDEIO::ERR_IS_FILE, url.path() ); + return; + } + + DIR *dp = 0L; + KDE_struct_dirent *ep; + + dp = opendir( _path.data() ); + if ( dp == 0 ) { + switch (errno) + { +#ifdef ENOMEDIUM + case ENOMEDIUM: + error( ERR_SLAVE_DEFINED, + i18n( "No media in device for %1" ).arg( url.path() ) ); + break; +#endif + default: + error( TDEIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() ); + break; + } + return; + } + + // Don't make this a TQStringList. The locale file name we get here + // should be passed intact to createUDSEntry to avoid problems with + // files where TQFile::encodeName(TQFile::decodeName(a)) != a. + TQStrList entryNames; + + while ( ( ep = KDE_readdir( dp ) ) != 0L ) { + entryNames.append( ep->d_name ); + } + + closedir( dp ); + totalSize( entryNames.count() ); + + /* set the current dir to the path to speed up + in not having to pass an absolute path. + We restore the path later to get out of the + path - the kernel wouldn't unmount or delete + directories we keep as active directory. And + as the slave runs in the background, it's hard + to see for the user what the problem would be */ +#if !defined(PATH_MAX) && defined(__GLIBC__) + char *path_buffer; + path_buffer = getcwd(NULL, 0); +#else + char path_buffer[PATH_MAX]; + (void) getcwd(path_buffer, PATH_MAX - 1); +#endif + if ( chdir( _path.data() ) ) { + if (errno == EACCES) + error(ERR_ACCESS_DENIED, _path); + else + error(ERR_CANNOT_ENTER_DIRECTORY, _path); + finished(); + } + + UDSEntry entry; + TQStrListIterator it(entryNames); + for (; it.current(); ++it) { + entry.clear(); + if ( createUDSEntry( TQFile::decodeName(*it), + *it /* we can use the filename as relative path*/, + entry, 2, true ) ) + listEntry( entry, false); + //else + // ;//Well, this should never happen... but with wrong encoding names + } + + listEntry( entry, true ); // ready + + kdDebug(7101) << "============= COMPLETED LIST ============" << endl; + + chdir(path_buffer); +#if !defined(PATH_MAX) && defined(__GLIBC__) + free(path_buffer); +#endif + + finished(); +} + +/* +void FileProtocol::testDir( const TQString& path ) +{ + TQCString _path( TQFile::encodeName(path)); + KDE_struct_stat buff; + if ( KDE_stat( _path.data(), &buff ) == -1 ) { + error( TDEIO::ERR_DOES_NOT_EXIST, path ); + return; + } + + if ( S_ISDIR( buff.st_mode ) ) + isDirectory(); + else + isFile(); + + finished(); +} +*/ + +void FileProtocol::special( const TQByteArray &data) +{ + int tmp; + TQDataStream stream(data, IO_ReadOnly); + + stream >> tmp; + switch (tmp) { + case 1: + { + TQString fstype, dev, point; + TQ_INT8 iRo; + + stream >> iRo >> fstype >> dev >> point; + + bool ro = ( iRo != 0 ); + + kdDebug(7101) << "MOUNTING fstype=" << fstype << " dev=" << dev << " point=" << point << " ro=" << ro << endl; + bool ok = pmount( dev ); + if (ok) + finished(); + else + mount( ro, fstype.ascii(), dev, point ); + + } + break; + case 2: + { + TQString point; + stream >> point; + bool ok = pumount( point ); + if (ok) + finished(); + else + unmount( point ); + } + break; + + case 3: + { + TQString filename; + stream >> filename; + KShred shred( filename ); + connect( &shred, TQT_SIGNAL( processedSize( TDEIO::filesize_t ) ), + this, TQT_SLOT( slotProcessedSize( TDEIO::filesize_t ) ) ); + connect( &shred, TQT_SIGNAL( infoMessage( const TQString & ) ), + this, TQT_SLOT( slotInfoMessage( const TQString & ) ) ); + if (!shred.shred()) + error( TDEIO::ERR_CANNOT_DELETE, filename ); + else + finished(); + break; + } + default: + break; + } +} + +// Connected to KShred +void FileProtocol::slotProcessedSize( TDEIO::filesize_t bytes ) +{ + kdDebug(7101) << "FileProtocol::slotProcessedSize (" << (unsigned int) bytes << ")" << endl; + processedSize( bytes ); +} + +// Connected to KShred +void FileProtocol::slotInfoMessage( const TQString & msg ) +{ + kdDebug(7101) << "FileProtocol::slotInfoMessage (" << msg << ")" << endl; + infoMessage( msg ); +} + +void FileProtocol::mount( bool _ro, const char *_fstype, const TQString& _dev, const TQString& _point ) +{ + kdDebug(7101) << "FileProtocol::mount _fstype=" << _fstype << endl; + TQCString buffer; + +#ifdef HAVE_VOLMGT + /* + * support for Solaris volume management + */ + TQString err; + TQCString devname = TQFile::encodeName( _dev ); + + if( volmgt_running() ) { +// kdDebug(7101) << "VOLMGT: vold ok." << endl; + if( volmgt_check( devname.data() ) == 0 ) { + kdDebug(7101) << "VOLMGT: no media in " + << devname.data() << endl; + err = i18n("No Media inserted or Media not recognized."); + error( TDEIO::ERR_COULD_NOT_MOUNT, err ); + return; + } else { + kdDebug(7101) << "VOLMGT: " << devname.data() + << ": media ok" << endl; + finished(); + return; + } + } else { + err = i18n("\"vold\" is not running."); + kdDebug(7101) << "VOLMGT: " << err << endl; + error( TDEIO::ERR_COULD_NOT_MOUNT, err ); + return; + } +#else + + + KTempFile tmpFile; + TQCString tmpFileC = TQFile::encodeName(tmpFile.name()); + const char *tmp = tmpFileC.data(); + TQCString dev; + if ( _dev.startsWith( "LABEL=" ) ) { // turn LABEL=foo into -L foo (#71430) + TQString labelName = _dev.mid( 6 ); + dev = "-L "; + dev += TQFile::encodeName( TDEProcess::quote( labelName ) ); // is it correct to assume same encoding as filesystem? + } else if ( _dev.startsWith( "UUID=" ) ) { // and UUID=bar into -U bar + TQString uuidName = _dev.mid( 5 ); + dev = "-U "; + dev += TQFile::encodeName( TDEProcess::quote( uuidName ) ); + } + else + dev = TQFile::encodeName( TDEProcess::quote(_dev) ); // get those ready to be given to a shell + + TQCString point = TQFile::encodeName( TDEProcess::quote(_point) ); + bool fstype_empty = !_fstype || !*_fstype; + TQCString fstype = TDEProcess::quote(_fstype).latin1(); // good guess + TQCString readonly = _ro ? "-r" : ""; + TQString epath = TQString::fromLatin1(getenv("PATH")); + TQString path = TQString::fromLatin1("/sbin:/bin"); + if(!epath.isEmpty()) + path += TQString::fromLatin1(":") + epath; + TQString mountProg = TDEGlobal::dirs()->findExe("mount", path); + if (mountProg.isEmpty()){ + error( TDEIO::ERR_COULD_NOT_MOUNT, i18n("Could not find program \"mount\"")); + return; + } + + // Two steps, in case mount doesn't like it when we pass all options + for ( int step = 0 ; step <= 1 ; step++ ) + { + // Mount using device only if no fstype nor mountpoint (KDE-1.x like) + if ( !_dev.isEmpty() && _point.isEmpty() && fstype_empty ) + buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), dev.data(), tmp ); + else + // Mount using the mountpoint, if no fstype nor device (impossible in first step) + if ( !_point.isEmpty() && _dev.isEmpty() && fstype_empty ) + buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), point.data(), tmp ); + else + // mount giving device + mountpoint but no fstype + if ( !_point.isEmpty() && !_dev.isEmpty() && fstype_empty ) + buffer.sprintf( "%s %s %s %s 2>%s", mountProg.latin1(), readonly.data(), dev.data(), point.data(), tmp ); + else + // mount giving device + mountpoint + fstype +#if defined(__svr4__) && defined(__sun__) // MARCO for Solaris 8 and I + // believe this is true for SVR4 in general + buffer.sprintf( "%s -F %s %s %s %s 2>%s" + mountProg.latin1() + fstype.data() + _ro ? "-oro" : "" + dev.data() + point.data() + tmp ); +#elif defined(__OpenBSD__) + buffer.sprintf( "%s %s %s -t %s %s %s 2>%s", "tdesu", mountProg.latin1(), readonly.data(), + fstype.data(), dev.data(), point.data(), tmp ); +#else + buffer.sprintf( "%s %s -t %s %s %s 2>%s", mountProg.latin1(), readonly.data(), + fstype.data(), dev.data(), point.data(), tmp ); +#endif + + kdDebug(7101) << buffer << endl; + + int mount_ret = system( buffer.data() ); + + TQString err = testLogFile( tmp ); + if ( err.isEmpty() && mount_ret == 0) + { + finished(); + return; + } + else + { + // Didn't work - or maybe we just got a warning + TQString mp = TDEIO::findDeviceMountPoint( _dev ); + // Is the device mounted ? + if ( !mp.isEmpty() && mount_ret == 0) + { + kdDebug(7101) << "mount got a warning: " << err << endl; + warning( err ); + finished(); + return; + } + else + { + if ( (step == 0) && !_point.isEmpty()) + { + kdDebug(7101) << err << endl; + kdDebug(7101) << "Mounting with those options didn't work, trying with only mountpoint" << endl; + fstype = ""; + fstype_empty = true; + dev = ""; + // The reason for trying with only mountpoint (instead of + // only device) is that some people (hi Malte!) have the + // same device associated with two mountpoints + // for different fstypes, like /dev/fd0 /mnt/e2floppy and + // /dev/fd0 /mnt/dosfloppy. + // If the user has the same mountpoint associated with two + // different devices, well they shouldn't specify the + // mountpoint but just the device. + } + else + { + error( TDEIO::ERR_COULD_NOT_MOUNT, err ); + return; + } + } + } + } +#endif /* ! HAVE_VOLMGT */ +} + + +void FileProtocol::unmount( const TQString& _point ) +{ + TQCString buffer; + + KTempFile tmpFile; + TQCString tmpFileC = TQFile::encodeName(tmpFile.name()); + TQString err; + const char *tmp = tmpFileC.data(); + +#ifdef HAVE_VOLMGT + /* + * support for Solaris volume management + */ + char *devname; + char *ptr; + FILE *mnttab; + struct mnttab mnt; + + if( volmgt_running() ) { + kdDebug(7101) << "VOLMGT: looking for " + << _point.local8Bit() << endl; + + if( (mnttab = KDE_fopen( MNTTAB, "r" )) == NULL ) { + err = "couldn't open mnttab"; + kdDebug(7101) << "VOLMGT: " << err << endl; + error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); + return; + } + + /* + * since there's no way to derive the device name from + * the mount point through the volmgt library (and + * media_findname() won't work in this case), we have to + * look ourselves... + */ + devname = NULL; + rewind( mnttab ); + while( getmntent( mnttab, &mnt ) == 0 ) { + if( strcmp( _point.local8Bit(), mnt.mnt_mountp ) == 0 ){ + devname = mnt.mnt_special; + break; + } + } + fclose( mnttab ); + + if( devname == NULL ) { + err = "not in mnttab"; + kdDebug(7101) << "VOLMGT: " + << TQFile::encodeName(_point).data() + << ": " << err << endl; + error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); + return; + } + + /* + * strip off the directory name (volume name) + * the eject(1) command will handle unmounting and + * physically eject the media (if possible) + */ + ptr = strrchr( devname, '/' ); + *ptr = '\0'; + TQCString qdevname(TQFile::encodeName(TDEProcess::quote(TQFile::decodeName(TQCString(devname)))).data()); + buffer.sprintf( "/usr/bin/eject %s 2>%s", qdevname.data(), tmp ); + kdDebug(7101) << "VOLMGT: eject " << qdevname << endl; + + /* + * from eject(1): exit status == 0 => need to manually eject + * exit status == 4 => media was ejected + */ +// if( WEXITSTATUS( system( buffer.local8Bit() )) == 4 ) { + if( WEXITSTATUS( system( buffer.data() )) == 4 ) { // Fix for TQString -> QCString? + /* + * this is not an error, so skip "testLogFile()" + * to avoid wrong/confusing error popup + */ + unlink( tmp ); + finished(); + return; + } + } else { + /* + * eject(1) should do its job without vold(1M) running, + * so we probably could call eject anyway, but since the + * media is mounted now, vold must've died for some reason + * during the user's session, so it should be restarted... + */ + err = i18n("\"vold\" is not running."); + kdDebug(7101) << "VOLMGT: " << err << endl; + error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); + return; + } +#else + TQString epath = getenv("PATH"); + TQString path = TQString::fromLatin1("/sbin:/bin"); + if (!epath.isEmpty()) + path += ":" + epath; + TQString umountProg = TDEGlobal::dirs()->findExe("umount", path); + + if (umountProg.isEmpty()) { + error( TDEIO::ERR_COULD_NOT_UNMOUNT, i18n("Could not find program \"umount\"")); + return; + } +#ifdef __OpenBSD__ + buffer.sprintf( "%s %s %s 2>%s", "tdesu", umountProg.latin1(), TQFile::encodeName(TDEProcess::quote(_point)).data(), tmp ); +#else + buffer.sprintf( "%s %s 2>%s", umountProg.latin1(), TQFile::encodeName(TDEProcess::quote(_point)).data(), tmp ); +#endif + system( buffer.data() ); +#endif /* HAVE_VOLMGT */ + + err = testLogFile( tmp ); + + if (err.contains("fstab") || err.contains("root")) { + TQString olderr; + err = TQString::null; + + DCOPRef d("kded", "mediamanager"); + d.setDCOPClient ( dcopClient() ); + DCOPReply reply = d.call("properties", _point); + TQString udi; + + if ( reply.isValid() ) { + TQStringList list = reply; + if (list.size()) + udi = list[0]; + } + + if (!udi.isEmpty()) + reply = d.call("unmount", udi); + + if (udi.isEmpty() || !reply.isValid()) + err = olderr; + else if (reply.isValid()) { + TQStringVariantMap unmountResult; + reply.get(unmountResult); + if (!unmountResult.contains("result") || !unmountResult["result"].toBool()) { + err = unmountResult.contains("errStr") ? unmountResult["errStr"].toString() : i18n("Unknown unmount error."); + } + } + } + + if ( err.isEmpty() ) + finished(); + else + error( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); +} + +/************************************* + * + * pmount handling + * + *************************************/ + +bool FileProtocol::pmount(const TQString &dev) +{ + TQString mountProg = TQString::null; + TQCString buffer; + +#ifdef WITH_UDISKS2 + // Use 'udisksctl' (UDISKS2) if available + mountProg = TDEGlobal::dirs()->findExe("udisksctl"); + if (!mountProg.isEmpty()) { + buffer.sprintf( "%s mount -b %s", TQFile::encodeName(mountProg).data(), + TQFile::encodeName(TDEProcess::quote(dev)).data() ); + } +#endif + +#ifdef WITH_UDISKS + // Use 'udisks' (UDISKS1) if available + if (mountProg.isEmpty()) { + mountProg = TDEGlobal::dirs()->findExe("udisks"); + if (!mountProg.isEmpty()) { + buffer.sprintf( "%s --mount %s", TQFile::encodeName(mountProg).data(), + TQFile::encodeName(TDEProcess::quote(dev)).data() ); + } + } +#endif + + // Use 'pmount', if available + if (mountProg.isEmpty()) { + mountProg = TDEGlobal::dirs()->findExe("pmount"); + if (!mountProg.isEmpty()) { + buffer.sprintf( "%s %s", TQFile::encodeName(mountProg).data(), + TQFile::encodeName(TDEProcess::quote(dev)).data() ); + } + } + + if (mountProg.isEmpty()) { + return false; + } + + int res = system( buffer.data() ); + + return res==0; +} + +bool FileProtocol::pumount(const TQString &point) +{ + TQString real_point = TDEStandardDirs::realPath(point); + + KMountPoint::List mtab = KMountPoint::currentMountPoints(); + + KMountPoint::List::const_iterator it = mtab.begin(); + KMountPoint::List::const_iterator end = mtab.end(); + + TQString dev; + + for (; it!=end; ++it) + { + TQString tmp = (*it)->mountedFrom(); + TQString mp = (*it)->mountPoint(); + mp = TDEStandardDirs::realPath(mp); + + if (mp==real_point) + dev = TDEStandardDirs::realPath(tmp); + } + + if (dev.isEmpty()) return false; + if (dev.endsWith("/")) dev.truncate(dev.length()-1); + + TQString umountProg = TQString::null; + TQCString buffer; + +#ifdef WITH_UDISKS2 + // Use 'udisksctl' (UDISKS2), if available + umountProg = TDEGlobal::dirs()->findExe("udisksctl"); + if (!umountProg.isEmpty()) { + buffer.sprintf( "%s unmount -b %s", TQFile::encodeName(umountProg).data(), + TQFile::encodeName(TDEProcess::quote(dev)).data() ); + } +#endif + +#ifdef WITH_UDISKS + // Use 'udisks' (UDISKS1), if available + if (umountProg.isEmpty()) { + umountProg = TDEGlobal::dirs()->findExe("udisks"); + if (!umountProg.isEmpty()) { + buffer.sprintf( "%s --unmount %s", TQFile::encodeName(umountProg).data(), + TQFile::encodeName(TDEProcess::quote(dev)).data() ); + } + } +#endif + + // Use 'pumount', if available + if (umountProg.isEmpty()) { + umountProg = TDEGlobal::dirs()->findExe("pumount"); + if (!umountProg.isEmpty()) { + buffer.sprintf( "%s %s", TQFile::encodeName(umountProg).data(), + TQFile::encodeName(TDEProcess::quote(dev)).data() ); + } + } + + if (umountProg.isEmpty()) { + return false; + } + + int res = system( buffer.data() ); + + return res==0; +} + +/************************************* + * + * Utilities + * + *************************************/ + +static TQString testLogFile( const char *_filename ) +{ + char buffer[ 1024 ]; + KDE_struct_stat buff; + + TQString result; + + KDE_stat( _filename, &buff ); + int size = buff.st_size; + if ( size == 0 ) { + unlink( _filename ); + return result; + } + + FILE * f = KDE_fopen( _filename, "rb" ); + if ( f == 0L ) { + unlink( _filename ); + result = i18n("Could not read %1").arg(TQFile::decodeName(_filename)); + return result; + } + + result = ""; + const char *p = ""; + while ( p != 0L ) { + p = fgets( buffer, sizeof(buffer)-1, f ); + if ( p != 0L ) + result += TQString::fromLocal8Bit(buffer); + } + + fclose( f ); + + unlink( _filename ); + + return result; +} + +/************************************* + * + * ACL handling helpers + * + *************************************/ +#ifdef USE_POSIX_ACL + +static bool isExtendedACL( acl_t acl ) +{ + return ( acl_equiv_mode( acl, 0 ) != 0 ); +} + +static TQString aclAsString( acl_t acl ) +{ + char *aclString = acl_to_text( acl, 0 ); + TQString ret = TQString::fromLatin1( aclString ); + acl_free( (void*)aclString ); + return ret; +} + +static void appendACLAtoms( const TQCString & path, UDSEntry& entry, mode_t type, bool withACL ) +{ + // first check for a noop +#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS + if ( acl_extended_file( path.data() ) == 0 ) return; +#endif + + acl_t acl = 0; + acl_t defaultAcl = 0; + UDSAtom atom; + bool isDir = S_ISDIR( type ); + // do we have an acl for the file, and/or a default acl for the dir, if it is one? + if ( ( acl = acl_get_file( path.data(), ACL_TYPE_ACCESS ) ) ) { + if ( !isExtendedACL( acl ) ) { + acl_free( acl ); + acl = 0; + } + } + + /* Sadly libacl does not provided a means of checking for extended ACL and default + * ACL separately. Since a directory can have both, we need to check again. */ + if ( isDir ) + defaultAcl = acl_get_file( path.data(), ACL_TYPE_DEFAULT ); + + if ( acl || defaultAcl ) { + kdDebug(7101) << path.data() << " has extended ACL entries " << endl; + atom.m_uds = TDEIO::UDS_EXTENDED_ACL; + atom.m_long = 1; + entry.append( atom ); + } + if ( withACL ) { + if ( acl ) { + atom.m_uds = TDEIO::UDS_ACL_STRING; + atom.m_str = aclAsString( acl ); + entry.append( atom ); + kdDebug(7101) << path.data() << "ACL: " << atom.m_str << endl; + } + if ( defaultAcl ) { + atom.m_uds = TDEIO::UDS_DEFAULT_ACL_STRING; + atom.m_str = aclAsString( defaultAcl ); + entry.append( atom ); + kdDebug(7101) << path.data() << "DEFAULT ACL: " << atom.m_str << endl; + } + } + if ( acl ) acl_free( acl ); + if ( defaultAcl ) acl_free( defaultAcl ); +} +#endif + +#include "file.moc" diff --git a/tdeioslave/ftp/CMakeLists.txt b/tdeioslave/ftp/CMakeLists.txt index 7ef877e9d..797c5ae9c 100644 --- a/tdeioslave/ftp/CMakeLists.txt +++ b/tdeioslave/ftp/CMakeLists.txt @@ -38,7 +38,7 @@ tde_create_translated_desktop( set( target tdeio_ftp ) set( ${target}_SRCS - ftp.cc + ftp.cpp ) tde_add_kpart( ${target} AUTOMOC diff --git a/tdeioslave/ftp/Makefile.am b/tdeioslave/ftp/Makefile.am index fef6e168f..816659625 100644 --- a/tdeioslave/ftp/Makefile.am +++ b/tdeioslave/ftp/Makefile.am @@ -4,7 +4,7 @@ INCLUDES= $(all_includes) kde_module_LTLIBRARIES = tdeio_ftp.la -tdeio_ftp_la_SOURCES = ftp.cc +tdeio_ftp_la_SOURCES = ftp.cpp tdeio_ftp_la_LIBADD = $(LIB_TDEIO) $(LIB_TQT) $(LIB_TDECORE) tdeio_ftp_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) diff --git a/tdeioslave/ftp/ftp.cc b/tdeioslave/ftp/ftp.cc deleted file mode 100644 index 65f3eedc5..000000000 --- a/tdeioslave/ftp/ftp.cc +++ /dev/null @@ -1,2674 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2000 David Faure - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Recommended reading explaining FTP details and quirks: - http://cr.yp.to/ftp.html (by D.J. Bernstein) -*/ - - -#define TDEIO_FTP_PRIVATE_INCLUDE -#include "ftp.h" - -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_SYS_SELECT_H -#include -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if TIME_WITH_SYS_TIME -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_STRTOLL - #define charToLongLong(a) strtoll(a, 0, 10) -#else - #define charToLongLong(a) strtol(a, 0, 10) -#endif - -// JPF: a remark on coding style (2004-03-06): -// Some calls to TQString::fromLatin1() were removed from the code. In most places -// the KDE code relies on implicit creation of QStrings. Also Qt has a lot of -// const char* overloads, so that using TQString::fromLatin1() can be ineffectient! - -#define FTP_LOGIN "anonymous" -#define FTP_PASSWD "anonymous@" - -//#undef kdDebug -#define ENABLE_CAN_RESUME - -// JPF: somebody should find a better solution for this or move this to TDEIO -// JPF: anyhow, in KDE 3.2.0 I found diffent MAX_IPC_SIZE definitions! -namespace TDEIO { - enum buffersizes - { /** - * largest buffer size that should be used to transfer data between - * TDEIO slaves using the data() function - */ - maximumIpcSize = 32 * 1024, - /** - * this is a reasonable value for an initial read() that a TDEIO slave - * can do to obtain data via a slow network connection. - */ - initialIpcSize = 2 * 1024, - /** - * recommended size of a data block passed to findBufferFileType() - */ - mimimumMimeSize = 1024 - }; - - // JPF: this helper was derived from write_all in file.cc (FileProtocol). - static // JPF: in ftp.cc we make it static - /** - * This helper handles some special issues (blocking and interrupted - * system call) when writing to a file handle. - * - * @return 0 on success or an error code on failure (ERR_COULD_NOT_WRITE, - * ERR_DISK_FULL, ERR_CONNECTION_BROKEN). - */ - int WriteToFile(int fd, const char *buf, size_t len) - { - while (len > 0) - { // JPF: shouldn't there be a KDE_write? - ssize_t written = write(fd, buf, len); - if (written >= 0) - { buf += written; - len -= written; - continue; - } - switch(errno) - { case EINTR: continue; - case EPIPE: return ERR_CONNECTION_BROKEN; - case ENOSPC: return ERR_DISK_FULL; - default: return ERR_COULD_NOT_WRITE; - } - } - return 0; - } -} - -TDEIO::filesize_t Ftp::UnknownSize = (TDEIO::filesize_t)-1; - -using namespace TDEIO; - -extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } - -int kdemain( int argc, char **argv ) -{ - TDELocale::setMainCatalogue("tdelibs"); - TDEInstance instance( "tdeio_ftp" ); - ( void ) TDEGlobal::locale(); - - kdDebug(7102) << "Starting " << getpid() << endl; - - if (argc != 4) - { - fprintf(stderr, "Usage: tdeio_ftp protocol domain-socket1 domain-socket2\n"); - exit(-1); - } - - Ftp slave(argv[2], argv[3]); - slave.dispatchLoop(); - - kdDebug(7102) << "Done" << endl; - return 0; -} - -//=============================================================================== -// FtpTextReader Read Text lines from a file (or socket) -//=============================================================================== - -void FtpTextReader::textClear() -{ m_iTextLine = m_iTextBuff = 0; - m_szText[0] = 0; - m_bTextEOF = m_bTextTruncated = false; -} - -int FtpTextReader::textRead(FtpSocket *pSock) -{ - // if we have still buffered data then move it to the left - char* pEOL; - if(m_iTextLine < m_iTextBuff) - { m_iTextBuff -= m_iTextLine; - memmove(m_szText, m_szText+m_iTextLine, m_iTextBuff); - pEOL = (char*)memchr(m_szText, '\n', m_iTextBuff); // have a complete line? - } - else - { m_iTextBuff = 0; - pEOL = NULL; - } - m_bTextEOF = m_bTextTruncated = false; - - // read data from the control socket until a complete line is read - int nBytes; - while(pEOL == NULL) - { - if(m_iTextBuff > textReadLimit) - { m_bTextTruncated = true; - m_iTextBuff = textReadLimit; - } - nBytes = pSock->read(m_szText+m_iTextBuff, sizeof(m_szText)-m_iTextBuff); - if(nBytes <= 0) - { - // This error can occur after the server closed the connection (after a timeout) - if(nBytes < 0) - pSock->debugMessage("textRead failed"); - m_bTextEOF = true; - pEOL = m_szText + m_iTextBuff; - } - else - { - m_iTextBuff += nBytes; - pEOL = (char*)memchr(m_szText, '\n', m_iTextBuff); - } - } - - nBytes = pEOL - m_szText; - m_iTextLine = nBytes + 1; - - if(nBytes > textReadLimit) - { m_bTextTruncated = true; - nBytes = textReadLimit; - } - if(nBytes && m_szText[nBytes-1] == '\r') - nBytes--; - m_szText[nBytes] = 0; - return nBytes; -} - -//=============================================================================== -// FtpSocket Helper Class for Data or Control Connections -//=============================================================================== -void FtpSocket::debugMessage(const char* pszMsg) const -{ - kdDebug(7102) << m_pszName << ": " << pszMsg << endl; -} - -int FtpSocket::errorMessage(int iErrorCode, const char* pszMsg) const -{ - kdError(7102) << m_pszName << ": " << pszMsg << endl; - return iErrorCode; -} - -int FtpSocket::connectSocket(int iTimeOutSec, bool bControl) -{ - closeSocket(); - - int iOpt = bControl ? KExtendedSocket::inetSocket - : KExtendedSocket::noResolve; - setSocketFlags(iOpt | socketFlags()); - setTimeout(iTimeOutSec); - - int iCon = KExtendedSocket::connect(); - if(iCon < 0) - { int iErrorCode = (status() == IO_LookupError) - ? ERR_UNKNOWN_HOST : ERR_COULD_NOT_CONNECT; - TQString strMsg = KExtendedSocket::strError(status(), systemError()); - strMsg.prepend("connect failed (code %1): "); - return errorMessage(iErrorCode, TQString(strMsg.arg(iCon)).latin1()); - } - if( !setAddressReusable(true) ) - return errorMessage(ERR_COULD_NOT_CREATE_SOCKET, "setAddressReusable failed"); - - if(!bControl) - { int on=1; - if( !setSocketOption(SO_KEEPALIVE, (char *)&on, sizeof(on)) ) - errorMessage(0, "Keepalive not allowed"); - - struct linger lng = { 1, 120 }; - if( !setSocketOption(SO_LINGER, (char *)&lng, sizeof (lng)) ) - errorMessage(0, "Linger mode was not allowed."); - } - - debugMessage("connected"); - return 0; -} - -void FtpSocket::closeSocket() -{ - if(m_server != -1 || fd() != -1) - debugMessage("disconnected"); - - if(m_server != -1) - { - ::shutdown(m_server, SHUT_RDWR); - ::close(m_server); - m_server = -1; - } - if(socketStatus() > nothing) - reset(); - textClear(); -} - -bool FtpSocket::setSocketOption(int opt, char*arg, socklen_t len) const -{ - return (setsockopt(sock(), SOL_SOCKET, opt, arg, len) != -1); -} - -//=============================================================================== -// Ftp -//=============================================================================== - -Ftp::Ftp( const TQCString &pool, const TQCString &app ) - : SlaveBase( "ftp", pool, app ) -{ - // init the socket data - m_data = m_control = NULL; - ftpCloseControlConnection(); - - // init other members - m_port = 0; - kdDebug(7102) << "Ftp::Ftp()" << endl; -} - - -Ftp::~Ftp() -{ - kdDebug(7102) << "Ftp::~Ftp()" << endl; - closeConnection(); -} - -/** - * This closes a data connection opened by ftpOpenDataConnection(). - */ -void Ftp::ftpCloseDataConnection() -{ - if(m_data != NULL) - { delete m_data; - m_data = NULL; - } -} - -/** - * This closes a control connection opened by ftpOpenControlConnection() and reinits the - * related states. This method gets called from the constructor with m_control = NULL. - */ -void Ftp::ftpCloseControlConnection() -{ - m_extControl = 0; - if(m_control) - delete m_control; - m_control = NULL; - m_cDataMode = 0; - m_bLoggedOn = false; // logon needs control connction - m_bTextMode = false; - m_bBusy = false; -} - -/** - * Returns the last response from the server (iOffset >= 0) -or- reads a new response - * (iOffset < 0). The result is returned (with iOffset chars skipped for iOffset > 0). - */ -const char* Ftp::ftpResponse(int iOffset) -{ - assert(m_control != NULL); // must have control connection socket - const char *pTxt = m_control->textLine(); - - // read the next line ... - if(iOffset < 0) - { - int iMore = 0; - m_iRespCode = 0; - - // If the server sends multiline responses "nnn-text" we loop here until - // a final "nnn text" line is reached. Only data from the final line will - // be stored. Some servers (OpenBSD) send a single "nnn-" followed by - // optional lines that start with a space and a final "nnn text" line. - do { - int nBytes = m_control->textRead(); - int iCode = atoi(pTxt); - if(iCode > 0) m_iRespCode = iCode; - - // ignore lines starting with a space in multiline response - if(iMore != 0 && pTxt[0] == 32) - ; - // otherwise the line should start with "nnn-" or "nnn " - else if(nBytes < 4 || iCode < 100) - iMore = 0; - // we got a valid line, now check for multiline responses ... - else if(iMore == 0 && pTxt[3] == '-') - iMore = iCode; - // "nnn " ends multiline mode ... - else if(iMore != 0 && (iMore != iCode || pTxt[3] != '-')) - iMore = 0; - - if(iMore != 0) - kdDebug(7102) << " > " << pTxt << endl; - } while(iMore != 0); - kdDebug(7102) << "resp> " << pTxt << endl; - - m_iRespType = (m_iRespCode > 0) ? m_iRespCode / 100 : 0; - } - - // return text with offset ... - while(iOffset-- > 0 && pTxt[0]) - pTxt++; - return pTxt; -} - - -void Ftp::closeConnection() -{ - if(m_control != NULL || m_data != NULL) - kdDebug(7102) << "Ftp::closeConnection m_bLoggedOn=" << m_bLoggedOn << " m_bBusy=" << m_bBusy << endl; - - if(m_bBusy) // ftpCloseCommand not called - { - kdWarning(7102) << "Ftp::closeConnection Abandoned data stream" << endl; - ftpCloseDataConnection(); - } - - if(m_bLoggedOn) // send quit - { - if( !ftpSendCmd( "quit", 0 ) || (m_iRespType != 2) ) - kdWarning(7102) << "Ftp::closeConnection QUIT returned error: " << m_iRespCode << endl; - } - - // close the data and control connections ... - ftpCloseDataConnection(); - ftpCloseControlConnection(); -} - -void Ftp::setHost( const TQString& _host, int _port, const TQString& _user, - const TQString& _pass ) -{ - kdDebug(7102) << "Ftp::setHost (" << getpid() << "): " << _host << endl; - - m_proxyURL = metaData("UseProxy"); - m_bUseProxy = (m_proxyURL.isValid() && m_proxyURL.protocol() == "ftp"); - - if ( m_host != _host || m_port != _port || - m_user != _user || m_pass != _pass ) - closeConnection(); - - m_host = _host; - m_port = _port; - m_user = _user; - m_pass = _pass; -} - -void Ftp::openConnection() -{ - ftpOpenConnection(loginExplicit); -} - -bool Ftp::ftpOpenConnection (LoginMode loginMode) -{ - // check for implicit login if we are already logged on ... - if(loginMode == loginImplicit && m_bLoggedOn) - { - assert(m_control != NULL); // must have control connection socket - return true; - } - - kdDebug(7102) << "ftpOpenConnection " << m_host << ":" << m_port << " " - << m_user << " [password hidden]" << endl; - - infoMessage( i18n("Opening connection to host %1").arg(m_host) ); - - if ( m_host.isEmpty() ) - { - error( ERR_UNKNOWN_HOST, TQString::null ); - return false; - } - - assert( !m_bLoggedOn ); - - m_initialPath = TQString::null; - m_currentPath = TQString::null; - - TQString host = m_bUseProxy ? m_proxyURL.host() : m_host; - unsigned short int port = m_bUseProxy ? m_proxyURL.port() : m_port; - - if (!ftpOpenControlConnection(host, port) ) - return false; // error emitted by ftpOpenControlConnection - infoMessage( i18n("Connected to host %1").arg(m_host) ); - - if(loginMode != loginDefered) - { - m_bLoggedOn = ftpLogin(); - if( !m_bLoggedOn ) - return false; // error emitted by ftpLogin - } - - m_bTextMode = config()->readBoolEntry("textmode", false); - connected(); - return true; -} - - -/** - * Called by @ref openConnection. It opens the control connection to the ftp server. - * - * @return true on success. - */ -bool Ftp::ftpOpenControlConnection( const TQString &host, unsigned short int port ) -{ - if ( port == 0 ) { - struct servent *pse; - if ( ( pse = getservbyname( "ftp", "tcp" ) ) == NULL ) - port = 21; - else - port = ntohs(pse->s_port); - } - - // implicitly close, then try to open a new connection ... - closeConnection(); - int iErrorCode = ERR_OUT_OF_MEMORY; - TQString sErrorMsg; - m_control = new FtpSocket("CNTL"); - if(m_control != NULL) - { - // now connect to the server and read the login message ... - m_control->setAddress(host, port); - iErrorCode = m_control->connectSocket(connectTimeout(), true); - sErrorMsg = host; - - // on connect success try to read the server message... - if(iErrorCode == 0) - { - const char* psz = ftpResponse(-1); - if(m_iRespType != 2) - { // login not successful, do we have an message text? - if(psz[0]) - sErrorMsg = i18n("%1.\n\nReason: %2").arg(host).arg(psz); - iErrorCode = ERR_COULD_NOT_CONNECT; - } - } - } - - // if there was a problem - report it ... - if(iErrorCode == 0) // OK, return success - return true; - closeConnection(); // clean-up on error - error(iErrorCode, sErrorMsg); - return false; -} - -/** - * Called by @ref openConnection. It logs us in. - * @ref m_initialPath is set to the current working directory - * if logging on was successful. - * - * @return true on success. - */ -bool Ftp::ftpLogin() -{ - infoMessage( i18n("Sending login information") ); - - assert( !m_bLoggedOn ); - - TQString user = m_user; - TQString pass = m_pass; - - if ( config()->readBoolEntry("EnableAutoLogin") ) - { - TQString au = config()->readEntry("autoLoginUser"); - if ( !au.isEmpty() ) - { - user = au; - pass = config()->readEntry("autoLoginPass"); - } - } - - // Try anonymous login if both username/password - // information is blank. - if (user.isEmpty() && pass.isEmpty()) - { - user = FTP_LOGIN; - pass = FTP_PASSWD; - } - - AuthInfo info; - info.url.setProtocol( "ftp" ); - info.url.setHost( m_host ); - info.url.setPort( m_port ); - info.url.setUser( user ); - - TQCString tempbuf; - int failedAuth = 0; - - do - { - // Check the cache and/or prompt user for password if 1st - // login attempt failed OR the user supplied a login name, - // but no password. - if ( failedAuth > 0 || (!user.isEmpty() && pass.isEmpty()) ) - { - TQString errorMsg; - kdDebug(7102) << "Prompting user for login info..." << endl; - - // Ask user if we should retry after when login fails! - if( failedAuth > 0 ) - { - errorMsg = i18n("Message sent:\nLogin using username=%1 and " - "password=[hidden]\n\nServer replied:\n%2\n\n" - ).arg(user).arg(ftpResponse(0)); - } - - if ( user != FTP_LOGIN ) - info.username = user; - - info.prompt = i18n("You need to supply a username and a password " - "to access this site."); - info.commentLabel = i18n( "Site:" ); - info.comment = i18n("%1").arg( m_host ); - info.keepPassword = true; // Prompt the user for persistence as well. - info.readOnly = (!m_user.isEmpty() && m_user != FTP_LOGIN); - - bool disablePassDlg = config()->readBoolEntry( "DisablePassDlg", false ); - if ( disablePassDlg || !openPassDlg( info, errorMsg ) ) - { - error( ERR_USER_CANCELED, m_host ); - return false; - } - else - { - user = info.username; - pass = info.password; - } - } - - tempbuf = "USER "; - tempbuf += user.latin1(); - if ( m_bUseProxy ) - { - tempbuf += '@'; - tempbuf += m_host.latin1(); - if ( m_port > 0 && m_port != DEFAULT_FTP_PORT ) - { - tempbuf += ':'; - tempbuf += TQString::number(m_port).latin1(); - } - } - - kdDebug(7102) << "Sending Login name: " << tempbuf << endl; - - bool loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) ); - bool needPass = (m_iRespCode == 331); - // Prompt user for login info if we do not - // get back a "230" or "331". - if ( !loggedIn && !needPass ) - { - kdDebug(7102) << "Login failed: " << ftpResponse(0) << endl; - ++failedAuth; - continue; // Well we failed, prompt the user please!! - } - - if( needPass ) - { - tempbuf = "pass "; - tempbuf += pass.latin1(); - kdDebug(7102) << "Sending Login password: " << "[protected]" << endl; - loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) ); - } - - if ( loggedIn ) - { - // Do not cache the default login!! - if( user != FTP_LOGIN && pass != FTP_PASSWD ) - cacheAuthentication( info ); - failedAuth = -1; - } - - } while( ++failedAuth ); - - - kdDebug(7102) << "Login OK" << endl; - infoMessage( i18n("Login OK") ); - - // Okay, we're logged in. If this is IIS 4, switch dir listing style to Unix: - // Thanks to jk@soegaard.net (Jens Kristian Søgaard) for this hint - if( ftpSendCmd("SYST") && (m_iRespType == 2) ) - { - if( !strncmp( ftpResponse(0), "215 Windows_NT", 14 ) ) // should do for any version - { - ftpSendCmd( "site dirstyle" ); - // Check if it was already in Unix style - // Patch from Keith Refson - if( !strncmp( ftpResponse(0), "200 MSDOS-like directory output is on", 37 )) - //It was in Unix style already! - ftpSendCmd( "site dirstyle" ); - // windows won't support chmod before KDE konquers their desktop... - m_extControl |= chmodUnknown; - } - } - else - kdWarning(7102) << "SYST failed" << endl; - - if ( config()->readBoolEntry ("EnableAutoLoginMacro") ) - ftpAutoLoginMacro (); - - // Get the current working directory - kdDebug(7102) << "Searching for pwd" << endl; - if( !ftpSendCmd("PWD") || (m_iRespType != 2) ) - { - kdDebug(7102) << "Couldn't issue pwd command" << endl; - error( ERR_COULD_NOT_LOGIN, i18n("Could not login to %1.").arg(m_host) ); // or anything better ? - return false; - } - - TQString sTmp = remoteEncoding()->decode( ftpResponse(3) ); - int iBeg = sTmp.find('"'); - int iEnd = sTmp.findRev('"'); - if(iBeg > 0 && iBeg < iEnd) - { - m_initialPath = sTmp.mid(iBeg+1, iEnd-iBeg-1); - if(m_initialPath[0] != '/') m_initialPath.prepend('/'); - kdDebug(7102) << "Initial path set to: " << m_initialPath << endl; - m_currentPath = m_initialPath; - } - return true; -} - -void Ftp::ftpAutoLoginMacro () -{ - TQString macro = metaData( "autoLoginMacro" ); - - if ( macro.isEmpty() ) - return; - - TQStringList list = TQStringList::split('\n', macro); - - for(TQStringList::Iterator it = list.begin() ; it != list.end() ; ++it ) - { - if ( (*it).startsWith("init") ) - { - list = TQStringList::split( '\\', macro); - it = list.begin(); - ++it; // ignore the macro name - - for( ; it != list.end() ; ++it ) - { - // TODO: Add support for arbitrary commands - // besides simply changing directory!! - if ( (*it).startsWith( "cwd" ) ) - ftpFolder( (*it).mid(4).stripWhiteSpace(), false ); - } - - break; - } - } -} - - -/** - * ftpSendCmd - send a command (@p cmd) and read response - * - * @param maxretries number of time it should retry. Since it recursively - * calls itself if it can't read the answer (this happens especially after - * timeouts), we need to limit the recursiveness ;-) - * - * return true if any response received, false on error - */ -bool Ftp::ftpSendCmd( const TQCString& cmd, int maxretries ) -{ - assert(m_control != NULL); // must have control connection socket - - if ( cmd.find( '\r' ) != -1 || cmd.find( '\n' ) != -1) - { - kdWarning(7102) << "Invalid command received (contains CR or LF):" - << cmd.data() << endl; - error( ERR_UNSUPPORTED_ACTION, m_host ); - return false; - } - - // Don't print out the password... - bool isPassCmd = (cmd.left(4).lower() == "pass"); - if ( !isPassCmd ) - kdDebug(7102) << "send> " << cmd.data() << endl; - else - kdDebug(7102) << "send> pass [protected]" << endl; - - // Send the message... - TQCString buf = cmd; - buf += "\r\n"; // Yes, must use CR/LF - see http://cr.yp.to/ftp/request.html - int num = m_control->write(buf.data(), buf.length()); - - // If we were able to successfully send the command, then we will - // attempt to read the response. Otherwise, take action to re-attempt - // the login based on the maximum number of retires specified... - if( num > 0 ) - ftpResponse(-1); - else - { m_iRespType = m_iRespCode = 0; - m_control->textClear(); - } - - // If respCh is NULL or the response is 421 (Timed-out), we try to re-send - // the command based on the value of maxretries. - if( (m_iRespType <= 0) || (m_iRespCode == 421) ) - { - // We have not yet logged on... - if (!m_bLoggedOn) - { - // The command was sent from the ftpLogin function, i.e. we are actually - // attempting to login in. NOTE: If we already sent the username, we - // return false and let the user decide whether (s)he wants to start from - // the beginning... - if (maxretries > 0 && !isPassCmd) - { - closeConnection (); - if( ftpOpenConnection(loginDefered) ) - ftpSendCmd ( cmd, maxretries - 1 ); - } - - return false; - } - else - { - if ( maxretries < 1 ) - return false; - else - { - kdDebug(7102) << "Was not able to communicate with " << m_host << endl - << "Attempting to re-establish connection." << endl; - - closeConnection(); // Close the old connection... - openConnection(); // Attempt to re-establish a new connection... - - if (!m_bLoggedOn) - { - if (m_control != NULL) // if openConnection succeeded ... - { - kdDebug(7102) << "Login failure, aborting" << endl; - error (ERR_COULD_NOT_LOGIN, m_host); - closeConnection (); - } - return false; - } - - kdDebug(7102) << "Logged back in, re-issuing command" << endl; - - // If we were able to login, resend the command... - if (maxretries) - maxretries--; - - return ftpSendCmd( cmd, maxretries ); - } - } - } - - return true; -} - -/* - * ftpOpenPASVDataConnection - set up data connection, using PASV mode - * - * return 1 if successful, 0 otherwise - * doesn't set error message, since non-pasv mode will always be tried if - * this one fails - */ -int Ftp::ftpOpenPASVDataConnection() -{ - assert(m_control != NULL); // must have control connection socket - assert(m_data == NULL); // ... but no data connection - - // Check that we can do PASV - const TDESocketAddress *sa = m_control->peerAddress(); - if (sa != NULL && sa->family() != PF_INET) - return ERR_INTERNAL; // no PASV for non-PF_INET connections - - const KInetSocketAddress *sin = static_cast(sa); - - if (m_extControl & pasvUnknown) - return ERR_INTERNAL; // already tried and got "unknown command" - - m_bPasv = true; - - /* Let's PASsiVe*/ - if( !ftpSendCmd("PASV") || (m_iRespType != 2) ) - { - kdDebug(7102) << "PASV attempt failed" << endl; - // unknown command? - if( m_iRespType == 5 ) - { - kdDebug(7102) << "disabling use of PASV" << endl; - m_extControl |= pasvUnknown; - } - return ERR_INTERNAL; - } - - // The usual answer is '227 Entering Passive Mode. (160,39,200,55,6,245)' - // but anonftpd gives '227 =160,39,200,55,6,245' - int i[6]; - const char *start = strchr(ftpResponse(3), '('); - if ( !start ) - start = strchr(ftpResponse(3), '='); - if ( !start || - ( sscanf(start, "(%d,%d,%d,%d,%d,%d)",&i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 && - sscanf(start, "=%d,%d,%d,%d,%d,%d", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 ) ) - { - kdError(7102) << "parsing IP and port numbers failed. String parsed: " << start << endl; - return ERR_INTERNAL; - } - - // Make hostname and port number ... - int port = i[4] << 8 | i[5]; - - // we ignore the host part on purpose for two reasons - // a) it might be wrong anyway - // b) it would make us being suceptible to a port scanning attack - - // now connect the data socket ... - m_data = new FtpSocket("PASV"); - m_data->setAddress(sin->nodeName(), port); - - kdDebug(7102) << "Connecting to " << sin->nodeName() << " on port " << port << endl; - return m_data->connectSocket(connectTimeout(), false); -} - -/* - * ftpOpenEPSVDataConnection - opens a data connection via EPSV - */ -int Ftp::ftpOpenEPSVDataConnection() -{ - assert(m_control != NULL); // must have control connection socket - assert(m_data == NULL); // ... but no data connection - - const TDESocketAddress *sa = m_control->peerAddress(); - int portnum; - // we are sure sa is a KInetSocketAddress, because we asked for KExtendedSocket::inetSocket - // when we connected - const KInetSocketAddress *sin = static_cast(sa); - - if (m_extControl & epsvUnknown || sa == NULL) - return ERR_INTERNAL; - - m_bPasv = true; - if( !ftpSendCmd("EPSV") || (m_iRespType != 2) ) - { - // unknown command? - if( m_iRespType == 5 ) - { - kdDebug(7102) << "disabling use of EPSV" << endl; - m_extControl |= epsvUnknown; - } - return ERR_INTERNAL; - } - - const char *start = strchr(ftpResponse(3), '|'); - if ( !start || sscanf(start, "|||%d|", &portnum) != 1) - return ERR_INTERNAL; - - m_data = new FtpSocket("EPSV"); - m_data->setAddress(sin->nodeName(), portnum); - return m_data->connectSocket(connectTimeout(), false) != 0; -} - -/* - * ftpOpenEPRTDataConnection - * @return 0 on success, ERR_INTERNAL if mode not acceptable -or- a fatal error code - */ -int Ftp::ftpOpenEPRTDataConnection() -{ - assert(m_control != NULL); // must have control connection socket - assert(m_data == NULL); // ... but no data connection - - // yes, we are sure this is a KInetSocketAddress - const KInetSocketAddress *sin = static_cast(m_control->localAddress()); - m_bPasv = false; - if (m_extControl & eprtUnknown || sin == NULL) - return ERR_INTERNAL; - - m_data = new FtpSocket("EPRT"); - m_data->setHost(sin->nodeName()); - m_data->setPort(0); // setting port to 0 will make us bind to a random, free port - m_data->setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket | - KExtendedSocket::inetSocket); - - if (m_data->listen(1) < 0) - return ERR_COULD_NOT_LISTEN; - - sin = static_cast(m_data->localAddress()); - if (sin == NULL) - return ERR_INTERNAL; - - // TQString command = TQString::fromLatin1("eprt |%1|%2|%3|").arg(sin->ianaFamily()) - // .arg(sin->nodeName()) - // .arg(sin->port()); - TQCString command; - command.sprintf("eprt |%d|%s|%d|", sin->ianaFamily(), - sin->nodeName().latin1(), sin->port()); - - // FIXME! Encoding for hostnames? - if( ftpSendCmd(command) && (m_iRespType == 2) ) - return 0; - - // unknown command? - if( m_iRespType == 5 ) - { - kdDebug(7102) << "disabling use of EPRT" << endl; - m_extControl |= eprtUnknown; - } - return ERR_INTERNAL; -} - -/* - * ftpOpenDataConnection - set up data connection - * - * The routine calls several ftpOpenXxxxConnection() helpers to find - * the best connection mode. If a helper cannot connect if returns - * ERR_INTERNAL - so this is not really an error! All other error - * codes are treated as fatal, e.g. they are passed back to the caller - * who is responsible for calling error(). ftpOpenPortDataConnection - * can be called as last try and it does never return ERR_INTERNAL. - * - * @return 0 if successful, err code otherwise - */ -int Ftp::ftpOpenDataConnection() -{ - // make sure that we are logged on and have no data connection... - assert( m_bLoggedOn ); - ftpCloseDataConnection(); - - int iErrCode = 0; - int iErrCodePASV = 0; // Remember error code from PASV - - // First try passive (EPSV & PASV) modes - if( !config()->readBoolEntry("DisablePassiveMode", false) ) - { - iErrCode = ftpOpenPASVDataConnection(); - if(iErrCode == 0) - return 0; // success - iErrCodePASV = iErrCode; - ftpCloseDataConnection(); - - if( !config()->readBoolEntry("DisableEPSV", false) ) - { - iErrCode = ftpOpenEPSVDataConnection(); - if(iErrCode == 0) - return 0; // success - ftpCloseDataConnection(); - } - - // if we sent EPSV ALL already and it was accepted, then we can't - // use active connections any more - if (m_extControl & epsvAllSent) - return iErrCodePASV ? iErrCodePASV : iErrCode; - } - - if( !config()->readBoolEntry("DisableEPRT", false) ) - { - iErrCode = ftpOpenEPRTDataConnection(); - if(iErrCode == 0) - return 0; // success - ftpCloseDataConnection(); - } - - // fall back to port mode - iErrCode = ftpOpenPortDataConnection(); - if(iErrCode == 0) - return 0; // success - - ftpCloseDataConnection(); - // prefer to return the error code from PASV if any, since that's what should have worked in the first place - return iErrCodePASV ? iErrCodePASV : iErrCode; -} - -/* - * ftpOpenPortDataConnection - set up data connection - * - * @return 0 if successfull, err code otherwise (but never ERR_INTERNAL - * because this is the last connection mode that is tried) - */ -int Ftp::ftpOpenPortDataConnection() -{ - assert(m_control != NULL); // must have control connection socket - assert(m_data == NULL); // ... but no data connection - - m_bPasv = false; - - // create a socket, bind it and let it listen ... - m_data = new FtpSocket("PORT"); - m_data->setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket | - KExtendedSocket::inetSocket); - - // yes, we are sure this is a KInetSocketAddress - const KInetSocketAddress* pAddr = static_cast(m_control->localAddress()); - m_data->setAddress(pAddr->nodeName(), "0"); - m_data->setAddressReusable(true); - - if(m_data->listen(1) < 0) - return ERR_COULD_NOT_LISTEN; - struct linger lng = { 0, 0 }; - if ( !m_data->setSocketOption(SO_LINGER, (char*)&lng, sizeof(lng)) ) - return ERR_COULD_NOT_CREATE_SOCKET; - - // send the PORT command ... - pAddr = static_cast(m_data->localAddress()); - struct sockaddr* psa = (struct sockaddr*)pAddr->addressV4(); - unsigned char* pData = (unsigned char*)(psa->sa_data); - TQCString portCmd; - portCmd.sprintf("port %d,%d,%d,%d,%d,%d", - pData[2], pData[3], pData[4], pData[5], pData[0], pData[1]); - if( ftpSendCmd(portCmd) && (m_iRespType == 2) ) - return 0; - return ERR_COULD_NOT_CONNECT; -} - -/* - * ftpAcceptConnect - wait for incoming connection - * Used by @ref ftpOpenCommand - * - * return false on error or timeout - */ -int Ftp::ftpAcceptConnect() -{ - assert(m_data != NULL); - - if ( m_bPasv ) - { - m_data->setServer(-1); - return true; - } - - int sSock = m_data->fd(); - struct sockaddr addr; - for(;;) - { - fd_set mask; - FD_ZERO(&mask); - FD_SET(sSock,&mask); - int r = KSocks::self()->select(sSock + 1, &mask, NULL, NULL, 0L); - if( r < 0 && errno != EINTR && errno != EAGAIN ) - continue; - if( r > 0 ) - break; - } - - ksocklen_t l = sizeof(addr); - m_data->setServer( KSocks::self()->accept(sSock, &addr, &l) ); - return (m_data->server() != -1); -} - -bool Ftp::ftpOpenCommand( const char *_command, const TQString & _path, char _mode, - int errorcode, TDEIO::fileoffset_t _offset ) -{ - int errCode = 0; - if( !ftpDataMode(_mode) ) - errCode = ERR_COULD_NOT_CONNECT; - else - errCode = ftpOpenDataConnection(); - - if(errCode != 0) - { - error(errCode, m_host); - return false; - } - - if ( _offset > 0 ) { - // send rest command if offset > 0, this applies to retr and stor commands - char buf[100]; - sprintf(buf, "rest %lld", _offset); - if ( !ftpSendCmd( buf ) ) - return false; - if( m_iRespType != 3 ) - { - error( ERR_CANNOT_RESUME, _path ); // should never happen - return false; - } - } - - TQCString tmp = _command; - TQString errormessage; - - if ( !_path.isEmpty() ) { - tmp += " "; - tmp += remoteEncoding()->encode(_path); - } - - if( !ftpSendCmd( tmp ) || (m_iRespType != 1) ) - { - if( _offset > 0 && strcmp(_command, "retr") == 0 && (m_iRespType == 4) ) - errorcode = ERR_CANNOT_RESUME; - // The error here depends on the command - errormessage = _path; - } - - else - { - // Only now we know for sure that we can resume - if ( _offset > 0 && strcmp(_command, "retr") == 0 ) - canResume(); - - if( ftpAcceptConnect() ) - { m_bBusy = true; // cleared in ftpCloseCommand - return true; - } - errorcode = ERR_COULD_NOT_ACCEPT; - } - - error(errorcode, errormessage); - return false; -} - - -bool Ftp::ftpCloseCommand() -{ - // first close data sockets (if opened), then read response that - // we got for whatever was used in ftpOpenCommand ( should be 226 ) - if(m_data) - { - delete m_data; - m_data = NULL; - } - if(!m_bBusy) - return true; - - kdDebug(7102) << "ftpCloseCommand: reading command result" << endl; - m_bBusy = false; - - if(!ftpResponse(-1) || (m_iRespType != 2) ) - { - kdDebug(7102) << "ftpCloseCommand: no transfer complete message" << endl; - return false; - } - return true; -} - -void Ftp::mkdir( const KURL & url, int permissions ) -{ - if( !ftpOpenConnection(loginImplicit) ) - return; - - TQString path = remoteEncoding()->encode(url); - TQCString buf = "mkd "; - buf += remoteEncoding()->encode(path); - - if( !ftpSendCmd( buf ) || (m_iRespType != 2) ) - { - TQString currentPath( m_currentPath ); - - // Check whether or not mkdir failed because - // the directory already exists... - if( ftpFolder( path, false ) ) - { - error( ERR_DIR_ALREADY_EXIST, path ); - // Change the directory back to what it was... - (void) ftpFolder( currentPath, false ); - return; - } - - error( ERR_COULD_NOT_MKDIR, path ); - return; - } - - if ( permissions != -1 ) - { - // chmod the dir we just created, ignoring errors. - (void) ftpChmod( path, permissions ); - } - - finished(); -} - -void Ftp::rename( const KURL& src, const KURL& dst, bool overwrite ) -{ - if( !ftpOpenConnection(loginImplicit) ) - return; - - // The actual functionality is in ftpRename because put needs it - if ( ftpRename( src.path(), dst.path(), overwrite ) ) - finished(); - else - error( ERR_CANNOT_RENAME, src.path() ); -} - -bool Ftp::ftpRename( const TQString & src, const TQString & dst, bool overwrite ) -{ - assert( m_bLoggedOn ); - - // Must check if dst already exists, RNFR+RNTO overwrites by default (#127793). - if (!overwrite) { - if (ftpSize(dst, 'I')) { - error(ERR_FILE_ALREADY_EXIST, dst); - return false; - } - } - if (ftpFolder(dst, false)) { - error(ERR_DIR_ALREADY_EXIST, dst); - return false; - } - - // Must check if dst already exists, RNFR+RNTO overwrites by default (#127793). - if (ftpFileExists(dst)) { - error(ERR_FILE_ALREADY_EXIST, dst); - return false; - } - if (ftpFolder(dst, false)) { - error(ERR_DIR_ALREADY_EXIST, dst); - return false; - } - - int pos = src.findRev("/"); - if( !ftpFolder(src.left(pos+1), false) ) - return false; - - TQCString from_cmd = "RNFR "; - from_cmd += remoteEncoding()->encode(src.mid(pos+1)); - if( !ftpSendCmd( from_cmd ) || (m_iRespType != 3) ) - return false; - - TQCString to_cmd = "RNTO "; - to_cmd += remoteEncoding()->encode(dst); - if( !ftpSendCmd( to_cmd ) || (m_iRespType != 2) ) - return false; - - return true; -} - -void Ftp::del( const KURL& url, bool isfile ) -{ - if( !ftpOpenConnection(loginImplicit) ) - return; - - // When deleting a directory, we must exit from it first - // The last command probably went into it (to stat it) - if ( !isfile ) - ftpFolder(remoteEncoding()->directory(url), false); // ignore errors - - TQCString cmd = isfile ? "DELE " : "RMD "; - cmd += remoteEncoding()->encode(url); - - if( !ftpSendCmd( cmd ) || (m_iRespType != 2) ) - error( ERR_CANNOT_DELETE, url.path() ); - else - finished(); -} - -bool Ftp::ftpChmod( const TQString & path, int permissions ) -{ - assert( m_bLoggedOn ); - - if(m_extControl & chmodUnknown) // previous errors? - return false; - - // we need to do bit AND 777 to get permissions, in case - // we were sent a full mode (unlikely) - TQCString cmd; - cmd.sprintf("SITE CHMOD %o ", permissions & 511 ); - cmd += remoteEncoding()->encode(path); - - ftpSendCmd(cmd); - if(m_iRespType == 2) - return true; - - if(m_iRespCode == 500) - { - m_extControl |= chmodUnknown; - kdDebug(7102) << "ftpChmod: CHMOD not supported - disabling"; - } - return false; -} - -void Ftp::chmod( const KURL & url, int permissions ) -{ - if( !ftpOpenConnection(loginImplicit) ) - return; - - if ( !ftpChmod( url.path(), permissions ) ) - error( ERR_CANNOT_CHMOD, url.path() ); - else - finished(); -} - -void Ftp::ftpCreateUDSEntry( const TQString & filename, FtpEntry& ftpEnt, UDSEntry& entry, bool isDir ) -{ - assert(entry.count() == 0); // by contract :-) - UDSAtom atom; - atom.m_uds = UDS_NAME; - atom.m_str = filename; - entry.append( atom ); - - atom.m_uds = UDS_SIZE; - atom.m_long = ftpEnt.size; - entry.append( atom ); - - atom.m_uds = UDS_MODIFICATION_TIME; - atom.m_long = ftpEnt.date; - entry.append( atom ); - - atom.m_uds = UDS_ACCESS; - atom.m_long = ftpEnt.access; - entry.append( atom ); - - atom.m_uds = UDS_USER; - atom.m_str = ftpEnt.owner; - entry.append( atom ); - - if ( !ftpEnt.group.isEmpty() ) - { - atom.m_uds = UDS_GROUP; - atom.m_str = ftpEnt.group; - entry.append( atom ); - } - - if ( !ftpEnt.link.isEmpty() ) - { - atom.m_uds = UDS_LINK_DEST; - atom.m_str = ftpEnt.link; - entry.append( atom ); - - KMimeType::Ptr mime = KMimeType::findByURL( KURL("ftp://host/" + filename ) ); - // Links on ftp sites are often links to dirs, and we have no way to check - // that. Let's do like Netscape : assume dirs generally. - // But we do this only when the mimetype can't be known from the filename. - // --> we do better than Netscape :-) - if ( mime->name() == KMimeType::defaultMimeType() ) - { - kdDebug(7102) << "Setting guessed mime type to inode/directory for " << filename << endl; - atom.m_uds = UDS_GUESSED_MIME_TYPE; - atom.m_str = "inode/directory"; - entry.append( atom ); - isDir = true; - } - } - - atom.m_uds = UDS_FILE_TYPE; - atom.m_long = isDir ? S_IFDIR : ftpEnt.type; - entry.append( atom ); - - /* atom.m_uds = UDS_ACCESS_TIME; - atom.m_long = buff.st_atime; - entry.append( atom ); - - atom.m_uds = UDS_CREATION_TIME; - atom.m_long = buff.st_ctime; - entry.append( atom ); */ -} - - -void Ftp::ftpShortStatAnswer( const TQString& filename, bool isDir ) -{ - UDSEntry entry; - UDSAtom atom; - - atom.m_uds = TDEIO::UDS_NAME; - atom.m_str = filename; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = isDir ? S_IFDIR : S_IFREG; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - entry.append( atom ); - - // No details about size, ownership, group, etc. - - statEntry(entry); - finished(); -} - -void Ftp::ftpStatAnswerNotFound( const TQString & path, const TQString & filename ) -{ - // Only do the 'hack' below if we want to download an existing file (i.e. when looking at the "source") - // When e.g. uploading a file, we still need stat() to return "not found" - // when the file doesn't exist. - TQString statSide = metaData("statSide"); - kdDebug(7102) << "Ftp::stat statSide=" << statSide << endl; - if ( statSide == "source" ) - { - kdDebug(7102) << "Not found, but assuming found, because some servers don't allow listing" << endl; - // MS Server is incapable of handling "list " in a case insensitive way - // But "retr " works. So lie in stat(), to get going... - // - // There's also the case of ftp://ftp2.3ddownloads.com/90380/linuxgames/loki/patches/ut/ut-patch-436.run - // where listing permissions are denied, but downloading is still possible. - ftpShortStatAnswer( filename, false /*file, not dir*/ ); - - return; - } - - error( ERR_DOES_NOT_EXIST, path ); -} - -void Ftp::stat( const KURL &url) -{ - kdDebug(7102) << "Ftp::stat : path='" << url.path() << "'" << endl; - if( !ftpOpenConnection(loginImplicit) ) - return; - - TQString path = TQDir::cleanDirPath( url.path() ); - kdDebug(7102) << "Ftp::stat : cleaned path='" << path << "'" << endl; - - // We can't stat root, but we know it's a dir. - if( path.isEmpty() || path == "/" ) - { - UDSEntry entry; - UDSAtom atom; - - atom.m_uds = TDEIO::UDS_NAME; - atom.m_str = TQString::null; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFDIR; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - atom.m_str = "root"; - entry.append( atom ); - atom.m_uds = TDEIO::UDS_GROUP; - entry.append( atom ); - - // no size - - statEntry( entry ); - finished(); - return; - } - - KURL tempurl( url ); - tempurl.setPath( path ); // take the clean one - TQString listarg; // = tempurl.directory(false /*keep trailing slash*/); - TQString parentDir; - TQString filename = tempurl.fileName(); - Q_ASSERT(!filename.isEmpty()); - TQString search = filename; - - // Try cwd into it, if it works it's a dir (and then we'll list the parent directory to get more info) - // if it doesn't work, it's a file (and then we'll use dir filename) - bool isDir = ftpFolder(path, false); - - // if we're only interested in "file or directory", we should stop here - TQString sDetails = metaData("details"); - int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); - kdDebug(7102) << "Ftp::stat details=" << details << endl; - if ( details == 0 ) - { - if ( !isDir && !ftpSize( path, 'I' ) ) // ok, not a dir -> is it a file ? - { // no -> it doesn't exist at all - ftpStatAnswerNotFound( path, filename ); - return; - } - ftpShortStatAnswer( filename, isDir ); // successfully found a dir or a file -> done - return; - } - - if (!isDir) - { - // It is a file or it doesn't exist, try going to parent directory - parentDir = tempurl.directory(false /*keep trailing slash*/); - // With files we can do "LIST " to avoid listing the whole dir - listarg = filename; - } - else - { - // --- New implementation: - // Don't list the parent dir. Too slow, might not show it, etc. - // Just return that it's a dir. - UDSEntry entry; - UDSAtom atom; - - atom.m_uds = TDEIO::UDS_NAME; - atom.m_str = filename; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFDIR; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - entry.append( atom ); - - // No clue about size, ownership, group, etc. - - statEntry(entry); - finished(); - return; - - // --- Old implementation: -#if 0 - // It's a dir, remember that - // Reason: it could be a symlink to a dir, in which case ftpReadDir - // in the parent dir will have no idea about that. But we know better. - isDir = true; - // If the dir starts with '.', we'll need '-a' to see it in the listing. - if ( search[0] == '.' ) - listarg = "-a"; - parentDir = ".."; -#endif - } - - // Now cwd the parent dir, to prepare for listing - if( !ftpFolder(parentDir, true) ) - return; - - if( !ftpOpenCommand( "list", listarg, 'I', ERR_DOES_NOT_EXIST ) ) - { - kdError(7102) << "COULD NOT LIST" << endl; - return; - } - kdDebug(7102) << "Starting of list was ok" << endl; - - Q_ASSERT( !search.isEmpty() && search != "/" ); - - bool bFound = false; - KURL linkURL; - FtpEntry ftpEnt; - while( ftpReadDir(ftpEnt) ) - { - // We look for search or filename, since some servers (e.g. ftp.tuwien.ac.at) - // return only the filename when doing "dir /full/path/to/file" - if ( !bFound ) - { - if ( ( search == ftpEnt.name || filename == ftpEnt.name ) ) { - if ( !filename.isEmpty() ) { - bFound = true; - UDSEntry entry; - ftpCreateUDSEntry( filename, ftpEnt, entry, isDir ); - statEntry( entry ); - } - } else if ( isDir && ( ftpEnt.name == listarg || ftpEnt.name+'/' == listarg ) ) { - // Damn, the dir we're trying to list is in fact a symlink - // Follow it and try again - if ( ftpEnt.link.isEmpty() ) - kdWarning(7102) << "Got " << listarg << " as answer, but empty link!" << endl; - else - { - linkURL = url; - kdDebug(7102) << "ftpEnt.link=" << ftpEnt.link << endl; - if ( ftpEnt.link[0] == '/' ) - linkURL.setPath( ftpEnt.link ); // Absolute link - else - { - // Relative link (stat will take care of cleaning ../.. etc.) - linkURL.setPath( listarg ); // this is what we were listing (the link) - linkURL.setPath( linkURL.directory() ); // go up one dir - linkURL.addPath( ftpEnt.link ); // replace link by its destination - kdDebug(7102) << "linkURL now " << linkURL.prettyURL() << endl; - } - // Re-add the filename we're looking for - linkURL.addPath( filename ); - } - bFound = true; - } - } - - // kdDebug(7102) << ftpEnt.name << endl; - } - - ftpCloseCommand(); // closes the data connection only - - if ( !bFound ) - { - ftpStatAnswerNotFound( path, filename ); - return; - } - - if ( !linkURL.isEmpty() ) - { - if ( linkURL == url || linkURL == tempurl ) - { - error( ERR_CYCLIC_LINK, linkURL.prettyURL() ); - return; - } - stat( linkURL ); - return; - } - - kdDebug(7102) << "stat : finished successfully" << endl; - finished(); -} - - -void Ftp::listDir( const KURL &url ) -{ - kdDebug(7102) << "Ftp::listDir " << url.prettyURL() << endl; - if( !ftpOpenConnection(loginImplicit) ) - return; - - // No path specified ? - TQString path = url.path(); - if ( path.isEmpty() ) - { - KURL realURL; - realURL.setProtocol( "ftp" ); - if ( m_user != FTP_LOGIN ) - realURL.setUser( m_user ); - // We set the password, so that we don't ask for it if it was given - if ( m_pass != FTP_PASSWD ) - realURL.setPass( m_pass ); - realURL.setHost( m_host ); - realURL.setPort( m_port ); - if ( m_initialPath.isEmpty() ) - m_initialPath = "/"; - realURL.setPath( m_initialPath ); - kdDebug(7102) << "REDIRECTION to " << realURL.prettyURL() << endl; - redirection( realURL ); - finished(); - return; - } - - kdDebug(7102) << "hunting for path '" << path << "'" << endl; - - if (!ftpOpenDir( path ) ) - { - if ( ftpSize( path, 'I' ) ) // is it a file ? - { - error( ERR_IS_FILE, path ); - return; - } - // not sure which to emit - //error( ERR_DOES_NOT_EXIST, path ); - error( ERR_CANNOT_ENTER_DIRECTORY, path ); - return; - } - - UDSEntry entry; - FtpEntry ftpEnt; - while( ftpReadDir(ftpEnt) ) - { - //kdDebug(7102) << ftpEnt.name << endl; - //Q_ASSERT( !ftpEnt.name.isEmpty() ); - if ( !ftpEnt.name.isEmpty() ) - { - //if ( S_ISDIR( (mode_t)ftpEnt.type ) ) - // kdDebug(7102) << "is a dir" << endl; - //if ( !ftpEnt.link.isEmpty() ) - // kdDebug(7102) << "is a link to " << ftpEnt.link << endl; - entry.clear(); - ftpCreateUDSEntry( ftpEnt.name, ftpEnt, entry, false ); - listEntry( entry, false ); - } - } - listEntry( entry, true ); // ready - ftpCloseCommand(); // closes the data connection only - finished(); -} - -void Ftp::slave_status() -{ - kdDebug(7102) << "Got slave_status host = " << (m_host.ascii() ? m_host.ascii() : "[None]") << " [" << (m_bLoggedOn ? "Connected" : "Not connected") << "]" << endl; - slaveStatus( m_host, m_bLoggedOn ); -} - -bool Ftp::ftpOpenDir( const TQString & path ) -{ - //TQString path( _url.path(-1) ); - - // We try to change to this directory first to see whether it really is a directory. - // (And also to follow symlinks) - TQString tmp = path.isEmpty() ? TQString("/") : path; - - // We get '550', whether it's a file or doesn't exist... - if( !ftpFolder(tmp, false) ) - return false; - - // Don't use the path in the list command: - // We changed into this directory anyway - so it's enough just to send "list". - // We use '-a' because the application MAY be interested in dot files. - // The only way to really know would be to have a metadata flag for this... - // Since some windows ftp server seems not to support the -a argument, we use a fallback here. - // In fact we have to use -la otherwise -a removes the default -l (e.g. ftp.trolltech.com) - if( !ftpOpenCommand( "list -la", TQString::null, 'I', ERR_CANNOT_ENTER_DIRECTORY ) ) - { - if ( !ftpOpenCommand( "list", TQString::null, 'I', ERR_CANNOT_ENTER_DIRECTORY ) ) - { - kdWarning(7102) << "Can't open for listing" << endl; - return false; - } - } - kdDebug(7102) << "Starting of list was ok" << endl; - return true; -} - -bool Ftp::ftpReadDir(FtpEntry& de) -{ - assert(m_data != NULL); - - // get a line from the data connecetion ... - while( !m_data->textEOF() ) - { - if(m_data->textRead() <= 0) - continue; - if(m_data->textTooLong()) - kdWarning(7102) << "ftpReadDir line too long - truncated" << endl; - - const char* buffer = m_data->textLine(); - kdDebug(7102) << "dir > " << buffer << endl; - - //Normally the listing looks like - // -rw-r--r-- 1 dfaure dfaure 102 Nov 9 12:30 log - // but on Netware servers like ftp://ci-1.ci.pwr.wroc.pl/ it looks like (#76442) - // d [RWCEAFMS] Admin 512 Oct 13 2004 PSI - - // we should always get the following 5 fields ... - const char *p_access, *p_junk, *p_owner, *p_group, *p_size; - if( (p_access = strtok((char*)buffer," ")) == 0) continue; - if( (p_junk = strtok(NULL," ")) == 0) continue; - if( (p_owner = strtok(NULL," ")) == 0) continue; - if( (p_group = strtok(NULL," ")) == 0) continue; - if( (p_size = strtok(NULL," ")) == 0) continue; - - //kdDebug(7102) << "p_access=" << p_access << " p_junk=" << p_junk << " p_owner=" << p_owner << " p_group=" << p_group << " p_size=" << p_size << endl; - - de.access = 0; - if ( strlen( p_access ) == 1 && p_junk[0] == '[' ) { // Netware - de.access = S_IRWXU | S_IRWXG | S_IRWXO; // unknown -> give all permissions - } - - const char *p_date_1, *p_date_2, *p_date_3, *p_name; - - // A special hack for "/dev". A listing may look like this: - // crw-rw-rw- 1 root root 1, 5 Jun 29 1997 zero - // So we just ignore the number in front of the ",". Ok, its a hack :-) - if ( strchr( p_size, ',' ) != 0L ) - { - //kdDebug(7102) << "Size contains a ',' -> reading size again (/dev hack)" << endl; - if ((p_size = strtok(NULL," ")) == 0) - continue; - } - - // Check whether the size we just read was really the size - // or a month (this happens when the server lists no group) - // Used to be the case on sunsite.uio.no, but not anymore - // This is needed for the Netware case, too. - if ( !isdigit( *p_size ) ) - { - p_date_1 = p_size; - p_size = p_group; - p_group = 0; - //kdDebug(7102) << "Size didn't have a digit -> size=" << p_size << " date_1=" << p_date_1 << endl; - } - else - { - p_date_1 = strtok(NULL," "); - //kdDebug(7102) << "Size has a digit -> ok. p_date_1=" << p_date_1 << endl; - } - - if ( p_date_1 != 0 && - (p_date_2 = strtok(NULL," ")) != 0 && - (p_date_3 = strtok(NULL," ")) != 0 && - (p_name = strtok(NULL,"\r\n")) != 0 ) - { - { - TQCString tmp( p_name ); - if ( p_access[0] == 'l' ) - { - int i = tmp.findRev( " -> " ); - if ( i != -1 ) { - de.link = remoteEncoding()->decode(p_name + i + 4); - tmp.truncate( i ); - } - else - de.link = TQString::null; - } - else - de.link = TQString::null; - - if ( tmp[0] == '/' ) // listing on ftp://ftp.gnupg.org/ starts with '/' - tmp.remove( 0, 1 ); - - if (tmp.find('/') != -1) - continue; // Don't trick us! - // Some sites put more than one space between the date and the name - // e.g. ftp://ftp.uni-marburg.de/mirror/ - de.name = remoteEncoding()->decode(tmp.stripWhiteSpace()); - } - - de.type = S_IFREG; - switch ( p_access[0] ) { - case 'd': - de.type = S_IFDIR; - break; - case 's': - de.type = S_IFSOCK; - break; - case 'b': - de.type = S_IFBLK; - break; - case 'c': - de.type = S_IFCHR; - break; - case 'l': - de.type = S_IFREG; - // we don't set S_IFLNK here. de.link says it. - break; - default: - break; - } - - if ( p_access[1] == 'r' ) - de.access |= S_IRUSR; - if ( p_access[2] == 'w' ) - de.access |= S_IWUSR; - if ( p_access[3] == 'x' || p_access[3] == 's' ) - de.access |= S_IXUSR; - if ( p_access[4] == 'r' ) - de.access |= S_IRGRP; - if ( p_access[5] == 'w' ) - de.access |= S_IWGRP; - if ( p_access[6] == 'x' || p_access[6] == 's' ) - de.access |= S_IXGRP; - if ( p_access[7] == 'r' ) - de.access |= S_IROTH; - if ( p_access[8] == 'w' ) - de.access |= S_IWOTH; - if ( p_access[9] == 'x' || p_access[9] == 't' ) - de.access |= S_IXOTH; - if ( p_access[3] == 's' || p_access[3] == 'S' ) - de.access |= S_ISUID; - if ( p_access[6] == 's' || p_access[6] == 'S' ) - de.access |= S_ISGID; - if ( p_access[9] == 't' || p_access[9] == 'T' ) - de.access |= S_ISVTX; - - de.owner = remoteEncoding()->decode(p_owner); - de.group = remoteEncoding()->decode(p_group); - de.size = charToLongLong(p_size); - - // Parsing the date is somewhat tricky - // Examples : "Oct 6 22:49", "May 13 1999" - - // First get current time - we need the current month and year - time_t currentTime = time( 0L ); - struct tm * tmptr = gmtime( ¤tTime ); - int currentMonth = tmptr->tm_mon; - //kdDebug(7102) << "Current time :" << asctime( tmptr ) << endl; - // Reset time fields - tmptr->tm_isdst = -1; // We do not know anything about day saving time (of any random day of the year) - tmptr->tm_sec = 0; - tmptr->tm_min = 0; - tmptr->tm_hour = 0; - // Get day number (always second field) - tmptr->tm_mday = atoi( p_date_2 ); - // Get month from first field - // NOTE : no, we don't want to use TDELocale here - // It seems all FTP servers use the English way - //kdDebug(7102) << "Looking for month " << p_date_1 << endl; - static const char * s_months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - for ( int c = 0 ; c < 12 ; c ++ ) - if ( !strcmp( p_date_1, s_months[c]) ) - { - //kdDebug(7102) << "Found month " << c << " for " << p_date_1 << endl; - tmptr->tm_mon = c; - break; - } - - // Parse third field - if ( strlen( p_date_3 ) == 4 ) // 4 digits, looks like a year - tmptr->tm_year = atoi( p_date_3 ) - 1900; - else - { - // otherwise, the year is implicit - // according to man ls, this happens when it is between than 6 months - // old and 1 hour in the future. - // So the year is : current year if tm_mon <= currentMonth+1 - // otherwise current year minus one - // (The +1 is a security for the "+1 hour" at the end of the month issue) - if ( tmptr->tm_mon > currentMonth + 1 ) - tmptr->tm_year--; - - // and p_date_3 contains probably a time - char * semicolon; - if ( ( semicolon = const_cast(strchr( p_date_3, ':' )) ) ) - { - *semicolon = '\0'; - tmptr->tm_min = atoi( semicolon + 1 ); - tmptr->tm_hour = atoi( p_date_3 ); - } - else - kdWarning(7102) << "Can't parse third field " << p_date_3 << endl; - } - - //kdDebug(7102) << asctime( tmptr ) << endl; - de.date = mktime( tmptr ); - return true; - } - } // line invalid, loop to get another line - return false; -} - -//=============================================================================== -// public: get download file from server -// helper: ftpGet called from get() and copy() -//=============================================================================== -void Ftp::get( const KURL & url ) -{ - kdDebug(7102) << "Ftp::get " << url.url() << endl; - int iError = 0; - ftpGet(iError, -1, url, 0); // iError gets status - if(iError) // can have only server side errs - error(iError, url.path()); - ftpCloseCommand(); // must close command! -} - -Ftp::StatusCode Ftp::ftpGet(int& iError, int iCopyFile, const KURL& url, TDEIO::fileoffset_t llOffset) -{ - // Calls error() by itself! - if( !ftpOpenConnection(loginImplicit) ) - return statusServerError; - - // Try to find the size of the file (and check that it exists at - // the same time). If we get back a 550, "File does not exist" - // or "not a plain file", check if it is a directory. If it is a - // directory, return an error; otherwise simply try to retrieve - // the request... - if ( !ftpSize( url.path(), '?' ) && (m_iRespCode == 550) && - ftpFolder(url.path(), false) ) - { - // Ok it's a dir in fact - kdDebug(7102) << "ftpGet: it is a directory in fact" << endl; - iError = ERR_IS_DIRECTORY; - return statusServerError; - } - - TQString resumeOffset = metaData("resume"); - if ( !resumeOffset.isEmpty() ) - { - llOffset = resumeOffset.toLongLong(); - kdDebug(7102) << "ftpGet: got offset from metadata : " << llOffset << endl; - } - - if( !ftpOpenCommand("retr", url.path(), '?', ERR_CANNOT_OPEN_FOR_READING, llOffset) ) - { - kdWarning(7102) << "ftpGet: Can't open for reading" << endl; - return statusServerError; - } - - // Read the size from the response string - if(m_size == UnknownSize) - { - const char* psz = strrchr( ftpResponse(4), '(' ); - if(psz) m_size = charToLongLong(psz+1); - if (!m_size) m_size = UnknownSize; - } - - TDEIO::filesize_t bytesLeft = 0; - if ( m_size != UnknownSize ) - bytesLeft = m_size - llOffset; - - kdDebug(7102) << "ftpGet: starting with offset=" << llOffset << endl; - TDEIO::fileoffset_t processed_size = llOffset; - - TQByteArray array; - bool mimetypeEmitted = false; - char buffer[maximumIpcSize]; - // start whith small data chunks in case of a slow data source (modem) - // - unfortunately this has a negative impact on performance for large - // - files - so we will increase the block size after a while ... - int iBlockSize = initialIpcSize; - int iBufferCur = 0; - - while(m_size == UnknownSize || bytesLeft > 0) - { // let the buffer size grow if the file is larger 64kByte ... - if(processed_size-llOffset > 1024 * 64) - iBlockSize = maximumIpcSize; - - // read the data and detect EOF or error ... - if(iBlockSize+iBufferCur > (int)sizeof(buffer)) - iBlockSize = sizeof(buffer) - iBufferCur; - int n = m_data->read( buffer+iBufferCur, iBlockSize ); - if(n <= 0) - { // this is how we detect EOF in case of unknown size - if( m_size == UnknownSize && n == 0 ) - break; - // unexpected eof. Happens when the daemon gets killed. - iError = ERR_COULD_NOT_READ; - return statusServerError; - } - processed_size += n; - - // collect very small data chunks in buffer before processing ... - if(m_size != UnknownSize) - { - bytesLeft -= n; - iBufferCur += n; - if(iBufferCur < mimimumMimeSize && bytesLeft > 0) - { - processedSize( processed_size ); - continue; - } - n = iBufferCur; - iBufferCur = 0; - } - - // get the mime type and set the total size ... - if(!mimetypeEmitted) - { - mimetypeEmitted = true; - - // We need a KMimeType::findByNameAndContent(data,filename) - // For now we do: find by extension, and if not found (or extension not reliable) - // then find by content. - bool accurate = false; - KMimeType::Ptr mime = KMimeType::findByURL( url, 0, false, true, &accurate ); - if ( !mime || mime->name() == KMimeType::defaultMimeType() - || !accurate ) - { - array.setRawData(buffer, n); - KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType(array, url.fileName()); - array.resetRawData(buffer, n); - if ( result->mimeType() != KMimeType::defaultMimeType() ) - mime = KMimeType::mimeType( result->mimeType() ); - } - - kdDebug(7102) << "ftpGet: Emitting mimetype " << mime->name() << endl; - mimeType( mime->name() ); - if( m_size != UnknownSize ) // Emit total size AFTER mimetype - totalSize( m_size ); - } - - // write output file or pass to data pump ... - if(iCopyFile == -1) - { - array.setRawData(buffer, n); - data( array ); - array.resetRawData(buffer, n); - } - else if( (iError = WriteToFile(iCopyFile, buffer, n)) != 0) - return statusClientError; // client side error - processedSize( processed_size ); - } - - kdDebug(7102) << "ftpGet: done" << endl; - if(iCopyFile == -1) // must signal EOF to data pump ... - data(array); // array is empty and must be empty! - - processedSize( m_size == UnknownSize ? processed_size : m_size ); - kdDebug(7102) << "ftpGet: emitting finished()" << endl; - finished(); - return statusSuccess; -} - -/* -void Ftp::mimetype( const KURL& url ) -{ - if( !ftpOpenConnection(loginImplicit) ) - return; - - if ( !ftpOpenCommand( "retr", url.path(), 'I', ERR_CANNOT_OPEN_FOR_READING, 0 ) ) { - kdWarning(7102) << "Can't open for reading" << endl; - return; - } - char buffer[ 2048 ]; - TQByteArray array; - // Get one chunk of data only and send it, TDEIO::Job will determine the - // mimetype from it using KMimeMagic - int n = m_data->read( buffer, 2048 ); - array.setRawData(buffer, n); - data( array ); - array.resetRawData(buffer, n); - - kdDebug(7102) << "aborting" << endl; - ftpAbortTransfer(); - - kdDebug(7102) << "finished" << endl; - finished(); - kdDebug(7102) << "after finished" << endl; -} - -void Ftp::ftpAbortTransfer() -{ - // RFC 959, page 34-35 - // IAC (interpret as command) = 255 ; IP (interrupt process) = 254 - // DM = 242 (data mark) - char msg[4]; - // 1. User system inserts the Telnet "Interrupt Process" (IP) signal - // in the Telnet stream. - msg[0] = (char) 255; //IAC - msg[1] = (char) 254; //IP - (void) send(sControl, msg, 2, 0); - // 2. User system sends the Telnet "Sync" signal. - msg[0] = (char) 255; //IAC - msg[1] = (char) 242; //DM - if (send(sControl, msg, 2, MSG_OOB) != 2) - ; // error... - - // Send ABOR - kdDebug(7102) << "send ABOR" << endl; - TQCString buf = "ABOR\r\n"; - if ( KSocks::self()->write( sControl, buf.data(), buf.length() ) <= 0 ) { - error( ERR_COULD_NOT_WRITE, TQString::null ); - return; - } - - // - kdDebug(7102) << "read resp" << endl; - if ( readresp() != '2' ) - { - error( ERR_COULD_NOT_READ, TQString::null ); - return; - } - - kdDebug(7102) << "close sockets" << endl; - closeSockets(); -} -*/ - -//=============================================================================== -// public: put upload file to server -// helper: ftpPut called from put() and copy() -//=============================================================================== -void Ftp::put(const KURL& url, int permissions, bool overwrite, bool resume) -{ - kdDebug(7102) << "Ftp::put " << url.url() << endl; - int iError = 0; // iError gets status - ftpPut(iError, -1, url, permissions, overwrite, resume); - if(iError) // can have only server side errs - error(iError, url.path()); - ftpCloseCommand(); // must close command! -} - -Ftp::StatusCode Ftp::ftpPut(int& iError, int iCopyFile, const KURL& dest_url, - int permissions, bool overwrite, bool resume) -{ - if( !ftpOpenConnection(loginImplicit) ) - return statusServerError; - - // Don't use mark partial over anonymous FTP. - // My incoming dir allows put but not rename... - bool bMarkPartial; - if (m_user.isEmpty () || m_user == FTP_LOGIN) - bMarkPartial = false; - else - bMarkPartial = config()->readBoolEntry("MarkPartial", true); - - TQString dest_orig = dest_url.path(); - TQString dest_part( dest_orig ); - dest_part += ".part"; - - if ( ftpSize( dest_orig, 'I' ) ) - { - if ( m_size == 0 ) - { // delete files with zero size - TQCString cmd = "DELE "; - cmd += remoteEncoding()->encode(dest_orig); - if( !ftpSendCmd( cmd ) || (m_iRespType != 2) ) - { - iError = ERR_CANNOT_DELETE_PARTIAL; - return statusServerError; - } - } - else if ( !overwrite && !resume ) - { - iError = ERR_FILE_ALREADY_EXIST; - return statusServerError; - } - else if ( bMarkPartial ) - { // when using mark partial, append .part extension - if ( !ftpRename( dest_orig, dest_part, true ) ) - { - iError = ERR_CANNOT_RENAME_PARTIAL; - return statusServerError; - } - } - // Don't chmod an existing file - permissions = -1; - } - else if ( bMarkPartial && ftpSize( dest_part, 'I' ) ) - { // file with extension .part exists - if ( m_size == 0 ) - { // delete files with zero size - TQCString cmd = "DELE "; - cmd += remoteEncoding()->encode(dest_part); - if ( !ftpSendCmd( cmd ) || (m_iRespType != 2) ) - { - iError = ERR_CANNOT_DELETE_PARTIAL; - return statusServerError; - } - } - else if ( !overwrite && !resume ) - { - resume = canResume (m_size); - if (!resume) - { - iError = ERR_FILE_ALREADY_EXIST; - return statusServerError; - } - } - } - else - m_size = 0; - - TQString dest; - - // if we are using marking of partial downloads -> add .part extension - if ( bMarkPartial ) { - kdDebug(7102) << "Adding .part extension to " << dest_orig << endl; - dest = dest_part; - } else - dest = dest_orig; - - TDEIO::fileoffset_t offset = 0; - - // set the mode according to offset - if( resume && m_size > 0 ) - { - offset = m_size; - if(iCopyFile != -1) - { - if( KDE_lseek(iCopyFile, offset, SEEK_SET) < 0 ) - { - iError = ERR_CANNOT_RESUME; - return statusClientError; - } - } - } - - if (! ftpOpenCommand( "stor", dest, '?', ERR_COULD_NOT_WRITE, offset ) ) - return statusServerError; - - kdDebug(7102) << "ftpPut: starting with offset=" << offset << endl; - TDEIO::fileoffset_t processed_size = offset; - - TQByteArray buffer; - int result; - int iBlockSize = initialIpcSize; - // Loop until we got 'dataEnd' - do - { - if(iCopyFile == -1) - { - dataReq(); // Request for data - result = readData( buffer ); - } - else - { // let the buffer size grow if the file is larger 64kByte ... - if(processed_size-offset > 1024 * 64) - iBlockSize = maximumIpcSize; - buffer.resize(iBlockSize); - result = ::read(iCopyFile, buffer.data(), buffer.size()); - if(result < 0) - iError = ERR_COULD_NOT_WRITE; - else - buffer.resize(result); - } - - if (result > 0) - { - m_data->write( buffer.data(), buffer.size() ); - processed_size += result; - processedSize (processed_size); - } - } - while ( result > 0 ); - - if (result != 0) // error - { - ftpCloseCommand(); // don't care about errors - kdDebug(7102) << "Error during 'put'. Aborting." << endl; - if (bMarkPartial) - { - // Remove if smaller than minimum size - if ( ftpSize( dest, 'I' ) && - ( processed_size < (unsigned long) config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE) ) ) - { - TQCString cmd = "DELE "; - cmd += remoteEncoding()->encode(dest); - (void) ftpSendCmd( cmd ); - } - } - return statusServerError; - } - - if ( !ftpCloseCommand() ) - { - iError = ERR_COULD_NOT_WRITE; - return statusServerError; - } - - // after full download rename the file back to original name - if ( bMarkPartial ) - { - kdDebug(7102) << "renaming dest (" << dest << ") back to dest_orig (" << dest_orig << ")" << endl; - if ( !ftpRename( dest, dest_orig, true ) ) - { - iError = ERR_CANNOT_RENAME_PARTIAL; - return statusServerError; - } - } - - // set final permissions - if ( permissions != -1 ) - { - if ( m_user == FTP_LOGIN ) - kdDebug(7102) << "Trying to chmod over anonymous FTP ???" << endl; - // chmod the file we just put - if ( ! ftpChmod( dest_orig, permissions ) ) - { - // To be tested - //if ( m_user != FTP_LOGIN ) - // warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) ); - } - } - - // We have done our job => finish - finished(); - return statusSuccess; -} - - -/** Use the SIZE command to get the file size. - Warning : the size depends on the transfer mode, hence the second arg. */ -bool Ftp::ftpSize( const TQString & path, char mode ) -{ - m_size = UnknownSize; - if( !ftpDataMode(mode) ) - return false; - - TQCString buf; - buf = "SIZE "; - buf += remoteEncoding()->encode(path); - if( !ftpSendCmd( buf ) || (m_iRespType != 2) ) - return false; - - // skip leading "213 " (response code) - const char* psz = ftpResponse(4); - if(!psz) - return false; - m_size = charToLongLong(psz); - if (!m_size) m_size = UnknownSize; - return true; -} - -bool Ftp::ftpFileExists(const TQString& path) -{ - TQCString buf; - buf = "SIZE "; - buf += remoteEncoding()->encode(path); - if( !ftpSendCmd( buf ) || (m_iRespType != 2) ) - return false; - - // skip leading "213 " (response code) - const char* psz = ftpResponse(4); - return psz != 0; -} - -// Today the differences between ASCII and BINARY are limited to -// CR or CR/LF line terminators. Many servers ignore ASCII (like -// win2003 -or- vsftp with default config). In the early days of -// computing, when even text-files had structure, this stuff was -// more important. -// Theoretically "list" could return different results in ASCII -// and BINARY mode. But again, most servers ignore ASCII here. -bool Ftp::ftpDataMode(char cMode) -{ - if(cMode == '?') cMode = m_bTextMode ? 'A' : 'I'; - else if(cMode == 'a') cMode = 'A'; - else if(cMode != 'A') cMode = 'I'; - - kdDebug(7102) << "ftpDataMode: want '" << cMode << "' has '" << m_cDataMode << "'" << endl; - if(m_cDataMode == cMode) - return true; - - TQCString buf; - buf.sprintf("TYPE %c", cMode); - if( !ftpSendCmd(buf) || (m_iRespType != 2) ) - return false; - m_cDataMode = cMode; - return true; -} - - -bool Ftp::ftpFolder(const TQString& path, bool bReportError) -{ - TQString newPath = path; - int iLen = newPath.length(); - if(iLen > 1 && newPath[iLen-1] == '/') newPath.truncate(iLen-1); - - //kdDebug(7102) << "ftpFolder: want '" << newPath << "' has '" << m_currentPath << "'" << endl; - if(m_currentPath == newPath) - return true; - - TQCString tmp = "cwd "; - tmp += remoteEncoding()->encode(newPath); - if( !ftpSendCmd(tmp) ) - return false; // connection failure - if(m_iRespType != 2) - { - if(bReportError) - error(ERR_CANNOT_ENTER_DIRECTORY, path); - return false; // not a folder - } - m_currentPath = newPath; - return true; -} - - -//=============================================================================== -// public: copy don't use tdeio data pump if one side is a local file -// helper: ftpCopyPut called from copy() on upload -// helper: ftpCopyGet called from copy() on download -//=============================================================================== -void Ftp::copy( const KURL &src, const KURL &dest, int permissions, bool overwrite ) -{ - int iError = 0; - int iCopyFile = -1; - StatusCode cs = statusSuccess; - bool bSrcLocal = src.isLocalFile(); - bool bDestLocal = dest.isLocalFile(); - TQString sCopyFile; - - if(bSrcLocal && !bDestLocal) // File -> Ftp - { - sCopyFile = src.path(); - kdDebug(7102) << "Ftp::copy local file '" << sCopyFile << "' -> ftp '" << dest.path() << "'" << endl; - cs = ftpCopyPut(iError, iCopyFile, sCopyFile, dest, permissions, overwrite); - if( cs == statusServerError) sCopyFile = dest.url(); - } - else if(!bSrcLocal && bDestLocal) // Ftp -> File - { - sCopyFile = dest.path(); - kdDebug(7102) << "Ftp::copy ftp '" << src.path() << "' -> local file '" << sCopyFile << "'" << endl; - cs = ftpCopyGet(iError, iCopyFile, sCopyFile, src, permissions, overwrite); - if( cs == statusServerError ) sCopyFile = src.url(); - } - else { - error( ERR_UNSUPPORTED_ACTION, TQString::null ); - return; - } - - // perform clean-ups and report error (if any) - if(iCopyFile != -1) - ::close(iCopyFile); - if(iError) - error(iError, sCopyFile); - ftpCloseCommand(); // must close command! -} - - -Ftp::StatusCode Ftp::ftpCopyPut(int& iError, int& iCopyFile, TQString sCopyFile, - const KURL& url, int permissions, bool overwrite) -{ - // check if source is ok ... - KDE_struct_stat buff; - TQCString sSrc( TQFile::encodeName(sCopyFile) ); - bool bSrcExists = (KDE_stat( sSrc.data(), &buff ) != -1); - if(bSrcExists) - { if(S_ISDIR(buff.st_mode)) - { - iError = ERR_IS_DIRECTORY; - return statusClientError; - } - } - else - { - iError = ERR_DOES_NOT_EXIST; - return statusClientError; - } - - iCopyFile = KDE_open( sSrc.data(), O_RDONLY ); - if(iCopyFile == -1) - { - iError = ERR_CANNOT_OPEN_FOR_READING; - return statusClientError; - } - - // delegate the real work (iError gets status) ... - totalSize(buff.st_size); -#ifdef ENABLE_CAN_RESUME - return ftpPut(iError, iCopyFile, url, permissions, overwrite, false); -#else - return ftpPut(iError, iCopyFile, url, permissions, overwrite, true); -#endif -} - - -Ftp::StatusCode Ftp::ftpCopyGet(int& iError, int& iCopyFile, const TQString sCopyFile, - const KURL& url, int permissions, bool overwrite) -{ - // check if destination is ok ... - KDE_struct_stat buff; - TQCString sDest( TQFile::encodeName(sCopyFile) ); - bool bDestExists = (KDE_stat( sDest.data(), &buff ) != -1); - if(bDestExists) - { if(S_ISDIR(buff.st_mode)) - { - iError = ERR_IS_DIRECTORY; - return statusClientError; - } - if(!overwrite) - { - iError = ERR_FILE_ALREADY_EXIST; - return statusClientError; - } - } - - // do we have a ".part" file? - TQCString sPart = TQFile::encodeName(sCopyFile + ".part"); - bool bResume = false; - bool bPartExists = (KDE_stat( sPart.data(), &buff ) != -1); - const bool bMarkPartial = config()->readBoolEntry("MarkPartial", true); - - if(!bMarkPartial) - { - sPart = TQFile::encodeName(sCopyFile); - } - else if(bPartExists && buff.st_size > 0) - { // must not be a folder! please fix a similar bug in tdeio_file!! - if(S_ISDIR(buff.st_mode)) - { - iError = ERR_DIR_ALREADY_EXIST; - return statusClientError; // client side error - } - //doesn't work for copy? -> design flaw? -#ifdef ENABLE_CAN_RESUME - bResume = canResume( buff.st_size ); -#else - bResume = true; -#endif - } - - if(bPartExists && !bResume) // get rid of an unwanted ".part" file - remove(sPart.data()); - - // JPF: in tdeio_file overwrite disables ".part" operations. I do not believe - // JPF: that this is a good behaviour! - if(bDestExists) // must delete for overwrite - remove(sDest.data()); - - // WABA: Make sure that we keep writing permissions ourselves, - // otherwise we can be in for a surprise on NFS. - mode_t initialMode; - if (permissions != -1) - initialMode = permissions | S_IWUSR; - else - initialMode = 0666; - - // open the output file ... - TDEIO::fileoffset_t hCopyOffset = 0; - if(bResume) - { - iCopyFile = KDE_open( sPart.data(), O_RDWR ); // append if resuming - hCopyOffset = KDE_lseek(iCopyFile, 0, SEEK_END); - if(hCopyOffset < 0) - { - iError = ERR_CANNOT_RESUME; - return statusClientError; // client side error - } - kdDebug(7102) << "copy: resuming at " << hCopyOffset << endl; - } - else - iCopyFile = KDE_open(sPart.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); - - if(iCopyFile == -1) - { - kdDebug(7102) << "copy: ### COULD NOT WRITE " << sCopyFile << endl; - iError = (errno == EACCES) ? ERR_WRITE_ACCESS_DENIED - : ERR_CANNOT_OPEN_FOR_WRITING; - return statusClientError; - } - - // delegate the real work (iError gets status) ... - StatusCode iRes = ftpGet(iError, iCopyFile, url, hCopyOffset); - if( ::close(iCopyFile) && iRes == statusSuccess ) - { - iError = ERR_COULD_NOT_WRITE; - iRes = statusClientError; - } - - // handle renaming or deletion of a partial file ... - if(bMarkPartial) - { - if(iRes == statusSuccess) - { // rename ".part" on success - if ( ::rename( sPart.data(), sDest.data() ) ) - { - kdDebug(7102) << "copy: cannot rename " << sPart << " to " << sDest << endl; - iError = ERR_CANNOT_RENAME_PARTIAL; - iRes = statusClientError; - } - } - else if(KDE_stat( sPart.data(), &buff ) == 0) - { // should a very small ".part" be deleted? - int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); - if (buff.st_size < size) - remove(sPart.data()); - } - } - return iRes; -} diff --git a/tdeioslave/ftp/ftp.cpp b/tdeioslave/ftp/ftp.cpp new file mode 100644 index 000000000..8e0f96b5d --- /dev/null +++ b/tdeioslave/ftp/ftp.cpp @@ -0,0 +1,2674 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Recommended reading explaining FTP details and quirks: + http://cr.yp.to/ftp.html (by D.J. Bernstein) +*/ + + +#define TDEIO_FTP_PRIVATE_INCLUDE +#include "ftp.h" + +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if TIME_WITH_SYS_TIME +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_STRTOLL + #define charToLongLong(a) strtoll(a, 0, 10) +#else + #define charToLongLong(a) strtol(a, 0, 10) +#endif + +// JPF: a remark on coding style (2004-03-06): +// Some calls to TQString::fromLatin1() were removed from the code. In most places +// the KDE code relies on implicit creation of QStrings. Also Qt has a lot of +// const char* overloads, so that using TQString::fromLatin1() can be ineffectient! + +#define FTP_LOGIN "anonymous" +#define FTP_PASSWD "anonymous@" + +//#undef kdDebug +#define ENABLE_CAN_RESUME + +// JPF: somebody should find a better solution for this or move this to TDEIO +// JPF: anyhow, in KDE 3.2.0 I found diffent MAX_IPC_SIZE definitions! +namespace TDEIO { + enum buffersizes + { /** + * largest buffer size that should be used to transfer data between + * TDEIO slaves using the data() function + */ + maximumIpcSize = 32 * 1024, + /** + * this is a reasonable value for an initial read() that a TDEIO slave + * can do to obtain data via a slow network connection. + */ + initialIpcSize = 2 * 1024, + /** + * recommended size of a data block passed to findBufferFileType() + */ + mimimumMimeSize = 1024 + }; + + // JPF: this helper was derived from write_all in file.cpp (FileProtocol). + static // JPF: in ftp.cpp we make it static + /** + * This helper handles some special issues (blocking and interrupted + * system call) when writing to a file handle. + * + * @return 0 on success or an error code on failure (ERR_COULD_NOT_WRITE, + * ERR_DISK_FULL, ERR_CONNECTION_BROKEN). + */ + int WriteToFile(int fd, const char *buf, size_t len) + { + while (len > 0) + { // JPF: shouldn't there be a KDE_write? + ssize_t written = write(fd, buf, len); + if (written >= 0) + { buf += written; + len -= written; + continue; + } + switch(errno) + { case EINTR: continue; + case EPIPE: return ERR_CONNECTION_BROKEN; + case ENOSPC: return ERR_DISK_FULL; + default: return ERR_COULD_NOT_WRITE; + } + } + return 0; + } +} + +TDEIO::filesize_t Ftp::UnknownSize = (TDEIO::filesize_t)-1; + +using namespace TDEIO; + +extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } + +int kdemain( int argc, char **argv ) +{ + TDELocale::setMainCatalogue("tdelibs"); + TDEInstance instance( "tdeio_ftp" ); + ( void ) TDEGlobal::locale(); + + kdDebug(7102) << "Starting " << getpid() << endl; + + if (argc != 4) + { + fprintf(stderr, "Usage: tdeio_ftp protocol domain-socket1 domain-socket2\n"); + exit(-1); + } + + Ftp slave(argv[2], argv[3]); + slave.dispatchLoop(); + + kdDebug(7102) << "Done" << endl; + return 0; +} + +//=============================================================================== +// FtpTextReader Read Text lines from a file (or socket) +//=============================================================================== + +void FtpTextReader::textClear() +{ m_iTextLine = m_iTextBuff = 0; + m_szText[0] = 0; + m_bTextEOF = m_bTextTruncated = false; +} + +int FtpTextReader::textRead(FtpSocket *pSock) +{ + // if we have still buffered data then move it to the left + char* pEOL; + if(m_iTextLine < m_iTextBuff) + { m_iTextBuff -= m_iTextLine; + memmove(m_szText, m_szText+m_iTextLine, m_iTextBuff); + pEOL = (char*)memchr(m_szText, '\n', m_iTextBuff); // have a complete line? + } + else + { m_iTextBuff = 0; + pEOL = NULL; + } + m_bTextEOF = m_bTextTruncated = false; + + // read data from the control socket until a complete line is read + int nBytes; + while(pEOL == NULL) + { + if(m_iTextBuff > textReadLimit) + { m_bTextTruncated = true; + m_iTextBuff = textReadLimit; + } + nBytes = pSock->read(m_szText+m_iTextBuff, sizeof(m_szText)-m_iTextBuff); + if(nBytes <= 0) + { + // This error can occur after the server closed the connection (after a timeout) + if(nBytes < 0) + pSock->debugMessage("textRead failed"); + m_bTextEOF = true; + pEOL = m_szText + m_iTextBuff; + } + else + { + m_iTextBuff += nBytes; + pEOL = (char*)memchr(m_szText, '\n', m_iTextBuff); + } + } + + nBytes = pEOL - m_szText; + m_iTextLine = nBytes + 1; + + if(nBytes > textReadLimit) + { m_bTextTruncated = true; + nBytes = textReadLimit; + } + if(nBytes && m_szText[nBytes-1] == '\r') + nBytes--; + m_szText[nBytes] = 0; + return nBytes; +} + +//=============================================================================== +// FtpSocket Helper Class for Data or Control Connections +//=============================================================================== +void FtpSocket::debugMessage(const char* pszMsg) const +{ + kdDebug(7102) << m_pszName << ": " << pszMsg << endl; +} + +int FtpSocket::errorMessage(int iErrorCode, const char* pszMsg) const +{ + kdError(7102) << m_pszName << ": " << pszMsg << endl; + return iErrorCode; +} + +int FtpSocket::connectSocket(int iTimeOutSec, bool bControl) +{ + closeSocket(); + + int iOpt = bControl ? KExtendedSocket::inetSocket + : KExtendedSocket::noResolve; + setSocketFlags(iOpt | socketFlags()); + setTimeout(iTimeOutSec); + + int iCon = KExtendedSocket::connect(); + if(iCon < 0) + { int iErrorCode = (status() == IO_LookupError) + ? ERR_UNKNOWN_HOST : ERR_COULD_NOT_CONNECT; + TQString strMsg = KExtendedSocket::strError(status(), systemError()); + strMsg.prepend("connect failed (code %1): "); + return errorMessage(iErrorCode, TQString(strMsg.arg(iCon)).latin1()); + } + if( !setAddressReusable(true) ) + return errorMessage(ERR_COULD_NOT_CREATE_SOCKET, "setAddressReusable failed"); + + if(!bControl) + { int on=1; + if( !setSocketOption(SO_KEEPALIVE, (char *)&on, sizeof(on)) ) + errorMessage(0, "Keepalive not allowed"); + + struct linger lng = { 1, 120 }; + if( !setSocketOption(SO_LINGER, (char *)&lng, sizeof (lng)) ) + errorMessage(0, "Linger mode was not allowed."); + } + + debugMessage("connected"); + return 0; +} + +void FtpSocket::closeSocket() +{ + if(m_server != -1 || fd() != -1) + debugMessage("disconnected"); + + if(m_server != -1) + { + ::shutdown(m_server, SHUT_RDWR); + ::close(m_server); + m_server = -1; + } + if(socketStatus() > nothing) + reset(); + textClear(); +} + +bool FtpSocket::setSocketOption(int opt, char*arg, socklen_t len) const +{ + return (setsockopt(sock(), SOL_SOCKET, opt, arg, len) != -1); +} + +//=============================================================================== +// Ftp +//=============================================================================== + +Ftp::Ftp( const TQCString &pool, const TQCString &app ) + : SlaveBase( "ftp", pool, app ) +{ + // init the socket data + m_data = m_control = NULL; + ftpCloseControlConnection(); + + // init other members + m_port = 0; + kdDebug(7102) << "Ftp::Ftp()" << endl; +} + + +Ftp::~Ftp() +{ + kdDebug(7102) << "Ftp::~Ftp()" << endl; + closeConnection(); +} + +/** + * This closes a data connection opened by ftpOpenDataConnection(). + */ +void Ftp::ftpCloseDataConnection() +{ + if(m_data != NULL) + { delete m_data; + m_data = NULL; + } +} + +/** + * This closes a control connection opened by ftpOpenControlConnection() and reinits the + * related states. This method gets called from the constructor with m_control = NULL. + */ +void Ftp::ftpCloseControlConnection() +{ + m_extControl = 0; + if(m_control) + delete m_control; + m_control = NULL; + m_cDataMode = 0; + m_bLoggedOn = false; // logon needs control connction + m_bTextMode = false; + m_bBusy = false; +} + +/** + * Returns the last response from the server (iOffset >= 0) -or- reads a new response + * (iOffset < 0). The result is returned (with iOffset chars skipped for iOffset > 0). + */ +const char* Ftp::ftpResponse(int iOffset) +{ + assert(m_control != NULL); // must have control connection socket + const char *pTxt = m_control->textLine(); + + // read the next line ... + if(iOffset < 0) + { + int iMore = 0; + m_iRespCode = 0; + + // If the server sends multiline responses "nnn-text" we loop here until + // a final "nnn text" line is reached. Only data from the final line will + // be stored. Some servers (OpenBSD) send a single "nnn-" followed by + // optional lines that start with a space and a final "nnn text" line. + do { + int nBytes = m_control->textRead(); + int iCode = atoi(pTxt); + if(iCode > 0) m_iRespCode = iCode; + + // ignore lines starting with a space in multiline response + if(iMore != 0 && pTxt[0] == 32) + ; + // otherwise the line should start with "nnn-" or "nnn " + else if(nBytes < 4 || iCode < 100) + iMore = 0; + // we got a valid line, now check for multiline responses ... + else if(iMore == 0 && pTxt[3] == '-') + iMore = iCode; + // "nnn " ends multiline mode ... + else if(iMore != 0 && (iMore != iCode || pTxt[3] != '-')) + iMore = 0; + + if(iMore != 0) + kdDebug(7102) << " > " << pTxt << endl; + } while(iMore != 0); + kdDebug(7102) << "resp> " << pTxt << endl; + + m_iRespType = (m_iRespCode > 0) ? m_iRespCode / 100 : 0; + } + + // return text with offset ... + while(iOffset-- > 0 && pTxt[0]) + pTxt++; + return pTxt; +} + + +void Ftp::closeConnection() +{ + if(m_control != NULL || m_data != NULL) + kdDebug(7102) << "Ftp::closeConnection m_bLoggedOn=" << m_bLoggedOn << " m_bBusy=" << m_bBusy << endl; + + if(m_bBusy) // ftpCloseCommand not called + { + kdWarning(7102) << "Ftp::closeConnection Abandoned data stream" << endl; + ftpCloseDataConnection(); + } + + if(m_bLoggedOn) // send quit + { + if( !ftpSendCmd( "quit", 0 ) || (m_iRespType != 2) ) + kdWarning(7102) << "Ftp::closeConnection QUIT returned error: " << m_iRespCode << endl; + } + + // close the data and control connections ... + ftpCloseDataConnection(); + ftpCloseControlConnection(); +} + +void Ftp::setHost( const TQString& _host, int _port, const TQString& _user, + const TQString& _pass ) +{ + kdDebug(7102) << "Ftp::setHost (" << getpid() << "): " << _host << endl; + + m_proxyURL = metaData("UseProxy"); + m_bUseProxy = (m_proxyURL.isValid() && m_proxyURL.protocol() == "ftp"); + + if ( m_host != _host || m_port != _port || + m_user != _user || m_pass != _pass ) + closeConnection(); + + m_host = _host; + m_port = _port; + m_user = _user; + m_pass = _pass; +} + +void Ftp::openConnection() +{ + ftpOpenConnection(loginExplicit); +} + +bool Ftp::ftpOpenConnection (LoginMode loginMode) +{ + // check for implicit login if we are already logged on ... + if(loginMode == loginImplicit && m_bLoggedOn) + { + assert(m_control != NULL); // must have control connection socket + return true; + } + + kdDebug(7102) << "ftpOpenConnection " << m_host << ":" << m_port << " " + << m_user << " [password hidden]" << endl; + + infoMessage( i18n("Opening connection to host %1").arg(m_host) ); + + if ( m_host.isEmpty() ) + { + error( ERR_UNKNOWN_HOST, TQString::null ); + return false; + } + + assert( !m_bLoggedOn ); + + m_initialPath = TQString::null; + m_currentPath = TQString::null; + + TQString host = m_bUseProxy ? m_proxyURL.host() : m_host; + unsigned short int port = m_bUseProxy ? m_proxyURL.port() : m_port; + + if (!ftpOpenControlConnection(host, port) ) + return false; // error emitted by ftpOpenControlConnection + infoMessage( i18n("Connected to host %1").arg(m_host) ); + + if(loginMode != loginDefered) + { + m_bLoggedOn = ftpLogin(); + if( !m_bLoggedOn ) + return false; // error emitted by ftpLogin + } + + m_bTextMode = config()->readBoolEntry("textmode", false); + connected(); + return true; +} + + +/** + * Called by @ref openConnection. It opens the control connection to the ftp server. + * + * @return true on success. + */ +bool Ftp::ftpOpenControlConnection( const TQString &host, unsigned short int port ) +{ + if ( port == 0 ) { + struct servent *pse; + if ( ( pse = getservbyname( "ftp", "tcp" ) ) == NULL ) + port = 21; + else + port = ntohs(pse->s_port); + } + + // implicitly close, then try to open a new connection ... + closeConnection(); + int iErrorCode = ERR_OUT_OF_MEMORY; + TQString sErrorMsg; + m_control = new FtpSocket("CNTL"); + if(m_control != NULL) + { + // now connect to the server and read the login message ... + m_control->setAddress(host, port); + iErrorCode = m_control->connectSocket(connectTimeout(), true); + sErrorMsg = host; + + // on connect success try to read the server message... + if(iErrorCode == 0) + { + const char* psz = ftpResponse(-1); + if(m_iRespType != 2) + { // login not successful, do we have an message text? + if(psz[0]) + sErrorMsg = i18n("%1.\n\nReason: %2").arg(host).arg(psz); + iErrorCode = ERR_COULD_NOT_CONNECT; + } + } + } + + // if there was a problem - report it ... + if(iErrorCode == 0) // OK, return success + return true; + closeConnection(); // clean-up on error + error(iErrorCode, sErrorMsg); + return false; +} + +/** + * Called by @ref openConnection. It logs us in. + * @ref m_initialPath is set to the current working directory + * if logging on was successful. + * + * @return true on success. + */ +bool Ftp::ftpLogin() +{ + infoMessage( i18n("Sending login information") ); + + assert( !m_bLoggedOn ); + + TQString user = m_user; + TQString pass = m_pass; + + if ( config()->readBoolEntry("EnableAutoLogin") ) + { + TQString au = config()->readEntry("autoLoginUser"); + if ( !au.isEmpty() ) + { + user = au; + pass = config()->readEntry("autoLoginPass"); + } + } + + // Try anonymous login if both username/password + // information is blank. + if (user.isEmpty() && pass.isEmpty()) + { + user = FTP_LOGIN; + pass = FTP_PASSWD; + } + + AuthInfo info; + info.url.setProtocol( "ftp" ); + info.url.setHost( m_host ); + info.url.setPort( m_port ); + info.url.setUser( user ); + + TQCString tempbuf; + int failedAuth = 0; + + do + { + // Check the cache and/or prompt user for password if 1st + // login attempt failed OR the user supplied a login name, + // but no password. + if ( failedAuth > 0 || (!user.isEmpty() && pass.isEmpty()) ) + { + TQString errorMsg; + kdDebug(7102) << "Prompting user for login info..." << endl; + + // Ask user if we should retry after when login fails! + if( failedAuth > 0 ) + { + errorMsg = i18n("Message sent:\nLogin using username=%1 and " + "password=[hidden]\n\nServer replied:\n%2\n\n" + ).arg(user).arg(ftpResponse(0)); + } + + if ( user != FTP_LOGIN ) + info.username = user; + + info.prompt = i18n("You need to supply a username and a password " + "to access this site."); + info.commentLabel = i18n( "Site:" ); + info.comment = i18n("%1").arg( m_host ); + info.keepPassword = true; // Prompt the user for persistence as well. + info.readOnly = (!m_user.isEmpty() && m_user != FTP_LOGIN); + + bool disablePassDlg = config()->readBoolEntry( "DisablePassDlg", false ); + if ( disablePassDlg || !openPassDlg( info, errorMsg ) ) + { + error( ERR_USER_CANCELED, m_host ); + return false; + } + else + { + user = info.username; + pass = info.password; + } + } + + tempbuf = "USER "; + tempbuf += user.latin1(); + if ( m_bUseProxy ) + { + tempbuf += '@'; + tempbuf += m_host.latin1(); + if ( m_port > 0 && m_port != DEFAULT_FTP_PORT ) + { + tempbuf += ':'; + tempbuf += TQString::number(m_port).latin1(); + } + } + + kdDebug(7102) << "Sending Login name: " << tempbuf << endl; + + bool loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) ); + bool needPass = (m_iRespCode == 331); + // Prompt user for login info if we do not + // get back a "230" or "331". + if ( !loggedIn && !needPass ) + { + kdDebug(7102) << "Login failed: " << ftpResponse(0) << endl; + ++failedAuth; + continue; // Well we failed, prompt the user please!! + } + + if( needPass ) + { + tempbuf = "pass "; + tempbuf += pass.latin1(); + kdDebug(7102) << "Sending Login password: " << "[protected]" << endl; + loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) ); + } + + if ( loggedIn ) + { + // Do not cache the default login!! + if( user != FTP_LOGIN && pass != FTP_PASSWD ) + cacheAuthentication( info ); + failedAuth = -1; + } + + } while( ++failedAuth ); + + + kdDebug(7102) << "Login OK" << endl; + infoMessage( i18n("Login OK") ); + + // Okay, we're logged in. If this is IIS 4, switch dir listing style to Unix: + // Thanks to jk@soegaard.net (Jens Kristian Søgaard) for this hint + if( ftpSendCmd("SYST") && (m_iRespType == 2) ) + { + if( !strncmp( ftpResponse(0), "215 Windows_NT", 14 ) ) // should do for any version + { + ftpSendCmd( "site dirstyle" ); + // Check if it was already in Unix style + // Patch from Keith Refson + if( !strncmp( ftpResponse(0), "200 MSDOS-like directory output is on", 37 )) + //It was in Unix style already! + ftpSendCmd( "site dirstyle" ); + // windows won't support chmod before KDE konquers their desktop... + m_extControl |= chmodUnknown; + } + } + else + kdWarning(7102) << "SYST failed" << endl; + + if ( config()->readBoolEntry ("EnableAutoLoginMacro") ) + ftpAutoLoginMacro (); + + // Get the current working directory + kdDebug(7102) << "Searching for pwd" << endl; + if( !ftpSendCmd("PWD") || (m_iRespType != 2) ) + { + kdDebug(7102) << "Couldn't issue pwd command" << endl; + error( ERR_COULD_NOT_LOGIN, i18n("Could not login to %1.").arg(m_host) ); // or anything better ? + return false; + } + + TQString sTmp = remoteEncoding()->decode( ftpResponse(3) ); + int iBeg = sTmp.find('"'); + int iEnd = sTmp.findRev('"'); + if(iBeg > 0 && iBeg < iEnd) + { + m_initialPath = sTmp.mid(iBeg+1, iEnd-iBeg-1); + if(m_initialPath[0] != '/') m_initialPath.prepend('/'); + kdDebug(7102) << "Initial path set to: " << m_initialPath << endl; + m_currentPath = m_initialPath; + } + return true; +} + +void Ftp::ftpAutoLoginMacro () +{ + TQString macro = metaData( "autoLoginMacro" ); + + if ( macro.isEmpty() ) + return; + + TQStringList list = TQStringList::split('\n', macro); + + for(TQStringList::Iterator it = list.begin() ; it != list.end() ; ++it ) + { + if ( (*it).startsWith("init") ) + { + list = TQStringList::split( '\\', macro); + it = list.begin(); + ++it; // ignore the macro name + + for( ; it != list.end() ; ++it ) + { + // TODO: Add support for arbitrary commands + // besides simply changing directory!! + if ( (*it).startsWith( "cwd" ) ) + ftpFolder( (*it).mid(4).stripWhiteSpace(), false ); + } + + break; + } + } +} + + +/** + * ftpSendCmd - send a command (@p cmd) and read response + * + * @param maxretries number of time it should retry. Since it recursively + * calls itself if it can't read the answer (this happens especially after + * timeouts), we need to limit the recursiveness ;-) + * + * return true if any response received, false on error + */ +bool Ftp::ftpSendCmd( const TQCString& cmd, int maxretries ) +{ + assert(m_control != NULL); // must have control connection socket + + if ( cmd.find( '\r' ) != -1 || cmd.find( '\n' ) != -1) + { + kdWarning(7102) << "Invalid command received (contains CR or LF):" + << cmd.data() << endl; + error( ERR_UNSUPPORTED_ACTION, m_host ); + return false; + } + + // Don't print out the password... + bool isPassCmd = (cmd.left(4).lower() == "pass"); + if ( !isPassCmd ) + kdDebug(7102) << "send> " << cmd.data() << endl; + else + kdDebug(7102) << "send> pass [protected]" << endl; + + // Send the message... + TQCString buf = cmd; + buf += "\r\n"; // Yes, must use CR/LF - see http://cr.yp.to/ftp/request.html + int num = m_control->write(buf.data(), buf.length()); + + // If we were able to successfully send the command, then we will + // attempt to read the response. Otherwise, take action to re-attempt + // the login based on the maximum number of retires specified... + if( num > 0 ) + ftpResponse(-1); + else + { m_iRespType = m_iRespCode = 0; + m_control->textClear(); + } + + // If respCh is NULL or the response is 421 (Timed-out), we try to re-send + // the command based on the value of maxretries. + if( (m_iRespType <= 0) || (m_iRespCode == 421) ) + { + // We have not yet logged on... + if (!m_bLoggedOn) + { + // The command was sent from the ftpLogin function, i.e. we are actually + // attempting to login in. NOTE: If we already sent the username, we + // return false and let the user decide whether (s)he wants to start from + // the beginning... + if (maxretries > 0 && !isPassCmd) + { + closeConnection (); + if( ftpOpenConnection(loginDefered) ) + ftpSendCmd ( cmd, maxretries - 1 ); + } + + return false; + } + else + { + if ( maxretries < 1 ) + return false; + else + { + kdDebug(7102) << "Was not able to communicate with " << m_host << endl + << "Attempting to re-establish connection." << endl; + + closeConnection(); // Close the old connection... + openConnection(); // Attempt to re-establish a new connection... + + if (!m_bLoggedOn) + { + if (m_control != NULL) // if openConnection succeeded ... + { + kdDebug(7102) << "Login failure, aborting" << endl; + error (ERR_COULD_NOT_LOGIN, m_host); + closeConnection (); + } + return false; + } + + kdDebug(7102) << "Logged back in, re-issuing command" << endl; + + // If we were able to login, resend the command... + if (maxretries) + maxretries--; + + return ftpSendCmd( cmd, maxretries ); + } + } + } + + return true; +} + +/* + * ftpOpenPASVDataConnection - set up data connection, using PASV mode + * + * return 1 if successful, 0 otherwise + * doesn't set error message, since non-pasv mode will always be tried if + * this one fails + */ +int Ftp::ftpOpenPASVDataConnection() +{ + assert(m_control != NULL); // must have control connection socket + assert(m_data == NULL); // ... but no data connection + + // Check that we can do PASV + const TDESocketAddress *sa = m_control->peerAddress(); + if (sa != NULL && sa->family() != PF_INET) + return ERR_INTERNAL; // no PASV for non-PF_INET connections + + const KInetSocketAddress *sin = static_cast(sa); + + if (m_extControl & pasvUnknown) + return ERR_INTERNAL; // already tried and got "unknown command" + + m_bPasv = true; + + /* Let's PASsiVe*/ + if( !ftpSendCmd("PASV") || (m_iRespType != 2) ) + { + kdDebug(7102) << "PASV attempt failed" << endl; + // unknown command? + if( m_iRespType == 5 ) + { + kdDebug(7102) << "disabling use of PASV" << endl; + m_extControl |= pasvUnknown; + } + return ERR_INTERNAL; + } + + // The usual answer is '227 Entering Passive Mode. (160,39,200,55,6,245)' + // but anonftpd gives '227 =160,39,200,55,6,245' + int i[6]; + const char *start = strchr(ftpResponse(3), '('); + if ( !start ) + start = strchr(ftpResponse(3), '='); + if ( !start || + ( sscanf(start, "(%d,%d,%d,%d,%d,%d)",&i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 && + sscanf(start, "=%d,%d,%d,%d,%d,%d", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 ) ) + { + kdError(7102) << "parsing IP and port numbers failed. String parsed: " << start << endl; + return ERR_INTERNAL; + } + + // Make hostname and port number ... + int port = i[4] << 8 | i[5]; + + // we ignore the host part on purpose for two reasons + // a) it might be wrong anyway + // b) it would make us being suceptible to a port scanning attack + + // now connect the data socket ... + m_data = new FtpSocket("PASV"); + m_data->setAddress(sin->nodeName(), port); + + kdDebug(7102) << "Connecting to " << sin->nodeName() << " on port " << port << endl; + return m_data->connectSocket(connectTimeout(), false); +} + +/* + * ftpOpenEPSVDataConnection - opens a data connection via EPSV + */ +int Ftp::ftpOpenEPSVDataConnection() +{ + assert(m_control != NULL); // must have control connection socket + assert(m_data == NULL); // ... but no data connection + + const TDESocketAddress *sa = m_control->peerAddress(); + int portnum; + // we are sure sa is a KInetSocketAddress, because we asked for KExtendedSocket::inetSocket + // when we connected + const KInetSocketAddress *sin = static_cast(sa); + + if (m_extControl & epsvUnknown || sa == NULL) + return ERR_INTERNAL; + + m_bPasv = true; + if( !ftpSendCmd("EPSV") || (m_iRespType != 2) ) + { + // unknown command? + if( m_iRespType == 5 ) + { + kdDebug(7102) << "disabling use of EPSV" << endl; + m_extControl |= epsvUnknown; + } + return ERR_INTERNAL; + } + + const char *start = strchr(ftpResponse(3), '|'); + if ( !start || sscanf(start, "|||%d|", &portnum) != 1) + return ERR_INTERNAL; + + m_data = new FtpSocket("EPSV"); + m_data->setAddress(sin->nodeName(), portnum); + return m_data->connectSocket(connectTimeout(), false) != 0; +} + +/* + * ftpOpenEPRTDataConnection + * @return 0 on success, ERR_INTERNAL if mode not acceptable -or- a fatal error code + */ +int Ftp::ftpOpenEPRTDataConnection() +{ + assert(m_control != NULL); // must have control connection socket + assert(m_data == NULL); // ... but no data connection + + // yes, we are sure this is a KInetSocketAddress + const KInetSocketAddress *sin = static_cast(m_control->localAddress()); + m_bPasv = false; + if (m_extControl & eprtUnknown || sin == NULL) + return ERR_INTERNAL; + + m_data = new FtpSocket("EPRT"); + m_data->setHost(sin->nodeName()); + m_data->setPort(0); // setting port to 0 will make us bind to a random, free port + m_data->setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket | + KExtendedSocket::inetSocket); + + if (m_data->listen(1) < 0) + return ERR_COULD_NOT_LISTEN; + + sin = static_cast(m_data->localAddress()); + if (sin == NULL) + return ERR_INTERNAL; + + // TQString command = TQString::fromLatin1("eprt |%1|%2|%3|").arg(sin->ianaFamily()) + // .arg(sin->nodeName()) + // .arg(sin->port()); + TQCString command; + command.sprintf("eprt |%d|%s|%d|", sin->ianaFamily(), + sin->nodeName().latin1(), sin->port()); + + // FIXME! Encoding for hostnames? + if( ftpSendCmd(command) && (m_iRespType == 2) ) + return 0; + + // unknown command? + if( m_iRespType == 5 ) + { + kdDebug(7102) << "disabling use of EPRT" << endl; + m_extControl |= eprtUnknown; + } + return ERR_INTERNAL; +} + +/* + * ftpOpenDataConnection - set up data connection + * + * The routine calls several ftpOpenXxxxConnection() helpers to find + * the best connection mode. If a helper cannot connect if returns + * ERR_INTERNAL - so this is not really an error! All other error + * codes are treated as fatal, e.g. they are passed back to the caller + * who is responsible for calling error(). ftpOpenPortDataConnection + * can be called as last try and it does never return ERR_INTERNAL. + * + * @return 0 if successful, err code otherwise + */ +int Ftp::ftpOpenDataConnection() +{ + // make sure that we are logged on and have no data connection... + assert( m_bLoggedOn ); + ftpCloseDataConnection(); + + int iErrCode = 0; + int iErrCodePASV = 0; // Remember error code from PASV + + // First try passive (EPSV & PASV) modes + if( !config()->readBoolEntry("DisablePassiveMode", false) ) + { + iErrCode = ftpOpenPASVDataConnection(); + if(iErrCode == 0) + return 0; // success + iErrCodePASV = iErrCode; + ftpCloseDataConnection(); + + if( !config()->readBoolEntry("DisableEPSV", false) ) + { + iErrCode = ftpOpenEPSVDataConnection(); + if(iErrCode == 0) + return 0; // success + ftpCloseDataConnection(); + } + + // if we sent EPSV ALL already and it was accepted, then we can't + // use active connections any more + if (m_extControl & epsvAllSent) + return iErrCodePASV ? iErrCodePASV : iErrCode; + } + + if( !config()->readBoolEntry("DisableEPRT", false) ) + { + iErrCode = ftpOpenEPRTDataConnection(); + if(iErrCode == 0) + return 0; // success + ftpCloseDataConnection(); + } + + // fall back to port mode + iErrCode = ftpOpenPortDataConnection(); + if(iErrCode == 0) + return 0; // success + + ftpCloseDataConnection(); + // prefer to return the error code from PASV if any, since that's what should have worked in the first place + return iErrCodePASV ? iErrCodePASV : iErrCode; +} + +/* + * ftpOpenPortDataConnection - set up data connection + * + * @return 0 if successfull, err code otherwise (but never ERR_INTERNAL + * because this is the last connection mode that is tried) + */ +int Ftp::ftpOpenPortDataConnection() +{ + assert(m_control != NULL); // must have control connection socket + assert(m_data == NULL); // ... but no data connection + + m_bPasv = false; + + // create a socket, bind it and let it listen ... + m_data = new FtpSocket("PORT"); + m_data->setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket | + KExtendedSocket::inetSocket); + + // yes, we are sure this is a KInetSocketAddress + const KInetSocketAddress* pAddr = static_cast(m_control->localAddress()); + m_data->setAddress(pAddr->nodeName(), "0"); + m_data->setAddressReusable(true); + + if(m_data->listen(1) < 0) + return ERR_COULD_NOT_LISTEN; + struct linger lng = { 0, 0 }; + if ( !m_data->setSocketOption(SO_LINGER, (char*)&lng, sizeof(lng)) ) + return ERR_COULD_NOT_CREATE_SOCKET; + + // send the PORT command ... + pAddr = static_cast(m_data->localAddress()); + struct sockaddr* psa = (struct sockaddr*)pAddr->addressV4(); + unsigned char* pData = (unsigned char*)(psa->sa_data); + TQCString portCmd; + portCmd.sprintf("port %d,%d,%d,%d,%d,%d", + pData[2], pData[3], pData[4], pData[5], pData[0], pData[1]); + if( ftpSendCmd(portCmd) && (m_iRespType == 2) ) + return 0; + return ERR_COULD_NOT_CONNECT; +} + +/* + * ftpAcceptConnect - wait for incoming connection + * Used by @ref ftpOpenCommand + * + * return false on error or timeout + */ +int Ftp::ftpAcceptConnect() +{ + assert(m_data != NULL); + + if ( m_bPasv ) + { + m_data->setServer(-1); + return true; + } + + int sSock = m_data->fd(); + struct sockaddr addr; + for(;;) + { + fd_set mask; + FD_ZERO(&mask); + FD_SET(sSock,&mask); + int r = KSocks::self()->select(sSock + 1, &mask, NULL, NULL, 0L); + if( r < 0 && errno != EINTR && errno != EAGAIN ) + continue; + if( r > 0 ) + break; + } + + ksocklen_t l = sizeof(addr); + m_data->setServer( KSocks::self()->accept(sSock, &addr, &l) ); + return (m_data->server() != -1); +} + +bool Ftp::ftpOpenCommand( const char *_command, const TQString & _path, char _mode, + int errorcode, TDEIO::fileoffset_t _offset ) +{ + int errCode = 0; + if( !ftpDataMode(_mode) ) + errCode = ERR_COULD_NOT_CONNECT; + else + errCode = ftpOpenDataConnection(); + + if(errCode != 0) + { + error(errCode, m_host); + return false; + } + + if ( _offset > 0 ) { + // send rest command if offset > 0, this applies to retr and stor commands + char buf[100]; + sprintf(buf, "rest %lld", _offset); + if ( !ftpSendCmd( buf ) ) + return false; + if( m_iRespType != 3 ) + { + error( ERR_CANNOT_RESUME, _path ); // should never happen + return false; + } + } + + TQCString tmp = _command; + TQString errormessage; + + if ( !_path.isEmpty() ) { + tmp += " "; + tmp += remoteEncoding()->encode(_path); + } + + if( !ftpSendCmd( tmp ) || (m_iRespType != 1) ) + { + if( _offset > 0 && strcmp(_command, "retr") == 0 && (m_iRespType == 4) ) + errorcode = ERR_CANNOT_RESUME; + // The error here depends on the command + errormessage = _path; + } + + else + { + // Only now we know for sure that we can resume + if ( _offset > 0 && strcmp(_command, "retr") == 0 ) + canResume(); + + if( ftpAcceptConnect() ) + { m_bBusy = true; // cleared in ftpCloseCommand + return true; + } + errorcode = ERR_COULD_NOT_ACCEPT; + } + + error(errorcode, errormessage); + return false; +} + + +bool Ftp::ftpCloseCommand() +{ + // first close data sockets (if opened), then read response that + // we got for whatever was used in ftpOpenCommand ( should be 226 ) + if(m_data) + { + delete m_data; + m_data = NULL; + } + if(!m_bBusy) + return true; + + kdDebug(7102) << "ftpCloseCommand: reading command result" << endl; + m_bBusy = false; + + if(!ftpResponse(-1) || (m_iRespType != 2) ) + { + kdDebug(7102) << "ftpCloseCommand: no transfer complete message" << endl; + return false; + } + return true; +} + +void Ftp::mkdir( const KURL & url, int permissions ) +{ + if( !ftpOpenConnection(loginImplicit) ) + return; + + TQString path = remoteEncoding()->encode(url); + TQCString buf = "mkd "; + buf += remoteEncoding()->encode(path); + + if( !ftpSendCmd( buf ) || (m_iRespType != 2) ) + { + TQString currentPath( m_currentPath ); + + // Check whether or not mkdir failed because + // the directory already exists... + if( ftpFolder( path, false ) ) + { + error( ERR_DIR_ALREADY_EXIST, path ); + // Change the directory back to what it was... + (void) ftpFolder( currentPath, false ); + return; + } + + error( ERR_COULD_NOT_MKDIR, path ); + return; + } + + if ( permissions != -1 ) + { + // chmod the dir we just created, ignoring errors. + (void) ftpChmod( path, permissions ); + } + + finished(); +} + +void Ftp::rename( const KURL& src, const KURL& dst, bool overwrite ) +{ + if( !ftpOpenConnection(loginImplicit) ) + return; + + // The actual functionality is in ftpRename because put needs it + if ( ftpRename( src.path(), dst.path(), overwrite ) ) + finished(); + else + error( ERR_CANNOT_RENAME, src.path() ); +} + +bool Ftp::ftpRename( const TQString & src, const TQString & dst, bool overwrite ) +{ + assert( m_bLoggedOn ); + + // Must check if dst already exists, RNFR+RNTO overwrites by default (#127793). + if (!overwrite) { + if (ftpSize(dst, 'I')) { + error(ERR_FILE_ALREADY_EXIST, dst); + return false; + } + } + if (ftpFolder(dst, false)) { + error(ERR_DIR_ALREADY_EXIST, dst); + return false; + } + + // Must check if dst already exists, RNFR+RNTO overwrites by default (#127793). + if (ftpFileExists(dst)) { + error(ERR_FILE_ALREADY_EXIST, dst); + return false; + } + if (ftpFolder(dst, false)) { + error(ERR_DIR_ALREADY_EXIST, dst); + return false; + } + + int pos = src.findRev("/"); + if( !ftpFolder(src.left(pos+1), false) ) + return false; + + TQCString from_cmd = "RNFR "; + from_cmd += remoteEncoding()->encode(src.mid(pos+1)); + if( !ftpSendCmd( from_cmd ) || (m_iRespType != 3) ) + return false; + + TQCString to_cmd = "RNTO "; + to_cmd += remoteEncoding()->encode(dst); + if( !ftpSendCmd( to_cmd ) || (m_iRespType != 2) ) + return false; + + return true; +} + +void Ftp::del( const KURL& url, bool isfile ) +{ + if( !ftpOpenConnection(loginImplicit) ) + return; + + // When deleting a directory, we must exit from it first + // The last command probably went into it (to stat it) + if ( !isfile ) + ftpFolder(remoteEncoding()->directory(url), false); // ignore errors + + TQCString cmd = isfile ? "DELE " : "RMD "; + cmd += remoteEncoding()->encode(url); + + if( !ftpSendCmd( cmd ) || (m_iRespType != 2) ) + error( ERR_CANNOT_DELETE, url.path() ); + else + finished(); +} + +bool Ftp::ftpChmod( const TQString & path, int permissions ) +{ + assert( m_bLoggedOn ); + + if(m_extControl & chmodUnknown) // previous errors? + return false; + + // we need to do bit AND 777 to get permissions, in case + // we were sent a full mode (unlikely) + TQCString cmd; + cmd.sprintf("SITE CHMOD %o ", permissions & 511 ); + cmd += remoteEncoding()->encode(path); + + ftpSendCmd(cmd); + if(m_iRespType == 2) + return true; + + if(m_iRespCode == 500) + { + m_extControl |= chmodUnknown; + kdDebug(7102) << "ftpChmod: CHMOD not supported - disabling"; + } + return false; +} + +void Ftp::chmod( const KURL & url, int permissions ) +{ + if( !ftpOpenConnection(loginImplicit) ) + return; + + if ( !ftpChmod( url.path(), permissions ) ) + error( ERR_CANNOT_CHMOD, url.path() ); + else + finished(); +} + +void Ftp::ftpCreateUDSEntry( const TQString & filename, FtpEntry& ftpEnt, UDSEntry& entry, bool isDir ) +{ + assert(entry.count() == 0); // by contract :-) + UDSAtom atom; + atom.m_uds = UDS_NAME; + atom.m_str = filename; + entry.append( atom ); + + atom.m_uds = UDS_SIZE; + atom.m_long = ftpEnt.size; + entry.append( atom ); + + atom.m_uds = UDS_MODIFICATION_TIME; + atom.m_long = ftpEnt.date; + entry.append( atom ); + + atom.m_uds = UDS_ACCESS; + atom.m_long = ftpEnt.access; + entry.append( atom ); + + atom.m_uds = UDS_USER; + atom.m_str = ftpEnt.owner; + entry.append( atom ); + + if ( !ftpEnt.group.isEmpty() ) + { + atom.m_uds = UDS_GROUP; + atom.m_str = ftpEnt.group; + entry.append( atom ); + } + + if ( !ftpEnt.link.isEmpty() ) + { + atom.m_uds = UDS_LINK_DEST; + atom.m_str = ftpEnt.link; + entry.append( atom ); + + KMimeType::Ptr mime = KMimeType::findByURL( KURL("ftp://host/" + filename ) ); + // Links on ftp sites are often links to dirs, and we have no way to check + // that. Let's do like Netscape : assume dirs generally. + // But we do this only when the mimetype can't be known from the filename. + // --> we do better than Netscape :-) + if ( mime->name() == KMimeType::defaultMimeType() ) + { + kdDebug(7102) << "Setting guessed mime type to inode/directory for " << filename << endl; + atom.m_uds = UDS_GUESSED_MIME_TYPE; + atom.m_str = "inode/directory"; + entry.append( atom ); + isDir = true; + } + } + + atom.m_uds = UDS_FILE_TYPE; + atom.m_long = isDir ? S_IFDIR : ftpEnt.type; + entry.append( atom ); + + /* atom.m_uds = UDS_ACCESS_TIME; + atom.m_long = buff.st_atime; + entry.append( atom ); + + atom.m_uds = UDS_CREATION_TIME; + atom.m_long = buff.st_ctime; + entry.append( atom ); */ +} + + +void Ftp::ftpShortStatAnswer( const TQString& filename, bool isDir ) +{ + UDSEntry entry; + UDSAtom atom; + + atom.m_uds = TDEIO::UDS_NAME; + atom.m_str = filename; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long = isDir ? S_IFDIR : S_IFREG; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + entry.append( atom ); + + // No details about size, ownership, group, etc. + + statEntry(entry); + finished(); +} + +void Ftp::ftpStatAnswerNotFound( const TQString & path, const TQString & filename ) +{ + // Only do the 'hack' below if we want to download an existing file (i.e. when looking at the "source") + // When e.g. uploading a file, we still need stat() to return "not found" + // when the file doesn't exist. + TQString statSide = metaData("statSide"); + kdDebug(7102) << "Ftp::stat statSide=" << statSide << endl; + if ( statSide == "source" ) + { + kdDebug(7102) << "Not found, but assuming found, because some servers don't allow listing" << endl; + // MS Server is incapable of handling "list " in a case insensitive way + // But "retr " works. So lie in stat(), to get going... + // + // There's also the case of ftp://ftp2.3ddownloads.com/90380/linuxgames/loki/patches/ut/ut-patch-436.run + // where listing permissions are denied, but downloading is still possible. + ftpShortStatAnswer( filename, false /*file, not dir*/ ); + + return; + } + + error( ERR_DOES_NOT_EXIST, path ); +} + +void Ftp::stat( const KURL &url) +{ + kdDebug(7102) << "Ftp::stat : path='" << url.path() << "'" << endl; + if( !ftpOpenConnection(loginImplicit) ) + return; + + TQString path = TQDir::cleanDirPath( url.path() ); + kdDebug(7102) << "Ftp::stat : cleaned path='" << path << "'" << endl; + + // We can't stat root, but we know it's a dir. + if( path.isEmpty() || path == "/" ) + { + UDSEntry entry; + UDSAtom atom; + + atom.m_uds = TDEIO::UDS_NAME; + atom.m_str = TQString::null; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long = S_IFDIR; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_USER; + atom.m_str = "root"; + entry.append( atom ); + atom.m_uds = TDEIO::UDS_GROUP; + entry.append( atom ); + + // no size + + statEntry( entry ); + finished(); + return; + } + + KURL tempurl( url ); + tempurl.setPath( path ); // take the clean one + TQString listarg; // = tempurl.directory(false /*keep trailing slash*/); + TQString parentDir; + TQString filename = tempurl.fileName(); + Q_ASSERT(!filename.isEmpty()); + TQString search = filename; + + // Try cwd into it, if it works it's a dir (and then we'll list the parent directory to get more info) + // if it doesn't work, it's a file (and then we'll use dir filename) + bool isDir = ftpFolder(path, false); + + // if we're only interested in "file or directory", we should stop here + TQString sDetails = metaData("details"); + int details = sDetails.isEmpty() ? 2 : sDetails.toInt(); + kdDebug(7102) << "Ftp::stat details=" << details << endl; + if ( details == 0 ) + { + if ( !isDir && !ftpSize( path, 'I' ) ) // ok, not a dir -> is it a file ? + { // no -> it doesn't exist at all + ftpStatAnswerNotFound( path, filename ); + return; + } + ftpShortStatAnswer( filename, isDir ); // successfully found a dir or a file -> done + return; + } + + if (!isDir) + { + // It is a file or it doesn't exist, try going to parent directory + parentDir = tempurl.directory(false /*keep trailing slash*/); + // With files we can do "LIST " to avoid listing the whole dir + listarg = filename; + } + else + { + // --- New implementation: + // Don't list the parent dir. Too slow, might not show it, etc. + // Just return that it's a dir. + UDSEntry entry; + UDSAtom atom; + + atom.m_uds = TDEIO::UDS_NAME; + atom.m_str = filename; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long = S_IFDIR; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + entry.append( atom ); + + // No clue about size, ownership, group, etc. + + statEntry(entry); + finished(); + return; + + // --- Old implementation: +#if 0 + // It's a dir, remember that + // Reason: it could be a symlink to a dir, in which case ftpReadDir + // in the parent dir will have no idea about that. But we know better. + isDir = true; + // If the dir starts with '.', we'll need '-a' to see it in the listing. + if ( search[0] == '.' ) + listarg = "-a"; + parentDir = ".."; +#endif + } + + // Now cwd the parent dir, to prepare for listing + if( !ftpFolder(parentDir, true) ) + return; + + if( !ftpOpenCommand( "list", listarg, 'I', ERR_DOES_NOT_EXIST ) ) + { + kdError(7102) << "COULD NOT LIST" << endl; + return; + } + kdDebug(7102) << "Starting of list was ok" << endl; + + Q_ASSERT( !search.isEmpty() && search != "/" ); + + bool bFound = false; + KURL linkURL; + FtpEntry ftpEnt; + while( ftpReadDir(ftpEnt) ) + { + // We look for search or filename, since some servers (e.g. ftp.tuwien.ac.at) + // return only the filename when doing "dir /full/path/to/file" + if ( !bFound ) + { + if ( ( search == ftpEnt.name || filename == ftpEnt.name ) ) { + if ( !filename.isEmpty() ) { + bFound = true; + UDSEntry entry; + ftpCreateUDSEntry( filename, ftpEnt, entry, isDir ); + statEntry( entry ); + } + } else if ( isDir && ( ftpEnt.name == listarg || ftpEnt.name+'/' == listarg ) ) { + // Damn, the dir we're trying to list is in fact a symlink + // Follow it and try again + if ( ftpEnt.link.isEmpty() ) + kdWarning(7102) << "Got " << listarg << " as answer, but empty link!" << endl; + else + { + linkURL = url; + kdDebug(7102) << "ftpEnt.link=" << ftpEnt.link << endl; + if ( ftpEnt.link[0] == '/' ) + linkURL.setPath( ftpEnt.link ); // Absolute link + else + { + // Relative link (stat will take care of cleaning ../.. etc.) + linkURL.setPath( listarg ); // this is what we were listing (the link) + linkURL.setPath( linkURL.directory() ); // go up one dir + linkURL.addPath( ftpEnt.link ); // replace link by its destination + kdDebug(7102) << "linkURL now " << linkURL.prettyURL() << endl; + } + // Re-add the filename we're looking for + linkURL.addPath( filename ); + } + bFound = true; + } + } + + // kdDebug(7102) << ftpEnt.name << endl; + } + + ftpCloseCommand(); // closes the data connection only + + if ( !bFound ) + { + ftpStatAnswerNotFound( path, filename ); + return; + } + + if ( !linkURL.isEmpty() ) + { + if ( linkURL == url || linkURL == tempurl ) + { + error( ERR_CYCLIC_LINK, linkURL.prettyURL() ); + return; + } + stat( linkURL ); + return; + } + + kdDebug(7102) << "stat : finished successfully" << endl; + finished(); +} + + +void Ftp::listDir( const KURL &url ) +{ + kdDebug(7102) << "Ftp::listDir " << url.prettyURL() << endl; + if( !ftpOpenConnection(loginImplicit) ) + return; + + // No path specified ? + TQString path = url.path(); + if ( path.isEmpty() ) + { + KURL realURL; + realURL.setProtocol( "ftp" ); + if ( m_user != FTP_LOGIN ) + realURL.setUser( m_user ); + // We set the password, so that we don't ask for it if it was given + if ( m_pass != FTP_PASSWD ) + realURL.setPass( m_pass ); + realURL.setHost( m_host ); + realURL.setPort( m_port ); + if ( m_initialPath.isEmpty() ) + m_initialPath = "/"; + realURL.setPath( m_initialPath ); + kdDebug(7102) << "REDIRECTION to " << realURL.prettyURL() << endl; + redirection( realURL ); + finished(); + return; + } + + kdDebug(7102) << "hunting for path '" << path << "'" << endl; + + if (!ftpOpenDir( path ) ) + { + if ( ftpSize( path, 'I' ) ) // is it a file ? + { + error( ERR_IS_FILE, path ); + return; + } + // not sure which to emit + //error( ERR_DOES_NOT_EXIST, path ); + error( ERR_CANNOT_ENTER_DIRECTORY, path ); + return; + } + + UDSEntry entry; + FtpEntry ftpEnt; + while( ftpReadDir(ftpEnt) ) + { + //kdDebug(7102) << ftpEnt.name << endl; + //Q_ASSERT( !ftpEnt.name.isEmpty() ); + if ( !ftpEnt.name.isEmpty() ) + { + //if ( S_ISDIR( (mode_t)ftpEnt.type ) ) + // kdDebug(7102) << "is a dir" << endl; + //if ( !ftpEnt.link.isEmpty() ) + // kdDebug(7102) << "is a link to " << ftpEnt.link << endl; + entry.clear(); + ftpCreateUDSEntry( ftpEnt.name, ftpEnt, entry, false ); + listEntry( entry, false ); + } + } + listEntry( entry, true ); // ready + ftpCloseCommand(); // closes the data connection only + finished(); +} + +void Ftp::slave_status() +{ + kdDebug(7102) << "Got slave_status host = " << (m_host.ascii() ? m_host.ascii() : "[None]") << " [" << (m_bLoggedOn ? "Connected" : "Not connected") << "]" << endl; + slaveStatus( m_host, m_bLoggedOn ); +} + +bool Ftp::ftpOpenDir( const TQString & path ) +{ + //TQString path( _url.path(-1) ); + + // We try to change to this directory first to see whether it really is a directory. + // (And also to follow symlinks) + TQString tmp = path.isEmpty() ? TQString("/") : path; + + // We get '550', whether it's a file or doesn't exist... + if( !ftpFolder(tmp, false) ) + return false; + + // Don't use the path in the list command: + // We changed into this directory anyway - so it's enough just to send "list". + // We use '-a' because the application MAY be interested in dot files. + // The only way to really know would be to have a metadata flag for this... + // Since some windows ftp server seems not to support the -a argument, we use a fallback here. + // In fact we have to use -la otherwise -a removes the default -l (e.g. ftp.trolltech.com) + if( !ftpOpenCommand( "list -la", TQString::null, 'I', ERR_CANNOT_ENTER_DIRECTORY ) ) + { + if ( !ftpOpenCommand( "list", TQString::null, 'I', ERR_CANNOT_ENTER_DIRECTORY ) ) + { + kdWarning(7102) << "Can't open for listing" << endl; + return false; + } + } + kdDebug(7102) << "Starting of list was ok" << endl; + return true; +} + +bool Ftp::ftpReadDir(FtpEntry& de) +{ + assert(m_data != NULL); + + // get a line from the data connecetion ... + while( !m_data->textEOF() ) + { + if(m_data->textRead() <= 0) + continue; + if(m_data->textTooLong()) + kdWarning(7102) << "ftpReadDir line too long - truncated" << endl; + + const char* buffer = m_data->textLine(); + kdDebug(7102) << "dir > " << buffer << endl; + + //Normally the listing looks like + // -rw-r--r-- 1 dfaure dfaure 102 Nov 9 12:30 log + // but on Netware servers like ftp://ci-1.ci.pwr.wroc.pl/ it looks like (#76442) + // d [RWCEAFMS] Admin 512 Oct 13 2004 PSI + + // we should always get the following 5 fields ... + const char *p_access, *p_junk, *p_owner, *p_group, *p_size; + if( (p_access = strtok((char*)buffer," ")) == 0) continue; + if( (p_junk = strtok(NULL," ")) == 0) continue; + if( (p_owner = strtok(NULL," ")) == 0) continue; + if( (p_group = strtok(NULL," ")) == 0) continue; + if( (p_size = strtok(NULL," ")) == 0) continue; + + //kdDebug(7102) << "p_access=" << p_access << " p_junk=" << p_junk << " p_owner=" << p_owner << " p_group=" << p_group << " p_size=" << p_size << endl; + + de.access = 0; + if ( strlen( p_access ) == 1 && p_junk[0] == '[' ) { // Netware + de.access = S_IRWXU | S_IRWXG | S_IRWXO; // unknown -> give all permissions + } + + const char *p_date_1, *p_date_2, *p_date_3, *p_name; + + // A special hack for "/dev". A listing may look like this: + // crw-rw-rw- 1 root root 1, 5 Jun 29 1997 zero + // So we just ignore the number in front of the ",". Ok, its a hack :-) + if ( strchr( p_size, ',' ) != 0L ) + { + //kdDebug(7102) << "Size contains a ',' -> reading size again (/dev hack)" << endl; + if ((p_size = strtok(NULL," ")) == 0) + continue; + } + + // Check whether the size we just read was really the size + // or a month (this happens when the server lists no group) + // Used to be the case on sunsite.uio.no, but not anymore + // This is needed for the Netware case, too. + if ( !isdigit( *p_size ) ) + { + p_date_1 = p_size; + p_size = p_group; + p_group = 0; + //kdDebug(7102) << "Size didn't have a digit -> size=" << p_size << " date_1=" << p_date_1 << endl; + } + else + { + p_date_1 = strtok(NULL," "); + //kdDebug(7102) << "Size has a digit -> ok. p_date_1=" << p_date_1 << endl; + } + + if ( p_date_1 != 0 && + (p_date_2 = strtok(NULL," ")) != 0 && + (p_date_3 = strtok(NULL," ")) != 0 && + (p_name = strtok(NULL,"\r\n")) != 0 ) + { + { + TQCString tmp( p_name ); + if ( p_access[0] == 'l' ) + { + int i = tmp.findRev( " -> " ); + if ( i != -1 ) { + de.link = remoteEncoding()->decode(p_name + i + 4); + tmp.truncate( i ); + } + else + de.link = TQString::null; + } + else + de.link = TQString::null; + + if ( tmp[0] == '/' ) // listing on ftp://ftp.gnupg.org/ starts with '/' + tmp.remove( 0, 1 ); + + if (tmp.find('/') != -1) + continue; // Don't trick us! + // Some sites put more than one space between the date and the name + // e.g. ftp://ftp.uni-marburg.de/mirror/ + de.name = remoteEncoding()->decode(tmp.stripWhiteSpace()); + } + + de.type = S_IFREG; + switch ( p_access[0] ) { + case 'd': + de.type = S_IFDIR; + break; + case 's': + de.type = S_IFSOCK; + break; + case 'b': + de.type = S_IFBLK; + break; + case 'c': + de.type = S_IFCHR; + break; + case 'l': + de.type = S_IFREG; + // we don't set S_IFLNK here. de.link says it. + break; + default: + break; + } + + if ( p_access[1] == 'r' ) + de.access |= S_IRUSR; + if ( p_access[2] == 'w' ) + de.access |= S_IWUSR; + if ( p_access[3] == 'x' || p_access[3] == 's' ) + de.access |= S_IXUSR; + if ( p_access[4] == 'r' ) + de.access |= S_IRGRP; + if ( p_access[5] == 'w' ) + de.access |= S_IWGRP; + if ( p_access[6] == 'x' || p_access[6] == 's' ) + de.access |= S_IXGRP; + if ( p_access[7] == 'r' ) + de.access |= S_IROTH; + if ( p_access[8] == 'w' ) + de.access |= S_IWOTH; + if ( p_access[9] == 'x' || p_access[9] == 't' ) + de.access |= S_IXOTH; + if ( p_access[3] == 's' || p_access[3] == 'S' ) + de.access |= S_ISUID; + if ( p_access[6] == 's' || p_access[6] == 'S' ) + de.access |= S_ISGID; + if ( p_access[9] == 't' || p_access[9] == 'T' ) + de.access |= S_ISVTX; + + de.owner = remoteEncoding()->decode(p_owner); + de.group = remoteEncoding()->decode(p_group); + de.size = charToLongLong(p_size); + + // Parsing the date is somewhat tricky + // Examples : "Oct 6 22:49", "May 13 1999" + + // First get current time - we need the current month and year + time_t currentTime = time( 0L ); + struct tm * tmptr = gmtime( ¤tTime ); + int currentMonth = tmptr->tm_mon; + //kdDebug(7102) << "Current time :" << asctime( tmptr ) << endl; + // Reset time fields + tmptr->tm_isdst = -1; // We do not know anything about day saving time (of any random day of the year) + tmptr->tm_sec = 0; + tmptr->tm_min = 0; + tmptr->tm_hour = 0; + // Get day number (always second field) + tmptr->tm_mday = atoi( p_date_2 ); + // Get month from first field + // NOTE : no, we don't want to use TDELocale here + // It seems all FTP servers use the English way + //kdDebug(7102) << "Looking for month " << p_date_1 << endl; + static const char * s_months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + for ( int c = 0 ; c < 12 ; c ++ ) + if ( !strcmp( p_date_1, s_months[c]) ) + { + //kdDebug(7102) << "Found month " << c << " for " << p_date_1 << endl; + tmptr->tm_mon = c; + break; + } + + // Parse third field + if ( strlen( p_date_3 ) == 4 ) // 4 digits, looks like a year + tmptr->tm_year = atoi( p_date_3 ) - 1900; + else + { + // otherwise, the year is implicit + // according to man ls, this happens when it is between than 6 months + // old and 1 hour in the future. + // So the year is : current year if tm_mon <= currentMonth+1 + // otherwise current year minus one + // (The +1 is a security for the "+1 hour" at the end of the month issue) + if ( tmptr->tm_mon > currentMonth + 1 ) + tmptr->tm_year--; + + // and p_date_3 contains probably a time + char * semicolon; + if ( ( semicolon = const_cast(strchr( p_date_3, ':' )) ) ) + { + *semicolon = '\0'; + tmptr->tm_min = atoi( semicolon + 1 ); + tmptr->tm_hour = atoi( p_date_3 ); + } + else + kdWarning(7102) << "Can't parse third field " << p_date_3 << endl; + } + + //kdDebug(7102) << asctime( tmptr ) << endl; + de.date = mktime( tmptr ); + return true; + } + } // line invalid, loop to get another line + return false; +} + +//=============================================================================== +// public: get download file from server +// helper: ftpGet called from get() and copy() +//=============================================================================== +void Ftp::get( const KURL & url ) +{ + kdDebug(7102) << "Ftp::get " << url.url() << endl; + int iError = 0; + ftpGet(iError, -1, url, 0); // iError gets status + if(iError) // can have only server side errs + error(iError, url.path()); + ftpCloseCommand(); // must close command! +} + +Ftp::StatusCode Ftp::ftpGet(int& iError, int iCopyFile, const KURL& url, TDEIO::fileoffset_t llOffset) +{ + // Calls error() by itself! + if( !ftpOpenConnection(loginImplicit) ) + return statusServerError; + + // Try to find the size of the file (and check that it exists at + // the same time). If we get back a 550, "File does not exist" + // or "not a plain file", check if it is a directory. If it is a + // directory, return an error; otherwise simply try to retrieve + // the request... + if ( !ftpSize( url.path(), '?' ) && (m_iRespCode == 550) && + ftpFolder(url.path(), false) ) + { + // Ok it's a dir in fact + kdDebug(7102) << "ftpGet: it is a directory in fact" << endl; + iError = ERR_IS_DIRECTORY; + return statusServerError; + } + + TQString resumeOffset = metaData("resume"); + if ( !resumeOffset.isEmpty() ) + { + llOffset = resumeOffset.toLongLong(); + kdDebug(7102) << "ftpGet: got offset from metadata : " << llOffset << endl; + } + + if( !ftpOpenCommand("retr", url.path(), '?', ERR_CANNOT_OPEN_FOR_READING, llOffset) ) + { + kdWarning(7102) << "ftpGet: Can't open for reading" << endl; + return statusServerError; + } + + // Read the size from the response string + if(m_size == UnknownSize) + { + const char* psz = strrchr( ftpResponse(4), '(' ); + if(psz) m_size = charToLongLong(psz+1); + if (!m_size) m_size = UnknownSize; + } + + TDEIO::filesize_t bytesLeft = 0; + if ( m_size != UnknownSize ) + bytesLeft = m_size - llOffset; + + kdDebug(7102) << "ftpGet: starting with offset=" << llOffset << endl; + TDEIO::fileoffset_t processed_size = llOffset; + + TQByteArray array; + bool mimetypeEmitted = false; + char buffer[maximumIpcSize]; + // start whith small data chunks in case of a slow data source (modem) + // - unfortunately this has a negative impact on performance for large + // - files - so we will increase the block size after a while ... + int iBlockSize = initialIpcSize; + int iBufferCur = 0; + + while(m_size == UnknownSize || bytesLeft > 0) + { // let the buffer size grow if the file is larger 64kByte ... + if(processed_size-llOffset > 1024 * 64) + iBlockSize = maximumIpcSize; + + // read the data and detect EOF or error ... + if(iBlockSize+iBufferCur > (int)sizeof(buffer)) + iBlockSize = sizeof(buffer) - iBufferCur; + int n = m_data->read( buffer+iBufferCur, iBlockSize ); + if(n <= 0) + { // this is how we detect EOF in case of unknown size + if( m_size == UnknownSize && n == 0 ) + break; + // unexpected eof. Happens when the daemon gets killed. + iError = ERR_COULD_NOT_READ; + return statusServerError; + } + processed_size += n; + + // collect very small data chunks in buffer before processing ... + if(m_size != UnknownSize) + { + bytesLeft -= n; + iBufferCur += n; + if(iBufferCur < mimimumMimeSize && bytesLeft > 0) + { + processedSize( processed_size ); + continue; + } + n = iBufferCur; + iBufferCur = 0; + } + + // get the mime type and set the total size ... + if(!mimetypeEmitted) + { + mimetypeEmitted = true; + + // We need a KMimeType::findByNameAndContent(data,filename) + // For now we do: find by extension, and if not found (or extension not reliable) + // then find by content. + bool accurate = false; + KMimeType::Ptr mime = KMimeType::findByURL( url, 0, false, true, &accurate ); + if ( !mime || mime->name() == KMimeType::defaultMimeType() + || !accurate ) + { + array.setRawData(buffer, n); + KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType(array, url.fileName()); + array.resetRawData(buffer, n); + if ( result->mimeType() != KMimeType::defaultMimeType() ) + mime = KMimeType::mimeType( result->mimeType() ); + } + + kdDebug(7102) << "ftpGet: Emitting mimetype " << mime->name() << endl; + mimeType( mime->name() ); + if( m_size != UnknownSize ) // Emit total size AFTER mimetype + totalSize( m_size ); + } + + // write output file or pass to data pump ... + if(iCopyFile == -1) + { + array.setRawData(buffer, n); + data( array ); + array.resetRawData(buffer, n); + } + else if( (iError = WriteToFile(iCopyFile, buffer, n)) != 0) + return statusClientError; // client side error + processedSize( processed_size ); + } + + kdDebug(7102) << "ftpGet: done" << endl; + if(iCopyFile == -1) // must signal EOF to data pump ... + data(array); // array is empty and must be empty! + + processedSize( m_size == UnknownSize ? processed_size : m_size ); + kdDebug(7102) << "ftpGet: emitting finished()" << endl; + finished(); + return statusSuccess; +} + +/* +void Ftp::mimetype( const KURL& url ) +{ + if( !ftpOpenConnection(loginImplicit) ) + return; + + if ( !ftpOpenCommand( "retr", url.path(), 'I', ERR_CANNOT_OPEN_FOR_READING, 0 ) ) { + kdWarning(7102) << "Can't open for reading" << endl; + return; + } + char buffer[ 2048 ]; + TQByteArray array; + // Get one chunk of data only and send it, TDEIO::Job will determine the + // mimetype from it using KMimeMagic + int n = m_data->read( buffer, 2048 ); + array.setRawData(buffer, n); + data( array ); + array.resetRawData(buffer, n); + + kdDebug(7102) << "aborting" << endl; + ftpAbortTransfer(); + + kdDebug(7102) << "finished" << endl; + finished(); + kdDebug(7102) << "after finished" << endl; +} + +void Ftp::ftpAbortTransfer() +{ + // RFC 959, page 34-35 + // IAC (interpret as command) = 255 ; IP (interrupt process) = 254 + // DM = 242 (data mark) + char msg[4]; + // 1. User system inserts the Telnet "Interrupt Process" (IP) signal + // in the Telnet stream. + msg[0] = (char) 255; //IAC + msg[1] = (char) 254; //IP + (void) send(sControl, msg, 2, 0); + // 2. User system sends the Telnet "Sync" signal. + msg[0] = (char) 255; //IAC + msg[1] = (char) 242; //DM + if (send(sControl, msg, 2, MSG_OOB) != 2) + ; // error... + + // Send ABOR + kdDebug(7102) << "send ABOR" << endl; + TQCString buf = "ABOR\r\n"; + if ( KSocks::self()->write( sControl, buf.data(), buf.length() ) <= 0 ) { + error( ERR_COULD_NOT_WRITE, TQString::null ); + return; + } + + // + kdDebug(7102) << "read resp" << endl; + if ( readresp() != '2' ) + { + error( ERR_COULD_NOT_READ, TQString::null ); + return; + } + + kdDebug(7102) << "close sockets" << endl; + closeSockets(); +} +*/ + +//=============================================================================== +// public: put upload file to server +// helper: ftpPut called from put() and copy() +//=============================================================================== +void Ftp::put(const KURL& url, int permissions, bool overwrite, bool resume) +{ + kdDebug(7102) << "Ftp::put " << url.url() << endl; + int iError = 0; // iError gets status + ftpPut(iError, -1, url, permissions, overwrite, resume); + if(iError) // can have only server side errs + error(iError, url.path()); + ftpCloseCommand(); // must close command! +} + +Ftp::StatusCode Ftp::ftpPut(int& iError, int iCopyFile, const KURL& dest_url, + int permissions, bool overwrite, bool resume) +{ + if( !ftpOpenConnection(loginImplicit) ) + return statusServerError; + + // Don't use mark partial over anonymous FTP. + // My incoming dir allows put but not rename... + bool bMarkPartial; + if (m_user.isEmpty () || m_user == FTP_LOGIN) + bMarkPartial = false; + else + bMarkPartial = config()->readBoolEntry("MarkPartial", true); + + TQString dest_orig = dest_url.path(); + TQString dest_part( dest_orig ); + dest_part += ".part"; + + if ( ftpSize( dest_orig, 'I' ) ) + { + if ( m_size == 0 ) + { // delete files with zero size + TQCString cmd = "DELE "; + cmd += remoteEncoding()->encode(dest_orig); + if( !ftpSendCmd( cmd ) || (m_iRespType != 2) ) + { + iError = ERR_CANNOT_DELETE_PARTIAL; + return statusServerError; + } + } + else if ( !overwrite && !resume ) + { + iError = ERR_FILE_ALREADY_EXIST; + return statusServerError; + } + else if ( bMarkPartial ) + { // when using mark partial, append .part extension + if ( !ftpRename( dest_orig, dest_part, true ) ) + { + iError = ERR_CANNOT_RENAME_PARTIAL; + return statusServerError; + } + } + // Don't chmod an existing file + permissions = -1; + } + else if ( bMarkPartial && ftpSize( dest_part, 'I' ) ) + { // file with extension .part exists + if ( m_size == 0 ) + { // delete files with zero size + TQCString cmd = "DELE "; + cmd += remoteEncoding()->encode(dest_part); + if ( !ftpSendCmd( cmd ) || (m_iRespType != 2) ) + { + iError = ERR_CANNOT_DELETE_PARTIAL; + return statusServerError; + } + } + else if ( !overwrite && !resume ) + { + resume = canResume (m_size); + if (!resume) + { + iError = ERR_FILE_ALREADY_EXIST; + return statusServerError; + } + } + } + else + m_size = 0; + + TQString dest; + + // if we are using marking of partial downloads -> add .part extension + if ( bMarkPartial ) { + kdDebug(7102) << "Adding .part extension to " << dest_orig << endl; + dest = dest_part; + } else + dest = dest_orig; + + TDEIO::fileoffset_t offset = 0; + + // set the mode according to offset + if( resume && m_size > 0 ) + { + offset = m_size; + if(iCopyFile != -1) + { + if( KDE_lseek(iCopyFile, offset, SEEK_SET) < 0 ) + { + iError = ERR_CANNOT_RESUME; + return statusClientError; + } + } + } + + if (! ftpOpenCommand( "stor", dest, '?', ERR_COULD_NOT_WRITE, offset ) ) + return statusServerError; + + kdDebug(7102) << "ftpPut: starting with offset=" << offset << endl; + TDEIO::fileoffset_t processed_size = offset; + + TQByteArray buffer; + int result; + int iBlockSize = initialIpcSize; + // Loop until we got 'dataEnd' + do + { + if(iCopyFile == -1) + { + dataReq(); // Request for data + result = readData( buffer ); + } + else + { // let the buffer size grow if the file is larger 64kByte ... + if(processed_size-offset > 1024 * 64) + iBlockSize = maximumIpcSize; + buffer.resize(iBlockSize); + result = ::read(iCopyFile, buffer.data(), buffer.size()); + if(result < 0) + iError = ERR_COULD_NOT_WRITE; + else + buffer.resize(result); + } + + if (result > 0) + { + m_data->write( buffer.data(), buffer.size() ); + processed_size += result; + processedSize (processed_size); + } + } + while ( result > 0 ); + + if (result != 0) // error + { + ftpCloseCommand(); // don't care about errors + kdDebug(7102) << "Error during 'put'. Aborting." << endl; + if (bMarkPartial) + { + // Remove if smaller than minimum size + if ( ftpSize( dest, 'I' ) && + ( processed_size < (unsigned long) config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE) ) ) + { + TQCString cmd = "DELE "; + cmd += remoteEncoding()->encode(dest); + (void) ftpSendCmd( cmd ); + } + } + return statusServerError; + } + + if ( !ftpCloseCommand() ) + { + iError = ERR_COULD_NOT_WRITE; + return statusServerError; + } + + // after full download rename the file back to original name + if ( bMarkPartial ) + { + kdDebug(7102) << "renaming dest (" << dest << ") back to dest_orig (" << dest_orig << ")" << endl; + if ( !ftpRename( dest, dest_orig, true ) ) + { + iError = ERR_CANNOT_RENAME_PARTIAL; + return statusServerError; + } + } + + // set final permissions + if ( permissions != -1 ) + { + if ( m_user == FTP_LOGIN ) + kdDebug(7102) << "Trying to chmod over anonymous FTP ???" << endl; + // chmod the file we just put + if ( ! ftpChmod( dest_orig, permissions ) ) + { + // To be tested + //if ( m_user != FTP_LOGIN ) + // warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) ); + } + } + + // We have done our job => finish + finished(); + return statusSuccess; +} + + +/** Use the SIZE command to get the file size. + Warning : the size depends on the transfer mode, hence the second arg. */ +bool Ftp::ftpSize( const TQString & path, char mode ) +{ + m_size = UnknownSize; + if( !ftpDataMode(mode) ) + return false; + + TQCString buf; + buf = "SIZE "; + buf += remoteEncoding()->encode(path); + if( !ftpSendCmd( buf ) || (m_iRespType != 2) ) + return false; + + // skip leading "213 " (response code) + const char* psz = ftpResponse(4); + if(!psz) + return false; + m_size = charToLongLong(psz); + if (!m_size) m_size = UnknownSize; + return true; +} + +bool Ftp::ftpFileExists(const TQString& path) +{ + TQCString buf; + buf = "SIZE "; + buf += remoteEncoding()->encode(path); + if( !ftpSendCmd( buf ) || (m_iRespType != 2) ) + return false; + + // skip leading "213 " (response code) + const char* psz = ftpResponse(4); + return psz != 0; +} + +// Today the differences between ASCII and BINARY are limited to +// CR or CR/LF line terminators. Many servers ignore ASCII (like +// win2003 -or- vsftp with default config). In the early days of +// computing, when even text-files had structure, this stuff was +// more important. +// Theoretically "list" could return different results in ASCII +// and BINARY mode. But again, most servers ignore ASCII here. +bool Ftp::ftpDataMode(char cMode) +{ + if(cMode == '?') cMode = m_bTextMode ? 'A' : 'I'; + else if(cMode == 'a') cMode = 'A'; + else if(cMode != 'A') cMode = 'I'; + + kdDebug(7102) << "ftpDataMode: want '" << cMode << "' has '" << m_cDataMode << "'" << endl; + if(m_cDataMode == cMode) + return true; + + TQCString buf; + buf.sprintf("TYPE %c", cMode); + if( !ftpSendCmd(buf) || (m_iRespType != 2) ) + return false; + m_cDataMode = cMode; + return true; +} + + +bool Ftp::ftpFolder(const TQString& path, bool bReportError) +{ + TQString newPath = path; + int iLen = newPath.length(); + if(iLen > 1 && newPath[iLen-1] == '/') newPath.truncate(iLen-1); + + //kdDebug(7102) << "ftpFolder: want '" << newPath << "' has '" << m_currentPath << "'" << endl; + if(m_currentPath == newPath) + return true; + + TQCString tmp = "cwd "; + tmp += remoteEncoding()->encode(newPath); + if( !ftpSendCmd(tmp) ) + return false; // connection failure + if(m_iRespType != 2) + { + if(bReportError) + error(ERR_CANNOT_ENTER_DIRECTORY, path); + return false; // not a folder + } + m_currentPath = newPath; + return true; +} + + +//=============================================================================== +// public: copy don't use tdeio data pump if one side is a local file +// helper: ftpCopyPut called from copy() on upload +// helper: ftpCopyGet called from copy() on download +//=============================================================================== +void Ftp::copy( const KURL &src, const KURL &dest, int permissions, bool overwrite ) +{ + int iError = 0; + int iCopyFile = -1; + StatusCode cs = statusSuccess; + bool bSrcLocal = src.isLocalFile(); + bool bDestLocal = dest.isLocalFile(); + TQString sCopyFile; + + if(bSrcLocal && !bDestLocal) // File -> Ftp + { + sCopyFile = src.path(); + kdDebug(7102) << "Ftp::copy local file '" << sCopyFile << "' -> ftp '" << dest.path() << "'" << endl; + cs = ftpCopyPut(iError, iCopyFile, sCopyFile, dest, permissions, overwrite); + if( cs == statusServerError) sCopyFile = dest.url(); + } + else if(!bSrcLocal && bDestLocal) // Ftp -> File + { + sCopyFile = dest.path(); + kdDebug(7102) << "Ftp::copy ftp '" << src.path() << "' -> local file '" << sCopyFile << "'" << endl; + cs = ftpCopyGet(iError, iCopyFile, sCopyFile, src, permissions, overwrite); + if( cs == statusServerError ) sCopyFile = src.url(); + } + else { + error( ERR_UNSUPPORTED_ACTION, TQString::null ); + return; + } + + // perform clean-ups and report error (if any) + if(iCopyFile != -1) + ::close(iCopyFile); + if(iError) + error(iError, sCopyFile); + ftpCloseCommand(); // must close command! +} + + +Ftp::StatusCode Ftp::ftpCopyPut(int& iError, int& iCopyFile, TQString sCopyFile, + const KURL& url, int permissions, bool overwrite) +{ + // check if source is ok ... + KDE_struct_stat buff; + TQCString sSrc( TQFile::encodeName(sCopyFile) ); + bool bSrcExists = (KDE_stat( sSrc.data(), &buff ) != -1); + if(bSrcExists) + { if(S_ISDIR(buff.st_mode)) + { + iError = ERR_IS_DIRECTORY; + return statusClientError; + } + } + else + { + iError = ERR_DOES_NOT_EXIST; + return statusClientError; + } + + iCopyFile = KDE_open( sSrc.data(), O_RDONLY ); + if(iCopyFile == -1) + { + iError = ERR_CANNOT_OPEN_FOR_READING; + return statusClientError; + } + + // delegate the real work (iError gets status) ... + totalSize(buff.st_size); +#ifdef ENABLE_CAN_RESUME + return ftpPut(iError, iCopyFile, url, permissions, overwrite, false); +#else + return ftpPut(iError, iCopyFile, url, permissions, overwrite, true); +#endif +} + + +Ftp::StatusCode Ftp::ftpCopyGet(int& iError, int& iCopyFile, const TQString sCopyFile, + const KURL& url, int permissions, bool overwrite) +{ + // check if destination is ok ... + KDE_struct_stat buff; + TQCString sDest( TQFile::encodeName(sCopyFile) ); + bool bDestExists = (KDE_stat( sDest.data(), &buff ) != -1); + if(bDestExists) + { if(S_ISDIR(buff.st_mode)) + { + iError = ERR_IS_DIRECTORY; + return statusClientError; + } + if(!overwrite) + { + iError = ERR_FILE_ALREADY_EXIST; + return statusClientError; + } + } + + // do we have a ".part" file? + TQCString sPart = TQFile::encodeName(sCopyFile + ".part"); + bool bResume = false; + bool bPartExists = (KDE_stat( sPart.data(), &buff ) != -1); + const bool bMarkPartial = config()->readBoolEntry("MarkPartial", true); + + if(!bMarkPartial) + { + sPart = TQFile::encodeName(sCopyFile); + } + else if(bPartExists && buff.st_size > 0) + { // must not be a folder! please fix a similar bug in tdeio_file!! + if(S_ISDIR(buff.st_mode)) + { + iError = ERR_DIR_ALREADY_EXIST; + return statusClientError; // client side error + } + //doesn't work for copy? -> design flaw? +#ifdef ENABLE_CAN_RESUME + bResume = canResume( buff.st_size ); +#else + bResume = true; +#endif + } + + if(bPartExists && !bResume) // get rid of an unwanted ".part" file + remove(sPart.data()); + + // JPF: in tdeio_file overwrite disables ".part" operations. I do not believe + // JPF: that this is a good behaviour! + if(bDestExists) // must delete for overwrite + remove(sDest.data()); + + // WABA: Make sure that we keep writing permissions ourselves, + // otherwise we can be in for a surprise on NFS. + mode_t initialMode; + if (permissions != -1) + initialMode = permissions | S_IWUSR; + else + initialMode = 0666; + + // open the output file ... + TDEIO::fileoffset_t hCopyOffset = 0; + if(bResume) + { + iCopyFile = KDE_open( sPart.data(), O_RDWR ); // append if resuming + hCopyOffset = KDE_lseek(iCopyFile, 0, SEEK_END); + if(hCopyOffset < 0) + { + iError = ERR_CANNOT_RESUME; + return statusClientError; // client side error + } + kdDebug(7102) << "copy: resuming at " << hCopyOffset << endl; + } + else + iCopyFile = KDE_open(sPart.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); + + if(iCopyFile == -1) + { + kdDebug(7102) << "copy: ### COULD NOT WRITE " << sCopyFile << endl; + iError = (errno == EACCES) ? ERR_WRITE_ACCESS_DENIED + : ERR_CANNOT_OPEN_FOR_WRITING; + return statusClientError; + } + + // delegate the real work (iError gets status) ... + StatusCode iRes = ftpGet(iError, iCopyFile, url, hCopyOffset); + if( ::close(iCopyFile) && iRes == statusSuccess ) + { + iError = ERR_COULD_NOT_WRITE; + iRes = statusClientError; + } + + // handle renaming or deletion of a partial file ... + if(bMarkPartial) + { + if(iRes == statusSuccess) + { // rename ".part" on success + if ( ::rename( sPart.data(), sDest.data() ) ) + { + kdDebug(7102) << "copy: cannot rename " << sPart << " to " << sDest << endl; + iError = ERR_CANNOT_RENAME_PARTIAL; + iRes = statusClientError; + } + } + else if(KDE_stat( sPart.data(), &buff ) == 0) + { // should a very small ".part" be deleted? + int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); + if (buff.st_size < size) + remove(sPart.data()); + } + } + return iRes; +} diff --git a/tdeioslave/http/CMakeLists.txt b/tdeioslave/http/CMakeLists.txt index a1a6c296a..a8570d60f 100644 --- a/tdeioslave/http/CMakeLists.txt +++ b/tdeioslave/http/CMakeLists.txt @@ -62,7 +62,7 @@ tde_add_tdeinit_executable( ${target} AUTOMOC set( target tdeio_http ) set( ${target}_SRCS - http.cc + http.cpp ) tde_add_kpart( ${target} AUTOMOC diff --git a/tdeioslave/http/Makefile.am b/tdeioslave/http/Makefile.am index 8e2eb4187..f4f4ddc7f 100644 --- a/tdeioslave/http/Makefile.am +++ b/tdeioslave/http/Makefile.am @@ -13,7 +13,7 @@ lib_LTLIBRARIES= tdeinit_LTLIBRARIES = tdeio_http_cache_cleaner.la kde_module_LTLIBRARIES = tdeio_http.la -tdeio_http_la_SOURCES = http.cc +tdeio_http_la_SOURCES = http.cpp tdeio_http_la_METASOURCES = AUTO tdeio_http_la_LIBADD = $(LIB_TDEIO) $(top_builddir)/tdeio/httpfilter/libhttpfilter.la $(LIB_TQT) $(LIB_TDECORE) $(LIBZ) $(top_builddir)/dcop/libDCOP.la $(top_builddir)/tdeio/misc/tdentlm/libtdentlm.la tdeio_http_la_LDFLAGS = $(all_libraries) $(GSSAPI_RPATH) -module $(KDE_PLUGIN) $(GSSAPI_LIBS) diff --git a/tdeioslave/http/README.webdav b/tdeioslave/http/README.webdav index d7f6cca26..e2a0f5d35 100644 --- a/tdeioslave/http/README.webdav +++ b/tdeioslave/http/README.webdav @@ -13,7 +13,7 @@ Applications supporting extended webdav features [none currently] Much of the info here is elaborated by rfc #2518; the rest can be understood by reading -davPropStat() in http.cc, specifically the setMetaData() calls. +davPropStat() in http.cpp, specifically the setMetaData() calls. Extended information is transferred via tdeio's metadata system... diff --git a/tdeioslave/http/http.cc b/tdeioslave/http/http.cc deleted file mode 100644 index 8cd0f7a64..000000000 --- a/tdeioslave/http/http.cc +++ /dev/null @@ -1,6131 +0,0 @@ -/* - Copyright (C) 2000-2003 Waldo Bastian - Copyright (C) 2000-2002 George Staikos - Copyright (C) 2000-2002 Dawit Alemayehu - Copyright (C) 2001,2002 Hamish Rodda - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License (LGPL) as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later - version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include // Required for AIX -#include -#include // must be explicitly included for MacOSX - -/* -#include -#include -#include -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tdeio/ioslave_defaults.h" -#include "tdeio/http_slave_defaults.h" - -#include "httpfilter.h" -#include "http.h" - -#ifdef HAVE_LIBGSSAPI -#ifdef GSSAPI_MIT -#include -#else -#include -#endif /* GSSAPI_MIT */ - -// Catch uncompatible crap (BR86019) -#if defined(GSS_RFC_COMPLIANT_OIDS) && (GSS_RFC_COMPLIANT_OIDS == 0) -#include -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#endif - -#endif /* HAVE_LIBGSSAPI */ - -#include - -using namespace TDEIO; - -extern "C" { - KDE_EXPORT int kdemain(int argc, char **argv); -} - -int kdemain( int argc, char **argv ) -{ - TDELocale::setMainCatalogue("tdelibs"); - TDEInstance instance( "tdeio_http" ); - ( void ) TDEGlobal::locale(); - - if (argc != 4) - { - fprintf(stderr, "Usage: tdeio_http protocol domain-socket1 domain-socket2\n"); - exit(-1); - } - - HTTPProtocol slave(argv[1], argv[2], argv[3]); - slave.dispatchLoop(); - return 0; -} - -/*********************************** Generic utility functions ********************/ - -static char * trimLead (char *orig_string) -{ - while (*orig_string == ' ') - orig_string++; - return orig_string; -} - -static bool isCrossDomainRequest( const TQString& fqdn, const TQString& originURL ) -{ - if (originURL == "true") // Backwards compatibility - return true; - - KURL url ( originURL ); - - // Document Origin domain - TQString a = url.host(); - - // Current request domain - TQString b = fqdn; - - if (a == b) - return false; - - TQStringList l1 = TQStringList::split('.', a); - TQStringList l2 = TQStringList::split('.', b); - - while(l1.count() > l2.count()) - l1.pop_front(); - - while(l2.count() > l1.count()) - l2.pop_front(); - - while(l2.count() >= 2) - { - if (l1 == l2) - return false; - - l1.pop_front(); - l2.pop_front(); - } - - return true; -} - -/* - Eliminates any custom header that could potentically alter the request -*/ -static TQString sanitizeCustomHTTPHeader(const TQString& _header) -{ - TQString sanitizedHeaders; - TQStringList headers = TQStringList::split(TQRegExp("[\r\n]"), _header); - - for(TQStringList::Iterator it = headers.begin(); it != headers.end(); ++it) - { - TQString header = (*it).lower(); - // Do not allow Request line to be specified and ignore - // the other HTTP headers. - if (header.find(':') == -1 || - header.startsWith("host") || - header.startsWith("via")) - continue; - - sanitizedHeaders += (*it); - sanitizedHeaders += "\r\n"; - } - - return sanitizedHeaders.stripWhiteSpace(); -} - -static TQString htmlEscape(const TQString &plain) -{ - TQString rich; - rich.reserve(uint(plain.length() * 1.1)); - for (uint i = 0; i < plain.length(); ++i) { - if (plain.at(i) == '<') { - rich += "<"; - } else if (plain.at(i) == '>') { - rich += ">"; - } else if (plain.at(i) == '&') { - rich += "&"; - } else if (plain.at(i) == '"') { - rich += """; - } else { - rich += plain.at(i); - } - } - rich.squeeze(); - return rich; -} - - -#define NO_SIZE ((TDEIO::filesize_t) -1) - -#ifdef HAVE_STRTOLL -#define STRTOLL strtoll -#else -#define STRTOLL strtol -#endif - - -/************************************** HTTPProtocol **********************************************/ - -HTTPProtocol::HTTPProtocol( const TQCString &protocol, const TQCString &pool, - const TQCString &app ) - :TCPSlaveBase( 0, protocol , pool, app, - (protocol == "https" || protocol == "webdavs") ) -{ - m_requestQueue.setAutoDelete(true); - - m_bBusy = false; - m_bFirstRequest = false; - m_bProxyAuthValid = false; - - m_iSize = NO_SIZE; - m_lineBufUnget = 0; - - m_protocol = protocol; - - m_maxCacheAge = DEFAULT_MAX_CACHE_AGE; - m_maxCacheSize = DEFAULT_MAX_CACHE_SIZE / 2; - m_remoteConnTimeout = DEFAULT_CONNECT_TIMEOUT; - m_remoteRespTimeout = DEFAULT_RESPONSE_TIMEOUT; - m_proxyConnTimeout = DEFAULT_PROXY_CONNECT_TIMEOUT; - - m_pid = getpid(); - - setMultipleAuthCaching( true ); - reparseConfiguration(); -} - -HTTPProtocol::~HTTPProtocol() -{ - httpClose(false); -} - -void HTTPProtocol::reparseConfiguration() -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::reparseConfiguration" << endl; - - m_strProxyRealm = TQString::null; - m_strProxyAuthorization = TQString::null; - ProxyAuthentication = AUTH_None; - m_bUseProxy = false; - - if (m_protocol == "https" || m_protocol == "webdavs") - m_iDefaultPort = DEFAULT_HTTPS_PORT; - else if (m_protocol == "ftp") - m_iDefaultPort = DEFAULT_FTP_PORT; - else - m_iDefaultPort = DEFAULT_HTTP_PORT; -} - -void HTTPProtocol::resetConnectionSettings() -{ - m_bEOF = false; - m_bError = false; - m_lineCount = 0; - m_iWWWAuthCount = 0; - m_lineCountUnget = 0; - m_iProxyAuthCount = 0; - -} - -void HTTPProtocol::resetResponseSettings() -{ - m_bRedirect = false; - m_redirectLocation = KURL(); - m_bChunked = false; - m_iSize = NO_SIZE; - - m_responseHeader.clear(); - m_qContentEncodings.clear(); - m_qTransferEncodings.clear(); - m_sContentMD5 = TQString::null; - m_strMimeType = TQString::null; - - setMetaData("request-id", m_request.id); -} - -void HTTPProtocol::resetSessionSettings() -{ - // Do not reset the URL on redirection if the proxy - // URL, username or password has not changed! - KURL proxy ( config()->readEntry("UseProxy") ); - - if ( m_strProxyRealm.isEmpty() || !proxy.isValid() || - m_proxyURL.host() != proxy.host() || - (!proxy.user().isNull() && proxy.user() != m_proxyURL.user()) || - (!proxy.pass().isNull() && proxy.pass() != m_proxyURL.pass()) ) - { - m_bProxyAuthValid = false; - m_proxyURL = proxy; - m_bUseProxy = m_proxyURL.isValid(); - - kdDebug(7113) << "(" << m_pid << ") Using proxy: " << m_bUseProxy << - " URL: " << m_proxyURL.prettyURL() << - " Realm: " << m_strProxyRealm << endl; - } - - m_bPersistentProxyConnection = config()->readBoolEntry("PersistentProxyConnection", false); - kdDebug(7113) << "(" << m_pid << ") Enable Persistent Proxy Connection: " - << m_bPersistentProxyConnection << endl; - - m_request.bUseCookiejar = config()->readBoolEntry("Cookies"); - m_request.bUseCache = config()->readBoolEntry("UseCache", true); - m_request.bErrorPage = config()->readBoolEntry("errorPage", true); - m_request.bNoAuth = config()->readBoolEntry("no-auth"); - m_strCacheDir = config()->readPathEntry("CacheDir"); - m_maxCacheAge = config()->readNumEntry("MaxCacheAge", DEFAULT_MAX_CACHE_AGE); - m_request.window = config()->readEntry("window-id"); - - kdDebug(7113) << "(" << m_pid << ") Window Id = " << m_request.window << endl; - kdDebug(7113) << "(" << m_pid << ") ssl_was_in_use = " - << metaData ("ssl_was_in_use") << endl; - - m_request.referrer = TQString::null; - if ( config()->readBoolEntry("SendReferrer", true) && - (m_protocol == "https" || m_protocol == "webdavs" || - metaData ("ssl_was_in_use") != "TRUE" ) ) - { - KURL referrerURL ( metaData("referrer") ); - if (referrerURL.isValid()) - { - // Sanitize - TQString protocol = referrerURL.protocol(); - if (protocol.startsWith("webdav")) - { - protocol.replace(0, 6, "http"); - referrerURL.setProtocol(protocol); - } - - if (protocol.startsWith("http")) - { - referrerURL.setRef(TQString::null); - referrerURL.setUser(TQString::null); - referrerURL.setPass(TQString::null); - m_request.referrer = referrerURL.url(); - } - } - } - - if ( config()->readBoolEntry("SendLanguageSettings", true) ) - { - m_request.charsets = config()->readEntry( "Charsets", "iso-8859-1" ); - - if ( !m_request.charsets.isEmpty() ) - m_request.charsets += DEFAULT_PARTIAL_CHARSET_HEADER; - - m_request.languages = config()->readEntry( "Languages", DEFAULT_LANGUAGE_HEADER ); - } - else - { - m_request.charsets = TQString::null; - m_request.languages = TQString::null; - } - - // Adjust the offset value based on the "resume" meta-data. - TQString resumeOffset = metaData("resume"); - if ( !resumeOffset.isEmpty() ) - m_request.offset = resumeOffset.toInt(); // TODO: Convert to 64 bit - else - m_request.offset = 0; - - m_request.disablePassDlg = config()->readBoolEntry("DisablePassDlg", false); - m_request.allowCompressedPage = config()->readBoolEntry("AllowCompressedPage", true); - m_request.id = metaData("request-id"); - - // Store user agent for this host. - if ( config()->readBoolEntry("SendUserAgent", true) ) - m_request.userAgent = metaData("UserAgent"); - else - m_request.userAgent = TQString::null; - - // Deal with cache cleaning. - // TODO: Find a smarter way to deal with cleaning the - // cache ? - if ( m_request.bUseCache ) - cleanCache(); - - // Deal with HTTP tunneling - if ( m_bIsSSL && m_bUseProxy && m_proxyURL.protocol() != "https" && - m_proxyURL.protocol() != "webdavs") - { - m_bNeedTunnel = true; - setRealHost( m_request.hostname ); - kdDebug(7113) << "(" << m_pid << ") SSL tunnel: Setting real hostname to: " - << m_request.hostname << endl; - } - else - { - m_bNeedTunnel = false; - setRealHost( TQString::null); - } - - m_responseCode = 0; - m_prevResponseCode = 0; - - m_strRealm = TQString::null; - m_strAuthorization = TQString::null; - Authentication = AUTH_None; - - // Obtain the proxy and remote server timeout values - m_proxyConnTimeout = proxyConnectTimeout(); - m_remoteConnTimeout = connectTimeout(); - m_remoteRespTimeout = responseTimeout(); - - // Set the SSL meta-data here... - setSSLMetaData(); - - // Bounce back the actual referrer sent - setMetaData("referrer", m_request.referrer); - - // Follow HTTP/1.1 spec and enable keep-alive by default - // unless the remote side tells us otherwise or we determine - // the persistent link has been terminated by the remote end. - m_bKeepAlive = true; - m_keepAliveTimeout = 0; - m_bUnauthorized = false; - - // A single request can require multiple exchanges with the remote - // server due to authentication challenges or SSL tunneling. - // m_bFirstRequest is a flag that indicates whether we are - // still processing the first request. This is important because we - // should not force a close of a keep-alive connection in the middle - // of the first request. - // m_bFirstRequest is set to "true" whenever a new connection is - // made in httpOpenConnection() - m_bFirstRequest = false; -} - -void HTTPProtocol::setHost( const TQString& host, int port, - const TQString& user, const TQString& pass ) -{ - // Reset the webdav-capable flags for this host - if ( m_request.hostname != host ) - m_davHostOk = m_davHostUnsupported = false; - - // is it an IPv6 address? - if (host.find(':') == -1) - { - m_request.hostname = host; - m_request.encoded_hostname = KIDNA::toAscii(host); - } - else - { - m_request.hostname = host; - int pos = host.find('%'); - if (pos == -1) - m_request.encoded_hostname = '[' + host + ']'; - else - // don't send the scope-id in IPv6 addresses to the server - m_request.encoded_hostname = '[' + host.left(pos) + ']'; - } - m_request.port = (port == 0) ? m_iDefaultPort : port; - m_request.user = user; - m_request.passwd = pass; - - m_bIsTunneled = false; - - kdDebug(7113) << "(" << m_pid << ") Hostname is now: " << m_request.hostname << - " (" << m_request.encoded_hostname << ")" <\r\n"; - request.append( "\r\n" ); - request.append( query.utf8() ); - request.append( "\r\n" ); - - davSetRequest( request ); - } else { - // We are only after certain features... - TQCString request; - request = "" - ""; - - // insert additional XML request from the davRequestResponse metadata - if ( hasMetaData( "davRequestResponse" ) ) - request += metaData( "davRequestResponse" ).utf8(); - else { - // No special request, ask for default properties - request += "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - ""; - } - request += ""; - - davSetRequest( request ); - } - - // WebDAV Stat or List... - m_request.method = query.isEmpty() ? DAV_PROPFIND : DAV_SEARCH; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - m_request.davData.depth = stat ? 0 : 1; - if (!stat) - m_request.url.adjustPath(+1); - - retrieveContent( true ); - - // Has a redirection already been called? If so, we're done. - if (m_bRedirect) { - finished(); - return; - } - - TQDomDocument multiResponse; - multiResponse.setContent( m_bufWebDavData, true ); - - bool hasResponse = false; - - for ( TQDomNode n = multiResponse.documentElement().firstChild(); - !n.isNull(); n = n.nextSibling()) - { - TQDomElement thisResponse = n.toElement(); - if (thisResponse.isNull()) - continue; - - hasResponse = true; - - TQDomElement href = thisResponse.namedItem( "href" ).toElement(); - if ( !href.isNull() ) - { - entry.clear(); - - TQString urlStr = href.text(); -#if 0 - int encoding = remoteEncoding()->encodingMib(); - if ((encoding == 106) && (!KStringHandler::isUtf8(KURL::decode_string(urlStr, 4).latin1()))) - encoding = 4; // Use latin1 if the file is not actually utf-8 -#else - TQUrl::decode(urlStr); - int encoding = 106; -#endif - - KURL thisURL ( urlStr, encoding ); - - atom.m_uds = TDEIO::UDS_NAME; - - if ( thisURL.isValid() ) { - // don't list the base dir of a listDir() - if ( !stat && thisURL.path(+1).length() == url.path(+1).length() ) - continue; - - atom.m_str = thisURL.fileName(); - } else { - // This is a relative URL. - atom.m_str = href.text(); - } - - entry.append( atom ); - - TQDomNodeList propstats = thisResponse.elementsByTagName( "propstat" ); - - davParsePropstats( propstats, entry ); - - if ( stat ) - { - // return an item - statEntry( entry ); - finished(); - return; - } - else - { - listEntry( entry, false ); - } - } - else - { - kdDebug(7113) << "Error: no URL contained in response to PROPFIND on " - << url.prettyURL() << endl; - } - } - - if ( stat || !hasResponse ) - { - error( ERR_DOES_NOT_EXIST, url.prettyURL() ); - } - else - { - listEntry( entry, true ); - finished(); - } -} - -void HTTPProtocol::davGeneric( const KURL& url, TDEIO::HTTP_METHOD method ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davGeneric " << url.prettyURL() - << endl; - - if ( !checkRequestURL( url ) ) - return; - - // check to make sure this host supports WebDAV - if ( !davHostOk() ) - return; - - // WebDAV method - m_request.method = method; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveContent( false ); -} - -int HTTPProtocol::codeFromResponse( const TQString& response ) -{ - int firstSpace = response.find( ' ' ); - int secondSpace = response.find( ' ', firstSpace + 1 ); - return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt(); -} - -void HTTPProtocol::davParsePropstats( const TQDomNodeList& propstats, UDSEntry& entry ) -{ - TQString mimeType; - UDSAtom atom; - bool foundExecutable = false; - bool isDirectory = false; - uint lockCount = 0; - uint supportedLockCount = 0; - - for ( uint i = 0; i < propstats.count(); i++) - { - TQDomElement propstat = propstats.item(i).toElement(); - - TQDomElement status = propstat.namedItem( "status" ).toElement(); - if ( status.isNull() ) - { - // error, no status code in this propstat - kdDebug(7113) << "Error, no status code in this propstat" << endl; - return; - } - - int code = codeFromResponse( status.text() ); - - if ( code != 200 ) - { - kdDebug(7113) << "Warning: status code " << code << " (this may mean that some properties are unavailable" << endl; - continue; - } - - TQDomElement prop = propstat.namedItem( "prop" ).toElement(); - if ( prop.isNull() ) - { - kdDebug(7113) << "Error: no prop segment in this propstat." << endl; - return; - } - - if ( hasMetaData( "davRequestResponse" ) ) - { - atom.m_uds = TDEIO::UDS_XML_PROPERTIES; - TQDomDocument doc; - doc.appendChild(prop); - atom.m_str = doc.toString(); - entry.append( atom ); - } - - for ( TQDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() ) - { - TQDomElement property = n.toElement(); - if (property.isNull()) - continue; - - if ( property.namespaceURI() != "DAV:" ) - { - // break out - we're only interested in properties from the DAV namespace - continue; - } - - if ( property.tagName() == "creationdate" ) - { - // Resource creation date. Should be is ISO 8601 format. - atom.m_uds = TDEIO::UDS_CREATION_TIME; - atom.m_long = parseDateTime( property.text(), property.attribute("dt") ); - entry.append( atom ); - } - else if ( property.tagName() == "getcontentlength" ) - { - // Content length (file size) - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = property.text().toULong(); - entry.append( atom ); - } - else if ( property.tagName() == "displayname" ) - { - // Name suitable for presentation to the user - setMetaData( "davDisplayName", property.text() ); - } - else if ( property.tagName() == "source" ) - { - // Source template location - TQDomElement source = property.namedItem( "link" ).toElement() - .namedItem( "dst" ).toElement(); - if ( !source.isNull() ) - setMetaData( "davSource", source.text() ); - } - else if ( property.tagName() == "getcontentlanguage" ) - { - // equiv. to Content-Language header on a GET - setMetaData( "davContentLanguage", property.text() ); - } - else if ( property.tagName() == "getcontenttype" ) - { - // Content type (mime type) - // This may require adjustments for other server-side webdav implementations - // (tested with Apache + mod_dav 1.0.3) - if ( property.text() == "httpd/unix-directory" ) - { - isDirectory = true; - } - else - { - mimeType = property.text(); - } - } - else if ( property.tagName() == "executable" ) - { - // File executable status - if ( property.text() == "T" ) - foundExecutable = true; - - } - else if ( property.tagName() == "getlastmodified" ) - { - // Last modification date - atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; - atom.m_long = parseDateTime( property.text(), property.attribute("dt") ); - entry.append( atom ); - - } - else if ( property.tagName() == "getetag" ) - { - // Entity tag - setMetaData( "davEntityTag", property.text() ); - } - else if ( property.tagName() == "supportedlock" ) - { - // Supported locking specifications - for ( TQDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) - { - TQDomElement lockEntry = n2.toElement(); - if ( lockEntry.tagName() == "lockentry" ) - { - TQDomElement lockScope = lockEntry.namedItem( "lockscope" ).toElement(); - TQDomElement lockType = lockEntry.namedItem( "locktype" ).toElement(); - if ( !lockScope.isNull() && !lockType.isNull() ) - { - // Lock type was properly specified - supportedLockCount++; - TQString scope = lockScope.firstChild().toElement().tagName(); - TQString type = lockType.firstChild().toElement().tagName(); - - setMetaData( TQString("davSupportedLockScope%1").arg(supportedLockCount), scope ); - setMetaData( TQString("davSupportedLockType%1").arg(supportedLockCount), type ); - } - } - } - } - else if ( property.tagName() == "lockdiscovery" ) - { - // Lists the available locks - davParseActiveLocks( property.elementsByTagName( "activelock" ), lockCount ); - } - else if ( property.tagName() == "resourcetype" ) - { - // Resource type. "Specifies the nature of the resource." - if ( !property.namedItem( "collection" ).toElement().isNull() ) - { - // This is a collection (directory) - isDirectory = true; - } - } - else - { - kdDebug(7113) << "Found unknown webdav property: " << property.tagName() << endl; - } - } - } - - setMetaData( "davLockCount", TQString("%1").arg(lockCount) ); - setMetaData( "davSupportedLockCount", TQString("%1").arg(supportedLockCount) ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = isDirectory ? S_IFDIR : S_IFREG; - entry.append( atom ); - - if ( foundExecutable || isDirectory ) - { - // File was executable, or is a directory. - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = 0700; - entry.append(atom); - } - else - { - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = 0600; - entry.append(atom); - } - - if ( !isDirectory && !mimeType.isEmpty() ) - { - atom.m_uds = TDEIO::UDS_MIME_TYPE; - atom.m_str = mimeType; - entry.append( atom ); - } -} - -void HTTPProtocol::davParseActiveLocks( const TQDomNodeList& activeLocks, - uint& lockCount ) -{ - for ( uint i = 0; i < activeLocks.count(); i++ ) - { - TQDomElement activeLock = activeLocks.item(i).toElement(); - - lockCount++; - // required - TQDomElement lockScope = activeLock.namedItem( "lockscope" ).toElement(); - TQDomElement lockType = activeLock.namedItem( "locktype" ).toElement(); - TQDomElement lockDepth = activeLock.namedItem( "depth" ).toElement(); - // optional - TQDomElement lockOwner = activeLock.namedItem( "owner" ).toElement(); - TQDomElement lockTimeout = activeLock.namedItem( "timeout" ).toElement(); - TQDomElement lockToken = activeLock.namedItem( "locktoken" ).toElement(); - - if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() ) - { - // lock was properly specified - lockCount++; - TQString scope = lockScope.firstChild().toElement().tagName(); - TQString type = lockType.firstChild().toElement().tagName(); - TQString depth = lockDepth.text(); - - setMetaData( TQString("davLockScope%1").arg( lockCount ), scope ); - setMetaData( TQString("davLockType%1").arg( lockCount ), type ); - setMetaData( TQString("davLockDepth%1").arg( lockCount ), depth ); - - if ( !lockOwner.isNull() ) - setMetaData( TQString("davLockOwner%1").arg( lockCount ), lockOwner.text() ); - - if ( !lockTimeout.isNull() ) - setMetaData( TQString("davLockTimeout%1").arg( lockCount ), lockTimeout.text() ); - - if ( !lockToken.isNull() ) - { - TQDomElement tokenVal = lockScope.namedItem( "href" ).toElement(); - if ( !tokenVal.isNull() ) - setMetaData( TQString("davLockToken%1").arg( lockCount ), tokenVal.text() ); - } - } - } -} - -long HTTPProtocol::parseDateTime( const TQString& input, const TQString& type ) -{ - if ( type == "dateTime.tz" ) - { - return KRFCDate::parseDateISO8601( input ); - } - else if ( type == "dateTime.rfc1123" ) - { - return KRFCDate::parseDate( input ); - } - - // format not advertised... try to parse anyway - time_t time = KRFCDate::parseDate( input ); - if ( time != 0 ) - return time; - - return KRFCDate::parseDateISO8601( input ); -} - -TQString HTTPProtocol::davProcessLocks() -{ - if ( hasMetaData( "davLockCount" ) ) - { - TQString response("If:"); - int numLocks; - numLocks = metaData( "davLockCount" ).toInt(); - bool bracketsOpen = false; - for ( int i = 0; i < numLocks; i++ ) - { - if ( hasMetaData( TQString("davLockToken%1").arg(i) ) ) - { - if ( hasMetaData( TQString("davLockURL%1").arg(i) ) ) - { - if ( bracketsOpen ) - { - response += ")"; - bracketsOpen = false; - } - response += " <" + metaData( TQString("davLockURL%1").arg(i) ) + ">"; - } - - if ( !bracketsOpen ) - { - response += " ("; - bracketsOpen = true; - } - else - { - response += " "; - } - - if ( hasMetaData( TQString("davLockNot%1").arg(i) ) ) - response += "Not "; - - response += "<" + metaData( TQString("davLockToken%1").arg(i) ) + ">"; - } - } - - if ( bracketsOpen ) - response += ")"; - - response += "\r\n"; - return response; - } - - return TQString::null; -} - -bool HTTPProtocol::davHostOk() -{ - // FIXME needs to be reworked. Switched off for now. - return true; - - // cached? - if ( m_davHostOk ) - { - kdDebug(7113) << "(" << m_pid << ") " << k_funcinfo << " true" << endl; - return true; - } - else if ( m_davHostUnsupported ) - { - kdDebug(7113) << "(" << m_pid << ") " << k_funcinfo << " false" << endl; - davError( -2 ); - return false; - } - - m_request.method = HTTP_OPTIONS; - - // query the server's capabilities generally, not for a specific URL - m_request.path = "*"; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - // clear davVersions variable, which holds the response to the DAV: header - m_davCapabilities.clear(); - - retrieveHeader(false); - - if (m_davCapabilities.count()) - { - for (uint i = 0; i < m_davCapabilities.count(); i++) - { - bool ok; - uint verNo = m_davCapabilities[i].toUInt(&ok); - if (ok && verNo > 0 && verNo < 3) - { - m_davHostOk = true; - kdDebug(7113) << "Server supports DAV version " << verNo << "." << endl; - } - } - - if ( m_davHostOk ) - return true; - } - - m_davHostUnsupported = true; - davError( -2 ); - return false; -} - -// This function is for closing retrieveHeader( false ); requests -// Required because there may or may not be further info expected -void HTTPProtocol::davFinished() -{ - // TODO: Check with the DAV extension developers - httpClose(m_bKeepAlive); - finished(); -} - -void HTTPProtocol::mkdir( const KURL& url, int ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::mkdir " << url.prettyURL() - << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = DAV_MKCOL; - m_request.path = url.path(); - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveHeader( false ); - - if ( m_responseCode == 201 ) - davFinished(); - else - davError(); -} - -void HTTPProtocol::get( const KURL& url ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::get " << url.prettyURL() - << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = HTTP_GET; - m_request.path = url.path(); - m_request.query = url.query(); - - TQString tmp = metaData("cache"); - if (!tmp.isEmpty()) - m_request.cache = parseCacheControl(tmp); - else - m_request.cache = DEFAULT_CACHE_CONTROL; - - m_request.passwd = url.pass(); - m_request.user = url.user(); - m_request.doProxy = m_bUseProxy; - - retrieveContent(); -} - -void HTTPProtocol::put( const KURL &url, int, bool overwrite, bool) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put " << url.prettyURL() - << endl; - - if ( !checkRequestURL( url ) ) - return; - - // Webdav hosts are capable of observing overwrite == false - if (!overwrite && m_protocol.left(6) == "webdav") { - // check to make sure this host supports WebDAV - if ( !davHostOk() ) - return; - - TQCString request; - request = "" - "" - "" - "" - "" - "" - ""; - - davSetRequest( request ); - - // WebDAV Stat or List... - m_request.method = DAV_PROPFIND; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - m_request.davData.depth = 0; - - retrieveContent(true); - - if (m_responseCode == 207) { - error(ERR_FILE_ALREADY_EXIST, TQString::null); - return; - } - - m_bError = false; - } - - m_request.method = HTTP_PUT; - m_request.path = url.path(); - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveHeader( false ); - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put error = " << m_bError << endl; - if (m_bError) - return; - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put responseCode = " << m_responseCode << endl; - - httpClose(false); // Always close connection. - - if ( (m_responseCode >= 200) && (m_responseCode < 300) ) - finished(); - else - httpError(); -} - -void HTTPProtocol::copy( const KURL& src, const KURL& dest, int, bool overwrite ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::copy " << src.prettyURL() - << " -> " << dest.prettyURL() << endl; - - if ( !checkRequestURL( dest ) || !checkRequestURL( src ) ) - return; - - // destination has to be "http(s)://..." - KURL newDest = dest; - if (newDest.protocol() == "webdavs") - newDest.setProtocol("https"); - else - newDest.setProtocol("http"); - - m_request.method = DAV_COPY; - m_request.path = src.path(); - m_request.davData.desturl = newDest.url(); - m_request.davData.overwrite = overwrite; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveHeader( false ); - - // The server returns a HTTP/1.1 201 Created or 204 No Content on successful completion - if ( m_responseCode == 201 || m_responseCode == 204 ) - davFinished(); - else - davError(); -} - -void HTTPProtocol::rename( const KURL& src, const KURL& dest, bool overwrite ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::rename " << src.prettyURL() - << " -> " << dest.prettyURL() << endl; - - if ( !checkRequestURL( dest ) || !checkRequestURL( src ) ) - return; - - // destination has to be "http://..." - KURL newDest = dest; - if (newDest.protocol() == "webdavs") - newDest.setProtocol("https"); - else - newDest.setProtocol("http"); - - m_request.method = DAV_MOVE; - m_request.path = src.path(); - m_request.davData.desturl = newDest.url(); - m_request.davData.overwrite = overwrite; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveHeader( false ); - - if ( m_responseCode == 301 ) - { - // Work around strict Apache-2 WebDAV implementation which refuses to cooperate - // with webdav://host/directory, instead requiring webdav://host/directory/ - // (strangely enough it accepts Destination: without a trailing slash) - - if (m_redirectLocation.protocol() == "https") - m_redirectLocation.setProtocol("webdavs"); - else - m_redirectLocation.setProtocol("webdav"); - - if ( !checkRequestURL( m_redirectLocation ) ) - return; - - m_request.method = DAV_MOVE; - m_request.path = m_redirectLocation.path(); - m_request.davData.desturl = newDest.url(); - m_request.davData.overwrite = overwrite; - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveHeader( false ); - } - - if ( m_responseCode == 201 ) - davFinished(); - else - davError(); -} - -void HTTPProtocol::del( const KURL& url, bool ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::del " << url.prettyURL() - << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = HTTP_DELETE; - m_request.path = url.path(); - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveHeader( false ); - - // The server returns a HTTP/1.1 200 Ok or HTTP/1.1 204 No Content - // on successful completion - if ( m_responseCode == 200 || m_responseCode == 204 ) - davFinished(); - else - davError(); -} - -void HTTPProtocol::post( const KURL& url ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::post " - << url.prettyURL() << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = HTTP_POST; - m_request.path = url.path(); - m_request.query = url.query(); - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveContent(); -} - -void HTTPProtocol::davLock( const KURL& url, const TQString& scope, - const TQString& type, const TQString& owner ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davLock " - << url.prettyURL() << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = DAV_LOCK; - m_request.path = url.path(); - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - /* Create appropriate lock XML request. */ - TQDomDocument lockReq; - - TQDomElement lockInfo = lockReq.createElementNS( "DAV:", "lockinfo" ); - lockReq.appendChild( lockInfo ); - - TQDomElement lockScope = lockReq.createElement( "lockscope" ); - lockInfo.appendChild( lockScope ); - - lockScope.appendChild( lockReq.createElement( scope ) ); - - TQDomElement lockType = lockReq.createElement( "locktype" ); - lockInfo.appendChild( lockType ); - - lockType.appendChild( lockReq.createElement( type ) ); - - if ( !owner.isNull() ) { - TQDomElement ownerElement = lockReq.createElement( "owner" ); - lockReq.appendChild( ownerElement ); - - TQDomElement ownerHref = lockReq.createElement( "href" ); - ownerElement.appendChild( ownerHref ); - - ownerHref.appendChild( lockReq.createTextNode( owner ) ); - } - - // insert the document into the POST buffer - m_bufPOST = lockReq.toCString(); - - retrieveContent( true ); - - if ( m_responseCode == 200 ) { - // success - TQDomDocument multiResponse; - multiResponse.setContent( m_bufWebDavData, true ); - - TQDomElement prop = multiResponse.documentElement().namedItem( "prop" ).toElement(); - - TQDomElement lockdiscovery = prop.namedItem( "lockdiscovery" ).toElement(); - - uint lockCount = 0; - davParseActiveLocks( lockdiscovery.elementsByTagName( "activelock" ), lockCount ); - - setMetaData( "davLockCount", TQString("%1").arg( lockCount ) ); - - finished(); - - } else - davError(); -} - -void HTTPProtocol::davUnlock( const KURL& url ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davUnlock " - << url.prettyURL() << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = DAV_UNLOCK; - m_request.path = url.path(); - m_request.query = TQString::null; - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - retrieveContent( true ); - - if ( m_responseCode == 200 ) - finished(); - else - davError(); -} - -TQString HTTPProtocol::davError( int code /* = -1 */, TQString url ) -{ - bool callError = false; - if ( code == -1 ) { - code = m_responseCode; - callError = true; - } - if ( code == -2 ) { - callError = true; - } - - // Huh? This looks like inverted logic to me (it doesn't make sense to me as - // written), but I'm only fixing the CVE now. -- Kevin Kofler - if ( !url.isNull() ) - url = m_request.url.prettyURL(); - - TQString action, errorString; - TDEIO::Error kError; - - // for 412 Precondition Failed - TQString ow = i18n( "Otherwise, the request would have succeeded." ); - - switch ( m_request.method ) { - case DAV_PROPFIND: - action = i18n( "retrieve property values" ); - break; - case DAV_PROPPATCH: - action = i18n( "set property values" ); - break; - case DAV_MKCOL: - action = i18n( "create the requested folder" ); - break; - case DAV_COPY: - action = i18n( "copy the specified file or folder" ); - break; - case DAV_MOVE: - action = i18n( "move the specified file or folder" ); - break; - case DAV_SEARCH: - action = i18n( "search in the specified folder" ); - break; - case DAV_LOCK: - action = i18n( "lock the specified file or folder" ); - break; - case DAV_UNLOCK: - action = i18n( "unlock the specified file or folder" ); - break; - case HTTP_DELETE: - action = i18n( "delete the specified file or folder" ); - break; - case HTTP_OPTIONS: - action = i18n( "query the server's capabilities" ); - break; - case HTTP_GET: - action = i18n( "retrieve the contents of the specified file or folder" ); - break; - case HTTP_PUT: - case HTTP_POST: - case HTTP_HEAD: - default: - // this should not happen, this function is for webdav errors only - Q_ASSERT(0); - } - - // default error message if the following code fails - kError = ERR_INTERNAL; - errorString = i18n("An unexpected error (%1) occurred while attempting to %2.") - .arg( code ).arg( action ); - - switch ( code ) - { - case -2: - // internal error: OPTIONS request did not specify DAV compliance - kError = ERR_UNSUPPORTED_PROTOCOL; - errorString = i18n("The server does not support the WebDAV protocol."); - break; - case 207: - // 207 Multi-status - { - // our error info is in the returned XML document. - // retrieve the XML document - - // there was an error retrieving the XML document. - // ironic, eh? - if ( !readBody( true ) && m_bError ) - return TQString::null; - - TQStringList errors; - TQDomDocument multiResponse; - - multiResponse.setContent( m_bufWebDavData, true ); - - TQDomElement multistatus = multiResponse.documentElement().namedItem( "multistatus" ).toElement(); - - TQDomNodeList responses = multistatus.elementsByTagName( "response" ); - - for (uint i = 0; i < responses.count(); i++) - { - int errCode; - TQString errUrl; - - TQDomElement response = responses.item(i).toElement(); - TQDomElement code = response.namedItem( "status" ).toElement(); - - if ( !code.isNull() ) - { - errCode = codeFromResponse( code.text() ); - TQDomElement href = response.namedItem( "href" ).toElement(); - if ( !href.isNull() ) - errUrl = href.text(); - errors << davError( errCode, errUrl ); - } - } - - //kError = ERR_SLAVE_DEFINED; - errorString = i18n("An error occurred while attempting to %1, %2. A " - "summary of the reasons is below.

    ").arg( action ).arg( url ); - - for ( TQStringList::Iterator it = errors.begin(); it != errors.end(); ++it ) - errorString += "
  • " + *it + "
  • "; - - errorString += "
"; - } - case 403: - case 500: // hack: Apache mod_dav returns this instead of 403 (!) - // 403 Forbidden - kError = ERR_ACCESS_DENIED; - errorString = i18n("Access was denied while attempting to %1.").arg( action ); - break; - case 405: - // 405 Method Not Allowed - if ( m_request.method == DAV_MKCOL ) - { - kError = ERR_DIR_ALREADY_EXIST; - errorString = i18n("The specified folder already exists."); - } - break; - case 409: - // 409 Conflict - kError = ERR_ACCESS_DENIED; - errorString = i18n("A resource cannot be created at the destination " - "until one or more intermediate collections (folders) " - "have been created."); - break; - case 412: - // 412 Precondition failed - if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE ) - { - kError = ERR_ACCESS_DENIED; - errorString = i18n("The server was unable to maintain the liveness of " - "the properties listed in the propertybehavior XML " - "element or you attempted to overwrite a file while " - "requesting that files are not overwritten. %1") - .arg( ow ); - - } - else if ( m_request.method == DAV_LOCK ) - { - kError = ERR_ACCESS_DENIED; - errorString = i18n("The requested lock could not be granted. %1").arg( ow ); - } - break; - case 415: - // 415 Unsupported Media Type - kError = ERR_ACCESS_DENIED; - errorString = i18n("The server does not support the request type of the body."); - break; - case 423: - // 423 Locked - kError = ERR_ACCESS_DENIED; - errorString = i18n("Unable to %1 because the resource is locked.").arg( action ); - break; - case 425: - // 424 Failed Dependency - errorString = i18n("This action was prevented by another error."); - break; - case 502: - // 502 Bad Gateway - if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE ) - { - kError = ERR_WRITE_ACCESS_DENIED; - errorString = i18n("Unable to %1 because the destination server refuses " - "to accept the file or folder.").arg( action ); - } - break; - case 507: - // 507 Insufficient Storage - kError = ERR_DISK_FULL; - errorString = i18n("The destination resource does not have sufficient space " - "to record the state of the resource after the execution " - "of this method."); - break; - } - - // if ( kError != ERR_SLAVE_DEFINED ) - //errorString += " (" + url + ")"; - - if ( callError ) - error( ERR_SLAVE_DEFINED, errorString ); - - return errorString; -} - -void HTTPProtocol::httpError() -{ - TQString action, errorString; - TDEIO::Error kError; - - switch ( m_request.method ) { - case HTTP_PUT: - action = i18n( "upload %1" ).arg(m_request.url.prettyURL()); - break; - default: - // this should not happen, this function is for http errors only - Q_ASSERT(0); - } - - // default error message if the following code fails - kError = ERR_INTERNAL; - errorString = i18n("An unexpected error (%1) occurred while attempting to %2.") - .arg( m_responseCode ).arg( action ); - - switch ( m_responseCode ) - { - case 403: - case 405: - case 500: // hack: Apache mod_dav returns this instead of 403 (!) - // 403 Forbidden - // 405 Method Not Allowed - kError = ERR_ACCESS_DENIED; - errorString = i18n("Access was denied while attempting to %1.").arg( action ); - break; - case 409: - // 409 Conflict - kError = ERR_ACCESS_DENIED; - errorString = i18n("A resource cannot be created at the destination " - "until one or more intermediate collections (folders) " - "have been created."); - break; - case 423: - // 423 Locked - kError = ERR_ACCESS_DENIED; - errorString = i18n("Unable to %1 because the resource is locked.").arg( action ); - break; - case 502: - // 502 Bad Gateway - kError = ERR_WRITE_ACCESS_DENIED; - errorString = i18n("Unable to %1 because the destination server refuses " - "to accept the file or folder.").arg( action ); - break; - case 507: - // 507 Insufficient Storage - kError = ERR_DISK_FULL; - errorString = i18n("The destination resource does not have sufficient space " - "to record the state of the resource after the execution " - "of this method."); - break; - } - - // if ( kError != ERR_SLAVE_DEFINED ) - //errorString += " (" + url + ")"; - - error( ERR_SLAVE_DEFINED, errorString ); -} - -bool HTTPProtocol::isOffline(const KURL &url) -{ - const int NetWorkStatusUnknown = 1; - const int NetWorkStatusOnline = 8; - TQCString replyType; - TQByteArray params; - TQByteArray reply; - - TQDataStream stream(params, IO_WriteOnly); - - if ( url.host() == TQString::fromLatin1("localhost") || url.host() == TQString::fromLatin1("127.0.0.1") || url.host() == TQString::fromLatin1("::") ) { - return false; - } - if ( dcopClient()->call( "kded", "networkstatus", "status()", - params, replyType, reply ) && (replyType == "int") ) - { - int result; - TQDataStream stream2( reply, IO_ReadOnly ); - stream2 >> result; - kdDebug(7113) << "(" << m_pid << ") networkstatus status = " << result << endl; - return (result != NetWorkStatusUnknown) && (result != NetWorkStatusOnline); - } - kdDebug(7113) << "(" << m_pid << ") networkstatus " << endl; - return false; // On error, assume we are online -} - -void HTTPProtocol::multiGet(const TQByteArray &data) -{ - TQDataStream stream(data, IO_ReadOnly); - TQ_UINT32 n; - stream >> n; - - kdDebug(7113) << "(" << m_pid << ") HTTPProtcool::multiGet n = " << n << endl; - - HTTPRequest saveRequest; - if (m_bBusy) - saveRequest = m_request; - -// m_requestQueue.clear(); - for(unsigned i = 0; i < n; i++) - { - KURL url; - stream >> url >> mIncomingMetaData; - - if ( !checkRequestURL( url ) ) - continue; - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::multi_get " << url.prettyURL() << endl; - - m_request.method = HTTP_GET; - m_request.path = url.path(); - m_request.query = url.query(); - TQString tmp = metaData("cache"); - if (!tmp.isEmpty()) - m_request.cache = parseCacheControl(tmp); - else - m_request.cache = DEFAULT_CACHE_CONTROL; - - m_request.passwd = url.pass(); - m_request.user = url.user(); - m_request.doProxy = m_bUseProxy; - - HTTPRequest *newRequest = new HTTPRequest(m_request); - m_requestQueue.append(newRequest); - } - - if (m_bBusy) - m_request = saveRequest; - - if (!m_bBusy) - { - m_bBusy = true; - while(!m_requestQueue.isEmpty()) - { - HTTPRequest *request = m_requestQueue.take(0); - m_request = *request; - delete request; - retrieveContent(); - } - m_bBusy = false; - } -} - -ssize_t HTTPProtocol::write (const void *_buf, size_t nbytes) -{ - int bytes_sent = 0; - const char* buf = static_cast(_buf); - while ( nbytes > 0 ) - { - int n = TCPSlaveBase::write(buf, nbytes); - - if ( n <= 0 ) - { - // remote side closed connection ? - if ( n == 0 ) - break; - // a valid exception(s) occurred, let's retry... - if (n < 0 && ((errno == EINTR) || (errno == EAGAIN))) - continue; - // some other error occurred ? - return -1; - } - - nbytes -= n; - buf += n; - bytes_sent += n; - } - - return bytes_sent; -} - -void HTTPProtocol::setRewindMarker() -{ - m_rewindCount = 0; -} - -void HTTPProtocol::rewind() -{ - m_linePtrUnget = m_rewindBuf, - m_lineCountUnget = m_rewindCount; - m_rewindCount = 0; -} - - -char *HTTPProtocol::gets (char *s, int size) -{ - int len=0; - char *buf=s; - char mybuf[2]={0,0}; - - while (len < size) - { - read(mybuf, 1); - if (m_bEOF) - break; - - if (m_rewindCount < sizeof(m_rewindBuf)) - m_rewindBuf[m_rewindCount++] = *mybuf; - - if (*mybuf == '\r') // Ignore! - continue; - - if ((*mybuf == '\n') || !*mybuf) - break; - - *buf++ = *mybuf; - len++; - } - - *buf=0; - return s; -} - -ssize_t HTTPProtocol::read (void *b, size_t nbytes) -{ - ssize_t ret = 0; - - if (m_lineCountUnget > 0) - { - ret = ( nbytes < m_lineCountUnget ? nbytes : m_lineCountUnget ); - m_lineCountUnget -= ret; - memcpy(b, m_linePtrUnget, ret); - m_linePtrUnget += ret; - - return ret; - } - - if (m_lineCount > 0) - { - ret = ( nbytes < m_lineCount ? nbytes : m_lineCount ); - m_lineCount -= ret; - memcpy(b, m_linePtr, ret); - m_linePtr += ret; - return ret; - } - - if (nbytes == 1) - { - ret = read(m_lineBuf, 1024); // Read into buffer - m_linePtr = m_lineBuf; - if (ret <= 0) - { - m_lineCount = 0; - return ret; - } - m_lineCount = ret; - return read(b, 1); // Read from buffer - } - - do - { - ret = TCPSlaveBase::read( b, nbytes); - if (ret == 0) - m_bEOF = true; - - } while ((ret == -1) && (errno == EAGAIN || errno == EINTR)); - - return ret; -} - -void HTTPProtocol::httpCheckConnection() -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpCheckConnection: " << - " Socket status: " << m_iSock << - " Keep Alive: " << m_bKeepAlive << - " First: " << m_bFirstRequest << endl; - - if ( !m_bFirstRequest && (m_iSock != -1) ) - { - bool closeDown = false; - if ( !isConnectionValid()) - { - kdDebug(7113) << "(" << m_pid << ") Connection lost!" << endl; - closeDown = true; - } - else if ( m_request.method != HTTP_GET ) - { - closeDown = true; - } - else if ( !m_state.doProxy && !m_request.doProxy ) - { - if (m_state.hostname != m_request.hostname || - m_state.port != m_request.port || - m_state.user != m_request.user || - m_state.passwd != m_request.passwd) - closeDown = true; - } - else - { - // Keep the connection to the proxy. - if ( !(m_request.doProxy && m_state.doProxy) ) - closeDown = true; - } - - if (closeDown) - httpCloseConnection(); - } - - // Let's update our current state - m_state.hostname = m_request.hostname; - m_state.encoded_hostname = m_request.encoded_hostname; - m_state.port = m_request.port; - m_state.user = m_request.user; - m_state.passwd = m_request.passwd; - m_state.doProxy = m_request.doProxy; -} - -bool HTTPProtocol::httpOpenConnection() -{ - int errCode; - TQString errMsg; - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpenConnection" << endl; - - setBlockConnection( true ); - // tdeio_http uses its own proxying: - KSocks::self()->disableSocks(); - - if ( m_state.doProxy ) - { - TQString proxy_host = m_proxyURL.host(); - int proxy_port = m_proxyURL.port(); - - kdDebug(7113) << "(" << m_pid << ") Connecting to proxy server: " - << proxy_host << ", port: " << proxy_port << endl; - - infoMessage( i18n("Connecting to %1...").arg(m_state.hostname) ); - - setConnectTimeout( m_proxyConnTimeout ); - - if ( !connectToHost(proxy_host, proxy_port, false) ) - { - if (userAborted()) { - error(ERR_NO_CONTENT, ""); - return false; - } - - switch ( connectResult() ) - { - case IO_LookupError: - errMsg = proxy_host; - errCode = ERR_UNKNOWN_PROXY_HOST; - break; - case IO_TimeOutError: - errMsg = i18n("Proxy %1 at port %2").arg(proxy_host).arg(proxy_port); - errCode = ERR_SERVER_TIMEOUT; - break; - default: - errMsg = i18n("Proxy %1 at port %2").arg(proxy_host).arg(proxy_port); - errCode = ERR_COULD_NOT_CONNECT; - } - error( errCode, errMsg ); - return false; - } - } - else - { - // Apparently we don't want a proxy. let's just connect directly - setConnectTimeout(m_remoteConnTimeout); - - if ( !connectToHost(m_state.hostname, m_state.port, false ) ) - { - if (userAborted()) { - error(ERR_NO_CONTENT, ""); - return false; - } - - switch ( connectResult() ) - { - case IO_LookupError: - errMsg = m_state.hostname; - errCode = ERR_UNKNOWN_HOST; - break; - case IO_TimeOutError: - errMsg = i18n("Connection was to %1 at port %2").arg(m_state.hostname).arg(m_state.port); - errCode = ERR_SERVER_TIMEOUT; - break; - default: - errCode = ERR_COULD_NOT_CONNECT; - if (m_state.port != m_iDefaultPort) - errMsg = i18n("%1 (port %2)").arg(m_state.hostname).arg(m_state.port); - else - errMsg = m_state.hostname; - } - error( errCode, errMsg ); - return false; - } - } - - // Set our special socket option!! - int on = 1; - (void) setsockopt( m_iSock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on) ); - - m_bFirstRequest = true; - - connected(); - return true; -} - - -/** - * This function is responsible for opening up the connection to the remote - * HTTP server and sending the header. If this requires special - * authentication or other such fun stuff, then it will handle it. This - * function will NOT receive anything from the server, however. This is in - * contrast to previous incarnations of 'httpOpen'. - * - * The reason for the change is due to one small fact: some requests require - * data to be sent in addition to the header (POST requests) and there is no - * way for this function to get that data. This function is called in the - * slotPut() or slotGet() functions which, in turn, are called (indirectly) as - * a result of a TDEIOJob::put() or TDEIOJob::get(). It is those latter functions - * which are responsible for starting up this ioslave in the first place. - * This means that 'httpOpen' is called (essentially) as soon as the ioslave - * is created -- BEFORE any data gets to this slave. - * - * The basic process now is this: - * - * 1) Open up the socket and port - * 2) Format our request/header - * 3) Send the header to the remote server - */ -bool HTTPProtocol::httpOpen() -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen" << endl; - - // Cannot have an https request without the m_bIsSSL being set! This can - // only happen if TCPSlaveBase::InitializeSSL() function failed in which it - // means the current installation does not support SSL... - if ( (m_protocol == "https" || m_protocol == "webdavs") && !m_bIsSSL ) - { - error( ERR_UNSUPPORTED_PROTOCOL, m_protocol ); - return false; - } - - m_request.fcache = 0; - m_request.bCachedRead = false; - m_request.bCachedWrite = false; - m_request.bMustRevalidate = false; - m_request.expireDate = 0; - m_request.creationDate = 0; - - if (m_request.bUseCache) - { - m_request.fcache = checkCacheEntry( ); - - bool bCacheOnly = (m_request.cache == TDEIO::CC_CacheOnly); - bool bOffline = isOffline(m_request.doProxy ? m_proxyURL : m_request.url); - if (bOffline && (m_request.cache != TDEIO::CC_Reload)) - m_request.cache = TDEIO::CC_CacheOnly; - - if (m_request.cache == CC_Reload && m_request.fcache) - { - if (m_request.fcache) - fclose(m_request.fcache); - m_request.fcache = 0; - } - if ((m_request.cache == TDEIO::CC_CacheOnly) || (m_request.cache == TDEIO::CC_Cache)) - m_request.bMustRevalidate = false; - - m_request.bCachedWrite = true; - - if (m_request.fcache && !m_request.bMustRevalidate) - { - // Cache entry is OK. - m_request.bCachedRead = true; // Cache hit. - return true; - } - else if (!m_request.fcache) - { - m_request.bMustRevalidate = false; // Cache miss - } - else - { - // Conditional cache hit. (Validate) - } - - if (bCacheOnly && bOffline) - { - error( ERR_OFFLINE_MODE, m_request.url.prettyURL() ); - return false; - } - if (bCacheOnly) - { - error( ERR_DOES_NOT_EXIST, m_request.url.prettyURL() ); - return false; - } - if (bOffline) - { - error( ERR_OFFLINE_MODE, m_request.url.prettyURL() ); - return false; - } - } - - TQString header; - TQString davHeader; - - bool moreData = false; - bool davData = false; - - // Clear out per-connection settings... - resetConnectionSettings (); - - // Check the validity of the current connection, if one exists. - httpCheckConnection(); - - if ( !m_bIsTunneled && m_bNeedTunnel ) - { - setEnableSSLTunnel( true ); - // We send a HTTP 1.0 header since some proxies refuse HTTP 1.1 and we don't - // need any HTTP 1.1 capabilities for CONNECT - Waba - header = TQString("CONNECT %1:%2 HTTP/1.0" - "\r\n").arg( m_request.encoded_hostname).arg(m_request.port); - - // Identify who you are to the proxy server! - if (!m_request.userAgent.isEmpty()) - header += "User-Agent: " + m_request.userAgent + "\r\n"; - - /* Add hostname information */ - header += "Host: " + m_state.encoded_hostname; - - if (m_state.port != m_iDefaultPort) - header += TQString(":%1").arg(m_state.port); - header += "\r\n"; - - header += proxyAuthenticationHeader(); - } - else - { - // Determine if this is a POST or GET method - switch (m_request.method) - { - case HTTP_GET: - header = "GET "; - break; - case HTTP_PUT: - header = "PUT "; - moreData = true; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case HTTP_POST: - header = "POST "; - moreData = true; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case HTTP_HEAD: - header = "HEAD "; - break; - case HTTP_DELETE: - header = "DELETE "; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case HTTP_OPTIONS: - header = "OPTIONS "; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case DAV_PROPFIND: - header = "PROPFIND "; - davData = true; - davHeader = "Depth: "; - if ( hasMetaData( "davDepth" ) ) - { - kdDebug(7113) << "Reading DAV depth from metadata: " << metaData( "davDepth" ) << endl; - davHeader += metaData( "davDepth" ); - } - else - { - if ( m_request.davData.depth == 2 ) - davHeader += "infinity"; - else - davHeader += TQString("%1").arg( m_request.davData.depth ); - } - davHeader += "\r\n"; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case DAV_PROPPATCH: - header = "PROPPATCH "; - davData = true; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case DAV_MKCOL: - header = "MKCOL "; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case DAV_COPY: - case DAV_MOVE: - header = ( m_request.method == DAV_COPY ) ? "COPY " : "MOVE "; - davHeader = "Destination: " + m_request.davData.desturl; - // infinity depth means copy recursively - // (optional for copy -> but is the desired action) - davHeader += "\r\nDepth: infinity\r\nOverwrite: "; - davHeader += m_request.davData.overwrite ? "T" : "F"; - davHeader += "\r\n"; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case DAV_LOCK: - header = "LOCK "; - davHeader = "Timeout: "; - { - uint timeout = 0; - if ( hasMetaData( "davTimeout" ) ) - timeout = metaData( "davTimeout" ).toUInt(); - if ( timeout == 0 ) - davHeader += "Infinite"; - else - davHeader += TQString("Seconds-%1").arg(timeout); - } - davHeader += "\r\n"; - m_request.bCachedWrite = false; // Do not put any result in the cache - davData = true; - break; - case DAV_UNLOCK: - header = "UNLOCK "; - davHeader = "Lock-token: " + metaData("davLockToken") + "\r\n"; - m_request.bCachedWrite = false; // Do not put any result in the cache - break; - case DAV_SEARCH: - header = "SEARCH "; - davData = true; - m_request.bCachedWrite = false; - break; - case DAV_SUBSCRIBE: - header = "SUBSCRIBE "; - m_request.bCachedWrite = false; - break; - case DAV_UNSUBSCRIBE: - header = "UNSUBSCRIBE "; - m_request.bCachedWrite = false; - break; - case DAV_POLL: - header = "POLL "; - m_request.bCachedWrite = false; - break; - default: - error (ERR_UNSUPPORTED_ACTION, TQString::null); - return false; - } - // DAV_POLL; DAV_NOTIFY - - // format the URI - if (m_state.doProxy && !m_bIsTunneled) - { - KURL u; - - if (m_protocol == "webdav") - u.setProtocol( "http" ); - else if (m_protocol == "webdavs" ) - u.setProtocol( "https" ); - else - u.setProtocol( m_protocol ); - - // For all protocols other than the once handled by this io-slave - // append the username. This fixes a long standing bug of ftp io-slave - // logging in anonymously in proxied connections even when the username - // is explicitly specified. - if (m_protocol != "http" && m_protocol != "https" && - !m_state.user.isEmpty()) - u.setUser (m_state.user); - - u.setHost( m_state.hostname ); - if (m_state.port != m_iDefaultPort) - u.setPort( m_state.port ); - u.setEncodedPathAndQuery( m_request.url.encodedPathAndQuery(0,true) ); - header += u.url(); - } - else - { - header += m_request.url.encodedPathAndQuery(0, true); - } - - header += " HTTP/1.1\r\n"; /* start header */ - - if (!m_request.userAgent.isEmpty()) - { - header += "User-Agent: "; - header += m_request.userAgent; - header += "\r\n"; - } - - if (!m_request.referrer.isEmpty()) - { - header += "Referer: "; //Don't try to correct spelling! - header += m_request.referrer; - header += "\r\n"; - } - - if ( m_request.offset > 0 ) - { - header += TQString("Range: bytes=%1-\r\n").arg(TDEIO::number(m_request.offset)); - kdDebug(7103) << "tdeio_http : Range = " << TDEIO::number(m_request.offset) << endl; - } - - if ( m_request.cache == CC_Reload ) - { - /* No caching for reload */ - header += "Pragma: no-cache\r\n"; /* for HTTP/1.0 caches */ - header += "Cache-control: no-cache\r\n"; /* for HTTP >=1.1 caches */ - } - - if (m_request.bMustRevalidate) - { - /* conditional get */ - if (!m_request.etag.isEmpty()) - header += "If-None-Match: "+m_request.etag+"\r\n"; - if (!m_request.lastModified.isEmpty()) - header += "If-Modified-Since: "+m_request.lastModified+"\r\n"; - } - - header += "Accept: "; - TQString acceptHeader = metaData("accept"); - if (!acceptHeader.isEmpty()) - header += acceptHeader; - else - header += DEFAULT_ACCEPT_HEADER; - header += "\r\n"; - -#ifdef DO_GZIP - if (m_request.allowCompressedPage) - header += "Accept-Encoding: x-gzip, x-deflate, gzip, deflate\r\n"; -#endif - - if (!m_request.charsets.isEmpty()) - header += "Accept-Charset: " + m_request.charsets + "\r\n"; - - if (!m_request.languages.isEmpty()) - header += "Accept-Language: " + m_request.languages + "\r\n"; - - - /* support for virtual hosts and required by HTTP 1.1 */ - header += "Host: " + m_state.encoded_hostname; - - if (m_state.port != m_iDefaultPort) - header += TQString(":%1").arg(m_state.port); - header += "\r\n"; - - TQString cookieStr; - TQString cookieMode = metaData("cookies").lower(); - if (cookieMode == "none") - { - m_request.cookieMode = HTTPRequest::CookiesNone; - } - else if (cookieMode == "manual") - { - m_request.cookieMode = HTTPRequest::CookiesManual; - cookieStr = metaData("setcookies"); - } - else - { - m_request.cookieMode = HTTPRequest::CookiesAuto; - if (m_request.bUseCookiejar) - cookieStr = findCookies( m_request.url.url()); - } - - if (!cookieStr.isEmpty()) - header += cookieStr + "\r\n"; - - TQString customHeader = metaData( "customHTTPHeader" ); - if (!customHeader.isEmpty()) - { - header += sanitizeCustomHTTPHeader(customHeader); - header += "\r\n"; - } - - if (m_request.method == HTTP_POST) - { - header += metaData("content-type"); - header += "\r\n"; - } - - // Only check for a cached copy if the previous - // response was NOT a 401 or 407. - // no caching for Negotiate auth. - if ( !m_request.bNoAuth && m_responseCode != 401 && m_responseCode != 407 && Authentication != AUTH_Negotiate ) - { - kdDebug(7113) << "(" << m_pid << ") Calling checkCachedAuthentication " << endl; - AuthInfo info; - info.url = m_request.url; - info.verifyPath = true; - if ( !m_request.user.isEmpty() ) - info.username = m_request.user; - if ( checkCachedAuthentication( info ) && !info.digestInfo.isEmpty() ) - { - Authentication = info.digestInfo.startsWith("Basic") ? AUTH_Basic : info.digestInfo.startsWith("NTLM") ? AUTH_NTLM : info.digestInfo.startsWith("Negotiate") ? AUTH_Negotiate : AUTH_Digest ; - m_state.user = info.username; - m_state.passwd = info.password; - m_strRealm = info.realmValue; - if ( Authentication != AUTH_NTLM && Authentication != AUTH_Negotiate ) // don't use the cached challenge - m_strAuthorization = info.digestInfo; - } - } - else - { - kdDebug(7113) << "(" << m_pid << ") Not calling checkCachedAuthentication " << endl; - } - - switch ( Authentication ) - { - case AUTH_Basic: - header += createBasicAuth(); - break; - case AUTH_Digest: - header += createDigestAuth(); - break; -#ifdef HAVE_LIBGSSAPI - case AUTH_Negotiate: - header += createNegotiateAuth(); - break; -#endif - case AUTH_NTLM: - header += createNTLMAuth(); - break; - case AUTH_None: - default: - break; - } - - /********* Only for debugging purpose *********/ - if ( Authentication != AUTH_None ) - { - kdDebug(7113) << "(" << m_pid << ") Using Authentication: " << endl; - kdDebug(7113) << "(" << m_pid << ") HOST= " << m_state.hostname << endl; - kdDebug(7113) << "(" << m_pid << ") PORT= " << m_state.port << endl; - kdDebug(7113) << "(" << m_pid << ") USER= " << m_state.user << endl; - kdDebug(7113) << "(" << m_pid << ") PASSWORD= [protected]" << endl; - kdDebug(7113) << "(" << m_pid << ") REALM= " << m_strRealm << endl; - kdDebug(7113) << "(" << m_pid << ") EXTRA= " << m_strAuthorization << endl; - } - - // Do we need to authorize to the proxy server ? - if ( m_state.doProxy && !m_bIsTunneled ) - header += proxyAuthenticationHeader(); - - // Support old HTTP/1.0 style keep-alive header for compatability - // purposes as well as performance improvements while giving end - // users the ability to disable this feature proxy servers that - // don't not support such feature, e.g. junkbuster proxy server. - if (!m_bUseProxy || m_bPersistentProxyConnection || m_bIsTunneled) - header += "Connection: Keep-Alive\r\n"; - else - header += "Connection: close\r\n"; - - if ( m_protocol == "webdav" || m_protocol == "webdavs" ) - { - header += davProcessLocks(); - - // add extra webdav headers, if supplied - TQString davExtraHeader = metaData("davHeader"); - if ( !davExtraHeader.isEmpty() ) - davHeader += davExtraHeader; - - // Set content type of webdav data - if (davData) - davHeader += "Content-Type: text/xml; charset=utf-8\r\n"; - - // add extra header elements for WebDAV - if ( !davHeader.isNull() ) - header += davHeader; - } - } - - kdDebug(7103) << "(" << m_pid << ") ============ Sending Header:" << endl; - - TQStringList headerOutput = TQStringList::split("\r\n", header); - TQStringList::Iterator it = headerOutput.begin(); - - for (; it != headerOutput.end(); it++) - kdDebug(7103) << "(" << m_pid << ") " << (*it) << endl; - - if ( !moreData && !davData) - header += "\r\n"; /* end header */ - - // Now that we have our formatted header, let's send it! - // Create a new connection to the remote machine if we do - // not already have one... - if ( m_iSock == -1) - { - if (!httpOpenConnection()) - return false; - } - - // Send the data to the remote machine... - bool sendOk = (write(header.latin1(), header.length()) == (ssize_t) header.length()); - if (!sendOk) - { - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen: " - "Connection broken! (" << m_state.hostname << ")" << endl; - - // With a Keep-Alive connection this can happen. - // Just reestablish the connection. - if (m_bKeepAlive) - { - httpCloseConnection(); - return true; // Try again - } - - if (!sendOk) - { - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen: sendOk==false." - " Connnection broken !" << endl; - error( ERR_CONNECTION_BROKEN, m_state.hostname ); - return false; - } - } - - bool res = true; - - if ( moreData || davData ) - res = sendBody(); - - infoMessage(i18n("%1 contacted. Waiting for reply...").arg(m_request.hostname)); - - return res; -} - -void HTTPProtocol::forwardHttpResponseHeader() -{ - // Send the response header if it was requested - if ( config()->readBoolEntry("PropagateHttpHeader", false) ) - { - setMetaData("HTTP-Headers", m_responseHeader.join("\n")); - sendMetaData(); - } - m_responseHeader.clear(); -} - -/** - * This function will read in the return header from the server. It will - * not read in the body of the return message. It will also not transmit - * the header to our client as the client doesn't need to know the gory - * details of HTTP headers. - */ -bool HTTPProtocol::readHeader() -{ -try_again: - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader" << endl; - - // Check - if (m_request.bCachedRead) - { - m_responseHeader << "HTTP-CACHE"; - // Read header from cache... - char buffer[4097]; - if (!fgets(buffer, 4096, m_request.fcache) ) - { - // Error, delete cache entry - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: " - << "Could not access cache to obtain mimetype!" << endl; - error( ERR_CONNECTION_BROKEN, m_state.hostname ); - return false; - } - - m_strMimeType = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace(); - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: cached " - << "data mimetype: " << m_strMimeType << endl; - - if (!fgets(buffer, 4096, m_request.fcache) ) - { - // Error, delete cache entry - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: " - << "Could not access cached data! " << endl; - error( ERR_CONNECTION_BROKEN, m_state.hostname ); - return false; - } - - m_request.strCharset = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace().lower(); - setMetaData("charset", m_request.strCharset); - if (!m_request.lastModified.isEmpty()) - setMetaData("modified", m_request.lastModified); - TQString tmp; - tmp.setNum(m_request.expireDate); - setMetaData("expire-date", tmp); - tmp.setNum(m_request.creationDate); - setMetaData("cache-creation-date", tmp); - mimeType(m_strMimeType); - forwardHttpResponseHeader(); - return true; - } - - TQCString locationStr; // In case we get a redirect. - TQCString cookieStr; // In case we get a cookie. - - TQString dispositionType; // In case we get a Content-Disposition type - TQString dispositionFilename; // In case we get a Content-Disposition filename - - TQString mediaValue; - TQString mediaAttribute; - - TQStringList upgradeOffers; - - bool upgradeRequired = false; // Server demands that we upgrade to something - // This is also true if we ask to upgrade and - // the server accepts, since we are now - // committed to doing so - bool canUpgrade = false; // The server offered an upgrade - - - m_request.etag = TQString::null; - m_request.lastModified = TQString::null; - m_request.strCharset = TQString::null; - - time_t dateHeader = 0; - time_t expireDate = 0; // 0 = no info, 1 = already expired, > 1 = actual date - int currentAge = 0; - int maxAge = -1; // -1 = no max age, 0 already expired, > 0 = actual time - int maxHeaderSize = 64*1024; // 64Kb to catch DOS-attacks - - // read in 8192 bytes at a time (HTTP cookies can be quite large.) - int len = 0; - char buffer[8193]; - bool cont = false; - bool cacheValidated = false; // Revalidation was successful - bool mayCache = true; - bool hasCacheDirective = false; - bool bCanResume = false; - - if (m_iSock == -1) - { - kdDebug(7113) << "HTTPProtocol::readHeader: No connection." << endl; - return false; // Restablish connection and try again - } - - if (!waitForResponse(m_remoteRespTimeout)) - { - // No response error - error( ERR_SERVER_TIMEOUT , m_state.hostname ); - return false; - } - - setRewindMarker(); - - gets(buffer, sizeof(buffer)-1); - - if (m_bEOF || *buffer == '\0') - { - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: " - << "EOF while waiting for header start." << endl; - if (m_bKeepAlive) // Try to reestablish connection. - { - httpCloseConnection(); - return false; // Reestablish connection and try again. - } - - if (m_request.method == HTTP_HEAD) - { - // HACK - // Some web-servers fail to respond properly to a HEAD request. - // We compensate for their failure to properly implement the HTTP standard - // by assuming that they will be sending html. - kdDebug(7113) << "(" << m_pid << ") HTTPPreadHeader: HEAD -> returned " - << "mimetype: " << DEFAULT_MIME_TYPE << endl; - mimeType(TQString::fromLatin1(DEFAULT_MIME_TYPE)); - return true; - } - - kdDebug(7113) << "HTTPProtocol::readHeader: Connection broken !" << endl; - error( ERR_CONNECTION_BROKEN, m_state.hostname ); - return false; - } - - kdDebug(7103) << "(" << m_pid << ") ============ Received Response:"<< endl; - - bool noHeader = true; - HTTP_REV httpRev = HTTP_None; - int headerSize = 0; - - do - { - // strip off \r and \n if we have them - len = strlen(buffer); - - while(len && (buffer[len-1] == '\n' || buffer[len-1] == '\r')) - buffer[--len] = 0; - - // if there was only a newline then continue - if (!len) - { - kdDebug(7103) << "(" << m_pid << ") --empty--" << endl; - continue; - } - - headerSize += len; - - // We have a response header. This flag is a work around for - // servers that append a "\r\n" before the beginning of the HEADER - // response!!! It only catches x number of \r\n being placed at the - // top of the reponse... - noHeader = false; - - kdDebug(7103) << "(" << m_pid << ") \"" << buffer << "\"" << endl; - - // Save broken servers from damnation!! - char* buf = buffer; - while( *buf == ' ' ) - buf++; - - - if (buf[0] == '<') - { - // We get XML / HTTP without a proper header - // put string back - kdDebug(7103) << "tdeio_http: No valid HTTP header found! Document starts with XML/HTML tag" << endl; - - // Document starts with a tag, assume html instead of text/plain - m_strMimeType = "text/html"; - - rewind(); - break; - } - - // Store the the headers so they can be passed to the - // calling application later - m_responseHeader << TQString::fromLatin1(buf); - - if ((strncasecmp(buf, "HTTP/", 5) == 0) || - (strncasecmp(buf, "ICY ", 4) == 0)) // Shoutcast support - { - if (strncasecmp(buf, "ICY ", 4) == 0) - { - // Shoutcast support - httpRev = SHOUTCAST; - m_bKeepAlive = false; - } - else if (strncmp((buf + 5), "1.0",3) == 0) - { - httpRev = HTTP_10; - // For 1.0 servers, the server itself has to explicitly - // tell us whether it supports persistent connection or - // not. By default, we assume it does not, but we do - // send the old style header "Connection: Keep-Alive" to - // inform it that we support persistence. - m_bKeepAlive = false; - } - else if (strncmp((buf + 5), "1.1",3) == 0) - { - httpRev = HTTP_11; - } - else - { - httpRev = HTTP_Unknown; - } - - if (m_responseCode) - m_prevResponseCode = m_responseCode; - - const char* rptr = buf; - while ( *rptr && *rptr > ' ' ) - ++rptr; - m_responseCode = atoi(rptr); - - // server side errors - if (m_responseCode >= 500 && m_responseCode <= 599) - { - if (m_request.method == HTTP_HEAD) - { - ; // Ignore error - } - else - { - if (m_request.bErrorPage) - errorPage(); - else - { - error(ERR_INTERNAL_SERVER, m_request.url.prettyURL()); - return false; - } - } - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - // Unauthorized access - else if (m_responseCode == 401 || m_responseCode == 407) - { - // Double authorization requests, i.e. a proxy auth - // request followed immediately by a regular auth request. - if ( m_prevResponseCode != m_responseCode && - (m_prevResponseCode == 401 || m_prevResponseCode == 407) ) - saveAuthorization(); - - m_bUnauthorized = true; - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - // - else if (m_responseCode == 416) // Range not supported - { - m_request.offset = 0; - httpCloseConnection(); - return false; // Try again. - } - // Upgrade Required - else if (m_responseCode == 426) - { - upgradeRequired = true; - } - // Any other client errors - else if (m_responseCode >= 400 && m_responseCode <= 499) - { - // Tell that we will only get an error page here. - if (m_request.bErrorPage) - errorPage(); - else - { - error(ERR_DOES_NOT_EXIST, m_request.url.prettyURL()); - return false; - } - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - else if (m_responseCode == 307) - { - // 307 Temporary Redirect - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - else if (m_responseCode == 304) - { - // 304 Not Modified - // The value in our cache is still valid. - cacheValidated = true; - } - else if (m_responseCode >= 301 && m_responseCode<= 303) - { - // 301 Moved permanently - if (m_responseCode == 301) - setMetaData("permanent-redirect", "true"); - - // 302 Found (temporary location) - // 303 See Other - if (m_request.method != HTTP_HEAD && m_request.method != HTTP_GET) - { -#if 0 - // Reset the POST buffer to avoid a double submit - // on redirection - if (m_request.method == HTTP_POST) - m_bufPOST.resize(0); -#endif - - // NOTE: This is wrong according to RFC 2616. However, - // because most other existing user agent implementations - // treat a 301/302 response as a 303 response and preform - // a GET action regardless of what the previous method was, - // many servers have simply adapted to this way of doing - // things!! Thus, we are forced to do the same thing or we - // won't be able to retrieve these pages correctly!! See RFC - // 2616 sections 10.3.[2/3/4/8] - m_request.method = HTTP_GET; // Force a GET - } - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - else if ( m_responseCode == 207 ) // Multi-status (for WebDav) - { - - } - else if ( m_responseCode == 204 ) // No content - { - // error(ERR_NO_CONTENT, i18n("Data have been successfully sent.")); - // Short circuit and do nothing! - - // The original handling here was wrong, this is not an error: eg. in the - // example of a 204 No Content response to a PUT completing. - // m_bError = true; - // return false; - } - else if ( m_responseCode == 206 ) - { - if ( m_request.offset ) - bCanResume = true; - } - else if (m_responseCode == 102) // Processing (for WebDAV) - { - /*** - * This status code is given when the server expects the - * command to take significant time to complete. So, inform - * the user. - */ - infoMessage( i18n( "Server processing request, please wait..." ) ); - cont = true; - } - else if (m_responseCode == 100) - { - // We got 'Continue' - ignore it - cont = true; - } - } - - // are we allowd to resume? this will tell us - else if (strncasecmp(buf, "Accept-Ranges:", 14) == 0) { - if (strncasecmp(trimLead(buf + 14), "none", 4) == 0) - bCanResume = false; - } - // Keep Alive - else if (strncasecmp(buf, "Keep-Alive:", 11) == 0) { - TQStringList options = TQStringList::split(',', - TQString::fromLatin1(trimLead(buf+11))); - for(TQStringList::ConstIterator it = options.begin(); - it != options.end(); - it++) - { - TQString option = (*it).stripWhiteSpace().lower(); - if (option.startsWith("timeout=")) - { - m_keepAliveTimeout = option.mid(8).toInt(); - } - } - } - - // Cache control - else if (strncasecmp(buf, "Cache-Control:", 14) == 0) { - TQStringList cacheControls = TQStringList::split(',', - TQString::fromLatin1(trimLead(buf+14))); - for(TQStringList::ConstIterator it = cacheControls.begin(); - it != cacheControls.end(); - it++) - { - TQString cacheControl = (*it).stripWhiteSpace(); - if (strncasecmp(cacheControl.latin1(), "no-cache", 8) == 0) - { - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - else if (strncasecmp(cacheControl.latin1(), "no-store", 8) == 0) - { - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - } - else if (strncasecmp(cacheControl.latin1(), "max-age=", 8) == 0) - { - TQString age = cacheControl.mid(8).stripWhiteSpace(); - if (!age.isNull()) - maxAge = STRTOLL(age.latin1(), 0, 10); - } - } - hasCacheDirective = true; - } - - // get the size of our data - else if (strncasecmp(buf, "Content-length:", 15) == 0) { - char* len = trimLead(buf + 15); - if (len) - m_iSize = STRTOLL(len, 0, 10); - } - - else if (strncasecmp(buf, "Content-location:", 17) == 0) { - setMetaData ("content-location", - TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace()); - } - - // what type of data do we have? - else if (strncasecmp(buf, "Content-type:", 13) == 0) { - char *start = trimLead(buf + 13); - char *pos = start; - - // Increment until we encounter ";" or the end of the buffer - while ( *pos && *pos != ';' ) pos++; - - // Assign the mime-type. - m_strMimeType = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower(); - kdDebug(7113) << "(" << m_pid << ") Content-type: " << m_strMimeType << endl; - - // If we still have text, then it means we have a mime-type with a - // parameter (eg: charset=iso-8851) ; so let's get that... - while (*pos) - { - start = ++pos; - while ( *pos && *pos != '=' ) pos++; - - char *end = pos; - while ( *end && *end != ';' ) end++; - - if (*pos) - { - mediaAttribute = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower(); - mediaValue = TQString::fromLatin1(pos+1, end-pos-1).stripWhiteSpace(); - pos = end; - if (mediaValue.length() && - (mediaValue[0] == '"') && - (mediaValue[mediaValue.length()-1] == '"')) - mediaValue = mediaValue.mid(1, mediaValue.length()-2); - - kdDebug (7113) << "(" << m_pid << ") Media-Parameter Attribute: " - << mediaAttribute << endl; - kdDebug (7113) << "(" << m_pid << ") Media-Parameter Value: " - << mediaValue << endl; - - if ( mediaAttribute == "charset") - { - mediaValue = mediaValue.lower(); - m_request.strCharset = mediaValue; - } - else - { - setMetaData("media-"+mediaAttribute, mediaValue); - } - } - } - } - - // Date - else if (strncasecmp(buf, "Date:", 5) == 0) { - dateHeader = KRFCDate::parseDate(trimLead(buf+5)); - } - - // Cache management - else if (strncasecmp(buf, "ETag:", 5) == 0) { - m_request.etag = trimLead(buf+5); - } - - // Cache management - else if (strncasecmp(buf, "Expires:", 8) == 0) { - expireDate = KRFCDate::parseDate(trimLead(buf+8)); - if (!expireDate) - expireDate = 1; // Already expired - } - - // Cache management - else if (strncasecmp(buf, "Last-Modified:", 14) == 0) { - m_request.lastModified = (TQString::fromLatin1(trimLead(buf+14))).stripWhiteSpace(); - } - - // whoops.. we received a warning - else if (strncasecmp(buf, "Warning:", 8) == 0) { - //Don't use warning() here, no need to bother the user. - //Those warnings are mostly about caches. - infoMessage(trimLead(buf + 8)); - } - - // Cache management (HTTP 1.0) - else if (strncasecmp(buf, "Pragma:", 7) == 0) { - TQCString pragma = TQCString(trimLead(buf+7)).stripWhiteSpace().lower(); - if (pragma == "no-cache") - { - m_request.bCachedWrite = false; // Don't put in cache - mayCache = false; - hasCacheDirective = true; - } - } - - // The deprecated Refresh Response - else if (strncasecmp(buf,"Refresh:", 8) == 0) { - mayCache = false; // Do not cache page as it defeats purpose of Refresh tag! - setMetaData( "http-refresh", TQString::fromLatin1(trimLead(buf+8)).stripWhiteSpace() ); - } - - // In fact we should do redirection only if we got redirection code - else if (strncasecmp(buf, "Location:", 9) == 0) { - // Redirect only for 3xx status code, will ya! Thanks, pal! - if ( m_responseCode > 299 && m_responseCode < 400 ) - locationStr = TQCString(trimLead(buf+9)).stripWhiteSpace(); - } - - // Check for cookies - else if (strncasecmp(buf, "Set-Cookie", 10) == 0) { - cookieStr += buf; - cookieStr += '\n'; - } - - // check for direct authentication - else if (strncasecmp(buf, "WWW-Authenticate:", 17) == 0) { - configAuth(trimLead(buf + 17), false); - } - - // check for proxy-based authentication - else if (strncasecmp(buf, "Proxy-Authenticate:", 19) == 0) { - configAuth(trimLead(buf + 19), true); - } - - else if (strncasecmp(buf, "Upgrade:", 8) == 0) { - // Now we have to check to see what is offered for the upgrade - TQString offered = &(buf[8]); - upgradeOffers = TQStringList::split(TQRegExp("[ \n,\r\t]"), offered); - } - - // content? - else if (strncasecmp(buf, "Content-Encoding:", 17) == 0) { - // This is so wrong !! No wonder tdeio_http is stripping the - // gzip encoding from downloaded files. This solves multiple - // bug reports and caitoo's problem with downloads when such a - // header is encountered... - - // A quote from RFC 2616: - // " When present, its (Content-Encoding) value indicates what additional - // content have been applied to the entity body, and thus what decoding - // mechanism must be applied to obtain the media-type referenced by the - // Content-Type header field. Content-Encoding is primarily used to allow - // a document to be compressed without loosing the identity of its underlying - // media type. Simply put if it is specified, this is the actual mime-type - // we should use when we pull the resource !!! - addEncoding(trimLead(buf + 17), m_qContentEncodings); - } - // Refer to RFC 2616 sec 15.5/19.5.1 and RFC 2183 - else if(strncasecmp(buf, "Content-Disposition:", 20) == 0) { - char* dispositionBuf = trimLead(buf + 20); - while ( *dispositionBuf ) - { - if ( strncasecmp( dispositionBuf, "filename", 8 ) == 0 ) - { - dispositionBuf += 8; - - while ( *dispositionBuf == ' ' || *dispositionBuf == '=' ) - dispositionBuf++; - - char* bufStart = dispositionBuf; - - while ( *dispositionBuf && *dispositionBuf != ';' ) - dispositionBuf++; - - if ( dispositionBuf > bufStart ) - { - // Skip any leading quotes... - while ( *bufStart == '"' ) - bufStart++; - - // Skip any trailing quotes as well as white spaces... - while ( *(dispositionBuf-1) == ' ' || *(dispositionBuf-1) == '"') - dispositionBuf--; - - if ( dispositionBuf > bufStart ) - dispositionFilename = TQString::fromLatin1( bufStart, dispositionBuf-bufStart ); - - break; - } - } - else - { - char *bufStart = dispositionBuf; - - while ( *dispositionBuf && *dispositionBuf != ';' ) - dispositionBuf++; - - if ( dispositionBuf > bufStart ) - dispositionType = TQString::fromLatin1( bufStart, dispositionBuf-bufStart ).stripWhiteSpace(); - - while ( *dispositionBuf == ';' || *dispositionBuf == ' ' ) - dispositionBuf++; - } - } - - // Content-Dispostion is not allowed to dictate directory - // path, thus we extract the filename only. - if ( !dispositionFilename.isEmpty() ) - { - int pos = dispositionFilename.findRev( '/' ); - - if( pos > -1 ) - dispositionFilename = dispositionFilename.mid(pos+1); - - kdDebug(7113) << "(" << m_pid << ") Content-Disposition: filename=" - << dispositionFilename<< endl; - } - } - else if(strncasecmp(buf, "Content-Language:", 17) == 0) { - TQString language = TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace(); - if (!language.isEmpty()) - setMetaData("content-language", language); - } - else if (strncasecmp(buf, "Proxy-Connection:", 17) == 0) - { - if (strncasecmp(trimLead(buf + 17), "Close", 5) == 0) - m_bKeepAlive = false; - else if (strncasecmp(trimLead(buf + 17), "Keep-Alive", 10)==0) - m_bKeepAlive = true; - } - else if (strncasecmp(buf, "Link:", 5) == 0) { - // We only support Link: ; rel="type" so far - TQStringList link = TQStringList::split(";", TQString(buf) - .replace(TQRegExp("^Link:[ ]*"), - "")); - if (link.count() == 2) { - TQString rel = link[1].stripWhiteSpace(); - if (rel.startsWith("rel=\"")) { - rel = rel.mid(5, rel.length() - 6); - if (rel.lower() == "pageservices") { - TQString url = TQString(link[0].replace(TQRegExp("[<>]"),"")).stripWhiteSpace(); - setMetaData("PageServices", url); - } - } - } - } - else if (strncasecmp(buf, "P3P:", 4) == 0) { - TQString p3pstr = buf; - p3pstr = p3pstr.mid(4).simplifyWhiteSpace(); - TQStringList policyrefs, compact; - TQStringList policyfields = TQStringList::split(TQRegExp(",[ ]*"), p3pstr); - for (TQStringList::Iterator it = policyfields.begin(); - it != policyfields.end(); - ++it) { - TQStringList policy = TQStringList::split("=", *it); - - if (policy.count() == 2) { - if (policy[0].lower() == "policyref") { - policyrefs << TQString(policy[1].replace(TQRegExp("[\"\']"), "")) - .stripWhiteSpace(); - } else if (policy[0].lower() == "cp") { - // We convert to cp\ncp\ncp\n[...]\ncp to be consistent with - // other metadata sent in strings. This could be a bit more - // efficient but I'm going for correctness right now. - TQStringList cps = TQStringList::split(" ", - TQString(policy[1].replace(TQRegExp("[\"\']"), "")) - .simplifyWhiteSpace()); - - for (TQStringList::Iterator j = cps.begin(); j != cps.end(); ++j) - compact << *j; - } - } - } - - if (!policyrefs.isEmpty()) - setMetaData("PrivacyPolicy", policyrefs.join("\n")); - - if (!compact.isEmpty()) - setMetaData("PrivacyCompactPolicy", compact.join("\n")); - } - // let them tell us if we should stay alive or not - else if (strncasecmp(buf, "Connection:", 11) == 0) - { - if (strncasecmp(trimLead(buf + 11), "Close", 5) == 0) - m_bKeepAlive = false; - else if (strncasecmp(trimLead(buf + 11), "Keep-Alive", 10)==0) - m_bKeepAlive = true; - else if (strncasecmp(trimLead(buf + 11), "Upgrade", 7)==0) - { - if (m_responseCode == 101) { - // Ok, an upgrade was accepted, now we must do it - upgradeRequired = true; - } else if (upgradeRequired) { // 426 - // Nothing to do since we did it above already - } else { - // Just an offer to upgrade - no need to take it - canUpgrade = true; - } - } - } - // continue only if we know that we're HTTP/1.1 - else if ( httpRev == HTTP_11) { - // what kind of encoding do we have? transfer? - if (strncasecmp(buf, "Transfer-Encoding:", 18) == 0) { - // If multiple encodings have been applied to an entity, the - // transfer-codings MUST be listed in the order in which they - // were applied. - addEncoding(trimLead(buf + 18), m_qTransferEncodings); - } - - // md5 signature - else if (strncasecmp(buf, "Content-MD5:", 12) == 0) { - m_sContentMD5 = TQString::fromLatin1(trimLead(buf + 12)); - } - - // *** Responses to the HTTP OPTIONS method follow - // WebDAV capabilities - else if (strncasecmp(buf, "DAV:", 4) == 0) { - if (m_davCapabilities.isEmpty()) { - m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4)); - } - else { - m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4)); - } - } - // *** Responses to the HTTP OPTIONS method finished - } - else if ((httpRev == HTTP_None) && (strlen(buf) != 0)) - { - // Remote server does not seem to speak HTTP at all - // Put the crap back into the buffer and hope for the best - rewind(); - if (m_responseCode) - m_prevResponseCode = m_responseCode; - - m_responseCode = 200; // Fake it - httpRev = HTTP_Unknown; - m_bKeepAlive = false; - break; - } - setRewindMarker(); - - // Clear out our buffer for further use. - memset(buffer, 0, sizeof(buffer)); - - } while (!m_bEOF && (len || noHeader) && (headerSize < maxHeaderSize) && (gets(buffer, sizeof(buffer)-1))); - - // Now process the HTTP/1.1 upgrade - TQStringList::Iterator opt = upgradeOffers.begin(); - for( ; opt != upgradeOffers.end(); ++opt) { - if (*opt == "TLS/1.0") { - if(upgradeRequired) { - if (!startTLS() && !usingTLS()) { - error(ERR_UPGRADE_REQUIRED, *opt); - return false; - } - } - } else if (*opt == "HTTP/1.1") { - httpRev = HTTP_11; - } else { - // unknown - if (upgradeRequired) { - error(ERR_UPGRADE_REQUIRED, *opt); - return false; - } - } - } - - setMetaData("charset", m_request.strCharset); - - // If we do not support the requested authentication method... - if ( (m_responseCode == 401 && Authentication == AUTH_None) || - (m_responseCode == 407 && ProxyAuthentication == AUTH_None) ) - { - m_bUnauthorized = false; - if (m_request.bErrorPage) - errorPage(); - else - { - error( ERR_UNSUPPORTED_ACTION, "Unknown Authorization method!" ); - return false; - } - } - - // Fixup expire date for clock drift. - if (expireDate && (expireDate <= dateHeader)) - expireDate = 1; // Already expired. - - // Convert max-age into expireDate (overriding previous set expireDate) - if (maxAge == 0) - expireDate = 1; // Already expired. - else if (maxAge > 0) - { - if (currentAge) - maxAge -= currentAge; - if (maxAge <=0) - maxAge = 0; - expireDate = time(0) + maxAge; - } - - if (!expireDate) - { - time_t lastModifiedDate = 0; - if (!m_request.lastModified.isEmpty()) - lastModifiedDate = KRFCDate::parseDate(m_request.lastModified); - - if (lastModifiedDate) - { - long diff = static_cast(difftime(dateHeader, lastModifiedDate)); - if (diff < 0) - expireDate = time(0) + 1; - else - expireDate = time(0) + (diff / 10); - } - else - { - expireDate = time(0) + DEFAULT_CACHE_EXPIRE; - } - } - - // DONE receiving the header! - if (!cookieStr.isEmpty()) - { - if ((m_request.cookieMode == HTTPRequest::CookiesAuto) && m_request.bUseCookiejar) - { - // Give cookies to the cookiejar. - TQString domain = config()->readEntry("cross-domain"); - if (!domain.isEmpty() && isCrossDomainRequest(m_request.url.host(), domain)) - cookieStr = "Cross-Domain\n" + cookieStr; - addCookies( m_request.url.url(), cookieStr ); - } - else if (m_request.cookieMode == HTTPRequest::CookiesManual) - { - // Pass cookie to application - setMetaData("setcookies", cookieStr); - } - } - - if (m_request.bMustRevalidate) - { - m_request.bMustRevalidate = false; // Reset just in case. - if (cacheValidated) - { - // Yippie, we can use the cached version. - // Update the cache with new "Expire" headers. - fclose(m_request.fcache); - m_request.fcache = 0; - updateExpireDate( expireDate, true ); - m_request.fcache = checkCacheEntry( ); // Re-read cache entry - - if (m_request.fcache) - { - m_request.bCachedRead = true; - goto try_again; // Read header again, but now from cache. - } - else - { - // Where did our cache entry go??? - } - } - else - { - // Validation failed. Close cache. - fclose(m_request.fcache); - m_request.fcache = 0; - } - } - - // We need to reread the header if we got a '100 Continue' or '102 Processing' - if ( cont ) - { - goto try_again; - } - - // Do not do a keep-alive connection if the size of the - // response is not known and the response is not Chunked. - if (!m_bChunked && (m_iSize == NO_SIZE)) - m_bKeepAlive = false; - - if ( m_responseCode == 204 ) - { - return true; - } - - // We need to try to login again if we failed earlier - if ( m_bUnauthorized ) - { - if ( (m_responseCode == 401) || - (m_bUseProxy && (m_responseCode == 407)) - ) - { - if ( getAuthorization() ) - { - // for NTLM Authentication we have to keep the connection open! - if ( Authentication == AUTH_NTLM && m_strAuthorization.length() > 4 ) - { - m_bKeepAlive = true; - readBody( true ); - } - else if (ProxyAuthentication == AUTH_NTLM && m_strProxyAuthorization.length() > 4) - { - readBody( true ); - } - else - httpCloseConnection(); - return false; // Try again. - } - - if (m_bError) - return false; // Error out - - // Show error page... - } - m_bUnauthorized = false; - } - - // We need to do a redirect - if (!locationStr.isEmpty()) - { - KURL u(m_request.url, locationStr); - if(!u.isValid()) - { - error(ERR_MALFORMED_URL, u.prettyURL()); - return false; - } - if ((u.protocol() != "http") && (u.protocol() != "https") && - (u.protocol() != "ftp") && (u.protocol() != "webdav") && - (u.protocol() != "webdavs")) - { - redirection(u); - error(ERR_ACCESS_DENIED, u.prettyURL()); - return false; - } - - // preserve #ref: (bug 124654) - // if we were at http://host/resource1#ref, we sent a GET for "/resource1" - // if we got redirected to http://host/resource2, then we have to re-add - // the fragment: - if (m_request.url.hasRef() && !u.hasRef() && - (m_request.url.host() == u.host()) && - (m_request.url.protocol() == u.protocol())) - u.setRef(m_request.url.ref()); - - m_bRedirect = true; - m_redirectLocation = u; - - if (!m_request.id.isEmpty()) - { - sendMetaData(); - } - - kdDebug(7113) << "(" << m_pid << ") request.url: " << m_request.url.prettyURL() - << endl << "LocationStr: " << locationStr.data() << endl; - - kdDebug(7113) << "(" << m_pid << ") Requesting redirection to: " << u.prettyURL() - << endl; - - // If we're redirected to a http:// url, remember that we're doing webdav... - if (m_protocol == "webdav" || m_protocol == "webdavs") - u.setProtocol(m_protocol); - - redirection(u); - m_request.bCachedWrite = false; // Turn off caching on re-direction (DA) - mayCache = false; - } - - // Inform the job that we can indeed resume... - if ( bCanResume && m_request.offset ) - canResume(); - else - m_request.offset = 0; - - // We don't cache certain text objects - if (m_strMimeType.startsWith("text/") && - (m_strMimeType != "text/css") && - (m_strMimeType != "text/x-javascript") && - !hasCacheDirective) - { - // Do not cache secure pages or pages - // originating from password protected sites - // unless the webserver explicitly allows it. - if ( m_bIsSSL || (Authentication != AUTH_None) ) - { - m_request.bCachedWrite = false; - mayCache = false; - } - } - - // WABA: Correct for tgz files with a gzip-encoding. - // They really shouldn't put gzip in the Content-Encoding field! - // Web-servers really shouldn't do this: They let Content-Size refer - // to the size of the tgz file, not to the size of the tar file, - // while the Content-Type refers to "tar" instead of "tgz". - if (m_qContentEncodings.last() == "gzip") - { - if (m_strMimeType == "application/x-tar") - { - m_qContentEncodings.remove(m_qContentEncodings.fromLast()); - m_strMimeType = TQString::fromLatin1("application/x-tgz"); - } - else if (m_strMimeType == "application/postscript") - { - // LEONB: Adding another exception for psgz files. - // Could we use the mimelnk files instead of hardcoding all this? - m_qContentEncodings.remove(m_qContentEncodings.fromLast()); - m_strMimeType = TQString::fromLatin1("application/x-gzpostscript"); - } - else if ( m_request.allowCompressedPage && - m_strMimeType != "application/x-tgz" && - m_strMimeType != "application/x-targz" && - m_strMimeType != "application/x-gzip" && - m_request.url.path().right(6) == ".ps.gz" ) - { - m_qContentEncodings.remove(m_qContentEncodings.fromLast()); - m_strMimeType = TQString::fromLatin1("application/x-gzpostscript"); - } - else if ( (m_request.allowCompressedPage && - m_strMimeType == "text/html") - || - (m_request.allowCompressedPage && - m_strMimeType != "application/x-tgz" && - m_strMimeType != "application/x-targz" && - m_strMimeType != "application/x-gzip" && - m_request.url.path().right(3) != ".gz") - ) - { - // Unzip! - } - else - { - m_qContentEncodings.remove(m_qContentEncodings.fromLast()); - m_strMimeType = TQString::fromLatin1("application/x-gzip"); - } - } - - // We can't handle "bzip2" encoding (yet). So if we get something with - // bzip2 encoding, we change the mimetype to "application/x-bzip2". - // Note for future changes: some web-servers send both "bzip2" as - // encoding and "application/x-bzip2" as mimetype. That is wrong. - // currently that doesn't bother us, because we remove the encoding - // and set the mimetype to x-bzip2 anyway. - if (m_qContentEncodings.last() == "bzip2") - { - m_qContentEncodings.remove(m_qContentEncodings.fromLast()); - m_strMimeType = TQString::fromLatin1("application/x-bzip2"); - } - - // Convert some common mimetypes to standard KDE mimetypes - if (m_strMimeType == "application/x-targz") - m_strMimeType = TQString::fromLatin1("application/x-tgz"); - else if (m_strMimeType == "application/zip") - m_strMimeType = TQString::fromLatin1("application/x-zip"); - else if (m_strMimeType == "image/x-png") - m_strMimeType = TQString::fromLatin1("image/png"); - else if (m_strMimeType == "image/bmp") - m_strMimeType = TQString::fromLatin1("image/x-bmp"); - else if (m_strMimeType == "audio/mpeg" || m_strMimeType == "audio/x-mpeg" || m_strMimeType == "audio/mp3") - m_strMimeType = TQString::fromLatin1("audio/x-mp3"); - else if (m_strMimeType == "audio/microsoft-wave") - m_strMimeType = TQString::fromLatin1("audio/x-wav"); - else if (m_strMimeType == "audio/midi") - m_strMimeType = TQString::fromLatin1("audio/x-midi"); - else if (m_strMimeType == "image/x-xpixmap") - m_strMimeType = TQString::fromLatin1("image/x-xpm"); - else if (m_strMimeType == "application/rtf") - m_strMimeType = TQString::fromLatin1("text/rtf"); - - // Crypto ones.... - else if (m_strMimeType == "application/pkix-cert" || - m_strMimeType == "application/binary-certificate") - { - m_strMimeType = TQString::fromLatin1("application/x-x509-ca-cert"); - } - - // Prefer application/x-tgz or x-gzpostscript over application/x-gzip. - else if (m_strMimeType == "application/x-gzip") - { - if ((m_request.url.path().right(7) == ".tar.gz") || - (m_request.url.path().right(4) == ".tar")) - m_strMimeType = TQString::fromLatin1("application/x-tgz"); - if ((m_request.url.path().right(6) == ".ps.gz")) - m_strMimeType = TQString::fromLatin1("application/x-gzpostscript"); - } - - // Some webservers say "text/plain" when they mean "application/x-bzip2" - else if ((m_strMimeType == "text/plain") || (m_strMimeType == "application/octet-stream")) - { - TQString ext = m_request.url.path().right(4).upper(); - if (ext == ".BZ2") - m_strMimeType = TQString::fromLatin1("application/x-bzip2"); - else if (ext == ".PEM") - m_strMimeType = TQString::fromLatin1("application/x-x509-ca-cert"); - else if (ext == ".SWF") - m_strMimeType = TQString::fromLatin1("application/x-shockwave-flash"); - else if (ext == ".PLS") - m_strMimeType = TQString::fromLatin1("audio/x-scpls"); - else if (ext == ".WMV") - m_strMimeType = TQString::fromLatin1("video/x-ms-wmv"); - } - -#if 0 - // Even if we can't rely on content-length, it seems that we should - // never get more data than content-length. Maybe less, if the - // content-length refers to the unzipped data. - if (!m_qContentEncodings.isEmpty()) - { - // If we still have content encoding we can't rely on the Content-Length. - m_iSize = NO_SIZE; - } -#endif - - if( !dispositionType.isEmpty() ) - { - kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition type to: " - << dispositionType << endl; - setMetaData("content-disposition-type", dispositionType); - } - if( !dispositionFilename.isEmpty() ) - { - kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition filename to: " - << dispositionFilename << endl; - // ### KDE4: setting content-disposition to filename for pre 3.5.2 compatability - setMetaData("content-disposition", dispositionFilename); - setMetaData("content-disposition-filename", dispositionFilename); - } - - if (!m_request.lastModified.isEmpty()) - setMetaData("modified", m_request.lastModified); - - if (!mayCache) - { - setMetaData("no-cache", "true"); - setMetaData("expire-date", "1"); // Expired - } - else - { - TQString tmp; - tmp.setNum(expireDate); - setMetaData("expire-date", tmp); - tmp.setNum(time(0)); // Cache entry will be created shortly. - setMetaData("cache-creation-date", tmp); - } - - // Let the app know about the mime-type iff this is not - // a redirection and the mime-type string is not empty. - if (locationStr.isEmpty() && (!m_strMimeType.isEmpty() || - m_request.method == HTTP_HEAD)) - { - kdDebug(7113) << "(" << m_pid << ") Emitting mimetype " << m_strMimeType << endl; - mimeType( m_strMimeType ); - } - - // Do not move send response header before any redirection as it seems - // to screw up some sites. See BR# 150904. - forwardHttpResponseHeader(); - - if (m_request.method == HTTP_HEAD) - return true; - - // Do we want to cache this request? - if (m_request.bUseCache) - { - ::unlink( TQFile::encodeName(m_request.cef)); - if ( m_request.bCachedWrite && !m_strMimeType.isEmpty() ) - { - // Check... - createCacheEntry(m_strMimeType, expireDate); // Create a cache entry - if (!m_request.fcache) - { - m_request.bCachedWrite = false; // Error creating cache entry. - kdDebug(7113) << "(" << m_pid << ") Error creating cache entry for " << m_request.url.prettyURL()<<"!\n"; - } - m_request.expireDate = expireDate; - m_maxCacheSize = config()->readNumEntry("MaxCacheSize", DEFAULT_MAX_CACHE_SIZE) / 2; - } - } - - if (m_request.bCachedWrite && !m_strMimeType.isEmpty()) - kdDebug(7113) << "(" << m_pid << ") Cache, adding \"" << m_request.url.prettyURL() << "\"" << endl; - else if (m_request.bCachedWrite && m_strMimeType.isEmpty()) - kdDebug(7113) << "(" << m_pid << ") Cache, pending \"" << m_request.url.prettyURL() << "\"" << endl; - else - kdDebug(7113) << "(" << m_pid << ") Cache, not adding \"" << m_request.url.prettyURL() << "\"" << endl; - return true; -} - - -void HTTPProtocol::addEncoding(TQString encoding, TQStringList &encs) -{ - encoding = encoding.stripWhiteSpace().lower(); - // Identity is the same as no encoding - if (encoding == "identity") { - return; - } else if (encoding == "8bit") { - // Strange encoding returned by http://linac.ikp.physik.tu-darmstadt.de - return; - } else if (encoding == "chunked") { - m_bChunked = true; - // Anyone know of a better way to handle unknown sizes possibly/ideally with unsigned ints? - //if ( m_cmd != CMD_COPY ) - m_iSize = NO_SIZE; - } else if ((encoding == "x-gzip") || (encoding == "gzip")) { - encs.append(TQString::fromLatin1("gzip")); - } else if ((encoding == "x-bzip2") || (encoding == "bzip2")) { - encs.append(TQString::fromLatin1("bzip2")); // Not yet supported! - } else if ((encoding == "x-deflate") || (encoding == "deflate")) { - encs.append(TQString::fromLatin1("deflate")); - } else { - kdDebug(7113) << "(" << m_pid << ") Unknown encoding encountered. " - << "Please write code. Encoding = \"" << encoding - << "\"" << endl; - } -} - -bool HTTPProtocol::sendBody() -{ - int result=-1; - int length=0; - - infoMessage( i18n( "Requesting data to send" ) ); - - // m_bufPOST will NOT be empty iff authentication was required before posting - // the data OR a re-connect is requested from ::readHeader because the - // connection was lost for some reason. - if ( !m_bufPOST.isNull() ) - { - kdDebug(7113) << "(" << m_pid << ") POST'ing saved data..." << endl; - - result = 0; - length = m_bufPOST.size(); - } - else - { - kdDebug(7113) << "(" << m_pid << ") POST'ing live data..." << endl; - - TQByteArray buffer; - int old_size; - - m_bufPOST.resize(0); - do - { - dataReq(); // Request for data - result = readData( buffer ); - if ( result > 0 ) - { - length += result; - old_size = m_bufPOST.size(); - m_bufPOST.resize( old_size+result ); - memcpy( m_bufPOST.data()+ old_size, buffer.data(), buffer.size() ); - buffer.resize(0); - } - } while ( result > 0 ); - } - - if ( result < 0 ) - { - error( ERR_ABORTED, m_request.hostname ); - return false; - } - - infoMessage( i18n( "Sending data to %1" ).arg( m_request.hostname ) ); - - TQString size = TQString ("Content-Length: %1\r\n\r\n").arg(length); - kdDebug( 7113 ) << "(" << m_pid << ")" << size << endl; - - // Send the content length... - bool sendOk = (write(size.latin1(), size.length()) == (ssize_t) size.length()); - if (!sendOk) - { - kdDebug( 7113 ) << "(" << m_pid << ") Connection broken when sending " - << "content length: (" << m_state.hostname << ")" << endl; - error( ERR_CONNECTION_BROKEN, m_state.hostname ); - return false; - } - - // Send the data... - // kdDebug( 7113 ) << "(" << m_pid << ") POST DATA: " << TQCString(m_bufPOST) << endl; - sendOk = (write(m_bufPOST.data(), m_bufPOST.size()) == (ssize_t) m_bufPOST.size()); - if (!sendOk) - { - kdDebug(7113) << "(" << m_pid << ") Connection broken when sending message body: (" - << m_state.hostname << ")" << endl; - error( ERR_CONNECTION_BROKEN, m_state.hostname ); - return false; - } - - return true; -} - -void HTTPProtocol::httpClose( bool keepAlive ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpClose" << endl; - - if (m_request.fcache) - { - fclose(m_request.fcache); - m_request.fcache = 0; - if (m_request.bCachedWrite) - { - TQString filename = m_request.cef + ".new"; - ::unlink( TQFile::encodeName(filename) ); - } - } - - // Only allow persistent connections for GET requests. - // NOTE: we might even want to narrow this down to non-form - // based submit requests which will require a meta-data from - // tdehtml. - if (keepAlive && (!m_bUseProxy || - m_bPersistentProxyConnection || m_bIsTunneled)) - { - if (!m_keepAliveTimeout) - m_keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT; - else if (m_keepAliveTimeout > 2*DEFAULT_KEEP_ALIVE_TIMEOUT) - m_keepAliveTimeout = 2*DEFAULT_KEEP_ALIVE_TIMEOUT; - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpClose: keep alive (" << m_keepAliveTimeout << ")" << endl; - TQByteArray data; - TQDataStream stream( data, IO_WriteOnly ); - stream << int(99); // special: Close connection - setTimeoutSpecialCommand(m_keepAliveTimeout, data); - return; - } - - httpCloseConnection(); -} - -void HTTPProtocol::closeConnection() -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::closeConnection" << endl; - httpCloseConnection (); -} - -void HTTPProtocol::httpCloseConnection () -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpCloseConnection" << endl; - m_bIsTunneled = false; - m_bKeepAlive = false; - closeDescriptor(); - setTimeoutSpecialCommand(-1); // Cancel any connection timeout -} - -void HTTPProtocol::slave_status() -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::slave_status" << endl; - - if ( m_iSock != -1 && !isConnectionValid() ) - httpCloseConnection(); - - slaveStatus( m_state.hostname, (m_iSock != -1) ); -} - -void HTTPProtocol::mimetype( const KURL& url ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::mimetype: " - << url.prettyURL() << endl; - - if ( !checkRequestURL( url ) ) - return; - - m_request.method = HTTP_HEAD; - m_request.path = url.path(); - m_request.query = url.query(); - m_request.cache = CC_Cache; - m_request.doProxy = m_bUseProxy; - - retrieveHeader(); - - kdDebug(7113) << "(" << m_pid << ") http: mimetype = " << m_strMimeType - << endl; -} - -void HTTPProtocol::special( const TQByteArray &data ) -{ - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::special" << endl; - - int tmp; - TQDataStream stream(data, IO_ReadOnly); - - stream >> tmp; - switch (tmp) { - case 1: // HTTP POST - { - KURL url; - stream >> url; - post( url ); - break; - } - case 2: // cache_update - { - KURL url; - bool no_cache; - time_t expireDate; - stream >> url >> no_cache >> expireDate; - cacheUpdate( url, no_cache, expireDate ); - break; - } - case 5: // WebDAV lock - { - KURL url; - TQString scope, type, owner; - stream >> url >> scope >> type >> owner; - davLock( url, scope, type, owner ); - break; - } - case 6: // WebDAV unlock - { - KURL url; - stream >> url; - davUnlock( url ); - break; - } - case 7: // Generic WebDAV - { - KURL url; - int method; - stream >> url >> method; - davGeneric( url, (TDEIO::HTTP_METHOD) method ); - break; - } - case 99: // Close Connection - { - httpCloseConnection(); - break; - } - default: - // Some command we don't understand. - // Just ignore it, it may come from some future version of KDE. - break; - } -} - -/** - * Read a chunk from the data stream. - */ -int HTTPProtocol::readChunked() -{ - if ((m_iBytesLeft == 0) || (m_iBytesLeft == NO_SIZE)) - { - setRewindMarker(); - - m_bufReceive.resize(4096); - - if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) - { - kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk header" << endl; - return -1; - } - // We could have got the CRLF of the previous chunk. - // If so, try again. - if (m_bufReceive[0] == '\0') - { - if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) - { - kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk header" << endl; - return -1; - } - } - - // m_bEOF is set to true when read called from gets returns 0. For chunked reading 0 - // means end of chunked transfer and not error. See RFC 2615 section 3.6.1 - #if 0 - if (m_bEOF) - { - kdDebug(7113) << "(" << m_pid << ") EOF on Chunk header" << endl; - return -1; - } - #endif - - long long trunkSize = STRTOLL(m_bufReceive.data(), 0, 16); - if (trunkSize < 0) - { - kdDebug(7113) << "(" << m_pid << ") Negative chunk size" << endl; - return -1; - } - m_iBytesLeft = trunkSize; - - // kdDebug(7113) << "(" << m_pid << ") Chunk size = " << m_iBytesLeft << " bytes" << endl; - - if (m_iBytesLeft == 0) - { - // Last chunk. - // Skip trailers. - do { - // Skip trailer of last chunk. - if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) - { - kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk trailer" << endl; - return -1; - } - // kdDebug(7113) << "(" << m_pid << ") Chunk trailer = \"" << m_bufReceive.data() << "\"" << endl; - } - while (strlen(m_bufReceive.data()) != 0); - - return 0; - } - } - - int bytesReceived = readLimited(); - if (!m_iBytesLeft) - m_iBytesLeft = NO_SIZE; // Don't stop, continue with next chunk - - // kdDebug(7113) << "(" << m_pid << ") readChunked: BytesReceived=" << bytesReceived << endl; - return bytesReceived; -} - -int HTTPProtocol::readLimited() -{ - if (!m_iBytesLeft) - return 0; - - m_bufReceive.resize(4096); - - int bytesReceived; - int bytesToReceive; - - if (m_iBytesLeft > m_bufReceive.size()) - bytesToReceive = m_bufReceive.size(); - else - bytesToReceive = m_iBytesLeft; - - bytesReceived = read(m_bufReceive.data(), bytesToReceive); - - if (bytesReceived <= 0) - return -1; // Error: connection lost - - m_iBytesLeft -= bytesReceived; - return bytesReceived; -} - -int HTTPProtocol::readUnlimited() -{ - if (m_bKeepAlive) - { - kdDebug(7113) << "(" << m_pid << ") Unbounded datastream on a Keep " - << "alive connection!" << endl; - m_bKeepAlive = false; - } - - m_bufReceive.resize(4096); - - int result = read(m_bufReceive.data(), m_bufReceive.size()); - if (result > 0) - return result; - - m_bEOF = true; - m_iBytesLeft = 0; - return 0; -} - -void HTTPProtocol::slotData(const TQByteArray &_d) -{ - if (!_d.size()) - { - m_bEOD = true; - return; - } - - if (m_iContentLeft != NO_SIZE) - { - if (m_iContentLeft >= _d.size()) - m_iContentLeft -= _d.size(); - else - m_iContentLeft = NO_SIZE; - } - - TQByteArray d = _d; - if ( !m_dataInternal ) - { - // If a broken server does not send the mime-type, - // we try to id it from the content before dealing - // with the content itself. - if ( m_strMimeType.isEmpty() && !m_bRedirect && - !( m_responseCode >= 300 && m_responseCode <=399) ) - { - kdDebug(7113) << "(" << m_pid << ") Determining mime-type from content..." << endl; - int old_size = m_mimeTypeBuffer.size(); - m_mimeTypeBuffer.resize( old_size + d.size() ); - memcpy( m_mimeTypeBuffer.data() + old_size, d.data(), d.size() ); - if ( (m_iBytesLeft != NO_SIZE) && (m_iBytesLeft > 0) - && (m_mimeTypeBuffer.size() < 1024) ) - { - m_cpMimeBuffer = true; - return; // Do not send up the data since we do not yet know its mimetype! - } - - kdDebug(7113) << "(" << m_pid << ") Mimetype buffer size: " << m_mimeTypeBuffer.size() - << endl; - - KMimeMagicResult *result; - result = KMimeMagic::self()->findBufferFileType( m_mimeTypeBuffer, - m_request.url.fileName() ); - if( result ) - { - m_strMimeType = result->mimeType(); - kdDebug(7113) << "(" << m_pid << ") Mimetype from content: " - << m_strMimeType << endl; - } - - if ( m_strMimeType.isEmpty() ) - { - m_strMimeType = TQString::fromLatin1( DEFAULT_MIME_TYPE ); - kdDebug(7113) << "(" << m_pid << ") Using default mimetype: " - << m_strMimeType << endl; - } - - if ( m_request.bCachedWrite ) - { - createCacheEntry( m_strMimeType, m_request.expireDate ); - if (!m_request.fcache) - m_request.bCachedWrite = false; - } - - if ( m_cpMimeBuffer ) - { - // Do not make any assumption about the state of the TQByteArray we received. - // Fix the crash described by BR# 130104. - d.detach(); - d.resize(0); - d.resize(m_mimeTypeBuffer.size()); - memcpy( d.data(), m_mimeTypeBuffer.data(), - d.size() ); - } - mimeType(m_strMimeType); - m_mimeTypeBuffer.resize(0); - } - - data( d ); - if (m_request.bCachedWrite && m_request.fcache) - writeCacheEntry(d.data(), d.size()); - } - else - { - uint old_size = m_bufWebDavData.size(); - m_bufWebDavData.resize (old_size + d.size()); - memcpy (m_bufWebDavData.data() + old_size, d.data(), d.size()); - } -} - -/** - * This function is our "receive" function. It is responsible for - * downloading the message (not the header) from the HTTP server. It - * is called either as a response to a client's TDEIOJob::dataEnd() - * (meaning that the client is done sending data) or by 'httpOpen()' - * (if we are in the process of a PUT/POST request). It can also be - * called by a webDAV function, to receive stat/list/property/etc. - * data; in this case the data is stored in m_bufWebDavData. - */ -bool HTTPProtocol::readBody( bool dataInternal /* = false */ ) -{ - if (m_responseCode == 204) - return true; - - m_bEOD = false; - // Note that when dataInternal is true, we are going to: - // 1) save the body data to a member variable, m_bufWebDavData - // 2) _not_ advertise the data, speed, size, etc., through the - // corresponding functions. - // This is used for returning data to WebDAV. - m_dataInternal = dataInternal; - if ( dataInternal ) - m_bufWebDavData.resize (0); - - // Check if we need to decode the data. - // If we are in copy mode, then use only transfer decoding. - bool useMD5 = !m_sContentMD5.isEmpty(); - - // Deal with the size of the file. - TDEIO::filesize_t sz = m_request.offset; - if ( sz ) - m_iSize += sz; - - // Update the application with total size except when - // it is compressed, or when the data is to be handled - // internally (webDAV). If compressed we have to wait - // until we uncompress to find out the actual data size - if ( !dataInternal ) { - if ( (m_iSize > 0) && (m_iSize != NO_SIZE)) { - totalSize(m_iSize); - infoMessage( i18n( "Retrieving %1 from %2...").arg(TDEIO::convertSize(m_iSize)) - .arg( m_request.hostname ) ); - } - else - { - totalSize ( 0 ); - } - } - else - infoMessage( i18n( "Retrieving from %1..." ).arg( m_request.hostname ) ); - - if (m_request.bCachedRead) - { - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readBody: read data from cache!" << endl; - m_request.bCachedWrite = false; - - char buffer[ MAX_IPC_SIZE ]; - - m_iContentLeft = NO_SIZE; - - // Jippie! It's already in the cache :-) - while (!feof(m_request.fcache) && !ferror(m_request.fcache)) - { - int nbytes = fread( buffer, 1, MAX_IPC_SIZE, m_request.fcache); - - if (nbytes > 0) - { - m_bufReceive.setRawData( buffer, nbytes); - slotData( m_bufReceive ); - m_bufReceive.resetRawData( buffer, nbytes ); - sz += nbytes; - } - } - - m_bufReceive.resize( 0 ); - - if ( !dataInternal ) - { - processedSize( sz ); - data( TQByteArray() ); - } - - return true; - } - - - if (m_iSize != NO_SIZE) - m_iBytesLeft = m_iSize - sz; - else - m_iBytesLeft = NO_SIZE; - - m_iContentLeft = m_iBytesLeft; - - if (m_bChunked) - m_iBytesLeft = NO_SIZE; - - kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readBody: retrieve data. " - << TDEIO::number(m_iBytesLeft) << " left." << endl; - - // Main incoming loop... Gather everything while we can... - m_cpMimeBuffer = false; - m_mimeTypeBuffer.resize(0); - struct timeval last_tv; - gettimeofday( &last_tv, 0L ); - - HTTPFilterChain chain; - - TQObject::connect(&chain, TQT_SIGNAL(output(const TQByteArray &)), - this, TQT_SLOT(slotData(const TQByteArray &))); - TQObject::connect(&chain, TQT_SIGNAL(error(int, const TQString &)), - this, TQT_SLOT(error(int, const TQString &))); - - // decode all of the transfer encodings - while (!m_qTransferEncodings.isEmpty()) - { - TQString enc = m_qTransferEncodings.last(); - m_qTransferEncodings.remove(m_qTransferEncodings.fromLast()); - if ( enc == "gzip" ) - chain.addFilter(new HTTPFilterGZip); - else if ( enc == "deflate" ) - chain.addFilter(new HTTPFilterDeflate); - } - - // From HTTP 1.1 Draft 6: - // The MD5 digest is computed based on the content of the entity-body, - // including any content-coding that has been applied, but not including - // any transfer-encoding applied to the message-body. If the message is - // received with a transfer-encoding, that encoding MUST be removed - // prior to checking the Content-MD5 value against the received entity. - HTTPFilterMD5 *md5Filter = 0; - if ( useMD5 ) - { - md5Filter = new HTTPFilterMD5; - chain.addFilter(md5Filter); - } - - // now decode all of the content encodings - // -- Why ?? We are not - // -- a proxy server, be a client side implementation!! The applications - // -- are capable of determinig how to extract the encoded implementation. - // WB: That's a misunderstanding. We are free to remove the encoding. - // WB: Some braindead www-servers however, give .tgz files an encoding - // WB: of "gzip" (or even "x-gzip") and a content-type of "applications/tar" - // WB: They shouldn't do that. We can work around that though... - while (!m_qContentEncodings.isEmpty()) - { - TQString enc = m_qContentEncodings.last(); - m_qContentEncodings.remove(m_qContentEncodings.fromLast()); - if ( enc == "gzip" ) - chain.addFilter(new HTTPFilterGZip); - else if ( enc == "deflate" ) - chain.addFilter(new HTTPFilterDeflate); - } - - while (!m_bEOF) - { - int bytesReceived; - - if (m_bChunked) - bytesReceived = readChunked(); - else if (m_iSize != NO_SIZE) - bytesReceived = readLimited(); - else - bytesReceived = readUnlimited(); - - // make sure that this wasn't an error, first - // kdDebug(7113) << "(" << (int) m_pid << ") readBody: bytesReceived: " - // << (int) bytesReceived << " m_iSize: " << (int) m_iSize << " Chunked: " - // << (int) m_bChunked << " BytesLeft: "<< (int) m_iBytesLeft << endl; - if (bytesReceived == -1) - { - if (m_iContentLeft == 0) - { - // gzip'ed data sometimes reports a too long content-length. - // (The length of the unzipped data) - m_iBytesLeft = 0; - break; - } - // Oh well... log an error and bug out - kdDebug(7113) << "(" << m_pid << ") readBody: bytesReceived==-1 sz=" << (int)sz - << " Connnection broken !" << endl; - error(ERR_CONNECTION_BROKEN, m_state.hostname); - return false; - } - - // I guess that nbytes == 0 isn't an error.. but we certainly - // won't work with it! - if (bytesReceived > 0) - { - // Important: truncate the buffer to the actual size received! - // Otherwise garbage will be passed to the app - m_bufReceive.truncate( bytesReceived ); - - chain.slotInput(m_bufReceive); - - if (m_bError) - return false; - - sz += bytesReceived; - if (!dataInternal) - processedSize( sz ); - } - m_bufReceive.resize(0); // res - - if (m_iBytesLeft && m_bEOD && !m_bChunked) - { - // gzip'ed data sometimes reports a too long content-length. - // (The length of the unzipped data) - m_iBytesLeft = 0; - } - - if (m_iBytesLeft == 0) - { - kdDebug(7113) << "("<call( "kded", "kcookiejar", "findCookies(TQString,long int)", - params, replyType, reply ) ) - { - kdWarning(7113) << "(" << m_pid << ") Can't communicate with kded_kcookiejar!" << endl; - return result; - } - if ( replyType == "TQString" ) - { - TQDataStream stream2( reply, IO_ReadOnly ); - stream2 >> result; - } - else - { - kdError(7113) << "(" << m_pid << ") DCOP function findCookies(...) returns " - << replyType << ", expected TQString" << endl; - } - return result; -} - -/******************************* CACHING CODE ****************************/ - - -void HTTPProtocol::cacheUpdate( const KURL& url, bool no_cache, time_t expireDate) -{ - if ( !checkRequestURL( url ) ) - return; - - m_request.path = url.path(); - m_request.query = url.query(); - m_request.cache = CC_Reload; - m_request.doProxy = m_bUseProxy; - - if (no_cache) - { - m_request.fcache = checkCacheEntry( ); - if (m_request.fcache) - { - fclose(m_request.fcache); - m_request.fcache = 0; - ::unlink( TQFile::encodeName(m_request.cef) ); - } - } - else - { - updateExpireDate( expireDate ); - } - finished(); -} - -// !START SYNC! -// The following code should be kept in sync -// with the code in http_cache_cleaner.cpp - -FILE* HTTPProtocol::checkCacheEntry( bool readWrite) -{ - const TQChar separator = '_'; - - TQString CEF = m_request.path; - - int p = CEF.find('/'); - - while(p != -1) - { - CEF[p] = separator; - p = CEF.find('/', p); - } - - TQString host = m_request.hostname.lower(); - CEF = host + CEF + '_'; - - TQString dir = m_strCacheDir; - if (dir[dir.length()-1] != '/') - dir += "/"; - - int l = host.length(); - for(int i = 0; i < l; i++) - { - if (host[i].isLetter() && (host[i] != 'w')) - { - dir += host[i]; - break; - } - } - if (dir[dir.length()-1] == '/') - dir += "0"; - - unsigned long hash = 0x00000000; - TQCString u = m_request.url.url().latin1(); - for(int i = u.length(); i--;) - { - hash = (hash * 12211 + static_cast(u.at(i))) % 2147483563; - } - - TQString hashString; - hashString.sprintf("%08lx", hash); - - CEF = CEF + hashString; - - CEF = dir + "/" + CEF; - - m_request.cef = CEF; - - const char *mode = (readWrite ? "r+" : "r"); - - FILE *fs = fopen( TQFile::encodeName(CEF), mode); // Open for reading and writing - if (!fs) - return 0; - - char buffer[401]; - bool ok = true; - - // CacheRevision - if (ok && (!fgets(buffer, 400, fs))) - ok = false; - if (ok && (strcmp(buffer, CACHE_REVISION) != 0)) - ok = false; - - time_t date; - time_t currentDate = time(0); - - // URL - if (ok && (!fgets(buffer, 400, fs))) - ok = false; - if (ok) - { - int l = strlen(buffer); - if (l>0) - buffer[l-1] = 0; // Strip newline - if (m_request.url.url() != buffer) - { - ok = false; // Hash collision - } - } - - // Creation Date - if (ok && (!fgets(buffer, 400, fs))) - ok = false; - if (ok) - { - date = (time_t) strtoul(buffer, 0, 10); - m_request.creationDate = date; - if (m_maxCacheAge && (difftime(currentDate, date) > m_maxCacheAge)) - { - m_request.bMustRevalidate = true; - m_request.expireDate = currentDate; - } - } - - // Expiration Date - m_request.cacheExpireDateOffset = ftell(fs); - if (ok && (!fgets(buffer, 400, fs))) - ok = false; - if (ok) - { - if (m_request.cache == CC_Verify) - { - date = (time_t) strtoul(buffer, 0, 10); - // After the expire date we need to revalidate. - if (!date || difftime(currentDate, date) >= 0) - m_request.bMustRevalidate = true; - m_request.expireDate = date; - } - else if (m_request.cache == CC_Refresh) - { - m_request.bMustRevalidate = true; - m_request.expireDate = currentDate; - } - } - - // ETag - if (ok && (!fgets(buffer, 400, fs))) - ok = false; - if (ok) - { - m_request.etag = TQString(buffer).stripWhiteSpace(); - } - - // Last-Modified - if (ok && (!fgets(buffer, 400, fs))) - ok = false; - if (ok) - { - m_request.lastModified = TQString(buffer).stripWhiteSpace(); - } - - if (ok) - return fs; - - fclose(fs); - unlink( TQFile::encodeName(CEF)); - return 0; -} - -void HTTPProtocol::updateExpireDate(time_t expireDate, bool updateCreationDate) -{ - bool ok = true; - - FILE *fs = checkCacheEntry(true); - if (fs) - { - TQString date; - char buffer[401]; - time_t creationDate; - - fseek(fs, 0, SEEK_SET); - if (ok && !fgets(buffer, 400, fs)) - ok = false; - if (ok && !fgets(buffer, 400, fs)) - ok = false; - long cacheCreationDateOffset = ftell(fs); - if (ok && !fgets(buffer, 400, fs)) - ok = false; - creationDate = strtoul(buffer, 0, 10); - if (!creationDate) - ok = false; - - if (updateCreationDate) - { - if (!ok || fseek(fs, cacheCreationDateOffset, SEEK_SET)) - return; - TQString date; - date.setNum( time(0) ); - date = date.leftJustify(16); - fputs(date.latin1(), fs); // Creation date - fputc('\n', fs); - } - - if (expireDate>(30*365*24*60*60)) - { - // expire date is a really a big number, it can't be - // a relative date. - date.setNum( expireDate ); - } - else - { - // expireDate before 2000. those values must be - // interpreted as relative expiration dates from - // tags. - // so we have to scan the creation time and add - // it to the expiryDate - date.setNum( creationDate + expireDate ); - } - date = date.leftJustify(16); - if (!ok || fseek(fs, m_request.cacheExpireDateOffset, SEEK_SET)) - return; - fputs(date.latin1(), fs); // Expire date - fseek(fs, 0, SEEK_END); - fclose(fs); - } -} - -void HTTPProtocol::createCacheEntry( const TQString &mimetype, time_t expireDate) -{ - TQString dir = m_request.cef; - int p = dir.findRev('/'); - if (p == -1) return; // Error. - dir.truncate(p); - - // Create file - (void) ::mkdir( TQFile::encodeName(dir), 0700 ); - - TQString filename = m_request.cef + ".new"; // Create a new cache entryexpireDate - -// kdDebug( 7103 ) << "creating new cache entry: " << filename << endl; - - m_request.fcache = fopen( TQFile::encodeName(filename), "w"); - if (!m_request.fcache) - { - kdWarning(7113) << "(" << m_pid << ")createCacheEntry: opening " << filename << " failed." << endl; - return; // Error. - } - - fputs(CACHE_REVISION, m_request.fcache); // Revision - - fputs(m_request.url.url().latin1(), m_request.fcache); // Url - fputc('\n', m_request.fcache); - - TQString date; - m_request.creationDate = time(0); - date.setNum( m_request.creationDate ); - date = date.leftJustify(16); - fputs(date.latin1(), m_request.fcache); // Creation date - fputc('\n', m_request.fcache); - - date.setNum( expireDate ); - date = date.leftJustify(16); - fputs(date.latin1(), m_request.fcache); // Expire date - fputc('\n', m_request.fcache); - - if (!m_request.etag.isEmpty()) - fputs(m_request.etag.latin1(), m_request.fcache); //ETag - fputc('\n', m_request.fcache); - - if (!m_request.lastModified.isEmpty()) - fputs(m_request.lastModified.latin1(), m_request.fcache); // Last modified - fputc('\n', m_request.fcache); - - fputs(mimetype.latin1(), m_request.fcache); // Mimetype - fputc('\n', m_request.fcache); - - if (!m_request.strCharset.isEmpty()) - fputs(m_request.strCharset.latin1(), m_request.fcache); // Charset - fputc('\n', m_request.fcache); - - return; -} -// The above code should be kept in sync -// with the code in http_cache_cleaner.cpp -// !END SYNC! - -void HTTPProtocol::writeCacheEntry( const char *buffer, int nbytes) -{ - if (fwrite( buffer, nbytes, 1, m_request.fcache) != 1) - { - kdWarning(7113) << "(" << m_pid << ") writeCacheEntry: writing " << nbytes << " bytes failed." << endl; - fclose(m_request.fcache); - m_request.fcache = 0; - TQString filename = m_request.cef + ".new"; - ::unlink( TQFile::encodeName(filename) ); - return; - } - long file_pos = ftell( m_request.fcache ) / 1024; - if ( file_pos > m_maxCacheSize ) - { - kdDebug(7113) << "writeCacheEntry: File size reaches " << file_pos - << "Kb, exceeds cache limits. (" << m_maxCacheSize << "Kb)" << endl; - fclose(m_request.fcache); - m_request.fcache = 0; - TQString filename = m_request.cef + ".new"; - ::unlink( TQFile::encodeName(filename) ); - return; - } -} - -void HTTPProtocol::closeCacheEntry() -{ - TQString filename = m_request.cef + ".new"; - int result = fclose( m_request.fcache); - m_request.fcache = 0; - if (result == 0) - { - if (::rename( TQFile::encodeName(filename), TQFile::encodeName(m_request.cef)) == 0) - return; // Success - - kdWarning(7113) << "(" << m_pid << ") closeCacheEntry: error renaming " - << "cache entry. (" << filename << " -> " << m_request.cef - << ")" << endl; - } - - kdWarning(7113) << "(" << m_pid << ") closeCacheEntry: error closing cache " - << "entry. (" << filename<< ")" << endl; -} - -void HTTPProtocol::cleanCache() -{ - const time_t maxAge = DEFAULT_CLEAN_CACHE_INTERVAL; // 30 Minutes. - bool doClean = false; - TQString cleanFile = m_strCacheDir; - if (cleanFile[cleanFile.length()-1] != '/') - cleanFile += "/"; - cleanFile += "cleaned"; - - struct stat stat_buf; - - int result = ::stat(TQFile::encodeName(cleanFile), &stat_buf); - if (result == -1) - { - int fd = creat( TQFile::encodeName(cleanFile), 0600); - if (fd != -1) - { - doClean = true; - ::close(fd); - } - } - else - { - time_t age = (time_t) difftime( time(0), stat_buf.st_mtime ); - if (age > maxAge) // - doClean = true; - } - if (doClean) - { - // Touch file. - utime(TQFile::encodeName(cleanFile), 0); - TDEApplication::startServiceByDesktopPath("http_cache_cleaner.desktop"); - } -} - - - -//************************** AUTHENTICATION CODE ********************/ - - -void HTTPProtocol::configAuth( char *p, bool isForProxy ) -{ - HTTP_AUTH f = AUTH_None; - const char *strAuth = p; - - if ( strncasecmp( p, "Basic", 5 ) == 0 ) - { - f = AUTH_Basic; - p += 5; - strAuth = "Basic"; // Correct for upper-case variations. - } - else if ( strncasecmp (p, "Digest", 6) == 0 ) - { - f = AUTH_Digest; - memcpy((void *)p, "Digest", 6); // Correct for upper-case variations. - p += 6; - } - else if (strncasecmp( p, "MBS_PWD_COOKIE", 14 ) == 0) - { - // Found on http://www.webscription.net/baen/default.asp - f = AUTH_Basic; - p += 14; - strAuth = "Basic"; - } -#ifdef HAVE_LIBGSSAPI - else if ( strncasecmp( p, "Negotiate", 9 ) == 0 ) - { - // if we get two 401 in a row let's assume for now that - // Negotiate isn't working and ignore it - if ( !isForProxy && !(m_responseCode == 401 && m_prevResponseCode == 401) ) - { - f = AUTH_Negotiate; - memcpy((void *)p, "Negotiate", 9); // Correct for upper-case variations. - p += 9; - }; - } -#endif - else if ( strncasecmp( p, "NTLM", 4 ) == 0 ) - { - f = AUTH_NTLM; - memcpy((void *)p, "NTLM", 4); // Correct for upper-case variations. - p += 4; - m_strRealm = "NTLM"; // set a dummy realm - } - else - { - kdWarning(7113) << "(" << m_pid << ") Unsupported or invalid authorization " - << "type requested" << endl; - if (isForProxy) - kdWarning(7113) << "(" << m_pid << ") Proxy URL: " << m_proxyURL << endl; - else - kdWarning(7113) << "(" << m_pid << ") URL: " << m_request.url << endl; - kdWarning(7113) << "(" << m_pid << ") Request Authorization: " << p << endl; - } - - /* - This check ensures the following: - 1.) Rejection of any unknown/unsupported authentication schemes - 2.) Usage of the strongest possible authentication schemes if - and when multiple Proxy-Authenticate or WWW-Authenticate - header field is sent. - */ - if (isForProxy) - { - if ((f == AUTH_None) || - ((m_iProxyAuthCount > 0) && (f < ProxyAuthentication))) - { - // Since I purposefully made the Proxy-Authentication settings - // persistent to reduce the number of round-trips to tdesud we - // have to take special care when an unknown/unsupported auth- - // scheme is received. This check accomplishes just that... - if ( m_iProxyAuthCount == 0) - ProxyAuthentication = f; - kdDebug(7113) << "(" << m_pid << ") Rejected proxy auth method: " << f << endl; - return; - } - m_iProxyAuthCount++; - kdDebug(7113) << "(" << m_pid << ") Accepted proxy auth method: " << f << endl; - } - else - { - if ((f == AUTH_None) || - ((m_iWWWAuthCount > 0) && (f < Authentication))) - { - kdDebug(7113) << "(" << m_pid << ") Rejected auth method: " << f << endl; - return; - } - m_iWWWAuthCount++; - kdDebug(7113) << "(" << m_pid << ") Accepted auth method: " << f << endl; - } - - - while (*p) - { - int i = 0; - while( (*p == ' ') || (*p == ',') || (*p == '\t') ) { p++; } - if ( strncasecmp( p, "realm=", 6 ) == 0 ) - { - //for sites like lib.homelinux.org - TQTextCodec* oldCodec=TQTextCodec::codecForCStrings(); - if (TDEGlobal::locale()->language().contains("ru")) - TQTextCodec::setCodecForCStrings(TQTextCodec::codecForName("CP1251")); - - p += 6; - if (*p == '"') p++; - while( p[i] && p[i] != '"' ) i++; - if( isForProxy ) - m_strProxyRealm = TQString::fromAscii( p, i ); - else - m_strRealm = TQString::fromAscii( p, i ); - - TQTextCodec::setCodecForCStrings(oldCodec); - - if (!p[i]) break; - } - p+=(i+1); - } - - if( isForProxy ) - { - ProxyAuthentication = f; - m_strProxyAuthorization = TQString::fromLatin1( strAuth ); - } - else - { - Authentication = f; - m_strAuthorization = TQString::fromLatin1( strAuth ); - } -} - - -bool HTTPProtocol::retryPrompt() -{ - TQString prompt; - switch ( m_responseCode ) - { - case 401: - prompt = i18n("Authentication Failed."); - break; - case 407: - prompt = i18n("Proxy Authentication Failed."); - break; - default: - break; - } - prompt += i18n(" Do you want to retry?"); - return (messageBox(QuestionYesNo, prompt, i18n("Authentication")) == 3); -} - -void HTTPProtocol::promptInfo( AuthInfo& info ) -{ - if ( m_responseCode == 401 ) - { - info.url = m_request.url; - if ( !m_state.user.isEmpty() ) - info.username = m_state.user; - info.readOnly = !m_request.url.user().isEmpty(); - info.prompt = i18n( "You need to supply a username and a " - "password to access this site." ); - info.keepPassword = true; // Prompt the user for persistence as well. - if ( !m_strRealm.isEmpty() ) - { - info.realmValue = m_strRealm; - info.verifyPath = false; - info.digestInfo = m_strAuthorization; - info.commentLabel = i18n( "Site:" ); - info.comment = i18n("%1 at %2").arg( htmlEscape(m_strRealm) ).arg( m_request.hostname ); - } - } - else if ( m_responseCode == 407 ) - { - info.url = m_proxyURL; - info.username = m_proxyURL.user(); - info.prompt = i18n( "You need to supply a username and a password for " - "the proxy server listed below before you are allowed " - "to access any sites." ); - info.keepPassword = true; - if ( !m_strProxyRealm.isEmpty() ) - { - info.realmValue = m_strProxyRealm; - info.verifyPath = false; - info.digestInfo = m_strProxyAuthorization; - info.commentLabel = i18n( "Proxy:" ); - info.comment = i18n("%1 at %2").arg( htmlEscape(m_strProxyRealm) ).arg( m_proxyURL.host() ); - } - } -} - -bool HTTPProtocol::getAuthorization() -{ - AuthInfo info; - bool result = false; - - kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::getAuthorization: " - << "Current Response: " << m_responseCode << ", " - << "Previous Response: " << m_prevResponseCode << ", " - << "Authentication: " << Authentication << ", " - << "ProxyAuthentication: " << ProxyAuthentication << endl; - - if (m_request.bNoAuth) - { - if (m_request.bErrorPage) - errorPage(); - else - error( ERR_COULD_NOT_LOGIN, i18n("Authentication needed for %1 but authentication is disabled.").arg(m_request.hostname)); - return false; - } - - bool repeatFailure = (m_prevResponseCode == m_responseCode); - - TQString errorMsg; - - if (repeatFailure) - { - bool prompt = true; - if ( Authentication == AUTH_Digest || ProxyAuthentication == AUTH_Digest ) - { - bool isStaleNonce = false; - TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization; - int pos = auth.find("stale", 0, false); - if ( pos != -1 ) - { - pos += 5; - int len = auth.length(); - while( pos < len && (auth[pos] == ' ' || auth[pos] == '=') ) pos++; - if ( pos < len && auth.find("true", pos, false) != -1 ) - { - isStaleNonce = true; - kdDebug(7113) << "(" << m_pid << ") Stale nonce value. " - << "Will retry using same info..." << endl; - } - } - if ( isStaleNonce ) - { - prompt = false; - result = true; - if ( m_responseCode == 401 ) - { - info.username = m_request.user; - info.password = m_request.passwd; - info.realmValue = m_strRealm; - info.digestInfo = m_strAuthorization; - } - else if ( m_responseCode == 407 ) - { - info.username = m_proxyURL.user(); - info.password = m_proxyURL.pass(); - info.realmValue = m_strProxyRealm; - info.digestInfo = m_strProxyAuthorization; - } - } - } - - if ( Authentication == AUTH_NTLM || ProxyAuthentication == AUTH_NTLM ) - { - TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization; - kdDebug(7113) << "auth: " << auth << endl; - if ( auth.length() > 4 ) - { - prompt = false; - result = true; - kdDebug(7113) << "(" << m_pid << ") NTLM auth second phase, " - << "sending response..." << endl; - if ( m_responseCode == 401 ) - { - info.username = m_request.user; - info.password = m_request.passwd; - info.realmValue = m_strRealm; - info.digestInfo = m_strAuthorization; - } - else if ( m_responseCode == 407 ) - { - info.username = m_proxyURL.user(); - info.password = m_proxyURL.pass(); - info.realmValue = m_strProxyRealm; - info.digestInfo = m_strProxyAuthorization; - } - } - } - - if ( prompt ) - { - switch ( m_responseCode ) - { - case 401: - errorMsg = i18n("Authentication Failed."); - break; - case 407: - errorMsg = i18n("Proxy Authentication Failed."); - break; - default: - break; - } - } - } - else - { - // At this point we know more details, so use it to find - // out if we have a cached version and avoid a re-prompt! - // We also do not use verify path unlike the pre-emptive - // requests because we already know the realm value... - - if (m_bProxyAuthValid) - { - // Reset cached proxy auth - m_bProxyAuthValid = false; - KURL proxy ( config()->readEntry("UseProxy") ); - m_proxyURL.setUser(proxy.user()); - m_proxyURL.setPass(proxy.pass()); - } - - info.verifyPath = false; - if ( m_responseCode == 407 ) - { - info.url = m_proxyURL; - info.username = m_proxyURL.user(); - info.password = m_proxyURL.pass(); - info.realmValue = m_strProxyRealm; - info.digestInfo = m_strProxyAuthorization; - } - else - { - info.url = m_request.url; - info.username = m_request.user; - info.password = m_request.passwd; - info.realmValue = m_strRealm; - info.digestInfo = m_strAuthorization; - } - - // If either username or password is not supplied - // with the request, check the password cache. - if ( info.username.isNull() || - info.password.isNull() ) - result = checkCachedAuthentication( info ); - - if ( Authentication == AUTH_Digest ) - { - TQString auth; - - if (m_responseCode == 401) - auth = m_strAuthorization; - else - auth = m_strProxyAuthorization; - - int pos = auth.find("stale", 0, false); - if ( pos != -1 ) - { - pos += 5; - int len = auth.length(); - while( pos < len && (auth[pos] == ' ' || auth[pos] == '=') ) pos++; - if ( pos < len && auth.find("true", pos, false) != -1 ) - { - info.digestInfo = (m_responseCode == 401) ? m_strAuthorization : m_strProxyAuthorization; - kdDebug(7113) << "(" << m_pid << ") Just a stale nonce value! " - << "Retrying using the new nonce sent..." << endl; - } - } - } - } - - if (!result ) - { - // Do not prompt if the username & password - // is already supplied and the login attempt - // did not fail before. - if ( !repeatFailure && - !info.username.isNull() && - !info.password.isNull() ) - result = true; - else - { - if (Authentication == AUTH_Negotiate) - { - if (!repeatFailure) - result = true; - } - else if ( m_request.disablePassDlg == false ) - { - kdDebug( 7113 ) << "(" << m_pid << ") Prompting the user for authorization..." << endl; - promptInfo( info ); - result = openPassDlg( info, errorMsg ); - } - } - } - - if ( result ) - { - switch (m_responseCode) - { - case 401: // Request-Authentication - m_request.user = info.username; - m_request.passwd = info.password; - m_strRealm = info.realmValue; - m_strAuthorization = info.digestInfo; - break; - case 407: // Proxy-Authentication - m_proxyURL.setUser( info.username ); - m_proxyURL.setPass( info.password ); - m_strProxyRealm = info.realmValue; - m_strProxyAuthorization = info.digestInfo; - break; - default: - break; - } - return true; - } - - if (m_request.bErrorPage) - errorPage(); - else - error( ERR_USER_CANCELED, TQString::null ); - return false; -} - -void HTTPProtocol::saveAuthorization() -{ - AuthInfo info; - if ( m_prevResponseCode == 407 ) - { - if (!m_bUseProxy) - return; - m_bProxyAuthValid = true; - info.url = m_proxyURL; - info.username = m_proxyURL.user(); - info.password = m_proxyURL.pass(); - info.realmValue = m_strProxyRealm; - info.digestInfo = m_strProxyAuthorization; - cacheAuthentication( info ); - } - else - { - info.url = m_request.url; - info.username = m_request.user; - info.password = m_request.passwd; - info.realmValue = m_strRealm; - info.digestInfo = m_strAuthorization; - cacheAuthentication( info ); - } -} - -#ifdef HAVE_LIBGSSAPI -TQCString HTTPProtocol::gssError( int major_status, int minor_status ) -{ - OM_uint32 new_status; - OM_uint32 msg_ctx = 0; - gss_buffer_desc major_string; - gss_buffer_desc minor_string; - OM_uint32 ret; - TQCString errorstr; - - errorstr = ""; - - do { - ret = gss_display_status(&new_status, major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &major_string); - errorstr += (const char *)major_string.value; - errorstr += " "; - ret = gss_display_status(&new_status, minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &minor_string); - errorstr += (const char *)minor_string.value; - errorstr += " "; - } while (!GSS_ERROR(ret) && msg_ctx != 0); - - return errorstr; -} - -TQString HTTPProtocol::createNegotiateAuth() -{ - TQString auth; - TQCString servicename; - TQByteArray input; - OM_uint32 major_status, minor_status; - OM_uint32 req_flags = 0; - gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - gss_name_t server; - gss_ctx_id_t ctx; - gss_OID mech_oid; - static gss_OID_desc krb5_oid_desc = {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; - static gss_OID_desc spnego_oid_desc = {6, (void *) "\x2b\x06\x01\x05\x05\x02"}; - int found = 0; - unsigned int i; - gss_OID_set mech_set; - gss_OID tmp_oid; - - ctx = GSS_C_NO_CONTEXT; - mech_oid = &krb5_oid_desc; - - // see whether we can use the SPNEGO mechanism - major_status = gss_indicate_mechs(&minor_status, &mech_set); - if (GSS_ERROR(major_status)) { - kdDebug(7113) << "(" << m_pid << ") gss_indicate_mechs failed: " << gssError(major_status, minor_status) << endl; - } else { - for (i=0; icount && !found; i++) { - tmp_oid = &mech_set->elements[i]; - if (tmp_oid->length == spnego_oid_desc.length && - !memcmp(tmp_oid->elements, spnego_oid_desc.elements, tmp_oid->length)) { - kdDebug(7113) << "(" << m_pid << ") createNegotiateAuth: found SPNEGO mech" << endl; - found = 1; - mech_oid = &spnego_oid_desc; - break; - } - } - gss_release_oid_set(&minor_status, &mech_set); - } - - // the service name is "HTTP/f.q.d.n" - servicename = "HTTP@"; - servicename += m_state.hostname.ascii(); - - input_token.value = (void *)servicename.data(); - input_token.length = servicename.length() + 1; - - major_status = gss_import_name(&minor_status, &input_token, - GSS_C_NT_HOSTBASED_SERVICE, &server); - - input_token.value = NULL; - input_token.length = 0; - - if (GSS_ERROR(major_status)) { - kdDebug(7113) << "(" << m_pid << ") gss_import_name failed: " << gssError(major_status, minor_status) << endl; - // reset the auth string so that subsequent methods aren't confused - m_strAuthorization = TQString::null; - return TQString::null; - } - - major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, - &ctx, server, mech_oid, - req_flags, GSS_C_INDEFINITE, - GSS_C_NO_CHANNEL_BINDINGS, - GSS_C_NO_BUFFER, NULL, &output_token, - NULL, NULL); - - - if (GSS_ERROR(major_status) || (output_token.length == 0)) { - kdDebug(7113) << "(" << m_pid << ") gss_init_sec_context failed: " << gssError(major_status, minor_status) << endl; - gss_release_name(&minor_status, &server); - if (ctx != GSS_C_NO_CONTEXT) { - gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER); - ctx = GSS_C_NO_CONTEXT; - } - // reset the auth string so that subsequent methods aren't confused - m_strAuthorization = TQString::null; - return TQString::null; - } - - input.duplicate((const char *)output_token.value, output_token.length); - auth = "Authorization: Negotiate "; - auth += KCodecs::base64Encode( input ); - auth += "\r\n"; - - // free everything - gss_release_name(&minor_status, &server); - if (ctx != GSS_C_NO_CONTEXT) { - gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER); - ctx = GSS_C_NO_CONTEXT; - } - gss_release_buffer(&minor_status, &output_token); - - return auth; -} -#else - -// Dummy -TQCString HTTPProtocol::gssError( int, int ) -{ - return ""; -} - -// Dummy -TQString HTTPProtocol::createNegotiateAuth() -{ - return TQString::null; -} -#endif - -TQString HTTPProtocol::createNTLMAuth( bool isForProxy ) -{ - uint len; - TQString auth, user, domain, passwd; - TQCString strauth; - TQByteArray buf; - - if ( isForProxy ) - { - auth = "Proxy-Connection: Keep-Alive\r\n"; - auth += "Proxy-Authorization: NTLM "; - user = m_proxyURL.user(); - passwd = m_proxyURL.pass(); - strauth = m_strProxyAuthorization.latin1(); - len = m_strProxyAuthorization.length(); - } - else - { - auth = "Authorization: NTLM "; - user = m_state.user; - passwd = m_state.passwd; - strauth = m_strAuthorization.latin1(); - len = m_strAuthorization.length(); - } - if ( user.contains('\\') ) { - domain = user.section( '\\', 0, 0); - user = user.section( '\\', 1 ); - } - - kdDebug(7113) << "(" << m_pid << ") NTLM length: " << len << endl; - if ( user.isEmpty() || passwd.isEmpty() || len < 4 ) - return TQString::null; - - if ( len > 4 ) - { - // create a response - TQByteArray challenge; - KCodecs::base64Decode( strauth.right( len - 5 ), challenge ); - KNTLM::getAuth( buf, challenge, user, passwd, domain, - KNetwork::KResolver::localHostName(), false, false ); - } - else - { - KNTLM::getNegotiate( buf ); - } - - // remove the challenge to prevent reuse - if ( isForProxy ) - m_strProxyAuthorization = "NTLM"; - else - m_strAuthorization = "NTLM"; - - auth += KCodecs::base64Encode( buf ); - auth += "\r\n"; - - return auth; -} - -TQString HTTPProtocol::createBasicAuth( bool isForProxy ) -{ - TQString auth; - TQCString user, passwd; - if ( isForProxy ) - { - auth = "Proxy-Authorization: Basic "; - user = m_proxyURL.user().latin1(); - passwd = m_proxyURL.pass().latin1(); - } - else - { - auth = "Authorization: Basic "; - user = m_state.user.latin1(); - passwd = m_state.passwd.latin1(); - } - - if ( user.isEmpty() ) - user = ""; - if ( passwd.isEmpty() ) - passwd = ""; - - user += ':'; - user += passwd; - auth += KCodecs::base64Encode( user ); - auth += "\r\n"; - - return auth; -} - -void HTTPProtocol::calculateResponse( DigestAuthInfo& info, TQCString& Response ) -{ - KMD5 md; - TQCString HA1; - TQCString HA2; - - // Calculate H(A1) - TQCString authStr = info.username; - authStr += ':'; - authStr += info.realm; - authStr += ':'; - authStr += info.password; - md.update( authStr ); - - if ( info.algorithm.lower() == "md5-sess" ) - { - authStr = md.hexDigest(); - authStr += ':'; - authStr += info.nonce; - authStr += ':'; - authStr += info.cnonce; - md.reset(); - md.update( authStr ); - } - HA1 = md.hexDigest(); - - kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A1 => " << HA1 << endl; - - // Calcualte H(A2) - authStr = info.method; - authStr += ':'; - authStr += m_request.url.encodedPathAndQuery(0, true).latin1(); - if ( info.qop == "auth-int" ) - { - authStr += ':'; - authStr += info.entityBody; - } - md.reset(); - md.update( authStr ); - HA2 = md.hexDigest(); - - kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A2 => " - << HA2 << endl; - - // Calcualte the response. - authStr = HA1; - authStr += ':'; - authStr += info.nonce; - authStr += ':'; - if ( !info.qop.isEmpty() ) - { - authStr += info.nc; - authStr += ':'; - authStr += info.cnonce; - authStr += ':'; - authStr += info.qop; - authStr += ':'; - } - authStr += HA2; - md.reset(); - md.update( authStr ); - Response = md.hexDigest(); - - kdDebug(7113) << "(" << m_pid << ") calculateResponse(): Response => " - << Response << endl; -} - -TQString HTTPProtocol::createDigestAuth ( bool isForProxy ) -{ - const char *p; - - TQString auth; - TQCString opaque; - TQCString Response; - - DigestAuthInfo info; - - opaque = ""; - if ( isForProxy ) - { - auth = "Proxy-Authorization: Digest "; - info.username = m_proxyURL.user().latin1(); - info.password = m_proxyURL.pass().latin1(); - p = m_strProxyAuthorization.latin1(); - } - else - { - auth = "Authorization: Digest "; - info.username = m_state.user.latin1(); - info.password = m_state.passwd.latin1(); - p = m_strAuthorization.latin1(); - } - if (!p || !*p) - return TQString::null; - - p += 6; // Skip "Digest" - - if ( info.username.isEmpty() || info.password.isEmpty() || !p ) - return TQString::null; - - // info.entityBody = p; // FIXME: send digest of data for POST action ?? - info.realm = ""; - info.algorithm = "MD5"; - info.nonce = ""; - info.qop = ""; - - // cnonce is recommended to contain about 64 bits of entropy - info.cnonce = TDEApplication::randomString(16).latin1(); - - // HACK: Should be fixed according to RFC 2617 section 3.2.2 - info.nc = "00000001"; - - // Set the method used... - switch ( m_request.method ) - { - case HTTP_GET: - info.method = "GET"; - break; - case HTTP_PUT: - info.method = "PUT"; - break; - case HTTP_POST: - info.method = "POST"; - break; - case HTTP_HEAD: - info.method = "HEAD"; - break; - case HTTP_DELETE: - info.method = "DELETE"; - break; - case DAV_PROPFIND: - info.method = "PROPFIND"; - break; - case DAV_PROPPATCH: - info.method = "PROPPATCH"; - break; - case DAV_MKCOL: - info.method = "MKCOL"; - break; - case DAV_COPY: - info.method = "COPY"; - break; - case DAV_MOVE: - info.method = "MOVE"; - break; - case DAV_LOCK: - info.method = "LOCK"; - break; - case DAV_UNLOCK: - info.method = "UNLOCK"; - break; - case DAV_SEARCH: - info.method = "SEARCH"; - break; - case DAV_SUBSCRIBE: - info.method = "SUBSCRIBE"; - break; - case DAV_UNSUBSCRIBE: - info.method = "UNSUBSCRIBE"; - break; - case DAV_POLL: - info.method = "POLL"; - break; - default: - error( ERR_UNSUPPORTED_ACTION, i18n("Unsupported method: authentication will fail. Please submit a bug report.")); - break; - } - - // Parse the Digest response.... - while (*p) - { - int i = 0; - while ( (*p == ' ') || (*p == ',') || (*p == '\t')) { p++; } - if (strncasecmp(p, "realm=", 6 )==0) - { - p+=6; - while ( *p == '"' ) p++; // Go past any number of " mark(s) first - while ( p[i] != '"' ) i++; // Read everything until the last " mark - info.realm = TQCString( p, i+1 ); - } - else if (strncasecmp(p, "algorith=", 9)==0) - { - p+=9; - while ( *p == '"' ) p++; // Go past any number of " mark(s) first - while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++; - info.algorithm = TQCString(p, i+1); - } - else if (strncasecmp(p, "algorithm=", 10)==0) - { - p+=10; - while ( *p == '"' ) p++; // Go past any " mark(s) first - while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++; - info.algorithm = TQCString(p,i+1); - } - else if (strncasecmp(p, "domain=", 7)==0) - { - p+=7; - while ( *p == '"' ) p++; // Go past any " mark(s) first - while ( p[i] != '"' ) i++; // Read everything until the last " mark - int pos; - int idx = 0; - TQCString uri = TQCString(p,i+1); - do - { - pos = uri.find( ' ', idx ); - if ( pos != -1 ) - { - KURL u (m_request.url, uri.mid(idx, pos-idx)); - if (u.isValid ()) - info.digestURI.append( u.url().latin1() ); - } - else - { - KURL u (m_request.url, uri.mid(idx, uri.length()-idx)); - if (u.isValid ()) - info.digestURI.append( u.url().latin1() ); - } - idx = pos+1; - } while ( pos != -1 ); - } - else if (strncasecmp(p, "nonce=", 6)==0) - { - p+=6; - while ( *p == '"' ) p++; // Go past any " mark(s) first - while ( p[i] != '"' ) i++; // Read everything until the last " mark - info.nonce = TQCString(p,i+1); - } - else if (strncasecmp(p, "opaque=", 7)==0) - { - p+=7; - while ( *p == '"' ) p++; // Go past any " mark(s) first - while ( p[i] != '"' ) i++; // Read everything until the last " mark - opaque = TQCString(p,i+1); - } - else if (strncasecmp(p, "qop=", 4)==0) - { - p+=4; - while ( *p == '"' ) p++; // Go past any " mark(s) first - while ( p[i] != '"' ) i++; // Read everything until the last " mark - info.qop = TQCString(p,i+1); - } - p+=(i+1); - } - - if (info.realm.isEmpty() || info.nonce.isEmpty()) - return TQString::null; - - // If the "domain" attribute was not specified and the current response code - // is authentication needed, add the current request url to the list over which - // this credential can be automatically applied. - if (info.digestURI.isEmpty() && (m_responseCode == 401 || m_responseCode == 407)) - info.digestURI.append (m_request.url.url().latin1()); - else - { - // Verify whether or not we should send a cached credential to the - // server based on the stored "domain" attribute... - bool send = true; - - // Determine the path of the request url... - TQString requestPath = m_request.url.directory(false, false); - if (requestPath.isEmpty()) - requestPath = "/"; - - int count = info.digestURI.count(); - - for (int i = 0; i < count; i++ ) - { - KURL u ( info.digestURI.at(i) ); - - send &= (m_request.url.protocol().lower() == u.protocol().lower()); - send &= (m_request.hostname.lower() == u.host().lower()); - - if (m_request.port > 0 && u.port() > 0) - send &= (m_request.port == u.port()); - - TQString digestPath = u.directory (false, false); - if (digestPath.isEmpty()) - digestPath = "/"; - - send &= (requestPath.startsWith(digestPath)); - - if (send) - break; - } - - kdDebug(7113) << "(" << m_pid << ") createDigestAuth(): passed digest " - "authentication credential test: " << send << endl; - - if (!send) - return TQString::null; - } - - kdDebug(7113) << "(" << m_pid << ") RESULT OF PARSING:" << endl; - kdDebug(7113) << "(" << m_pid << ") algorithm: " << info.algorithm << endl; - kdDebug(7113) << "(" << m_pid << ") realm: " << info.realm << endl; - kdDebug(7113) << "(" << m_pid << ") nonce: " << info.nonce << endl; - kdDebug(7113) << "(" << m_pid << ") opaque: " << opaque << endl; - kdDebug(7113) << "(" << m_pid << ") qop: " << info.qop << endl; - - // Calculate the response... - calculateResponse( info, Response ); - - auth += "username=\""; - auth += info.username; - - auth += "\", realm=\""; - auth += info.realm; - auth += "\""; - - auth += ", nonce=\""; - auth += info.nonce; - - auth += "\", uri=\""; - auth += m_request.url.encodedPathAndQuery(0, true); - - auth += "\", algorithm=\""; - auth += info.algorithm; - auth +="\""; - - if ( !info.qop.isEmpty() ) - { - auth += ", qop=\""; - auth += info.qop; - auth += "\", cnonce=\""; - auth += info.cnonce; - auth += "\", nc="; - auth += info.nc; - } - - auth += ", response=\""; - auth += Response; - if ( !opaque.isEmpty() ) - { - auth += "\", opaque=\""; - auth += opaque; - } - auth += "\"\r\n"; - - return auth; -} - -TQString HTTPProtocol::proxyAuthenticationHeader() -{ - TQString header; - - // We keep proxy authentication locally until they are changed. - // Thus, no need to check with the password manager for every - // connection. - if ( m_strProxyRealm.isEmpty() ) - { - AuthInfo info; - info.url = m_proxyURL; - info.username = m_proxyURL.user(); - info.password = m_proxyURL.pass(); - info.verifyPath = true; - - // If the proxy URL already contains username - // and password simply attempt to retrieve it - // without prompting the user... - if ( !info.username.isNull() && !info.password.isNull() ) - { - if( m_strProxyAuthorization.isEmpty() ) - ProxyAuthentication = AUTH_None; - else if( m_strProxyAuthorization.startsWith("Basic") ) - ProxyAuthentication = AUTH_Basic; - else if( m_strProxyAuthorization.startsWith("NTLM") ) - ProxyAuthentication = AUTH_NTLM; - else - ProxyAuthentication = AUTH_Digest; - } - else - { - if ( checkCachedAuthentication(info) && !info.digestInfo.isEmpty() ) - { - m_proxyURL.setUser( info.username ); - m_proxyURL.setPass( info.password ); - m_strProxyRealm = info.realmValue; - m_strProxyAuthorization = info.digestInfo; - if( m_strProxyAuthorization.startsWith("Basic") ) - ProxyAuthentication = AUTH_Basic; - else if( m_strProxyAuthorization.startsWith("NTLM") ) - ProxyAuthentication = AUTH_NTLM; - else - ProxyAuthentication = AUTH_Digest; - } - else - { - ProxyAuthentication = AUTH_None; - } - } - } - - /********* Only for debugging purpose... *********/ - if ( ProxyAuthentication != AUTH_None ) - { - kdDebug(7113) << "(" << m_pid << ") Using Proxy Authentication: " << endl; - kdDebug(7113) << "(" << m_pid << ") HOST= " << m_proxyURL.host() << endl; - kdDebug(7113) << "(" << m_pid << ") PORT= " << m_proxyURL.port() << endl; - kdDebug(7113) << "(" << m_pid << ") USER= " << m_proxyURL.user() << endl; - kdDebug(7113) << "(" << m_pid << ") PASSWORD= [protected]" << endl; - kdDebug(7113) << "(" << m_pid << ") REALM= " << m_strProxyRealm << endl; - kdDebug(7113) << "(" << m_pid << ") EXTRA= " << m_strProxyAuthorization << endl; - } - - switch ( ProxyAuthentication ) - { - case AUTH_Basic: - header += createBasicAuth( true ); - break; - case AUTH_Digest: - header += createDigestAuth( true ); - break; - case AUTH_NTLM: - if ( m_bFirstRequest ) header += createNTLMAuth( true ); - break; - case AUTH_None: - default: - break; - } - - return header; -} - -#include "http.moc" diff --git a/tdeioslave/http/http.cpp b/tdeioslave/http/http.cpp new file mode 100644 index 000000000..8cd0f7a64 --- /dev/null +++ b/tdeioslave/http/http.cpp @@ -0,0 +1,6131 @@ +/* + Copyright (C) 2000-2003 Waldo Bastian + Copyright (C) 2000-2002 George Staikos + Copyright (C) 2000-2002 Dawit Alemayehu + Copyright (C) 2001,2002 Hamish Rodda + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include // Required for AIX +#include +#include // must be explicitly included for MacOSX + +/* +#include +#include +#include +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tdeio/ioslave_defaults.h" +#include "tdeio/http_slave_defaults.h" + +#include "httpfilter.h" +#include "http.h" + +#ifdef HAVE_LIBGSSAPI +#ifdef GSSAPI_MIT +#include +#else +#include +#endif /* GSSAPI_MIT */ + +// Catch uncompatible crap (BR86019) +#if defined(GSS_RFC_COMPLIANT_OIDS) && (GSS_RFC_COMPLIANT_OIDS == 0) +#include +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#endif + +#endif /* HAVE_LIBGSSAPI */ + +#include + +using namespace TDEIO; + +extern "C" { + KDE_EXPORT int kdemain(int argc, char **argv); +} + +int kdemain( int argc, char **argv ) +{ + TDELocale::setMainCatalogue("tdelibs"); + TDEInstance instance( "tdeio_http" ); + ( void ) TDEGlobal::locale(); + + if (argc != 4) + { + fprintf(stderr, "Usage: tdeio_http protocol domain-socket1 domain-socket2\n"); + exit(-1); + } + + HTTPProtocol slave(argv[1], argv[2], argv[3]); + slave.dispatchLoop(); + return 0; +} + +/*********************************** Generic utility functions ********************/ + +static char * trimLead (char *orig_string) +{ + while (*orig_string == ' ') + orig_string++; + return orig_string; +} + +static bool isCrossDomainRequest( const TQString& fqdn, const TQString& originURL ) +{ + if (originURL == "true") // Backwards compatibility + return true; + + KURL url ( originURL ); + + // Document Origin domain + TQString a = url.host(); + + // Current request domain + TQString b = fqdn; + + if (a == b) + return false; + + TQStringList l1 = TQStringList::split('.', a); + TQStringList l2 = TQStringList::split('.', b); + + while(l1.count() > l2.count()) + l1.pop_front(); + + while(l2.count() > l1.count()) + l2.pop_front(); + + while(l2.count() >= 2) + { + if (l1 == l2) + return false; + + l1.pop_front(); + l2.pop_front(); + } + + return true; +} + +/* + Eliminates any custom header that could potentically alter the request +*/ +static TQString sanitizeCustomHTTPHeader(const TQString& _header) +{ + TQString sanitizedHeaders; + TQStringList headers = TQStringList::split(TQRegExp("[\r\n]"), _header); + + for(TQStringList::Iterator it = headers.begin(); it != headers.end(); ++it) + { + TQString header = (*it).lower(); + // Do not allow Request line to be specified and ignore + // the other HTTP headers. + if (header.find(':') == -1 || + header.startsWith("host") || + header.startsWith("via")) + continue; + + sanitizedHeaders += (*it); + sanitizedHeaders += "\r\n"; + } + + return sanitizedHeaders.stripWhiteSpace(); +} + +static TQString htmlEscape(const TQString &plain) +{ + TQString rich; + rich.reserve(uint(plain.length() * 1.1)); + for (uint i = 0; i < plain.length(); ++i) { + if (plain.at(i) == '<') { + rich += "<"; + } else if (plain.at(i) == '>') { + rich += ">"; + } else if (plain.at(i) == '&') { + rich += "&"; + } else if (plain.at(i) == '"') { + rich += """; + } else { + rich += plain.at(i); + } + } + rich.squeeze(); + return rich; +} + + +#define NO_SIZE ((TDEIO::filesize_t) -1) + +#ifdef HAVE_STRTOLL +#define STRTOLL strtoll +#else +#define STRTOLL strtol +#endif + + +/************************************** HTTPProtocol **********************************************/ + +HTTPProtocol::HTTPProtocol( const TQCString &protocol, const TQCString &pool, + const TQCString &app ) + :TCPSlaveBase( 0, protocol , pool, app, + (protocol == "https" || protocol == "webdavs") ) +{ + m_requestQueue.setAutoDelete(true); + + m_bBusy = false; + m_bFirstRequest = false; + m_bProxyAuthValid = false; + + m_iSize = NO_SIZE; + m_lineBufUnget = 0; + + m_protocol = protocol; + + m_maxCacheAge = DEFAULT_MAX_CACHE_AGE; + m_maxCacheSize = DEFAULT_MAX_CACHE_SIZE / 2; + m_remoteConnTimeout = DEFAULT_CONNECT_TIMEOUT; + m_remoteRespTimeout = DEFAULT_RESPONSE_TIMEOUT; + m_proxyConnTimeout = DEFAULT_PROXY_CONNECT_TIMEOUT; + + m_pid = getpid(); + + setMultipleAuthCaching( true ); + reparseConfiguration(); +} + +HTTPProtocol::~HTTPProtocol() +{ + httpClose(false); +} + +void HTTPProtocol::reparseConfiguration() +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::reparseConfiguration" << endl; + + m_strProxyRealm = TQString::null; + m_strProxyAuthorization = TQString::null; + ProxyAuthentication = AUTH_None; + m_bUseProxy = false; + + if (m_protocol == "https" || m_protocol == "webdavs") + m_iDefaultPort = DEFAULT_HTTPS_PORT; + else if (m_protocol == "ftp") + m_iDefaultPort = DEFAULT_FTP_PORT; + else + m_iDefaultPort = DEFAULT_HTTP_PORT; +} + +void HTTPProtocol::resetConnectionSettings() +{ + m_bEOF = false; + m_bError = false; + m_lineCount = 0; + m_iWWWAuthCount = 0; + m_lineCountUnget = 0; + m_iProxyAuthCount = 0; + +} + +void HTTPProtocol::resetResponseSettings() +{ + m_bRedirect = false; + m_redirectLocation = KURL(); + m_bChunked = false; + m_iSize = NO_SIZE; + + m_responseHeader.clear(); + m_qContentEncodings.clear(); + m_qTransferEncodings.clear(); + m_sContentMD5 = TQString::null; + m_strMimeType = TQString::null; + + setMetaData("request-id", m_request.id); +} + +void HTTPProtocol::resetSessionSettings() +{ + // Do not reset the URL on redirection if the proxy + // URL, username or password has not changed! + KURL proxy ( config()->readEntry("UseProxy") ); + + if ( m_strProxyRealm.isEmpty() || !proxy.isValid() || + m_proxyURL.host() != proxy.host() || + (!proxy.user().isNull() && proxy.user() != m_proxyURL.user()) || + (!proxy.pass().isNull() && proxy.pass() != m_proxyURL.pass()) ) + { + m_bProxyAuthValid = false; + m_proxyURL = proxy; + m_bUseProxy = m_proxyURL.isValid(); + + kdDebug(7113) << "(" << m_pid << ") Using proxy: " << m_bUseProxy << + " URL: " << m_proxyURL.prettyURL() << + " Realm: " << m_strProxyRealm << endl; + } + + m_bPersistentProxyConnection = config()->readBoolEntry("PersistentProxyConnection", false); + kdDebug(7113) << "(" << m_pid << ") Enable Persistent Proxy Connection: " + << m_bPersistentProxyConnection << endl; + + m_request.bUseCookiejar = config()->readBoolEntry("Cookies"); + m_request.bUseCache = config()->readBoolEntry("UseCache", true); + m_request.bErrorPage = config()->readBoolEntry("errorPage", true); + m_request.bNoAuth = config()->readBoolEntry("no-auth"); + m_strCacheDir = config()->readPathEntry("CacheDir"); + m_maxCacheAge = config()->readNumEntry("MaxCacheAge", DEFAULT_MAX_CACHE_AGE); + m_request.window = config()->readEntry("window-id"); + + kdDebug(7113) << "(" << m_pid << ") Window Id = " << m_request.window << endl; + kdDebug(7113) << "(" << m_pid << ") ssl_was_in_use = " + << metaData ("ssl_was_in_use") << endl; + + m_request.referrer = TQString::null; + if ( config()->readBoolEntry("SendReferrer", true) && + (m_protocol == "https" || m_protocol == "webdavs" || + metaData ("ssl_was_in_use") != "TRUE" ) ) + { + KURL referrerURL ( metaData("referrer") ); + if (referrerURL.isValid()) + { + // Sanitize + TQString protocol = referrerURL.protocol(); + if (protocol.startsWith("webdav")) + { + protocol.replace(0, 6, "http"); + referrerURL.setProtocol(protocol); + } + + if (protocol.startsWith("http")) + { + referrerURL.setRef(TQString::null); + referrerURL.setUser(TQString::null); + referrerURL.setPass(TQString::null); + m_request.referrer = referrerURL.url(); + } + } + } + + if ( config()->readBoolEntry("SendLanguageSettings", true) ) + { + m_request.charsets = config()->readEntry( "Charsets", "iso-8859-1" ); + + if ( !m_request.charsets.isEmpty() ) + m_request.charsets += DEFAULT_PARTIAL_CHARSET_HEADER; + + m_request.languages = config()->readEntry( "Languages", DEFAULT_LANGUAGE_HEADER ); + } + else + { + m_request.charsets = TQString::null; + m_request.languages = TQString::null; + } + + // Adjust the offset value based on the "resume" meta-data. + TQString resumeOffset = metaData("resume"); + if ( !resumeOffset.isEmpty() ) + m_request.offset = resumeOffset.toInt(); // TODO: Convert to 64 bit + else + m_request.offset = 0; + + m_request.disablePassDlg = config()->readBoolEntry("DisablePassDlg", false); + m_request.allowCompressedPage = config()->readBoolEntry("AllowCompressedPage", true); + m_request.id = metaData("request-id"); + + // Store user agent for this host. + if ( config()->readBoolEntry("SendUserAgent", true) ) + m_request.userAgent = metaData("UserAgent"); + else + m_request.userAgent = TQString::null; + + // Deal with cache cleaning. + // TODO: Find a smarter way to deal with cleaning the + // cache ? + if ( m_request.bUseCache ) + cleanCache(); + + // Deal with HTTP tunneling + if ( m_bIsSSL && m_bUseProxy && m_proxyURL.protocol() != "https" && + m_proxyURL.protocol() != "webdavs") + { + m_bNeedTunnel = true; + setRealHost( m_request.hostname ); + kdDebug(7113) << "(" << m_pid << ") SSL tunnel: Setting real hostname to: " + << m_request.hostname << endl; + } + else + { + m_bNeedTunnel = false; + setRealHost( TQString::null); + } + + m_responseCode = 0; + m_prevResponseCode = 0; + + m_strRealm = TQString::null; + m_strAuthorization = TQString::null; + Authentication = AUTH_None; + + // Obtain the proxy and remote server timeout values + m_proxyConnTimeout = proxyConnectTimeout(); + m_remoteConnTimeout = connectTimeout(); + m_remoteRespTimeout = responseTimeout(); + + // Set the SSL meta-data here... + setSSLMetaData(); + + // Bounce back the actual referrer sent + setMetaData("referrer", m_request.referrer); + + // Follow HTTP/1.1 spec and enable keep-alive by default + // unless the remote side tells us otherwise or we determine + // the persistent link has been terminated by the remote end. + m_bKeepAlive = true; + m_keepAliveTimeout = 0; + m_bUnauthorized = false; + + // A single request can require multiple exchanges with the remote + // server due to authentication challenges or SSL tunneling. + // m_bFirstRequest is a flag that indicates whether we are + // still processing the first request. This is important because we + // should not force a close of a keep-alive connection in the middle + // of the first request. + // m_bFirstRequest is set to "true" whenever a new connection is + // made in httpOpenConnection() + m_bFirstRequest = false; +} + +void HTTPProtocol::setHost( const TQString& host, int port, + const TQString& user, const TQString& pass ) +{ + // Reset the webdav-capable flags for this host + if ( m_request.hostname != host ) + m_davHostOk = m_davHostUnsupported = false; + + // is it an IPv6 address? + if (host.find(':') == -1) + { + m_request.hostname = host; + m_request.encoded_hostname = KIDNA::toAscii(host); + } + else + { + m_request.hostname = host; + int pos = host.find('%'); + if (pos == -1) + m_request.encoded_hostname = '[' + host + ']'; + else + // don't send the scope-id in IPv6 addresses to the server + m_request.encoded_hostname = '[' + host.left(pos) + ']'; + } + m_request.port = (port == 0) ? m_iDefaultPort : port; + m_request.user = user; + m_request.passwd = pass; + + m_bIsTunneled = false; + + kdDebug(7113) << "(" << m_pid << ") Hostname is now: " << m_request.hostname << + " (" << m_request.encoded_hostname << ")" <\r\n"; + request.append( "\r\n" ); + request.append( query.utf8() ); + request.append( "\r\n" ); + + davSetRequest( request ); + } else { + // We are only after certain features... + TQCString request; + request = "" + ""; + + // insert additional XML request from the davRequestResponse metadata + if ( hasMetaData( "davRequestResponse" ) ) + request += metaData( "davRequestResponse" ).utf8(); + else { + // No special request, ask for default properties + request += "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + } + request += ""; + + davSetRequest( request ); + } + + // WebDAV Stat or List... + m_request.method = query.isEmpty() ? DAV_PROPFIND : DAV_SEARCH; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + m_request.davData.depth = stat ? 0 : 1; + if (!stat) + m_request.url.adjustPath(+1); + + retrieveContent( true ); + + // Has a redirection already been called? If so, we're done. + if (m_bRedirect) { + finished(); + return; + } + + TQDomDocument multiResponse; + multiResponse.setContent( m_bufWebDavData, true ); + + bool hasResponse = false; + + for ( TQDomNode n = multiResponse.documentElement().firstChild(); + !n.isNull(); n = n.nextSibling()) + { + TQDomElement thisResponse = n.toElement(); + if (thisResponse.isNull()) + continue; + + hasResponse = true; + + TQDomElement href = thisResponse.namedItem( "href" ).toElement(); + if ( !href.isNull() ) + { + entry.clear(); + + TQString urlStr = href.text(); +#if 0 + int encoding = remoteEncoding()->encodingMib(); + if ((encoding == 106) && (!KStringHandler::isUtf8(KURL::decode_string(urlStr, 4).latin1()))) + encoding = 4; // Use latin1 if the file is not actually utf-8 +#else + TQUrl::decode(urlStr); + int encoding = 106; +#endif + + KURL thisURL ( urlStr, encoding ); + + atom.m_uds = TDEIO::UDS_NAME; + + if ( thisURL.isValid() ) { + // don't list the base dir of a listDir() + if ( !stat && thisURL.path(+1).length() == url.path(+1).length() ) + continue; + + atom.m_str = thisURL.fileName(); + } else { + // This is a relative URL. + atom.m_str = href.text(); + } + + entry.append( atom ); + + TQDomNodeList propstats = thisResponse.elementsByTagName( "propstat" ); + + davParsePropstats( propstats, entry ); + + if ( stat ) + { + // return an item + statEntry( entry ); + finished(); + return; + } + else + { + listEntry( entry, false ); + } + } + else + { + kdDebug(7113) << "Error: no URL contained in response to PROPFIND on " + << url.prettyURL() << endl; + } + } + + if ( stat || !hasResponse ) + { + error( ERR_DOES_NOT_EXIST, url.prettyURL() ); + } + else + { + listEntry( entry, true ); + finished(); + } +} + +void HTTPProtocol::davGeneric( const KURL& url, TDEIO::HTTP_METHOD method ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davGeneric " << url.prettyURL() + << endl; + + if ( !checkRequestURL( url ) ) + return; + + // check to make sure this host supports WebDAV + if ( !davHostOk() ) + return; + + // WebDAV method + m_request.method = method; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveContent( false ); +} + +int HTTPProtocol::codeFromResponse( const TQString& response ) +{ + int firstSpace = response.find( ' ' ); + int secondSpace = response.find( ' ', firstSpace + 1 ); + return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt(); +} + +void HTTPProtocol::davParsePropstats( const TQDomNodeList& propstats, UDSEntry& entry ) +{ + TQString mimeType; + UDSAtom atom; + bool foundExecutable = false; + bool isDirectory = false; + uint lockCount = 0; + uint supportedLockCount = 0; + + for ( uint i = 0; i < propstats.count(); i++) + { + TQDomElement propstat = propstats.item(i).toElement(); + + TQDomElement status = propstat.namedItem( "status" ).toElement(); + if ( status.isNull() ) + { + // error, no status code in this propstat + kdDebug(7113) << "Error, no status code in this propstat" << endl; + return; + } + + int code = codeFromResponse( status.text() ); + + if ( code != 200 ) + { + kdDebug(7113) << "Warning: status code " << code << " (this may mean that some properties are unavailable" << endl; + continue; + } + + TQDomElement prop = propstat.namedItem( "prop" ).toElement(); + if ( prop.isNull() ) + { + kdDebug(7113) << "Error: no prop segment in this propstat." << endl; + return; + } + + if ( hasMetaData( "davRequestResponse" ) ) + { + atom.m_uds = TDEIO::UDS_XML_PROPERTIES; + TQDomDocument doc; + doc.appendChild(prop); + atom.m_str = doc.toString(); + entry.append( atom ); + } + + for ( TQDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() ) + { + TQDomElement property = n.toElement(); + if (property.isNull()) + continue; + + if ( property.namespaceURI() != "DAV:" ) + { + // break out - we're only interested in properties from the DAV namespace + continue; + } + + if ( property.tagName() == "creationdate" ) + { + // Resource creation date. Should be is ISO 8601 format. + atom.m_uds = TDEIO::UDS_CREATION_TIME; + atom.m_long = parseDateTime( property.text(), property.attribute("dt") ); + entry.append( atom ); + } + else if ( property.tagName() == "getcontentlength" ) + { + // Content length (file size) + atom.m_uds = TDEIO::UDS_SIZE; + atom.m_long = property.text().toULong(); + entry.append( atom ); + } + else if ( property.tagName() == "displayname" ) + { + // Name suitable for presentation to the user + setMetaData( "davDisplayName", property.text() ); + } + else if ( property.tagName() == "source" ) + { + // Source template location + TQDomElement source = property.namedItem( "link" ).toElement() + .namedItem( "dst" ).toElement(); + if ( !source.isNull() ) + setMetaData( "davSource", source.text() ); + } + else if ( property.tagName() == "getcontentlanguage" ) + { + // equiv. to Content-Language header on a GET + setMetaData( "davContentLanguage", property.text() ); + } + else if ( property.tagName() == "getcontenttype" ) + { + // Content type (mime type) + // This may require adjustments for other server-side webdav implementations + // (tested with Apache + mod_dav 1.0.3) + if ( property.text() == "httpd/unix-directory" ) + { + isDirectory = true; + } + else + { + mimeType = property.text(); + } + } + else if ( property.tagName() == "executable" ) + { + // File executable status + if ( property.text() == "T" ) + foundExecutable = true; + + } + else if ( property.tagName() == "getlastmodified" ) + { + // Last modification date + atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; + atom.m_long = parseDateTime( property.text(), property.attribute("dt") ); + entry.append( atom ); + + } + else if ( property.tagName() == "getetag" ) + { + // Entity tag + setMetaData( "davEntityTag", property.text() ); + } + else if ( property.tagName() == "supportedlock" ) + { + // Supported locking specifications + for ( TQDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) + { + TQDomElement lockEntry = n2.toElement(); + if ( lockEntry.tagName() == "lockentry" ) + { + TQDomElement lockScope = lockEntry.namedItem( "lockscope" ).toElement(); + TQDomElement lockType = lockEntry.namedItem( "locktype" ).toElement(); + if ( !lockScope.isNull() && !lockType.isNull() ) + { + // Lock type was properly specified + supportedLockCount++; + TQString scope = lockScope.firstChild().toElement().tagName(); + TQString type = lockType.firstChild().toElement().tagName(); + + setMetaData( TQString("davSupportedLockScope%1").arg(supportedLockCount), scope ); + setMetaData( TQString("davSupportedLockType%1").arg(supportedLockCount), type ); + } + } + } + } + else if ( property.tagName() == "lockdiscovery" ) + { + // Lists the available locks + davParseActiveLocks( property.elementsByTagName( "activelock" ), lockCount ); + } + else if ( property.tagName() == "resourcetype" ) + { + // Resource type. "Specifies the nature of the resource." + if ( !property.namedItem( "collection" ).toElement().isNull() ) + { + // This is a collection (directory) + isDirectory = true; + } + } + else + { + kdDebug(7113) << "Found unknown webdav property: " << property.tagName() << endl; + } + } + } + + setMetaData( "davLockCount", TQString("%1").arg(lockCount) ); + setMetaData( "davSupportedLockCount", TQString("%1").arg(supportedLockCount) ); + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long = isDirectory ? S_IFDIR : S_IFREG; + entry.append( atom ); + + if ( foundExecutable || isDirectory ) + { + // File was executable, or is a directory. + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = 0700; + entry.append(atom); + } + else + { + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long = 0600; + entry.append(atom); + } + + if ( !isDirectory && !mimeType.isEmpty() ) + { + atom.m_uds = TDEIO::UDS_MIME_TYPE; + atom.m_str = mimeType; + entry.append( atom ); + } +} + +void HTTPProtocol::davParseActiveLocks( const TQDomNodeList& activeLocks, + uint& lockCount ) +{ + for ( uint i = 0; i < activeLocks.count(); i++ ) + { + TQDomElement activeLock = activeLocks.item(i).toElement(); + + lockCount++; + // required + TQDomElement lockScope = activeLock.namedItem( "lockscope" ).toElement(); + TQDomElement lockType = activeLock.namedItem( "locktype" ).toElement(); + TQDomElement lockDepth = activeLock.namedItem( "depth" ).toElement(); + // optional + TQDomElement lockOwner = activeLock.namedItem( "owner" ).toElement(); + TQDomElement lockTimeout = activeLock.namedItem( "timeout" ).toElement(); + TQDomElement lockToken = activeLock.namedItem( "locktoken" ).toElement(); + + if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() ) + { + // lock was properly specified + lockCount++; + TQString scope = lockScope.firstChild().toElement().tagName(); + TQString type = lockType.firstChild().toElement().tagName(); + TQString depth = lockDepth.text(); + + setMetaData( TQString("davLockScope%1").arg( lockCount ), scope ); + setMetaData( TQString("davLockType%1").arg( lockCount ), type ); + setMetaData( TQString("davLockDepth%1").arg( lockCount ), depth ); + + if ( !lockOwner.isNull() ) + setMetaData( TQString("davLockOwner%1").arg( lockCount ), lockOwner.text() ); + + if ( !lockTimeout.isNull() ) + setMetaData( TQString("davLockTimeout%1").arg( lockCount ), lockTimeout.text() ); + + if ( !lockToken.isNull() ) + { + TQDomElement tokenVal = lockScope.namedItem( "href" ).toElement(); + if ( !tokenVal.isNull() ) + setMetaData( TQString("davLockToken%1").arg( lockCount ), tokenVal.text() ); + } + } + } +} + +long HTTPProtocol::parseDateTime( const TQString& input, const TQString& type ) +{ + if ( type == "dateTime.tz" ) + { + return KRFCDate::parseDateISO8601( input ); + } + else if ( type == "dateTime.rfc1123" ) + { + return KRFCDate::parseDate( input ); + } + + // format not advertised... try to parse anyway + time_t time = KRFCDate::parseDate( input ); + if ( time != 0 ) + return time; + + return KRFCDate::parseDateISO8601( input ); +} + +TQString HTTPProtocol::davProcessLocks() +{ + if ( hasMetaData( "davLockCount" ) ) + { + TQString response("If:"); + int numLocks; + numLocks = metaData( "davLockCount" ).toInt(); + bool bracketsOpen = false; + for ( int i = 0; i < numLocks; i++ ) + { + if ( hasMetaData( TQString("davLockToken%1").arg(i) ) ) + { + if ( hasMetaData( TQString("davLockURL%1").arg(i) ) ) + { + if ( bracketsOpen ) + { + response += ")"; + bracketsOpen = false; + } + response += " <" + metaData( TQString("davLockURL%1").arg(i) ) + ">"; + } + + if ( !bracketsOpen ) + { + response += " ("; + bracketsOpen = true; + } + else + { + response += " "; + } + + if ( hasMetaData( TQString("davLockNot%1").arg(i) ) ) + response += "Not "; + + response += "<" + metaData( TQString("davLockToken%1").arg(i) ) + ">"; + } + } + + if ( bracketsOpen ) + response += ")"; + + response += "\r\n"; + return response; + } + + return TQString::null; +} + +bool HTTPProtocol::davHostOk() +{ + // FIXME needs to be reworked. Switched off for now. + return true; + + // cached? + if ( m_davHostOk ) + { + kdDebug(7113) << "(" << m_pid << ") " << k_funcinfo << " true" << endl; + return true; + } + else if ( m_davHostUnsupported ) + { + kdDebug(7113) << "(" << m_pid << ") " << k_funcinfo << " false" << endl; + davError( -2 ); + return false; + } + + m_request.method = HTTP_OPTIONS; + + // query the server's capabilities generally, not for a specific URL + m_request.path = "*"; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + // clear davVersions variable, which holds the response to the DAV: header + m_davCapabilities.clear(); + + retrieveHeader(false); + + if (m_davCapabilities.count()) + { + for (uint i = 0; i < m_davCapabilities.count(); i++) + { + bool ok; + uint verNo = m_davCapabilities[i].toUInt(&ok); + if (ok && verNo > 0 && verNo < 3) + { + m_davHostOk = true; + kdDebug(7113) << "Server supports DAV version " << verNo << "." << endl; + } + } + + if ( m_davHostOk ) + return true; + } + + m_davHostUnsupported = true; + davError( -2 ); + return false; +} + +// This function is for closing retrieveHeader( false ); requests +// Required because there may or may not be further info expected +void HTTPProtocol::davFinished() +{ + // TODO: Check with the DAV extension developers + httpClose(m_bKeepAlive); + finished(); +} + +void HTTPProtocol::mkdir( const KURL& url, int ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::mkdir " << url.prettyURL() + << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = DAV_MKCOL; + m_request.path = url.path(); + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveHeader( false ); + + if ( m_responseCode == 201 ) + davFinished(); + else + davError(); +} + +void HTTPProtocol::get( const KURL& url ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::get " << url.prettyURL() + << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = HTTP_GET; + m_request.path = url.path(); + m_request.query = url.query(); + + TQString tmp = metaData("cache"); + if (!tmp.isEmpty()) + m_request.cache = parseCacheControl(tmp); + else + m_request.cache = DEFAULT_CACHE_CONTROL; + + m_request.passwd = url.pass(); + m_request.user = url.user(); + m_request.doProxy = m_bUseProxy; + + retrieveContent(); +} + +void HTTPProtocol::put( const KURL &url, int, bool overwrite, bool) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put " << url.prettyURL() + << endl; + + if ( !checkRequestURL( url ) ) + return; + + // Webdav hosts are capable of observing overwrite == false + if (!overwrite && m_protocol.left(6) == "webdav") { + // check to make sure this host supports WebDAV + if ( !davHostOk() ) + return; + + TQCString request; + request = "" + "" + "" + "" + "" + "" + ""; + + davSetRequest( request ); + + // WebDAV Stat or List... + m_request.method = DAV_PROPFIND; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + m_request.davData.depth = 0; + + retrieveContent(true); + + if (m_responseCode == 207) { + error(ERR_FILE_ALREADY_EXIST, TQString::null); + return; + } + + m_bError = false; + } + + m_request.method = HTTP_PUT; + m_request.path = url.path(); + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveHeader( false ); + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put error = " << m_bError << endl; + if (m_bError) + return; + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put responseCode = " << m_responseCode << endl; + + httpClose(false); // Always close connection. + + if ( (m_responseCode >= 200) && (m_responseCode < 300) ) + finished(); + else + httpError(); +} + +void HTTPProtocol::copy( const KURL& src, const KURL& dest, int, bool overwrite ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::copy " << src.prettyURL() + << " -> " << dest.prettyURL() << endl; + + if ( !checkRequestURL( dest ) || !checkRequestURL( src ) ) + return; + + // destination has to be "http(s)://..." + KURL newDest = dest; + if (newDest.protocol() == "webdavs") + newDest.setProtocol("https"); + else + newDest.setProtocol("http"); + + m_request.method = DAV_COPY; + m_request.path = src.path(); + m_request.davData.desturl = newDest.url(); + m_request.davData.overwrite = overwrite; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveHeader( false ); + + // The server returns a HTTP/1.1 201 Created or 204 No Content on successful completion + if ( m_responseCode == 201 || m_responseCode == 204 ) + davFinished(); + else + davError(); +} + +void HTTPProtocol::rename( const KURL& src, const KURL& dest, bool overwrite ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::rename " << src.prettyURL() + << " -> " << dest.prettyURL() << endl; + + if ( !checkRequestURL( dest ) || !checkRequestURL( src ) ) + return; + + // destination has to be "http://..." + KURL newDest = dest; + if (newDest.protocol() == "webdavs") + newDest.setProtocol("https"); + else + newDest.setProtocol("http"); + + m_request.method = DAV_MOVE; + m_request.path = src.path(); + m_request.davData.desturl = newDest.url(); + m_request.davData.overwrite = overwrite; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveHeader( false ); + + if ( m_responseCode == 301 ) + { + // Work around strict Apache-2 WebDAV implementation which refuses to cooperate + // with webdav://host/directory, instead requiring webdav://host/directory/ + // (strangely enough it accepts Destination: without a trailing slash) + + if (m_redirectLocation.protocol() == "https") + m_redirectLocation.setProtocol("webdavs"); + else + m_redirectLocation.setProtocol("webdav"); + + if ( !checkRequestURL( m_redirectLocation ) ) + return; + + m_request.method = DAV_MOVE; + m_request.path = m_redirectLocation.path(); + m_request.davData.desturl = newDest.url(); + m_request.davData.overwrite = overwrite; + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveHeader( false ); + } + + if ( m_responseCode == 201 ) + davFinished(); + else + davError(); +} + +void HTTPProtocol::del( const KURL& url, bool ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::del " << url.prettyURL() + << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = HTTP_DELETE; + m_request.path = url.path(); + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveHeader( false ); + + // The server returns a HTTP/1.1 200 Ok or HTTP/1.1 204 No Content + // on successful completion + if ( m_responseCode == 200 || m_responseCode == 204 ) + davFinished(); + else + davError(); +} + +void HTTPProtocol::post( const KURL& url ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::post " + << url.prettyURL() << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = HTTP_POST; + m_request.path = url.path(); + m_request.query = url.query(); + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveContent(); +} + +void HTTPProtocol::davLock( const KURL& url, const TQString& scope, + const TQString& type, const TQString& owner ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davLock " + << url.prettyURL() << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = DAV_LOCK; + m_request.path = url.path(); + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + /* Create appropriate lock XML request. */ + TQDomDocument lockReq; + + TQDomElement lockInfo = lockReq.createElementNS( "DAV:", "lockinfo" ); + lockReq.appendChild( lockInfo ); + + TQDomElement lockScope = lockReq.createElement( "lockscope" ); + lockInfo.appendChild( lockScope ); + + lockScope.appendChild( lockReq.createElement( scope ) ); + + TQDomElement lockType = lockReq.createElement( "locktype" ); + lockInfo.appendChild( lockType ); + + lockType.appendChild( lockReq.createElement( type ) ); + + if ( !owner.isNull() ) { + TQDomElement ownerElement = lockReq.createElement( "owner" ); + lockReq.appendChild( ownerElement ); + + TQDomElement ownerHref = lockReq.createElement( "href" ); + ownerElement.appendChild( ownerHref ); + + ownerHref.appendChild( lockReq.createTextNode( owner ) ); + } + + // insert the document into the POST buffer + m_bufPOST = lockReq.toCString(); + + retrieveContent( true ); + + if ( m_responseCode == 200 ) { + // success + TQDomDocument multiResponse; + multiResponse.setContent( m_bufWebDavData, true ); + + TQDomElement prop = multiResponse.documentElement().namedItem( "prop" ).toElement(); + + TQDomElement lockdiscovery = prop.namedItem( "lockdiscovery" ).toElement(); + + uint lockCount = 0; + davParseActiveLocks( lockdiscovery.elementsByTagName( "activelock" ), lockCount ); + + setMetaData( "davLockCount", TQString("%1").arg( lockCount ) ); + + finished(); + + } else + davError(); +} + +void HTTPProtocol::davUnlock( const KURL& url ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davUnlock " + << url.prettyURL() << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = DAV_UNLOCK; + m_request.path = url.path(); + m_request.query = TQString::null; + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + retrieveContent( true ); + + if ( m_responseCode == 200 ) + finished(); + else + davError(); +} + +TQString HTTPProtocol::davError( int code /* = -1 */, TQString url ) +{ + bool callError = false; + if ( code == -1 ) { + code = m_responseCode; + callError = true; + } + if ( code == -2 ) { + callError = true; + } + + // Huh? This looks like inverted logic to me (it doesn't make sense to me as + // written), but I'm only fixing the CVE now. -- Kevin Kofler + if ( !url.isNull() ) + url = m_request.url.prettyURL(); + + TQString action, errorString; + TDEIO::Error kError; + + // for 412 Precondition Failed + TQString ow = i18n( "Otherwise, the request would have succeeded." ); + + switch ( m_request.method ) { + case DAV_PROPFIND: + action = i18n( "retrieve property values" ); + break; + case DAV_PROPPATCH: + action = i18n( "set property values" ); + break; + case DAV_MKCOL: + action = i18n( "create the requested folder" ); + break; + case DAV_COPY: + action = i18n( "copy the specified file or folder" ); + break; + case DAV_MOVE: + action = i18n( "move the specified file or folder" ); + break; + case DAV_SEARCH: + action = i18n( "search in the specified folder" ); + break; + case DAV_LOCK: + action = i18n( "lock the specified file or folder" ); + break; + case DAV_UNLOCK: + action = i18n( "unlock the specified file or folder" ); + break; + case HTTP_DELETE: + action = i18n( "delete the specified file or folder" ); + break; + case HTTP_OPTIONS: + action = i18n( "query the server's capabilities" ); + break; + case HTTP_GET: + action = i18n( "retrieve the contents of the specified file or folder" ); + break; + case HTTP_PUT: + case HTTP_POST: + case HTTP_HEAD: + default: + // this should not happen, this function is for webdav errors only + Q_ASSERT(0); + } + + // default error message if the following code fails + kError = ERR_INTERNAL; + errorString = i18n("An unexpected error (%1) occurred while attempting to %2.") + .arg( code ).arg( action ); + + switch ( code ) + { + case -2: + // internal error: OPTIONS request did not specify DAV compliance + kError = ERR_UNSUPPORTED_PROTOCOL; + errorString = i18n("The server does not support the WebDAV protocol."); + break; + case 207: + // 207 Multi-status + { + // our error info is in the returned XML document. + // retrieve the XML document + + // there was an error retrieving the XML document. + // ironic, eh? + if ( !readBody( true ) && m_bError ) + return TQString::null; + + TQStringList errors; + TQDomDocument multiResponse; + + multiResponse.setContent( m_bufWebDavData, true ); + + TQDomElement multistatus = multiResponse.documentElement().namedItem( "multistatus" ).toElement(); + + TQDomNodeList responses = multistatus.elementsByTagName( "response" ); + + for (uint i = 0; i < responses.count(); i++) + { + int errCode; + TQString errUrl; + + TQDomElement response = responses.item(i).toElement(); + TQDomElement code = response.namedItem( "status" ).toElement(); + + if ( !code.isNull() ) + { + errCode = codeFromResponse( code.text() ); + TQDomElement href = response.namedItem( "href" ).toElement(); + if ( !href.isNull() ) + errUrl = href.text(); + errors << davError( errCode, errUrl ); + } + } + + //kError = ERR_SLAVE_DEFINED; + errorString = i18n("An error occurred while attempting to %1, %2. A " + "summary of the reasons is below.
    ").arg( action ).arg( url ); + + for ( TQStringList::Iterator it = errors.begin(); it != errors.end(); ++it ) + errorString += "
  • " + *it + "
  • "; + + errorString += "
"; + } + case 403: + case 500: // hack: Apache mod_dav returns this instead of 403 (!) + // 403 Forbidden + kError = ERR_ACCESS_DENIED; + errorString = i18n("Access was denied while attempting to %1.").arg( action ); + break; + case 405: + // 405 Method Not Allowed + if ( m_request.method == DAV_MKCOL ) + { + kError = ERR_DIR_ALREADY_EXIST; + errorString = i18n("The specified folder already exists."); + } + break; + case 409: + // 409 Conflict + kError = ERR_ACCESS_DENIED; + errorString = i18n("A resource cannot be created at the destination " + "until one or more intermediate collections (folders) " + "have been created."); + break; + case 412: + // 412 Precondition failed + if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE ) + { + kError = ERR_ACCESS_DENIED; + errorString = i18n("The server was unable to maintain the liveness of " + "the properties listed in the propertybehavior XML " + "element or you attempted to overwrite a file while " + "requesting that files are not overwritten. %1") + .arg( ow ); + + } + else if ( m_request.method == DAV_LOCK ) + { + kError = ERR_ACCESS_DENIED; + errorString = i18n("The requested lock could not be granted. %1").arg( ow ); + } + break; + case 415: + // 415 Unsupported Media Type + kError = ERR_ACCESS_DENIED; + errorString = i18n("The server does not support the request type of the body."); + break; + case 423: + // 423 Locked + kError = ERR_ACCESS_DENIED; + errorString = i18n("Unable to %1 because the resource is locked.").arg( action ); + break; + case 425: + // 424 Failed Dependency + errorString = i18n("This action was prevented by another error."); + break; + case 502: + // 502 Bad Gateway + if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE ) + { + kError = ERR_WRITE_ACCESS_DENIED; + errorString = i18n("Unable to %1 because the destination server refuses " + "to accept the file or folder.").arg( action ); + } + break; + case 507: + // 507 Insufficient Storage + kError = ERR_DISK_FULL; + errorString = i18n("The destination resource does not have sufficient space " + "to record the state of the resource after the execution " + "of this method."); + break; + } + + // if ( kError != ERR_SLAVE_DEFINED ) + //errorString += " (" + url + ")"; + + if ( callError ) + error( ERR_SLAVE_DEFINED, errorString ); + + return errorString; +} + +void HTTPProtocol::httpError() +{ + TQString action, errorString; + TDEIO::Error kError; + + switch ( m_request.method ) { + case HTTP_PUT: + action = i18n( "upload %1" ).arg(m_request.url.prettyURL()); + break; + default: + // this should not happen, this function is for http errors only + Q_ASSERT(0); + } + + // default error message if the following code fails + kError = ERR_INTERNAL; + errorString = i18n("An unexpected error (%1) occurred while attempting to %2.") + .arg( m_responseCode ).arg( action ); + + switch ( m_responseCode ) + { + case 403: + case 405: + case 500: // hack: Apache mod_dav returns this instead of 403 (!) + // 403 Forbidden + // 405 Method Not Allowed + kError = ERR_ACCESS_DENIED; + errorString = i18n("Access was denied while attempting to %1.").arg( action ); + break; + case 409: + // 409 Conflict + kError = ERR_ACCESS_DENIED; + errorString = i18n("A resource cannot be created at the destination " + "until one or more intermediate collections (folders) " + "have been created."); + break; + case 423: + // 423 Locked + kError = ERR_ACCESS_DENIED; + errorString = i18n("Unable to %1 because the resource is locked.").arg( action ); + break; + case 502: + // 502 Bad Gateway + kError = ERR_WRITE_ACCESS_DENIED; + errorString = i18n("Unable to %1 because the destination server refuses " + "to accept the file or folder.").arg( action ); + break; + case 507: + // 507 Insufficient Storage + kError = ERR_DISK_FULL; + errorString = i18n("The destination resource does not have sufficient space " + "to record the state of the resource after the execution " + "of this method."); + break; + } + + // if ( kError != ERR_SLAVE_DEFINED ) + //errorString += " (" + url + ")"; + + error( ERR_SLAVE_DEFINED, errorString ); +} + +bool HTTPProtocol::isOffline(const KURL &url) +{ + const int NetWorkStatusUnknown = 1; + const int NetWorkStatusOnline = 8; + TQCString replyType; + TQByteArray params; + TQByteArray reply; + + TQDataStream stream(params, IO_WriteOnly); + + if ( url.host() == TQString::fromLatin1("localhost") || url.host() == TQString::fromLatin1("127.0.0.1") || url.host() == TQString::fromLatin1("::") ) { + return false; + } + if ( dcopClient()->call( "kded", "networkstatus", "status()", + params, replyType, reply ) && (replyType == "int") ) + { + int result; + TQDataStream stream2( reply, IO_ReadOnly ); + stream2 >> result; + kdDebug(7113) << "(" << m_pid << ") networkstatus status = " << result << endl; + return (result != NetWorkStatusUnknown) && (result != NetWorkStatusOnline); + } + kdDebug(7113) << "(" << m_pid << ") networkstatus " << endl; + return false; // On error, assume we are online +} + +void HTTPProtocol::multiGet(const TQByteArray &data) +{ + TQDataStream stream(data, IO_ReadOnly); + TQ_UINT32 n; + stream >> n; + + kdDebug(7113) << "(" << m_pid << ") HTTPProtcool::multiGet n = " << n << endl; + + HTTPRequest saveRequest; + if (m_bBusy) + saveRequest = m_request; + +// m_requestQueue.clear(); + for(unsigned i = 0; i < n; i++) + { + KURL url; + stream >> url >> mIncomingMetaData; + + if ( !checkRequestURL( url ) ) + continue; + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::multi_get " << url.prettyURL() << endl; + + m_request.method = HTTP_GET; + m_request.path = url.path(); + m_request.query = url.query(); + TQString tmp = metaData("cache"); + if (!tmp.isEmpty()) + m_request.cache = parseCacheControl(tmp); + else + m_request.cache = DEFAULT_CACHE_CONTROL; + + m_request.passwd = url.pass(); + m_request.user = url.user(); + m_request.doProxy = m_bUseProxy; + + HTTPRequest *newRequest = new HTTPRequest(m_request); + m_requestQueue.append(newRequest); + } + + if (m_bBusy) + m_request = saveRequest; + + if (!m_bBusy) + { + m_bBusy = true; + while(!m_requestQueue.isEmpty()) + { + HTTPRequest *request = m_requestQueue.take(0); + m_request = *request; + delete request; + retrieveContent(); + } + m_bBusy = false; + } +} + +ssize_t HTTPProtocol::write (const void *_buf, size_t nbytes) +{ + int bytes_sent = 0; + const char* buf = static_cast(_buf); + while ( nbytes > 0 ) + { + int n = TCPSlaveBase::write(buf, nbytes); + + if ( n <= 0 ) + { + // remote side closed connection ? + if ( n == 0 ) + break; + // a valid exception(s) occurred, let's retry... + if (n < 0 && ((errno == EINTR) || (errno == EAGAIN))) + continue; + // some other error occurred ? + return -1; + } + + nbytes -= n; + buf += n; + bytes_sent += n; + } + + return bytes_sent; +} + +void HTTPProtocol::setRewindMarker() +{ + m_rewindCount = 0; +} + +void HTTPProtocol::rewind() +{ + m_linePtrUnget = m_rewindBuf, + m_lineCountUnget = m_rewindCount; + m_rewindCount = 0; +} + + +char *HTTPProtocol::gets (char *s, int size) +{ + int len=0; + char *buf=s; + char mybuf[2]={0,0}; + + while (len < size) + { + read(mybuf, 1); + if (m_bEOF) + break; + + if (m_rewindCount < sizeof(m_rewindBuf)) + m_rewindBuf[m_rewindCount++] = *mybuf; + + if (*mybuf == '\r') // Ignore! + continue; + + if ((*mybuf == '\n') || !*mybuf) + break; + + *buf++ = *mybuf; + len++; + } + + *buf=0; + return s; +} + +ssize_t HTTPProtocol::read (void *b, size_t nbytes) +{ + ssize_t ret = 0; + + if (m_lineCountUnget > 0) + { + ret = ( nbytes < m_lineCountUnget ? nbytes : m_lineCountUnget ); + m_lineCountUnget -= ret; + memcpy(b, m_linePtrUnget, ret); + m_linePtrUnget += ret; + + return ret; + } + + if (m_lineCount > 0) + { + ret = ( nbytes < m_lineCount ? nbytes : m_lineCount ); + m_lineCount -= ret; + memcpy(b, m_linePtr, ret); + m_linePtr += ret; + return ret; + } + + if (nbytes == 1) + { + ret = read(m_lineBuf, 1024); // Read into buffer + m_linePtr = m_lineBuf; + if (ret <= 0) + { + m_lineCount = 0; + return ret; + } + m_lineCount = ret; + return read(b, 1); // Read from buffer + } + + do + { + ret = TCPSlaveBase::read( b, nbytes); + if (ret == 0) + m_bEOF = true; + + } while ((ret == -1) && (errno == EAGAIN || errno == EINTR)); + + return ret; +} + +void HTTPProtocol::httpCheckConnection() +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpCheckConnection: " << + " Socket status: " << m_iSock << + " Keep Alive: " << m_bKeepAlive << + " First: " << m_bFirstRequest << endl; + + if ( !m_bFirstRequest && (m_iSock != -1) ) + { + bool closeDown = false; + if ( !isConnectionValid()) + { + kdDebug(7113) << "(" << m_pid << ") Connection lost!" << endl; + closeDown = true; + } + else if ( m_request.method != HTTP_GET ) + { + closeDown = true; + } + else if ( !m_state.doProxy && !m_request.doProxy ) + { + if (m_state.hostname != m_request.hostname || + m_state.port != m_request.port || + m_state.user != m_request.user || + m_state.passwd != m_request.passwd) + closeDown = true; + } + else + { + // Keep the connection to the proxy. + if ( !(m_request.doProxy && m_state.doProxy) ) + closeDown = true; + } + + if (closeDown) + httpCloseConnection(); + } + + // Let's update our current state + m_state.hostname = m_request.hostname; + m_state.encoded_hostname = m_request.encoded_hostname; + m_state.port = m_request.port; + m_state.user = m_request.user; + m_state.passwd = m_request.passwd; + m_state.doProxy = m_request.doProxy; +} + +bool HTTPProtocol::httpOpenConnection() +{ + int errCode; + TQString errMsg; + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpenConnection" << endl; + + setBlockConnection( true ); + // tdeio_http uses its own proxying: + KSocks::self()->disableSocks(); + + if ( m_state.doProxy ) + { + TQString proxy_host = m_proxyURL.host(); + int proxy_port = m_proxyURL.port(); + + kdDebug(7113) << "(" << m_pid << ") Connecting to proxy server: " + << proxy_host << ", port: " << proxy_port << endl; + + infoMessage( i18n("Connecting to %1...").arg(m_state.hostname) ); + + setConnectTimeout( m_proxyConnTimeout ); + + if ( !connectToHost(proxy_host, proxy_port, false) ) + { + if (userAborted()) { + error(ERR_NO_CONTENT, ""); + return false; + } + + switch ( connectResult() ) + { + case IO_LookupError: + errMsg = proxy_host; + errCode = ERR_UNKNOWN_PROXY_HOST; + break; + case IO_TimeOutError: + errMsg = i18n("Proxy %1 at port %2").arg(proxy_host).arg(proxy_port); + errCode = ERR_SERVER_TIMEOUT; + break; + default: + errMsg = i18n("Proxy %1 at port %2").arg(proxy_host).arg(proxy_port); + errCode = ERR_COULD_NOT_CONNECT; + } + error( errCode, errMsg ); + return false; + } + } + else + { + // Apparently we don't want a proxy. let's just connect directly + setConnectTimeout(m_remoteConnTimeout); + + if ( !connectToHost(m_state.hostname, m_state.port, false ) ) + { + if (userAborted()) { + error(ERR_NO_CONTENT, ""); + return false; + } + + switch ( connectResult() ) + { + case IO_LookupError: + errMsg = m_state.hostname; + errCode = ERR_UNKNOWN_HOST; + break; + case IO_TimeOutError: + errMsg = i18n("Connection was to %1 at port %2").arg(m_state.hostname).arg(m_state.port); + errCode = ERR_SERVER_TIMEOUT; + break; + default: + errCode = ERR_COULD_NOT_CONNECT; + if (m_state.port != m_iDefaultPort) + errMsg = i18n("%1 (port %2)").arg(m_state.hostname).arg(m_state.port); + else + errMsg = m_state.hostname; + } + error( errCode, errMsg ); + return false; + } + } + + // Set our special socket option!! + int on = 1; + (void) setsockopt( m_iSock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on) ); + + m_bFirstRequest = true; + + connected(); + return true; +} + + +/** + * This function is responsible for opening up the connection to the remote + * HTTP server and sending the header. If this requires special + * authentication or other such fun stuff, then it will handle it. This + * function will NOT receive anything from the server, however. This is in + * contrast to previous incarnations of 'httpOpen'. + * + * The reason for the change is due to one small fact: some requests require + * data to be sent in addition to the header (POST requests) and there is no + * way for this function to get that data. This function is called in the + * slotPut() or slotGet() functions which, in turn, are called (indirectly) as + * a result of a TDEIOJob::put() or TDEIOJob::get(). It is those latter functions + * which are responsible for starting up this ioslave in the first place. + * This means that 'httpOpen' is called (essentially) as soon as the ioslave + * is created -- BEFORE any data gets to this slave. + * + * The basic process now is this: + * + * 1) Open up the socket and port + * 2) Format our request/header + * 3) Send the header to the remote server + */ +bool HTTPProtocol::httpOpen() +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen" << endl; + + // Cannot have an https request without the m_bIsSSL being set! This can + // only happen if TCPSlaveBase::InitializeSSL() function failed in which it + // means the current installation does not support SSL... + if ( (m_protocol == "https" || m_protocol == "webdavs") && !m_bIsSSL ) + { + error( ERR_UNSUPPORTED_PROTOCOL, m_protocol ); + return false; + } + + m_request.fcache = 0; + m_request.bCachedRead = false; + m_request.bCachedWrite = false; + m_request.bMustRevalidate = false; + m_request.expireDate = 0; + m_request.creationDate = 0; + + if (m_request.bUseCache) + { + m_request.fcache = checkCacheEntry( ); + + bool bCacheOnly = (m_request.cache == TDEIO::CC_CacheOnly); + bool bOffline = isOffline(m_request.doProxy ? m_proxyURL : m_request.url); + if (bOffline && (m_request.cache != TDEIO::CC_Reload)) + m_request.cache = TDEIO::CC_CacheOnly; + + if (m_request.cache == CC_Reload && m_request.fcache) + { + if (m_request.fcache) + fclose(m_request.fcache); + m_request.fcache = 0; + } + if ((m_request.cache == TDEIO::CC_CacheOnly) || (m_request.cache == TDEIO::CC_Cache)) + m_request.bMustRevalidate = false; + + m_request.bCachedWrite = true; + + if (m_request.fcache && !m_request.bMustRevalidate) + { + // Cache entry is OK. + m_request.bCachedRead = true; // Cache hit. + return true; + } + else if (!m_request.fcache) + { + m_request.bMustRevalidate = false; // Cache miss + } + else + { + // Conditional cache hit. (Validate) + } + + if (bCacheOnly && bOffline) + { + error( ERR_OFFLINE_MODE, m_request.url.prettyURL() ); + return false; + } + if (bCacheOnly) + { + error( ERR_DOES_NOT_EXIST, m_request.url.prettyURL() ); + return false; + } + if (bOffline) + { + error( ERR_OFFLINE_MODE, m_request.url.prettyURL() ); + return false; + } + } + + TQString header; + TQString davHeader; + + bool moreData = false; + bool davData = false; + + // Clear out per-connection settings... + resetConnectionSettings (); + + // Check the validity of the current connection, if one exists. + httpCheckConnection(); + + if ( !m_bIsTunneled && m_bNeedTunnel ) + { + setEnableSSLTunnel( true ); + // We send a HTTP 1.0 header since some proxies refuse HTTP 1.1 and we don't + // need any HTTP 1.1 capabilities for CONNECT - Waba + header = TQString("CONNECT %1:%2 HTTP/1.0" + "\r\n").arg( m_request.encoded_hostname).arg(m_request.port); + + // Identify who you are to the proxy server! + if (!m_request.userAgent.isEmpty()) + header += "User-Agent: " + m_request.userAgent + "\r\n"; + + /* Add hostname information */ + header += "Host: " + m_state.encoded_hostname; + + if (m_state.port != m_iDefaultPort) + header += TQString(":%1").arg(m_state.port); + header += "\r\n"; + + header += proxyAuthenticationHeader(); + } + else + { + // Determine if this is a POST or GET method + switch (m_request.method) + { + case HTTP_GET: + header = "GET "; + break; + case HTTP_PUT: + header = "PUT "; + moreData = true; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case HTTP_POST: + header = "POST "; + moreData = true; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case HTTP_HEAD: + header = "HEAD "; + break; + case HTTP_DELETE: + header = "DELETE "; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case HTTP_OPTIONS: + header = "OPTIONS "; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case DAV_PROPFIND: + header = "PROPFIND "; + davData = true; + davHeader = "Depth: "; + if ( hasMetaData( "davDepth" ) ) + { + kdDebug(7113) << "Reading DAV depth from metadata: " << metaData( "davDepth" ) << endl; + davHeader += metaData( "davDepth" ); + } + else + { + if ( m_request.davData.depth == 2 ) + davHeader += "infinity"; + else + davHeader += TQString("%1").arg( m_request.davData.depth ); + } + davHeader += "\r\n"; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case DAV_PROPPATCH: + header = "PROPPATCH "; + davData = true; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case DAV_MKCOL: + header = "MKCOL "; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case DAV_COPY: + case DAV_MOVE: + header = ( m_request.method == DAV_COPY ) ? "COPY " : "MOVE "; + davHeader = "Destination: " + m_request.davData.desturl; + // infinity depth means copy recursively + // (optional for copy -> but is the desired action) + davHeader += "\r\nDepth: infinity\r\nOverwrite: "; + davHeader += m_request.davData.overwrite ? "T" : "F"; + davHeader += "\r\n"; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case DAV_LOCK: + header = "LOCK "; + davHeader = "Timeout: "; + { + uint timeout = 0; + if ( hasMetaData( "davTimeout" ) ) + timeout = metaData( "davTimeout" ).toUInt(); + if ( timeout == 0 ) + davHeader += "Infinite"; + else + davHeader += TQString("Seconds-%1").arg(timeout); + } + davHeader += "\r\n"; + m_request.bCachedWrite = false; // Do not put any result in the cache + davData = true; + break; + case DAV_UNLOCK: + header = "UNLOCK "; + davHeader = "Lock-token: " + metaData("davLockToken") + "\r\n"; + m_request.bCachedWrite = false; // Do not put any result in the cache + break; + case DAV_SEARCH: + header = "SEARCH "; + davData = true; + m_request.bCachedWrite = false; + break; + case DAV_SUBSCRIBE: + header = "SUBSCRIBE "; + m_request.bCachedWrite = false; + break; + case DAV_UNSUBSCRIBE: + header = "UNSUBSCRIBE "; + m_request.bCachedWrite = false; + break; + case DAV_POLL: + header = "POLL "; + m_request.bCachedWrite = false; + break; + default: + error (ERR_UNSUPPORTED_ACTION, TQString::null); + return false; + } + // DAV_POLL; DAV_NOTIFY + + // format the URI + if (m_state.doProxy && !m_bIsTunneled) + { + KURL u; + + if (m_protocol == "webdav") + u.setProtocol( "http" ); + else if (m_protocol == "webdavs" ) + u.setProtocol( "https" ); + else + u.setProtocol( m_protocol ); + + // For all protocols other than the once handled by this io-slave + // append the username. This fixes a long standing bug of ftp io-slave + // logging in anonymously in proxied connections even when the username + // is explicitly specified. + if (m_protocol != "http" && m_protocol != "https" && + !m_state.user.isEmpty()) + u.setUser (m_state.user); + + u.setHost( m_state.hostname ); + if (m_state.port != m_iDefaultPort) + u.setPort( m_state.port ); + u.setEncodedPathAndQuery( m_request.url.encodedPathAndQuery(0,true) ); + header += u.url(); + } + else + { + header += m_request.url.encodedPathAndQuery(0, true); + } + + header += " HTTP/1.1\r\n"; /* start header */ + + if (!m_request.userAgent.isEmpty()) + { + header += "User-Agent: "; + header += m_request.userAgent; + header += "\r\n"; + } + + if (!m_request.referrer.isEmpty()) + { + header += "Referer: "; //Don't try to correct spelling! + header += m_request.referrer; + header += "\r\n"; + } + + if ( m_request.offset > 0 ) + { + header += TQString("Range: bytes=%1-\r\n").arg(TDEIO::number(m_request.offset)); + kdDebug(7103) << "tdeio_http : Range = " << TDEIO::number(m_request.offset) << endl; + } + + if ( m_request.cache == CC_Reload ) + { + /* No caching for reload */ + header += "Pragma: no-cache\r\n"; /* for HTTP/1.0 caches */ + header += "Cache-control: no-cache\r\n"; /* for HTTP >=1.1 caches */ + } + + if (m_request.bMustRevalidate) + { + /* conditional get */ + if (!m_request.etag.isEmpty()) + header += "If-None-Match: "+m_request.etag+"\r\n"; + if (!m_request.lastModified.isEmpty()) + header += "If-Modified-Since: "+m_request.lastModified+"\r\n"; + } + + header += "Accept: "; + TQString acceptHeader = metaData("accept"); + if (!acceptHeader.isEmpty()) + header += acceptHeader; + else + header += DEFAULT_ACCEPT_HEADER; + header += "\r\n"; + +#ifdef DO_GZIP + if (m_request.allowCompressedPage) + header += "Accept-Encoding: x-gzip, x-deflate, gzip, deflate\r\n"; +#endif + + if (!m_request.charsets.isEmpty()) + header += "Accept-Charset: " + m_request.charsets + "\r\n"; + + if (!m_request.languages.isEmpty()) + header += "Accept-Language: " + m_request.languages + "\r\n"; + + + /* support for virtual hosts and required by HTTP 1.1 */ + header += "Host: " + m_state.encoded_hostname; + + if (m_state.port != m_iDefaultPort) + header += TQString(":%1").arg(m_state.port); + header += "\r\n"; + + TQString cookieStr; + TQString cookieMode = metaData("cookies").lower(); + if (cookieMode == "none") + { + m_request.cookieMode = HTTPRequest::CookiesNone; + } + else if (cookieMode == "manual") + { + m_request.cookieMode = HTTPRequest::CookiesManual; + cookieStr = metaData("setcookies"); + } + else + { + m_request.cookieMode = HTTPRequest::CookiesAuto; + if (m_request.bUseCookiejar) + cookieStr = findCookies( m_request.url.url()); + } + + if (!cookieStr.isEmpty()) + header += cookieStr + "\r\n"; + + TQString customHeader = metaData( "customHTTPHeader" ); + if (!customHeader.isEmpty()) + { + header += sanitizeCustomHTTPHeader(customHeader); + header += "\r\n"; + } + + if (m_request.method == HTTP_POST) + { + header += metaData("content-type"); + header += "\r\n"; + } + + // Only check for a cached copy if the previous + // response was NOT a 401 or 407. + // no caching for Negotiate auth. + if ( !m_request.bNoAuth && m_responseCode != 401 && m_responseCode != 407 && Authentication != AUTH_Negotiate ) + { + kdDebug(7113) << "(" << m_pid << ") Calling checkCachedAuthentication " << endl; + AuthInfo info; + info.url = m_request.url; + info.verifyPath = true; + if ( !m_request.user.isEmpty() ) + info.username = m_request.user; + if ( checkCachedAuthentication( info ) && !info.digestInfo.isEmpty() ) + { + Authentication = info.digestInfo.startsWith("Basic") ? AUTH_Basic : info.digestInfo.startsWith("NTLM") ? AUTH_NTLM : info.digestInfo.startsWith("Negotiate") ? AUTH_Negotiate : AUTH_Digest ; + m_state.user = info.username; + m_state.passwd = info.password; + m_strRealm = info.realmValue; + if ( Authentication != AUTH_NTLM && Authentication != AUTH_Negotiate ) // don't use the cached challenge + m_strAuthorization = info.digestInfo; + } + } + else + { + kdDebug(7113) << "(" << m_pid << ") Not calling checkCachedAuthentication " << endl; + } + + switch ( Authentication ) + { + case AUTH_Basic: + header += createBasicAuth(); + break; + case AUTH_Digest: + header += createDigestAuth(); + break; +#ifdef HAVE_LIBGSSAPI + case AUTH_Negotiate: + header += createNegotiateAuth(); + break; +#endif + case AUTH_NTLM: + header += createNTLMAuth(); + break; + case AUTH_None: + default: + break; + } + + /********* Only for debugging purpose *********/ + if ( Authentication != AUTH_None ) + { + kdDebug(7113) << "(" << m_pid << ") Using Authentication: " << endl; + kdDebug(7113) << "(" << m_pid << ") HOST= " << m_state.hostname << endl; + kdDebug(7113) << "(" << m_pid << ") PORT= " << m_state.port << endl; + kdDebug(7113) << "(" << m_pid << ") USER= " << m_state.user << endl; + kdDebug(7113) << "(" << m_pid << ") PASSWORD= [protected]" << endl; + kdDebug(7113) << "(" << m_pid << ") REALM= " << m_strRealm << endl; + kdDebug(7113) << "(" << m_pid << ") EXTRA= " << m_strAuthorization << endl; + } + + // Do we need to authorize to the proxy server ? + if ( m_state.doProxy && !m_bIsTunneled ) + header += proxyAuthenticationHeader(); + + // Support old HTTP/1.0 style keep-alive header for compatability + // purposes as well as performance improvements while giving end + // users the ability to disable this feature proxy servers that + // don't not support such feature, e.g. junkbuster proxy server. + if (!m_bUseProxy || m_bPersistentProxyConnection || m_bIsTunneled) + header += "Connection: Keep-Alive\r\n"; + else + header += "Connection: close\r\n"; + + if ( m_protocol == "webdav" || m_protocol == "webdavs" ) + { + header += davProcessLocks(); + + // add extra webdav headers, if supplied + TQString davExtraHeader = metaData("davHeader"); + if ( !davExtraHeader.isEmpty() ) + davHeader += davExtraHeader; + + // Set content type of webdav data + if (davData) + davHeader += "Content-Type: text/xml; charset=utf-8\r\n"; + + // add extra header elements for WebDAV + if ( !davHeader.isNull() ) + header += davHeader; + } + } + + kdDebug(7103) << "(" << m_pid << ") ============ Sending Header:" << endl; + + TQStringList headerOutput = TQStringList::split("\r\n", header); + TQStringList::Iterator it = headerOutput.begin(); + + for (; it != headerOutput.end(); it++) + kdDebug(7103) << "(" << m_pid << ") " << (*it) << endl; + + if ( !moreData && !davData) + header += "\r\n"; /* end header */ + + // Now that we have our formatted header, let's send it! + // Create a new connection to the remote machine if we do + // not already have one... + if ( m_iSock == -1) + { + if (!httpOpenConnection()) + return false; + } + + // Send the data to the remote machine... + bool sendOk = (write(header.latin1(), header.length()) == (ssize_t) header.length()); + if (!sendOk) + { + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen: " + "Connection broken! (" << m_state.hostname << ")" << endl; + + // With a Keep-Alive connection this can happen. + // Just reestablish the connection. + if (m_bKeepAlive) + { + httpCloseConnection(); + return true; // Try again + } + + if (!sendOk) + { + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen: sendOk==false." + " Connnection broken !" << endl; + error( ERR_CONNECTION_BROKEN, m_state.hostname ); + return false; + } + } + + bool res = true; + + if ( moreData || davData ) + res = sendBody(); + + infoMessage(i18n("%1 contacted. Waiting for reply...").arg(m_request.hostname)); + + return res; +} + +void HTTPProtocol::forwardHttpResponseHeader() +{ + // Send the response header if it was requested + if ( config()->readBoolEntry("PropagateHttpHeader", false) ) + { + setMetaData("HTTP-Headers", m_responseHeader.join("\n")); + sendMetaData(); + } + m_responseHeader.clear(); +} + +/** + * This function will read in the return header from the server. It will + * not read in the body of the return message. It will also not transmit + * the header to our client as the client doesn't need to know the gory + * details of HTTP headers. + */ +bool HTTPProtocol::readHeader() +{ +try_again: + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader" << endl; + + // Check + if (m_request.bCachedRead) + { + m_responseHeader << "HTTP-CACHE"; + // Read header from cache... + char buffer[4097]; + if (!fgets(buffer, 4096, m_request.fcache) ) + { + // Error, delete cache entry + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: " + << "Could not access cache to obtain mimetype!" << endl; + error( ERR_CONNECTION_BROKEN, m_state.hostname ); + return false; + } + + m_strMimeType = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace(); + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: cached " + << "data mimetype: " << m_strMimeType << endl; + + if (!fgets(buffer, 4096, m_request.fcache) ) + { + // Error, delete cache entry + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: " + << "Could not access cached data! " << endl; + error( ERR_CONNECTION_BROKEN, m_state.hostname ); + return false; + } + + m_request.strCharset = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace().lower(); + setMetaData("charset", m_request.strCharset); + if (!m_request.lastModified.isEmpty()) + setMetaData("modified", m_request.lastModified); + TQString tmp; + tmp.setNum(m_request.expireDate); + setMetaData("expire-date", tmp); + tmp.setNum(m_request.creationDate); + setMetaData("cache-creation-date", tmp); + mimeType(m_strMimeType); + forwardHttpResponseHeader(); + return true; + } + + TQCString locationStr; // In case we get a redirect. + TQCString cookieStr; // In case we get a cookie. + + TQString dispositionType; // In case we get a Content-Disposition type + TQString dispositionFilename; // In case we get a Content-Disposition filename + + TQString mediaValue; + TQString mediaAttribute; + + TQStringList upgradeOffers; + + bool upgradeRequired = false; // Server demands that we upgrade to something + // This is also true if we ask to upgrade and + // the server accepts, since we are now + // committed to doing so + bool canUpgrade = false; // The server offered an upgrade + + + m_request.etag = TQString::null; + m_request.lastModified = TQString::null; + m_request.strCharset = TQString::null; + + time_t dateHeader = 0; + time_t expireDate = 0; // 0 = no info, 1 = already expired, > 1 = actual date + int currentAge = 0; + int maxAge = -1; // -1 = no max age, 0 already expired, > 0 = actual time + int maxHeaderSize = 64*1024; // 64Kb to catch DOS-attacks + + // read in 8192 bytes at a time (HTTP cookies can be quite large.) + int len = 0; + char buffer[8193]; + bool cont = false; + bool cacheValidated = false; // Revalidation was successful + bool mayCache = true; + bool hasCacheDirective = false; + bool bCanResume = false; + + if (m_iSock == -1) + { + kdDebug(7113) << "HTTPProtocol::readHeader: No connection." << endl; + return false; // Restablish connection and try again + } + + if (!waitForResponse(m_remoteRespTimeout)) + { + // No response error + error( ERR_SERVER_TIMEOUT , m_state.hostname ); + return false; + } + + setRewindMarker(); + + gets(buffer, sizeof(buffer)-1); + + if (m_bEOF || *buffer == '\0') + { + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: " + << "EOF while waiting for header start." << endl; + if (m_bKeepAlive) // Try to reestablish connection. + { + httpCloseConnection(); + return false; // Reestablish connection and try again. + } + + if (m_request.method == HTTP_HEAD) + { + // HACK + // Some web-servers fail to respond properly to a HEAD request. + // We compensate for their failure to properly implement the HTTP standard + // by assuming that they will be sending html. + kdDebug(7113) << "(" << m_pid << ") HTTPPreadHeader: HEAD -> returned " + << "mimetype: " << DEFAULT_MIME_TYPE << endl; + mimeType(TQString::fromLatin1(DEFAULT_MIME_TYPE)); + return true; + } + + kdDebug(7113) << "HTTPProtocol::readHeader: Connection broken !" << endl; + error( ERR_CONNECTION_BROKEN, m_state.hostname ); + return false; + } + + kdDebug(7103) << "(" << m_pid << ") ============ Received Response:"<< endl; + + bool noHeader = true; + HTTP_REV httpRev = HTTP_None; + int headerSize = 0; + + do + { + // strip off \r and \n if we have them + len = strlen(buffer); + + while(len && (buffer[len-1] == '\n' || buffer[len-1] == '\r')) + buffer[--len] = 0; + + // if there was only a newline then continue + if (!len) + { + kdDebug(7103) << "(" << m_pid << ") --empty--" << endl; + continue; + } + + headerSize += len; + + // We have a response header. This flag is a work around for + // servers that append a "\r\n" before the beginning of the HEADER + // response!!! It only catches x number of \r\n being placed at the + // top of the reponse... + noHeader = false; + + kdDebug(7103) << "(" << m_pid << ") \"" << buffer << "\"" << endl; + + // Save broken servers from damnation!! + char* buf = buffer; + while( *buf == ' ' ) + buf++; + + + if (buf[0] == '<') + { + // We get XML / HTTP without a proper header + // put string back + kdDebug(7103) << "tdeio_http: No valid HTTP header found! Document starts with XML/HTML tag" << endl; + + // Document starts with a tag, assume html instead of text/plain + m_strMimeType = "text/html"; + + rewind(); + break; + } + + // Store the the headers so they can be passed to the + // calling application later + m_responseHeader << TQString::fromLatin1(buf); + + if ((strncasecmp(buf, "HTTP/", 5) == 0) || + (strncasecmp(buf, "ICY ", 4) == 0)) // Shoutcast support + { + if (strncasecmp(buf, "ICY ", 4) == 0) + { + // Shoutcast support + httpRev = SHOUTCAST; + m_bKeepAlive = false; + } + else if (strncmp((buf + 5), "1.0",3) == 0) + { + httpRev = HTTP_10; + // For 1.0 servers, the server itself has to explicitly + // tell us whether it supports persistent connection or + // not. By default, we assume it does not, but we do + // send the old style header "Connection: Keep-Alive" to + // inform it that we support persistence. + m_bKeepAlive = false; + } + else if (strncmp((buf + 5), "1.1",3) == 0) + { + httpRev = HTTP_11; + } + else + { + httpRev = HTTP_Unknown; + } + + if (m_responseCode) + m_prevResponseCode = m_responseCode; + + const char* rptr = buf; + while ( *rptr && *rptr > ' ' ) + ++rptr; + m_responseCode = atoi(rptr); + + // server side errors + if (m_responseCode >= 500 && m_responseCode <= 599) + { + if (m_request.method == HTTP_HEAD) + { + ; // Ignore error + } + else + { + if (m_request.bErrorPage) + errorPage(); + else + { + error(ERR_INTERNAL_SERVER, m_request.url.prettyURL()); + return false; + } + } + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + // Unauthorized access + else if (m_responseCode == 401 || m_responseCode == 407) + { + // Double authorization requests, i.e. a proxy auth + // request followed immediately by a regular auth request. + if ( m_prevResponseCode != m_responseCode && + (m_prevResponseCode == 401 || m_prevResponseCode == 407) ) + saveAuthorization(); + + m_bUnauthorized = true; + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + // + else if (m_responseCode == 416) // Range not supported + { + m_request.offset = 0; + httpCloseConnection(); + return false; // Try again. + } + // Upgrade Required + else if (m_responseCode == 426) + { + upgradeRequired = true; + } + // Any other client errors + else if (m_responseCode >= 400 && m_responseCode <= 499) + { + // Tell that we will only get an error page here. + if (m_request.bErrorPage) + errorPage(); + else + { + error(ERR_DOES_NOT_EXIST, m_request.url.prettyURL()); + return false; + } + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + else if (m_responseCode == 307) + { + // 307 Temporary Redirect + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + else if (m_responseCode == 304) + { + // 304 Not Modified + // The value in our cache is still valid. + cacheValidated = true; + } + else if (m_responseCode >= 301 && m_responseCode<= 303) + { + // 301 Moved permanently + if (m_responseCode == 301) + setMetaData("permanent-redirect", "true"); + + // 302 Found (temporary location) + // 303 See Other + if (m_request.method != HTTP_HEAD && m_request.method != HTTP_GET) + { +#if 0 + // Reset the POST buffer to avoid a double submit + // on redirection + if (m_request.method == HTTP_POST) + m_bufPOST.resize(0); +#endif + + // NOTE: This is wrong according to RFC 2616. However, + // because most other existing user agent implementations + // treat a 301/302 response as a 303 response and preform + // a GET action regardless of what the previous method was, + // many servers have simply adapted to this way of doing + // things!! Thus, we are forced to do the same thing or we + // won't be able to retrieve these pages correctly!! See RFC + // 2616 sections 10.3.[2/3/4/8] + m_request.method = HTTP_GET; // Force a GET + } + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + else if ( m_responseCode == 207 ) // Multi-status (for WebDav) + { + + } + else if ( m_responseCode == 204 ) // No content + { + // error(ERR_NO_CONTENT, i18n("Data have been successfully sent.")); + // Short circuit and do nothing! + + // The original handling here was wrong, this is not an error: eg. in the + // example of a 204 No Content response to a PUT completing. + // m_bError = true; + // return false; + } + else if ( m_responseCode == 206 ) + { + if ( m_request.offset ) + bCanResume = true; + } + else if (m_responseCode == 102) // Processing (for WebDAV) + { + /*** + * This status code is given when the server expects the + * command to take significant time to complete. So, inform + * the user. + */ + infoMessage( i18n( "Server processing request, please wait..." ) ); + cont = true; + } + else if (m_responseCode == 100) + { + // We got 'Continue' - ignore it + cont = true; + } + } + + // are we allowd to resume? this will tell us + else if (strncasecmp(buf, "Accept-Ranges:", 14) == 0) { + if (strncasecmp(trimLead(buf + 14), "none", 4) == 0) + bCanResume = false; + } + // Keep Alive + else if (strncasecmp(buf, "Keep-Alive:", 11) == 0) { + TQStringList options = TQStringList::split(',', + TQString::fromLatin1(trimLead(buf+11))); + for(TQStringList::ConstIterator it = options.begin(); + it != options.end(); + it++) + { + TQString option = (*it).stripWhiteSpace().lower(); + if (option.startsWith("timeout=")) + { + m_keepAliveTimeout = option.mid(8).toInt(); + } + } + } + + // Cache control + else if (strncasecmp(buf, "Cache-Control:", 14) == 0) { + TQStringList cacheControls = TQStringList::split(',', + TQString::fromLatin1(trimLead(buf+14))); + for(TQStringList::ConstIterator it = cacheControls.begin(); + it != cacheControls.end(); + it++) + { + TQString cacheControl = (*it).stripWhiteSpace(); + if (strncasecmp(cacheControl.latin1(), "no-cache", 8) == 0) + { + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + else if (strncasecmp(cacheControl.latin1(), "no-store", 8) == 0) + { + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + } + else if (strncasecmp(cacheControl.latin1(), "max-age=", 8) == 0) + { + TQString age = cacheControl.mid(8).stripWhiteSpace(); + if (!age.isNull()) + maxAge = STRTOLL(age.latin1(), 0, 10); + } + } + hasCacheDirective = true; + } + + // get the size of our data + else if (strncasecmp(buf, "Content-length:", 15) == 0) { + char* len = trimLead(buf + 15); + if (len) + m_iSize = STRTOLL(len, 0, 10); + } + + else if (strncasecmp(buf, "Content-location:", 17) == 0) { + setMetaData ("content-location", + TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace()); + } + + // what type of data do we have? + else if (strncasecmp(buf, "Content-type:", 13) == 0) { + char *start = trimLead(buf + 13); + char *pos = start; + + // Increment until we encounter ";" or the end of the buffer + while ( *pos && *pos != ';' ) pos++; + + // Assign the mime-type. + m_strMimeType = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower(); + kdDebug(7113) << "(" << m_pid << ") Content-type: " << m_strMimeType << endl; + + // If we still have text, then it means we have a mime-type with a + // parameter (eg: charset=iso-8851) ; so let's get that... + while (*pos) + { + start = ++pos; + while ( *pos && *pos != '=' ) pos++; + + char *end = pos; + while ( *end && *end != ';' ) end++; + + if (*pos) + { + mediaAttribute = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower(); + mediaValue = TQString::fromLatin1(pos+1, end-pos-1).stripWhiteSpace(); + pos = end; + if (mediaValue.length() && + (mediaValue[0] == '"') && + (mediaValue[mediaValue.length()-1] == '"')) + mediaValue = mediaValue.mid(1, mediaValue.length()-2); + + kdDebug (7113) << "(" << m_pid << ") Media-Parameter Attribute: " + << mediaAttribute << endl; + kdDebug (7113) << "(" << m_pid << ") Media-Parameter Value: " + << mediaValue << endl; + + if ( mediaAttribute == "charset") + { + mediaValue = mediaValue.lower(); + m_request.strCharset = mediaValue; + } + else + { + setMetaData("media-"+mediaAttribute, mediaValue); + } + } + } + } + + // Date + else if (strncasecmp(buf, "Date:", 5) == 0) { + dateHeader = KRFCDate::parseDate(trimLead(buf+5)); + } + + // Cache management + else if (strncasecmp(buf, "ETag:", 5) == 0) { + m_request.etag = trimLead(buf+5); + } + + // Cache management + else if (strncasecmp(buf, "Expires:", 8) == 0) { + expireDate = KRFCDate::parseDate(trimLead(buf+8)); + if (!expireDate) + expireDate = 1; // Already expired + } + + // Cache management + else if (strncasecmp(buf, "Last-Modified:", 14) == 0) { + m_request.lastModified = (TQString::fromLatin1(trimLead(buf+14))).stripWhiteSpace(); + } + + // whoops.. we received a warning + else if (strncasecmp(buf, "Warning:", 8) == 0) { + //Don't use warning() here, no need to bother the user. + //Those warnings are mostly about caches. + infoMessage(trimLead(buf + 8)); + } + + // Cache management (HTTP 1.0) + else if (strncasecmp(buf, "Pragma:", 7) == 0) { + TQCString pragma = TQCString(trimLead(buf+7)).stripWhiteSpace().lower(); + if (pragma == "no-cache") + { + m_request.bCachedWrite = false; // Don't put in cache + mayCache = false; + hasCacheDirective = true; + } + } + + // The deprecated Refresh Response + else if (strncasecmp(buf,"Refresh:", 8) == 0) { + mayCache = false; // Do not cache page as it defeats purpose of Refresh tag! + setMetaData( "http-refresh", TQString::fromLatin1(trimLead(buf+8)).stripWhiteSpace() ); + } + + // In fact we should do redirection only if we got redirection code + else if (strncasecmp(buf, "Location:", 9) == 0) { + // Redirect only for 3xx status code, will ya! Thanks, pal! + if ( m_responseCode > 299 && m_responseCode < 400 ) + locationStr = TQCString(trimLead(buf+9)).stripWhiteSpace(); + } + + // Check for cookies + else if (strncasecmp(buf, "Set-Cookie", 10) == 0) { + cookieStr += buf; + cookieStr += '\n'; + } + + // check for direct authentication + else if (strncasecmp(buf, "WWW-Authenticate:", 17) == 0) { + configAuth(trimLead(buf + 17), false); + } + + // check for proxy-based authentication + else if (strncasecmp(buf, "Proxy-Authenticate:", 19) == 0) { + configAuth(trimLead(buf + 19), true); + } + + else if (strncasecmp(buf, "Upgrade:", 8) == 0) { + // Now we have to check to see what is offered for the upgrade + TQString offered = &(buf[8]); + upgradeOffers = TQStringList::split(TQRegExp("[ \n,\r\t]"), offered); + } + + // content? + else if (strncasecmp(buf, "Content-Encoding:", 17) == 0) { + // This is so wrong !! No wonder tdeio_http is stripping the + // gzip encoding from downloaded files. This solves multiple + // bug reports and caitoo's problem with downloads when such a + // header is encountered... + + // A quote from RFC 2616: + // " When present, its (Content-Encoding) value indicates what additional + // content have been applied to the entity body, and thus what decoding + // mechanism must be applied to obtain the media-type referenced by the + // Content-Type header field. Content-Encoding is primarily used to allow + // a document to be compressed without loosing the identity of its underlying + // media type. Simply put if it is specified, this is the actual mime-type + // we should use when we pull the resource !!! + addEncoding(trimLead(buf + 17), m_qContentEncodings); + } + // Refer to RFC 2616 sec 15.5/19.5.1 and RFC 2183 + else if(strncasecmp(buf, "Content-Disposition:", 20) == 0) { + char* dispositionBuf = trimLead(buf + 20); + while ( *dispositionBuf ) + { + if ( strncasecmp( dispositionBuf, "filename", 8 ) == 0 ) + { + dispositionBuf += 8; + + while ( *dispositionBuf == ' ' || *dispositionBuf == '=' ) + dispositionBuf++; + + char* bufStart = dispositionBuf; + + while ( *dispositionBuf && *dispositionBuf != ';' ) + dispositionBuf++; + + if ( dispositionBuf > bufStart ) + { + // Skip any leading quotes... + while ( *bufStart == '"' ) + bufStart++; + + // Skip any trailing quotes as well as white spaces... + while ( *(dispositionBuf-1) == ' ' || *(dispositionBuf-1) == '"') + dispositionBuf--; + + if ( dispositionBuf > bufStart ) + dispositionFilename = TQString::fromLatin1( bufStart, dispositionBuf-bufStart ); + + break; + } + } + else + { + char *bufStart = dispositionBuf; + + while ( *dispositionBuf && *dispositionBuf != ';' ) + dispositionBuf++; + + if ( dispositionBuf > bufStart ) + dispositionType = TQString::fromLatin1( bufStart, dispositionBuf-bufStart ).stripWhiteSpace(); + + while ( *dispositionBuf == ';' || *dispositionBuf == ' ' ) + dispositionBuf++; + } + } + + // Content-Dispostion is not allowed to dictate directory + // path, thus we extract the filename only. + if ( !dispositionFilename.isEmpty() ) + { + int pos = dispositionFilename.findRev( '/' ); + + if( pos > -1 ) + dispositionFilename = dispositionFilename.mid(pos+1); + + kdDebug(7113) << "(" << m_pid << ") Content-Disposition: filename=" + << dispositionFilename<< endl; + } + } + else if(strncasecmp(buf, "Content-Language:", 17) == 0) { + TQString language = TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace(); + if (!language.isEmpty()) + setMetaData("content-language", language); + } + else if (strncasecmp(buf, "Proxy-Connection:", 17) == 0) + { + if (strncasecmp(trimLead(buf + 17), "Close", 5) == 0) + m_bKeepAlive = false; + else if (strncasecmp(trimLead(buf + 17), "Keep-Alive", 10)==0) + m_bKeepAlive = true; + } + else if (strncasecmp(buf, "Link:", 5) == 0) { + // We only support Link: ; rel="type" so far + TQStringList link = TQStringList::split(";", TQString(buf) + .replace(TQRegExp("^Link:[ ]*"), + "")); + if (link.count() == 2) { + TQString rel = link[1].stripWhiteSpace(); + if (rel.startsWith("rel=\"")) { + rel = rel.mid(5, rel.length() - 6); + if (rel.lower() == "pageservices") { + TQString url = TQString(link[0].replace(TQRegExp("[<>]"),"")).stripWhiteSpace(); + setMetaData("PageServices", url); + } + } + } + } + else if (strncasecmp(buf, "P3P:", 4) == 0) { + TQString p3pstr = buf; + p3pstr = p3pstr.mid(4).simplifyWhiteSpace(); + TQStringList policyrefs, compact; + TQStringList policyfields = TQStringList::split(TQRegExp(",[ ]*"), p3pstr); + for (TQStringList::Iterator it = policyfields.begin(); + it != policyfields.end(); + ++it) { + TQStringList policy = TQStringList::split("=", *it); + + if (policy.count() == 2) { + if (policy[0].lower() == "policyref") { + policyrefs << TQString(policy[1].replace(TQRegExp("[\"\']"), "")) + .stripWhiteSpace(); + } else if (policy[0].lower() == "cp") { + // We convert to cp\ncp\ncp\n[...]\ncp to be consistent with + // other metadata sent in strings. This could be a bit more + // efficient but I'm going for correctness right now. + TQStringList cps = TQStringList::split(" ", + TQString(policy[1].replace(TQRegExp("[\"\']"), "")) + .simplifyWhiteSpace()); + + for (TQStringList::Iterator j = cps.begin(); j != cps.end(); ++j) + compact << *j; + } + } + } + + if (!policyrefs.isEmpty()) + setMetaData("PrivacyPolicy", policyrefs.join("\n")); + + if (!compact.isEmpty()) + setMetaData("PrivacyCompactPolicy", compact.join("\n")); + } + // let them tell us if we should stay alive or not + else if (strncasecmp(buf, "Connection:", 11) == 0) + { + if (strncasecmp(trimLead(buf + 11), "Close", 5) == 0) + m_bKeepAlive = false; + else if (strncasecmp(trimLead(buf + 11), "Keep-Alive", 10)==0) + m_bKeepAlive = true; + else if (strncasecmp(trimLead(buf + 11), "Upgrade", 7)==0) + { + if (m_responseCode == 101) { + // Ok, an upgrade was accepted, now we must do it + upgradeRequired = true; + } else if (upgradeRequired) { // 426 + // Nothing to do since we did it above already + } else { + // Just an offer to upgrade - no need to take it + canUpgrade = true; + } + } + } + // continue only if we know that we're HTTP/1.1 + else if ( httpRev == HTTP_11) { + // what kind of encoding do we have? transfer? + if (strncasecmp(buf, "Transfer-Encoding:", 18) == 0) { + // If multiple encodings have been applied to an entity, the + // transfer-codings MUST be listed in the order in which they + // were applied. + addEncoding(trimLead(buf + 18), m_qTransferEncodings); + } + + // md5 signature + else if (strncasecmp(buf, "Content-MD5:", 12) == 0) { + m_sContentMD5 = TQString::fromLatin1(trimLead(buf + 12)); + } + + // *** Responses to the HTTP OPTIONS method follow + // WebDAV capabilities + else if (strncasecmp(buf, "DAV:", 4) == 0) { + if (m_davCapabilities.isEmpty()) { + m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4)); + } + else { + m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4)); + } + } + // *** Responses to the HTTP OPTIONS method finished + } + else if ((httpRev == HTTP_None) && (strlen(buf) != 0)) + { + // Remote server does not seem to speak HTTP at all + // Put the crap back into the buffer and hope for the best + rewind(); + if (m_responseCode) + m_prevResponseCode = m_responseCode; + + m_responseCode = 200; // Fake it + httpRev = HTTP_Unknown; + m_bKeepAlive = false; + break; + } + setRewindMarker(); + + // Clear out our buffer for further use. + memset(buffer, 0, sizeof(buffer)); + + } while (!m_bEOF && (len || noHeader) && (headerSize < maxHeaderSize) && (gets(buffer, sizeof(buffer)-1))); + + // Now process the HTTP/1.1 upgrade + TQStringList::Iterator opt = upgradeOffers.begin(); + for( ; opt != upgradeOffers.end(); ++opt) { + if (*opt == "TLS/1.0") { + if(upgradeRequired) { + if (!startTLS() && !usingTLS()) { + error(ERR_UPGRADE_REQUIRED, *opt); + return false; + } + } + } else if (*opt == "HTTP/1.1") { + httpRev = HTTP_11; + } else { + // unknown + if (upgradeRequired) { + error(ERR_UPGRADE_REQUIRED, *opt); + return false; + } + } + } + + setMetaData("charset", m_request.strCharset); + + // If we do not support the requested authentication method... + if ( (m_responseCode == 401 && Authentication == AUTH_None) || + (m_responseCode == 407 && ProxyAuthentication == AUTH_None) ) + { + m_bUnauthorized = false; + if (m_request.bErrorPage) + errorPage(); + else + { + error( ERR_UNSUPPORTED_ACTION, "Unknown Authorization method!" ); + return false; + } + } + + // Fixup expire date for clock drift. + if (expireDate && (expireDate <= dateHeader)) + expireDate = 1; // Already expired. + + // Convert max-age into expireDate (overriding previous set expireDate) + if (maxAge == 0) + expireDate = 1; // Already expired. + else if (maxAge > 0) + { + if (currentAge) + maxAge -= currentAge; + if (maxAge <=0) + maxAge = 0; + expireDate = time(0) + maxAge; + } + + if (!expireDate) + { + time_t lastModifiedDate = 0; + if (!m_request.lastModified.isEmpty()) + lastModifiedDate = KRFCDate::parseDate(m_request.lastModified); + + if (lastModifiedDate) + { + long diff = static_cast(difftime(dateHeader, lastModifiedDate)); + if (diff < 0) + expireDate = time(0) + 1; + else + expireDate = time(0) + (diff / 10); + } + else + { + expireDate = time(0) + DEFAULT_CACHE_EXPIRE; + } + } + + // DONE receiving the header! + if (!cookieStr.isEmpty()) + { + if ((m_request.cookieMode == HTTPRequest::CookiesAuto) && m_request.bUseCookiejar) + { + // Give cookies to the cookiejar. + TQString domain = config()->readEntry("cross-domain"); + if (!domain.isEmpty() && isCrossDomainRequest(m_request.url.host(), domain)) + cookieStr = "Cross-Domain\n" + cookieStr; + addCookies( m_request.url.url(), cookieStr ); + } + else if (m_request.cookieMode == HTTPRequest::CookiesManual) + { + // Pass cookie to application + setMetaData("setcookies", cookieStr); + } + } + + if (m_request.bMustRevalidate) + { + m_request.bMustRevalidate = false; // Reset just in case. + if (cacheValidated) + { + // Yippie, we can use the cached version. + // Update the cache with new "Expire" headers. + fclose(m_request.fcache); + m_request.fcache = 0; + updateExpireDate( expireDate, true ); + m_request.fcache = checkCacheEntry( ); // Re-read cache entry + + if (m_request.fcache) + { + m_request.bCachedRead = true; + goto try_again; // Read header again, but now from cache. + } + else + { + // Where did our cache entry go??? + } + } + else + { + // Validation failed. Close cache. + fclose(m_request.fcache); + m_request.fcache = 0; + } + } + + // We need to reread the header if we got a '100 Continue' or '102 Processing' + if ( cont ) + { + goto try_again; + } + + // Do not do a keep-alive connection if the size of the + // response is not known and the response is not Chunked. + if (!m_bChunked && (m_iSize == NO_SIZE)) + m_bKeepAlive = false; + + if ( m_responseCode == 204 ) + { + return true; + } + + // We need to try to login again if we failed earlier + if ( m_bUnauthorized ) + { + if ( (m_responseCode == 401) || + (m_bUseProxy && (m_responseCode == 407)) + ) + { + if ( getAuthorization() ) + { + // for NTLM Authentication we have to keep the connection open! + if ( Authentication == AUTH_NTLM && m_strAuthorization.length() > 4 ) + { + m_bKeepAlive = true; + readBody( true ); + } + else if (ProxyAuthentication == AUTH_NTLM && m_strProxyAuthorization.length() > 4) + { + readBody( true ); + } + else + httpCloseConnection(); + return false; // Try again. + } + + if (m_bError) + return false; // Error out + + // Show error page... + } + m_bUnauthorized = false; + } + + // We need to do a redirect + if (!locationStr.isEmpty()) + { + KURL u(m_request.url, locationStr); + if(!u.isValid()) + { + error(ERR_MALFORMED_URL, u.prettyURL()); + return false; + } + if ((u.protocol() != "http") && (u.protocol() != "https") && + (u.protocol() != "ftp") && (u.protocol() != "webdav") && + (u.protocol() != "webdavs")) + { + redirection(u); + error(ERR_ACCESS_DENIED, u.prettyURL()); + return false; + } + + // preserve #ref: (bug 124654) + // if we were at http://host/resource1#ref, we sent a GET for "/resource1" + // if we got redirected to http://host/resource2, then we have to re-add + // the fragment: + if (m_request.url.hasRef() && !u.hasRef() && + (m_request.url.host() == u.host()) && + (m_request.url.protocol() == u.protocol())) + u.setRef(m_request.url.ref()); + + m_bRedirect = true; + m_redirectLocation = u; + + if (!m_request.id.isEmpty()) + { + sendMetaData(); + } + + kdDebug(7113) << "(" << m_pid << ") request.url: " << m_request.url.prettyURL() + << endl << "LocationStr: " << locationStr.data() << endl; + + kdDebug(7113) << "(" << m_pid << ") Requesting redirection to: " << u.prettyURL() + << endl; + + // If we're redirected to a http:// url, remember that we're doing webdav... + if (m_protocol == "webdav" || m_protocol == "webdavs") + u.setProtocol(m_protocol); + + redirection(u); + m_request.bCachedWrite = false; // Turn off caching on re-direction (DA) + mayCache = false; + } + + // Inform the job that we can indeed resume... + if ( bCanResume && m_request.offset ) + canResume(); + else + m_request.offset = 0; + + // We don't cache certain text objects + if (m_strMimeType.startsWith("text/") && + (m_strMimeType != "text/css") && + (m_strMimeType != "text/x-javascript") && + !hasCacheDirective) + { + // Do not cache secure pages or pages + // originating from password protected sites + // unless the webserver explicitly allows it. + if ( m_bIsSSL || (Authentication != AUTH_None) ) + { + m_request.bCachedWrite = false; + mayCache = false; + } + } + + // WABA: Correct for tgz files with a gzip-encoding. + // They really shouldn't put gzip in the Content-Encoding field! + // Web-servers really shouldn't do this: They let Content-Size refer + // to the size of the tgz file, not to the size of the tar file, + // while the Content-Type refers to "tar" instead of "tgz". + if (m_qContentEncodings.last() == "gzip") + { + if (m_strMimeType == "application/x-tar") + { + m_qContentEncodings.remove(m_qContentEncodings.fromLast()); + m_strMimeType = TQString::fromLatin1("application/x-tgz"); + } + else if (m_strMimeType == "application/postscript") + { + // LEONB: Adding another exception for psgz files. + // Could we use the mimelnk files instead of hardcoding all this? + m_qContentEncodings.remove(m_qContentEncodings.fromLast()); + m_strMimeType = TQString::fromLatin1("application/x-gzpostscript"); + } + else if ( m_request.allowCompressedPage && + m_strMimeType != "application/x-tgz" && + m_strMimeType != "application/x-targz" && + m_strMimeType != "application/x-gzip" && + m_request.url.path().right(6) == ".ps.gz" ) + { + m_qContentEncodings.remove(m_qContentEncodings.fromLast()); + m_strMimeType = TQString::fromLatin1("application/x-gzpostscript"); + } + else if ( (m_request.allowCompressedPage && + m_strMimeType == "text/html") + || + (m_request.allowCompressedPage && + m_strMimeType != "application/x-tgz" && + m_strMimeType != "application/x-targz" && + m_strMimeType != "application/x-gzip" && + m_request.url.path().right(3) != ".gz") + ) + { + // Unzip! + } + else + { + m_qContentEncodings.remove(m_qContentEncodings.fromLast()); + m_strMimeType = TQString::fromLatin1("application/x-gzip"); + } + } + + // We can't handle "bzip2" encoding (yet). So if we get something with + // bzip2 encoding, we change the mimetype to "application/x-bzip2". + // Note for future changes: some web-servers send both "bzip2" as + // encoding and "application/x-bzip2" as mimetype. That is wrong. + // currently that doesn't bother us, because we remove the encoding + // and set the mimetype to x-bzip2 anyway. + if (m_qContentEncodings.last() == "bzip2") + { + m_qContentEncodings.remove(m_qContentEncodings.fromLast()); + m_strMimeType = TQString::fromLatin1("application/x-bzip2"); + } + + // Convert some common mimetypes to standard KDE mimetypes + if (m_strMimeType == "application/x-targz") + m_strMimeType = TQString::fromLatin1("application/x-tgz"); + else if (m_strMimeType == "application/zip") + m_strMimeType = TQString::fromLatin1("application/x-zip"); + else if (m_strMimeType == "image/x-png") + m_strMimeType = TQString::fromLatin1("image/png"); + else if (m_strMimeType == "image/bmp") + m_strMimeType = TQString::fromLatin1("image/x-bmp"); + else if (m_strMimeType == "audio/mpeg" || m_strMimeType == "audio/x-mpeg" || m_strMimeType == "audio/mp3") + m_strMimeType = TQString::fromLatin1("audio/x-mp3"); + else if (m_strMimeType == "audio/microsoft-wave") + m_strMimeType = TQString::fromLatin1("audio/x-wav"); + else if (m_strMimeType == "audio/midi") + m_strMimeType = TQString::fromLatin1("audio/x-midi"); + else if (m_strMimeType == "image/x-xpixmap") + m_strMimeType = TQString::fromLatin1("image/x-xpm"); + else if (m_strMimeType == "application/rtf") + m_strMimeType = TQString::fromLatin1("text/rtf"); + + // Crypto ones.... + else if (m_strMimeType == "application/pkix-cert" || + m_strMimeType == "application/binary-certificate") + { + m_strMimeType = TQString::fromLatin1("application/x-x509-ca-cert"); + } + + // Prefer application/x-tgz or x-gzpostscript over application/x-gzip. + else if (m_strMimeType == "application/x-gzip") + { + if ((m_request.url.path().right(7) == ".tar.gz") || + (m_request.url.path().right(4) == ".tar")) + m_strMimeType = TQString::fromLatin1("application/x-tgz"); + if ((m_request.url.path().right(6) == ".ps.gz")) + m_strMimeType = TQString::fromLatin1("application/x-gzpostscript"); + } + + // Some webservers say "text/plain" when they mean "application/x-bzip2" + else if ((m_strMimeType == "text/plain") || (m_strMimeType == "application/octet-stream")) + { + TQString ext = m_request.url.path().right(4).upper(); + if (ext == ".BZ2") + m_strMimeType = TQString::fromLatin1("application/x-bzip2"); + else if (ext == ".PEM") + m_strMimeType = TQString::fromLatin1("application/x-x509-ca-cert"); + else if (ext == ".SWF") + m_strMimeType = TQString::fromLatin1("application/x-shockwave-flash"); + else if (ext == ".PLS") + m_strMimeType = TQString::fromLatin1("audio/x-scpls"); + else if (ext == ".WMV") + m_strMimeType = TQString::fromLatin1("video/x-ms-wmv"); + } + +#if 0 + // Even if we can't rely on content-length, it seems that we should + // never get more data than content-length. Maybe less, if the + // content-length refers to the unzipped data. + if (!m_qContentEncodings.isEmpty()) + { + // If we still have content encoding we can't rely on the Content-Length. + m_iSize = NO_SIZE; + } +#endif + + if( !dispositionType.isEmpty() ) + { + kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition type to: " + << dispositionType << endl; + setMetaData("content-disposition-type", dispositionType); + } + if( !dispositionFilename.isEmpty() ) + { + kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition filename to: " + << dispositionFilename << endl; + // ### KDE4: setting content-disposition to filename for pre 3.5.2 compatability + setMetaData("content-disposition", dispositionFilename); + setMetaData("content-disposition-filename", dispositionFilename); + } + + if (!m_request.lastModified.isEmpty()) + setMetaData("modified", m_request.lastModified); + + if (!mayCache) + { + setMetaData("no-cache", "true"); + setMetaData("expire-date", "1"); // Expired + } + else + { + TQString tmp; + tmp.setNum(expireDate); + setMetaData("expire-date", tmp); + tmp.setNum(time(0)); // Cache entry will be created shortly. + setMetaData("cache-creation-date", tmp); + } + + // Let the app know about the mime-type iff this is not + // a redirection and the mime-type string is not empty. + if (locationStr.isEmpty() && (!m_strMimeType.isEmpty() || + m_request.method == HTTP_HEAD)) + { + kdDebug(7113) << "(" << m_pid << ") Emitting mimetype " << m_strMimeType << endl; + mimeType( m_strMimeType ); + } + + // Do not move send response header before any redirection as it seems + // to screw up some sites. See BR# 150904. + forwardHttpResponseHeader(); + + if (m_request.method == HTTP_HEAD) + return true; + + // Do we want to cache this request? + if (m_request.bUseCache) + { + ::unlink( TQFile::encodeName(m_request.cef)); + if ( m_request.bCachedWrite && !m_strMimeType.isEmpty() ) + { + // Check... + createCacheEntry(m_strMimeType, expireDate); // Create a cache entry + if (!m_request.fcache) + { + m_request.bCachedWrite = false; // Error creating cache entry. + kdDebug(7113) << "(" << m_pid << ") Error creating cache entry for " << m_request.url.prettyURL()<<"!\n"; + } + m_request.expireDate = expireDate; + m_maxCacheSize = config()->readNumEntry("MaxCacheSize", DEFAULT_MAX_CACHE_SIZE) / 2; + } + } + + if (m_request.bCachedWrite && !m_strMimeType.isEmpty()) + kdDebug(7113) << "(" << m_pid << ") Cache, adding \"" << m_request.url.prettyURL() << "\"" << endl; + else if (m_request.bCachedWrite && m_strMimeType.isEmpty()) + kdDebug(7113) << "(" << m_pid << ") Cache, pending \"" << m_request.url.prettyURL() << "\"" << endl; + else + kdDebug(7113) << "(" << m_pid << ") Cache, not adding \"" << m_request.url.prettyURL() << "\"" << endl; + return true; +} + + +void HTTPProtocol::addEncoding(TQString encoding, TQStringList &encs) +{ + encoding = encoding.stripWhiteSpace().lower(); + // Identity is the same as no encoding + if (encoding == "identity") { + return; + } else if (encoding == "8bit") { + // Strange encoding returned by http://linac.ikp.physik.tu-darmstadt.de + return; + } else if (encoding == "chunked") { + m_bChunked = true; + // Anyone know of a better way to handle unknown sizes possibly/ideally with unsigned ints? + //if ( m_cmd != CMD_COPY ) + m_iSize = NO_SIZE; + } else if ((encoding == "x-gzip") || (encoding == "gzip")) { + encs.append(TQString::fromLatin1("gzip")); + } else if ((encoding == "x-bzip2") || (encoding == "bzip2")) { + encs.append(TQString::fromLatin1("bzip2")); // Not yet supported! + } else if ((encoding == "x-deflate") || (encoding == "deflate")) { + encs.append(TQString::fromLatin1("deflate")); + } else { + kdDebug(7113) << "(" << m_pid << ") Unknown encoding encountered. " + << "Please write code. Encoding = \"" << encoding + << "\"" << endl; + } +} + +bool HTTPProtocol::sendBody() +{ + int result=-1; + int length=0; + + infoMessage( i18n( "Requesting data to send" ) ); + + // m_bufPOST will NOT be empty iff authentication was required before posting + // the data OR a re-connect is requested from ::readHeader because the + // connection was lost for some reason. + if ( !m_bufPOST.isNull() ) + { + kdDebug(7113) << "(" << m_pid << ") POST'ing saved data..." << endl; + + result = 0; + length = m_bufPOST.size(); + } + else + { + kdDebug(7113) << "(" << m_pid << ") POST'ing live data..." << endl; + + TQByteArray buffer; + int old_size; + + m_bufPOST.resize(0); + do + { + dataReq(); // Request for data + result = readData( buffer ); + if ( result > 0 ) + { + length += result; + old_size = m_bufPOST.size(); + m_bufPOST.resize( old_size+result ); + memcpy( m_bufPOST.data()+ old_size, buffer.data(), buffer.size() ); + buffer.resize(0); + } + } while ( result > 0 ); + } + + if ( result < 0 ) + { + error( ERR_ABORTED, m_request.hostname ); + return false; + } + + infoMessage( i18n( "Sending data to %1" ).arg( m_request.hostname ) ); + + TQString size = TQString ("Content-Length: %1\r\n\r\n").arg(length); + kdDebug( 7113 ) << "(" << m_pid << ")" << size << endl; + + // Send the content length... + bool sendOk = (write(size.latin1(), size.length()) == (ssize_t) size.length()); + if (!sendOk) + { + kdDebug( 7113 ) << "(" << m_pid << ") Connection broken when sending " + << "content length: (" << m_state.hostname << ")" << endl; + error( ERR_CONNECTION_BROKEN, m_state.hostname ); + return false; + } + + // Send the data... + // kdDebug( 7113 ) << "(" << m_pid << ") POST DATA: " << TQCString(m_bufPOST) << endl; + sendOk = (write(m_bufPOST.data(), m_bufPOST.size()) == (ssize_t) m_bufPOST.size()); + if (!sendOk) + { + kdDebug(7113) << "(" << m_pid << ") Connection broken when sending message body: (" + << m_state.hostname << ")" << endl; + error( ERR_CONNECTION_BROKEN, m_state.hostname ); + return false; + } + + return true; +} + +void HTTPProtocol::httpClose( bool keepAlive ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpClose" << endl; + + if (m_request.fcache) + { + fclose(m_request.fcache); + m_request.fcache = 0; + if (m_request.bCachedWrite) + { + TQString filename = m_request.cef + ".new"; + ::unlink( TQFile::encodeName(filename) ); + } + } + + // Only allow persistent connections for GET requests. + // NOTE: we might even want to narrow this down to non-form + // based submit requests which will require a meta-data from + // tdehtml. + if (keepAlive && (!m_bUseProxy || + m_bPersistentProxyConnection || m_bIsTunneled)) + { + if (!m_keepAliveTimeout) + m_keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT; + else if (m_keepAliveTimeout > 2*DEFAULT_KEEP_ALIVE_TIMEOUT) + m_keepAliveTimeout = 2*DEFAULT_KEEP_ALIVE_TIMEOUT; + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpClose: keep alive (" << m_keepAliveTimeout << ")" << endl; + TQByteArray data; + TQDataStream stream( data, IO_WriteOnly ); + stream << int(99); // special: Close connection + setTimeoutSpecialCommand(m_keepAliveTimeout, data); + return; + } + + httpCloseConnection(); +} + +void HTTPProtocol::closeConnection() +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::closeConnection" << endl; + httpCloseConnection (); +} + +void HTTPProtocol::httpCloseConnection () +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpCloseConnection" << endl; + m_bIsTunneled = false; + m_bKeepAlive = false; + closeDescriptor(); + setTimeoutSpecialCommand(-1); // Cancel any connection timeout +} + +void HTTPProtocol::slave_status() +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::slave_status" << endl; + + if ( m_iSock != -1 && !isConnectionValid() ) + httpCloseConnection(); + + slaveStatus( m_state.hostname, (m_iSock != -1) ); +} + +void HTTPProtocol::mimetype( const KURL& url ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::mimetype: " + << url.prettyURL() << endl; + + if ( !checkRequestURL( url ) ) + return; + + m_request.method = HTTP_HEAD; + m_request.path = url.path(); + m_request.query = url.query(); + m_request.cache = CC_Cache; + m_request.doProxy = m_bUseProxy; + + retrieveHeader(); + + kdDebug(7113) << "(" << m_pid << ") http: mimetype = " << m_strMimeType + << endl; +} + +void HTTPProtocol::special( const TQByteArray &data ) +{ + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::special" << endl; + + int tmp; + TQDataStream stream(data, IO_ReadOnly); + + stream >> tmp; + switch (tmp) { + case 1: // HTTP POST + { + KURL url; + stream >> url; + post( url ); + break; + } + case 2: // cache_update + { + KURL url; + bool no_cache; + time_t expireDate; + stream >> url >> no_cache >> expireDate; + cacheUpdate( url, no_cache, expireDate ); + break; + } + case 5: // WebDAV lock + { + KURL url; + TQString scope, type, owner; + stream >> url >> scope >> type >> owner; + davLock( url, scope, type, owner ); + break; + } + case 6: // WebDAV unlock + { + KURL url; + stream >> url; + davUnlock( url ); + break; + } + case 7: // Generic WebDAV + { + KURL url; + int method; + stream >> url >> method; + davGeneric( url, (TDEIO::HTTP_METHOD) method ); + break; + } + case 99: // Close Connection + { + httpCloseConnection(); + break; + } + default: + // Some command we don't understand. + // Just ignore it, it may come from some future version of KDE. + break; + } +} + +/** + * Read a chunk from the data stream. + */ +int HTTPProtocol::readChunked() +{ + if ((m_iBytesLeft == 0) || (m_iBytesLeft == NO_SIZE)) + { + setRewindMarker(); + + m_bufReceive.resize(4096); + + if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) + { + kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk header" << endl; + return -1; + } + // We could have got the CRLF of the previous chunk. + // If so, try again. + if (m_bufReceive[0] == '\0') + { + if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) + { + kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk header" << endl; + return -1; + } + } + + // m_bEOF is set to true when read called from gets returns 0. For chunked reading 0 + // means end of chunked transfer and not error. See RFC 2615 section 3.6.1 + #if 0 + if (m_bEOF) + { + kdDebug(7113) << "(" << m_pid << ") EOF on Chunk header" << endl; + return -1; + } + #endif + + long long trunkSize = STRTOLL(m_bufReceive.data(), 0, 16); + if (trunkSize < 0) + { + kdDebug(7113) << "(" << m_pid << ") Negative chunk size" << endl; + return -1; + } + m_iBytesLeft = trunkSize; + + // kdDebug(7113) << "(" << m_pid << ") Chunk size = " << m_iBytesLeft << " bytes" << endl; + + if (m_iBytesLeft == 0) + { + // Last chunk. + // Skip trailers. + do { + // Skip trailer of last chunk. + if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) + { + kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk trailer" << endl; + return -1; + } + // kdDebug(7113) << "(" << m_pid << ") Chunk trailer = \"" << m_bufReceive.data() << "\"" << endl; + } + while (strlen(m_bufReceive.data()) != 0); + + return 0; + } + } + + int bytesReceived = readLimited(); + if (!m_iBytesLeft) + m_iBytesLeft = NO_SIZE; // Don't stop, continue with next chunk + + // kdDebug(7113) << "(" << m_pid << ") readChunked: BytesReceived=" << bytesReceived << endl; + return bytesReceived; +} + +int HTTPProtocol::readLimited() +{ + if (!m_iBytesLeft) + return 0; + + m_bufReceive.resize(4096); + + int bytesReceived; + int bytesToReceive; + + if (m_iBytesLeft > m_bufReceive.size()) + bytesToReceive = m_bufReceive.size(); + else + bytesToReceive = m_iBytesLeft; + + bytesReceived = read(m_bufReceive.data(), bytesToReceive); + + if (bytesReceived <= 0) + return -1; // Error: connection lost + + m_iBytesLeft -= bytesReceived; + return bytesReceived; +} + +int HTTPProtocol::readUnlimited() +{ + if (m_bKeepAlive) + { + kdDebug(7113) << "(" << m_pid << ") Unbounded datastream on a Keep " + << "alive connection!" << endl; + m_bKeepAlive = false; + } + + m_bufReceive.resize(4096); + + int result = read(m_bufReceive.data(), m_bufReceive.size()); + if (result > 0) + return result; + + m_bEOF = true; + m_iBytesLeft = 0; + return 0; +} + +void HTTPProtocol::slotData(const TQByteArray &_d) +{ + if (!_d.size()) + { + m_bEOD = true; + return; + } + + if (m_iContentLeft != NO_SIZE) + { + if (m_iContentLeft >= _d.size()) + m_iContentLeft -= _d.size(); + else + m_iContentLeft = NO_SIZE; + } + + TQByteArray d = _d; + if ( !m_dataInternal ) + { + // If a broken server does not send the mime-type, + // we try to id it from the content before dealing + // with the content itself. + if ( m_strMimeType.isEmpty() && !m_bRedirect && + !( m_responseCode >= 300 && m_responseCode <=399) ) + { + kdDebug(7113) << "(" << m_pid << ") Determining mime-type from content..." << endl; + int old_size = m_mimeTypeBuffer.size(); + m_mimeTypeBuffer.resize( old_size + d.size() ); + memcpy( m_mimeTypeBuffer.data() + old_size, d.data(), d.size() ); + if ( (m_iBytesLeft != NO_SIZE) && (m_iBytesLeft > 0) + && (m_mimeTypeBuffer.size() < 1024) ) + { + m_cpMimeBuffer = true; + return; // Do not send up the data since we do not yet know its mimetype! + } + + kdDebug(7113) << "(" << m_pid << ") Mimetype buffer size: " << m_mimeTypeBuffer.size() + << endl; + + KMimeMagicResult *result; + result = KMimeMagic::self()->findBufferFileType( m_mimeTypeBuffer, + m_request.url.fileName() ); + if( result ) + { + m_strMimeType = result->mimeType(); + kdDebug(7113) << "(" << m_pid << ") Mimetype from content: " + << m_strMimeType << endl; + } + + if ( m_strMimeType.isEmpty() ) + { + m_strMimeType = TQString::fromLatin1( DEFAULT_MIME_TYPE ); + kdDebug(7113) << "(" << m_pid << ") Using default mimetype: " + << m_strMimeType << endl; + } + + if ( m_request.bCachedWrite ) + { + createCacheEntry( m_strMimeType, m_request.expireDate ); + if (!m_request.fcache) + m_request.bCachedWrite = false; + } + + if ( m_cpMimeBuffer ) + { + // Do not make any assumption about the state of the TQByteArray we received. + // Fix the crash described by BR# 130104. + d.detach(); + d.resize(0); + d.resize(m_mimeTypeBuffer.size()); + memcpy( d.data(), m_mimeTypeBuffer.data(), + d.size() ); + } + mimeType(m_strMimeType); + m_mimeTypeBuffer.resize(0); + } + + data( d ); + if (m_request.bCachedWrite && m_request.fcache) + writeCacheEntry(d.data(), d.size()); + } + else + { + uint old_size = m_bufWebDavData.size(); + m_bufWebDavData.resize (old_size + d.size()); + memcpy (m_bufWebDavData.data() + old_size, d.data(), d.size()); + } +} + +/** + * This function is our "receive" function. It is responsible for + * downloading the message (not the header) from the HTTP server. It + * is called either as a response to a client's TDEIOJob::dataEnd() + * (meaning that the client is done sending data) or by 'httpOpen()' + * (if we are in the process of a PUT/POST request). It can also be + * called by a webDAV function, to receive stat/list/property/etc. + * data; in this case the data is stored in m_bufWebDavData. + */ +bool HTTPProtocol::readBody( bool dataInternal /* = false */ ) +{ + if (m_responseCode == 204) + return true; + + m_bEOD = false; + // Note that when dataInternal is true, we are going to: + // 1) save the body data to a member variable, m_bufWebDavData + // 2) _not_ advertise the data, speed, size, etc., through the + // corresponding functions. + // This is used for returning data to WebDAV. + m_dataInternal = dataInternal; + if ( dataInternal ) + m_bufWebDavData.resize (0); + + // Check if we need to decode the data. + // If we are in copy mode, then use only transfer decoding. + bool useMD5 = !m_sContentMD5.isEmpty(); + + // Deal with the size of the file. + TDEIO::filesize_t sz = m_request.offset; + if ( sz ) + m_iSize += sz; + + // Update the application with total size except when + // it is compressed, or when the data is to be handled + // internally (webDAV). If compressed we have to wait + // until we uncompress to find out the actual data size + if ( !dataInternal ) { + if ( (m_iSize > 0) && (m_iSize != NO_SIZE)) { + totalSize(m_iSize); + infoMessage( i18n( "Retrieving %1 from %2...").arg(TDEIO::convertSize(m_iSize)) + .arg( m_request.hostname ) ); + } + else + { + totalSize ( 0 ); + } + } + else + infoMessage( i18n( "Retrieving from %1..." ).arg( m_request.hostname ) ); + + if (m_request.bCachedRead) + { + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readBody: read data from cache!" << endl; + m_request.bCachedWrite = false; + + char buffer[ MAX_IPC_SIZE ]; + + m_iContentLeft = NO_SIZE; + + // Jippie! It's already in the cache :-) + while (!feof(m_request.fcache) && !ferror(m_request.fcache)) + { + int nbytes = fread( buffer, 1, MAX_IPC_SIZE, m_request.fcache); + + if (nbytes > 0) + { + m_bufReceive.setRawData( buffer, nbytes); + slotData( m_bufReceive ); + m_bufReceive.resetRawData( buffer, nbytes ); + sz += nbytes; + } + } + + m_bufReceive.resize( 0 ); + + if ( !dataInternal ) + { + processedSize( sz ); + data( TQByteArray() ); + } + + return true; + } + + + if (m_iSize != NO_SIZE) + m_iBytesLeft = m_iSize - sz; + else + m_iBytesLeft = NO_SIZE; + + m_iContentLeft = m_iBytesLeft; + + if (m_bChunked) + m_iBytesLeft = NO_SIZE; + + kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readBody: retrieve data. " + << TDEIO::number(m_iBytesLeft) << " left." << endl; + + // Main incoming loop... Gather everything while we can... + m_cpMimeBuffer = false; + m_mimeTypeBuffer.resize(0); + struct timeval last_tv; + gettimeofday( &last_tv, 0L ); + + HTTPFilterChain chain; + + TQObject::connect(&chain, TQT_SIGNAL(output(const TQByteArray &)), + this, TQT_SLOT(slotData(const TQByteArray &))); + TQObject::connect(&chain, TQT_SIGNAL(error(int, const TQString &)), + this, TQT_SLOT(error(int, const TQString &))); + + // decode all of the transfer encodings + while (!m_qTransferEncodings.isEmpty()) + { + TQString enc = m_qTransferEncodings.last(); + m_qTransferEncodings.remove(m_qTransferEncodings.fromLast()); + if ( enc == "gzip" ) + chain.addFilter(new HTTPFilterGZip); + else if ( enc == "deflate" ) + chain.addFilter(new HTTPFilterDeflate); + } + + // From HTTP 1.1 Draft 6: + // The MD5 digest is computed based on the content of the entity-body, + // including any content-coding that has been applied, but not including + // any transfer-encoding applied to the message-body. If the message is + // received with a transfer-encoding, that encoding MUST be removed + // prior to checking the Content-MD5 value against the received entity. + HTTPFilterMD5 *md5Filter = 0; + if ( useMD5 ) + { + md5Filter = new HTTPFilterMD5; + chain.addFilter(md5Filter); + } + + // now decode all of the content encodings + // -- Why ?? We are not + // -- a proxy server, be a client side implementation!! The applications + // -- are capable of determinig how to extract the encoded implementation. + // WB: That's a misunderstanding. We are free to remove the encoding. + // WB: Some braindead www-servers however, give .tgz files an encoding + // WB: of "gzip" (or even "x-gzip") and a content-type of "applications/tar" + // WB: They shouldn't do that. We can work around that though... + while (!m_qContentEncodings.isEmpty()) + { + TQString enc = m_qContentEncodings.last(); + m_qContentEncodings.remove(m_qContentEncodings.fromLast()); + if ( enc == "gzip" ) + chain.addFilter(new HTTPFilterGZip); + else if ( enc == "deflate" ) + chain.addFilter(new HTTPFilterDeflate); + } + + while (!m_bEOF) + { + int bytesReceived; + + if (m_bChunked) + bytesReceived = readChunked(); + else if (m_iSize != NO_SIZE) + bytesReceived = readLimited(); + else + bytesReceived = readUnlimited(); + + // make sure that this wasn't an error, first + // kdDebug(7113) << "(" << (int) m_pid << ") readBody: bytesReceived: " + // << (int) bytesReceived << " m_iSize: " << (int) m_iSize << " Chunked: " + // << (int) m_bChunked << " BytesLeft: "<< (int) m_iBytesLeft << endl; + if (bytesReceived == -1) + { + if (m_iContentLeft == 0) + { + // gzip'ed data sometimes reports a too long content-length. + // (The length of the unzipped data) + m_iBytesLeft = 0; + break; + } + // Oh well... log an error and bug out + kdDebug(7113) << "(" << m_pid << ") readBody: bytesReceived==-1 sz=" << (int)sz + << " Connnection broken !" << endl; + error(ERR_CONNECTION_BROKEN, m_state.hostname); + return false; + } + + // I guess that nbytes == 0 isn't an error.. but we certainly + // won't work with it! + if (bytesReceived > 0) + { + // Important: truncate the buffer to the actual size received! + // Otherwise garbage will be passed to the app + m_bufReceive.truncate( bytesReceived ); + + chain.slotInput(m_bufReceive); + + if (m_bError) + return false; + + sz += bytesReceived; + if (!dataInternal) + processedSize( sz ); + } + m_bufReceive.resize(0); // res + + if (m_iBytesLeft && m_bEOD && !m_bChunked) + { + // gzip'ed data sometimes reports a too long content-length. + // (The length of the unzipped data) + m_iBytesLeft = 0; + } + + if (m_iBytesLeft == 0) + { + kdDebug(7113) << "("<call( "kded", "kcookiejar", "findCookies(TQString,long int)", + params, replyType, reply ) ) + { + kdWarning(7113) << "(" << m_pid << ") Can't communicate with kded_kcookiejar!" << endl; + return result; + } + if ( replyType == "TQString" ) + { + TQDataStream stream2( reply, IO_ReadOnly ); + stream2 >> result; + } + else + { + kdError(7113) << "(" << m_pid << ") DCOP function findCookies(...) returns " + << replyType << ", expected TQString" << endl; + } + return result; +} + +/******************************* CACHING CODE ****************************/ + + +void HTTPProtocol::cacheUpdate( const KURL& url, bool no_cache, time_t expireDate) +{ + if ( !checkRequestURL( url ) ) + return; + + m_request.path = url.path(); + m_request.query = url.query(); + m_request.cache = CC_Reload; + m_request.doProxy = m_bUseProxy; + + if (no_cache) + { + m_request.fcache = checkCacheEntry( ); + if (m_request.fcache) + { + fclose(m_request.fcache); + m_request.fcache = 0; + ::unlink( TQFile::encodeName(m_request.cef) ); + } + } + else + { + updateExpireDate( expireDate ); + } + finished(); +} + +// !START SYNC! +// The following code should be kept in sync +// with the code in http_cache_cleaner.cpp + +FILE* HTTPProtocol::checkCacheEntry( bool readWrite) +{ + const TQChar separator = '_'; + + TQString CEF = m_request.path; + + int p = CEF.find('/'); + + while(p != -1) + { + CEF[p] = separator; + p = CEF.find('/', p); + } + + TQString host = m_request.hostname.lower(); + CEF = host + CEF + '_'; + + TQString dir = m_strCacheDir; + if (dir[dir.length()-1] != '/') + dir += "/"; + + int l = host.length(); + for(int i = 0; i < l; i++) + { + if (host[i].isLetter() && (host[i] != 'w')) + { + dir += host[i]; + break; + } + } + if (dir[dir.length()-1] == '/') + dir += "0"; + + unsigned long hash = 0x00000000; + TQCString u = m_request.url.url().latin1(); + for(int i = u.length(); i--;) + { + hash = (hash * 12211 + static_cast(u.at(i))) % 2147483563; + } + + TQString hashString; + hashString.sprintf("%08lx", hash); + + CEF = CEF + hashString; + + CEF = dir + "/" + CEF; + + m_request.cef = CEF; + + const char *mode = (readWrite ? "r+" : "r"); + + FILE *fs = fopen( TQFile::encodeName(CEF), mode); // Open for reading and writing + if (!fs) + return 0; + + char buffer[401]; + bool ok = true; + + // CacheRevision + if (ok && (!fgets(buffer, 400, fs))) + ok = false; + if (ok && (strcmp(buffer, CACHE_REVISION) != 0)) + ok = false; + + time_t date; + time_t currentDate = time(0); + + // URL + if (ok && (!fgets(buffer, 400, fs))) + ok = false; + if (ok) + { + int l = strlen(buffer); + if (l>0) + buffer[l-1] = 0; // Strip newline + if (m_request.url.url() != buffer) + { + ok = false; // Hash collision + } + } + + // Creation Date + if (ok && (!fgets(buffer, 400, fs))) + ok = false; + if (ok) + { + date = (time_t) strtoul(buffer, 0, 10); + m_request.creationDate = date; + if (m_maxCacheAge && (difftime(currentDate, date) > m_maxCacheAge)) + { + m_request.bMustRevalidate = true; + m_request.expireDate = currentDate; + } + } + + // Expiration Date + m_request.cacheExpireDateOffset = ftell(fs); + if (ok && (!fgets(buffer, 400, fs))) + ok = false; + if (ok) + { + if (m_request.cache == CC_Verify) + { + date = (time_t) strtoul(buffer, 0, 10); + // After the expire date we need to revalidate. + if (!date || difftime(currentDate, date) >= 0) + m_request.bMustRevalidate = true; + m_request.expireDate = date; + } + else if (m_request.cache == CC_Refresh) + { + m_request.bMustRevalidate = true; + m_request.expireDate = currentDate; + } + } + + // ETag + if (ok && (!fgets(buffer, 400, fs))) + ok = false; + if (ok) + { + m_request.etag = TQString(buffer).stripWhiteSpace(); + } + + // Last-Modified + if (ok && (!fgets(buffer, 400, fs))) + ok = false; + if (ok) + { + m_request.lastModified = TQString(buffer).stripWhiteSpace(); + } + + if (ok) + return fs; + + fclose(fs); + unlink( TQFile::encodeName(CEF)); + return 0; +} + +void HTTPProtocol::updateExpireDate(time_t expireDate, bool updateCreationDate) +{ + bool ok = true; + + FILE *fs = checkCacheEntry(true); + if (fs) + { + TQString date; + char buffer[401]; + time_t creationDate; + + fseek(fs, 0, SEEK_SET); + if (ok && !fgets(buffer, 400, fs)) + ok = false; + if (ok && !fgets(buffer, 400, fs)) + ok = false; + long cacheCreationDateOffset = ftell(fs); + if (ok && !fgets(buffer, 400, fs)) + ok = false; + creationDate = strtoul(buffer, 0, 10); + if (!creationDate) + ok = false; + + if (updateCreationDate) + { + if (!ok || fseek(fs, cacheCreationDateOffset, SEEK_SET)) + return; + TQString date; + date.setNum( time(0) ); + date = date.leftJustify(16); + fputs(date.latin1(), fs); // Creation date + fputc('\n', fs); + } + + if (expireDate>(30*365*24*60*60)) + { + // expire date is a really a big number, it can't be + // a relative date. + date.setNum( expireDate ); + } + else + { + // expireDate before 2000. those values must be + // interpreted as relative expiration dates from + // tags. + // so we have to scan the creation time and add + // it to the expiryDate + date.setNum( creationDate + expireDate ); + } + date = date.leftJustify(16); + if (!ok || fseek(fs, m_request.cacheExpireDateOffset, SEEK_SET)) + return; + fputs(date.latin1(), fs); // Expire date + fseek(fs, 0, SEEK_END); + fclose(fs); + } +} + +void HTTPProtocol::createCacheEntry( const TQString &mimetype, time_t expireDate) +{ + TQString dir = m_request.cef; + int p = dir.findRev('/'); + if (p == -1) return; // Error. + dir.truncate(p); + + // Create file + (void) ::mkdir( TQFile::encodeName(dir), 0700 ); + + TQString filename = m_request.cef + ".new"; // Create a new cache entryexpireDate + +// kdDebug( 7103 ) << "creating new cache entry: " << filename << endl; + + m_request.fcache = fopen( TQFile::encodeName(filename), "w"); + if (!m_request.fcache) + { + kdWarning(7113) << "(" << m_pid << ")createCacheEntry: opening " << filename << " failed." << endl; + return; // Error. + } + + fputs(CACHE_REVISION, m_request.fcache); // Revision + + fputs(m_request.url.url().latin1(), m_request.fcache); // Url + fputc('\n', m_request.fcache); + + TQString date; + m_request.creationDate = time(0); + date.setNum( m_request.creationDate ); + date = date.leftJustify(16); + fputs(date.latin1(), m_request.fcache); // Creation date + fputc('\n', m_request.fcache); + + date.setNum( expireDate ); + date = date.leftJustify(16); + fputs(date.latin1(), m_request.fcache); // Expire date + fputc('\n', m_request.fcache); + + if (!m_request.etag.isEmpty()) + fputs(m_request.etag.latin1(), m_request.fcache); //ETag + fputc('\n', m_request.fcache); + + if (!m_request.lastModified.isEmpty()) + fputs(m_request.lastModified.latin1(), m_request.fcache); // Last modified + fputc('\n', m_request.fcache); + + fputs(mimetype.latin1(), m_request.fcache); // Mimetype + fputc('\n', m_request.fcache); + + if (!m_request.strCharset.isEmpty()) + fputs(m_request.strCharset.latin1(), m_request.fcache); // Charset + fputc('\n', m_request.fcache); + + return; +} +// The above code should be kept in sync +// with the code in http_cache_cleaner.cpp +// !END SYNC! + +void HTTPProtocol::writeCacheEntry( const char *buffer, int nbytes) +{ + if (fwrite( buffer, nbytes, 1, m_request.fcache) != 1) + { + kdWarning(7113) << "(" << m_pid << ") writeCacheEntry: writing " << nbytes << " bytes failed." << endl; + fclose(m_request.fcache); + m_request.fcache = 0; + TQString filename = m_request.cef + ".new"; + ::unlink( TQFile::encodeName(filename) ); + return; + } + long file_pos = ftell( m_request.fcache ) / 1024; + if ( file_pos > m_maxCacheSize ) + { + kdDebug(7113) << "writeCacheEntry: File size reaches " << file_pos + << "Kb, exceeds cache limits. (" << m_maxCacheSize << "Kb)" << endl; + fclose(m_request.fcache); + m_request.fcache = 0; + TQString filename = m_request.cef + ".new"; + ::unlink( TQFile::encodeName(filename) ); + return; + } +} + +void HTTPProtocol::closeCacheEntry() +{ + TQString filename = m_request.cef + ".new"; + int result = fclose( m_request.fcache); + m_request.fcache = 0; + if (result == 0) + { + if (::rename( TQFile::encodeName(filename), TQFile::encodeName(m_request.cef)) == 0) + return; // Success + + kdWarning(7113) << "(" << m_pid << ") closeCacheEntry: error renaming " + << "cache entry. (" << filename << " -> " << m_request.cef + << ")" << endl; + } + + kdWarning(7113) << "(" << m_pid << ") closeCacheEntry: error closing cache " + << "entry. (" << filename<< ")" << endl; +} + +void HTTPProtocol::cleanCache() +{ + const time_t maxAge = DEFAULT_CLEAN_CACHE_INTERVAL; // 30 Minutes. + bool doClean = false; + TQString cleanFile = m_strCacheDir; + if (cleanFile[cleanFile.length()-1] != '/') + cleanFile += "/"; + cleanFile += "cleaned"; + + struct stat stat_buf; + + int result = ::stat(TQFile::encodeName(cleanFile), &stat_buf); + if (result == -1) + { + int fd = creat( TQFile::encodeName(cleanFile), 0600); + if (fd != -1) + { + doClean = true; + ::close(fd); + } + } + else + { + time_t age = (time_t) difftime( time(0), stat_buf.st_mtime ); + if (age > maxAge) // + doClean = true; + } + if (doClean) + { + // Touch file. + utime(TQFile::encodeName(cleanFile), 0); + TDEApplication::startServiceByDesktopPath("http_cache_cleaner.desktop"); + } +} + + + +//************************** AUTHENTICATION CODE ********************/ + + +void HTTPProtocol::configAuth( char *p, bool isForProxy ) +{ + HTTP_AUTH f = AUTH_None; + const char *strAuth = p; + + if ( strncasecmp( p, "Basic", 5 ) == 0 ) + { + f = AUTH_Basic; + p += 5; + strAuth = "Basic"; // Correct for upper-case variations. + } + else if ( strncasecmp (p, "Digest", 6) == 0 ) + { + f = AUTH_Digest; + memcpy((void *)p, "Digest", 6); // Correct for upper-case variations. + p += 6; + } + else if (strncasecmp( p, "MBS_PWD_COOKIE", 14 ) == 0) + { + // Found on http://www.webscription.net/baen/default.asp + f = AUTH_Basic; + p += 14; + strAuth = "Basic"; + } +#ifdef HAVE_LIBGSSAPI + else if ( strncasecmp( p, "Negotiate", 9 ) == 0 ) + { + // if we get two 401 in a row let's assume for now that + // Negotiate isn't working and ignore it + if ( !isForProxy && !(m_responseCode == 401 && m_prevResponseCode == 401) ) + { + f = AUTH_Negotiate; + memcpy((void *)p, "Negotiate", 9); // Correct for upper-case variations. + p += 9; + }; + } +#endif + else if ( strncasecmp( p, "NTLM", 4 ) == 0 ) + { + f = AUTH_NTLM; + memcpy((void *)p, "NTLM", 4); // Correct for upper-case variations. + p += 4; + m_strRealm = "NTLM"; // set a dummy realm + } + else + { + kdWarning(7113) << "(" << m_pid << ") Unsupported or invalid authorization " + << "type requested" << endl; + if (isForProxy) + kdWarning(7113) << "(" << m_pid << ") Proxy URL: " << m_proxyURL << endl; + else + kdWarning(7113) << "(" << m_pid << ") URL: " << m_request.url << endl; + kdWarning(7113) << "(" << m_pid << ") Request Authorization: " << p << endl; + } + + /* + This check ensures the following: + 1.) Rejection of any unknown/unsupported authentication schemes + 2.) Usage of the strongest possible authentication schemes if + and when multiple Proxy-Authenticate or WWW-Authenticate + header field is sent. + */ + if (isForProxy) + { + if ((f == AUTH_None) || + ((m_iProxyAuthCount > 0) && (f < ProxyAuthentication))) + { + // Since I purposefully made the Proxy-Authentication settings + // persistent to reduce the number of round-trips to tdesud we + // have to take special care when an unknown/unsupported auth- + // scheme is received. This check accomplishes just that... + if ( m_iProxyAuthCount == 0) + ProxyAuthentication = f; + kdDebug(7113) << "(" << m_pid << ") Rejected proxy auth method: " << f << endl; + return; + } + m_iProxyAuthCount++; + kdDebug(7113) << "(" << m_pid << ") Accepted proxy auth method: " << f << endl; + } + else + { + if ((f == AUTH_None) || + ((m_iWWWAuthCount > 0) && (f < Authentication))) + { + kdDebug(7113) << "(" << m_pid << ") Rejected auth method: " << f << endl; + return; + } + m_iWWWAuthCount++; + kdDebug(7113) << "(" << m_pid << ") Accepted auth method: " << f << endl; + } + + + while (*p) + { + int i = 0; + while( (*p == ' ') || (*p == ',') || (*p == '\t') ) { p++; } + if ( strncasecmp( p, "realm=", 6 ) == 0 ) + { + //for sites like lib.homelinux.org + TQTextCodec* oldCodec=TQTextCodec::codecForCStrings(); + if (TDEGlobal::locale()->language().contains("ru")) + TQTextCodec::setCodecForCStrings(TQTextCodec::codecForName("CP1251")); + + p += 6; + if (*p == '"') p++; + while( p[i] && p[i] != '"' ) i++; + if( isForProxy ) + m_strProxyRealm = TQString::fromAscii( p, i ); + else + m_strRealm = TQString::fromAscii( p, i ); + + TQTextCodec::setCodecForCStrings(oldCodec); + + if (!p[i]) break; + } + p+=(i+1); + } + + if( isForProxy ) + { + ProxyAuthentication = f; + m_strProxyAuthorization = TQString::fromLatin1( strAuth ); + } + else + { + Authentication = f; + m_strAuthorization = TQString::fromLatin1( strAuth ); + } +} + + +bool HTTPProtocol::retryPrompt() +{ + TQString prompt; + switch ( m_responseCode ) + { + case 401: + prompt = i18n("Authentication Failed."); + break; + case 407: + prompt = i18n("Proxy Authentication Failed."); + break; + default: + break; + } + prompt += i18n(" Do you want to retry?"); + return (messageBox(QuestionYesNo, prompt, i18n("Authentication")) == 3); +} + +void HTTPProtocol::promptInfo( AuthInfo& info ) +{ + if ( m_responseCode == 401 ) + { + info.url = m_request.url; + if ( !m_state.user.isEmpty() ) + info.username = m_state.user; + info.readOnly = !m_request.url.user().isEmpty(); + info.prompt = i18n( "You need to supply a username and a " + "password to access this site." ); + info.keepPassword = true; // Prompt the user for persistence as well. + if ( !m_strRealm.isEmpty() ) + { + info.realmValue = m_strRealm; + info.verifyPath = false; + info.digestInfo = m_strAuthorization; + info.commentLabel = i18n( "Site:" ); + info.comment = i18n("%1 at %2").arg( htmlEscape(m_strRealm) ).arg( m_request.hostname ); + } + } + else if ( m_responseCode == 407 ) + { + info.url = m_proxyURL; + info.username = m_proxyURL.user(); + info.prompt = i18n( "You need to supply a username and a password for " + "the proxy server listed below before you are allowed " + "to access any sites." ); + info.keepPassword = true; + if ( !m_strProxyRealm.isEmpty() ) + { + info.realmValue = m_strProxyRealm; + info.verifyPath = false; + info.digestInfo = m_strProxyAuthorization; + info.commentLabel = i18n( "Proxy:" ); + info.comment = i18n("%1 at %2").arg( htmlEscape(m_strProxyRealm) ).arg( m_proxyURL.host() ); + } + } +} + +bool HTTPProtocol::getAuthorization() +{ + AuthInfo info; + bool result = false; + + kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::getAuthorization: " + << "Current Response: " << m_responseCode << ", " + << "Previous Response: " << m_prevResponseCode << ", " + << "Authentication: " << Authentication << ", " + << "ProxyAuthentication: " << ProxyAuthentication << endl; + + if (m_request.bNoAuth) + { + if (m_request.bErrorPage) + errorPage(); + else + error( ERR_COULD_NOT_LOGIN, i18n("Authentication needed for %1 but authentication is disabled.").arg(m_request.hostname)); + return false; + } + + bool repeatFailure = (m_prevResponseCode == m_responseCode); + + TQString errorMsg; + + if (repeatFailure) + { + bool prompt = true; + if ( Authentication == AUTH_Digest || ProxyAuthentication == AUTH_Digest ) + { + bool isStaleNonce = false; + TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization; + int pos = auth.find("stale", 0, false); + if ( pos != -1 ) + { + pos += 5; + int len = auth.length(); + while( pos < len && (auth[pos] == ' ' || auth[pos] == '=') ) pos++; + if ( pos < len && auth.find("true", pos, false) != -1 ) + { + isStaleNonce = true; + kdDebug(7113) << "(" << m_pid << ") Stale nonce value. " + << "Will retry using same info..." << endl; + } + } + if ( isStaleNonce ) + { + prompt = false; + result = true; + if ( m_responseCode == 401 ) + { + info.username = m_request.user; + info.password = m_request.passwd; + info.realmValue = m_strRealm; + info.digestInfo = m_strAuthorization; + } + else if ( m_responseCode == 407 ) + { + info.username = m_proxyURL.user(); + info.password = m_proxyURL.pass(); + info.realmValue = m_strProxyRealm; + info.digestInfo = m_strProxyAuthorization; + } + } + } + + if ( Authentication == AUTH_NTLM || ProxyAuthentication == AUTH_NTLM ) + { + TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization; + kdDebug(7113) << "auth: " << auth << endl; + if ( auth.length() > 4 ) + { + prompt = false; + result = true; + kdDebug(7113) << "(" << m_pid << ") NTLM auth second phase, " + << "sending response..." << endl; + if ( m_responseCode == 401 ) + { + info.username = m_request.user; + info.password = m_request.passwd; + info.realmValue = m_strRealm; + info.digestInfo = m_strAuthorization; + } + else if ( m_responseCode == 407 ) + { + info.username = m_proxyURL.user(); + info.password = m_proxyURL.pass(); + info.realmValue = m_strProxyRealm; + info.digestInfo = m_strProxyAuthorization; + } + } + } + + if ( prompt ) + { + switch ( m_responseCode ) + { + case 401: + errorMsg = i18n("Authentication Failed."); + break; + case 407: + errorMsg = i18n("Proxy Authentication Failed."); + break; + default: + break; + } + } + } + else + { + // At this point we know more details, so use it to find + // out if we have a cached version and avoid a re-prompt! + // We also do not use verify path unlike the pre-emptive + // requests because we already know the realm value... + + if (m_bProxyAuthValid) + { + // Reset cached proxy auth + m_bProxyAuthValid = false; + KURL proxy ( config()->readEntry("UseProxy") ); + m_proxyURL.setUser(proxy.user()); + m_proxyURL.setPass(proxy.pass()); + } + + info.verifyPath = false; + if ( m_responseCode == 407 ) + { + info.url = m_proxyURL; + info.username = m_proxyURL.user(); + info.password = m_proxyURL.pass(); + info.realmValue = m_strProxyRealm; + info.digestInfo = m_strProxyAuthorization; + } + else + { + info.url = m_request.url; + info.username = m_request.user; + info.password = m_request.passwd; + info.realmValue = m_strRealm; + info.digestInfo = m_strAuthorization; + } + + // If either username or password is not supplied + // with the request, check the password cache. + if ( info.username.isNull() || + info.password.isNull() ) + result = checkCachedAuthentication( info ); + + if ( Authentication == AUTH_Digest ) + { + TQString auth; + + if (m_responseCode == 401) + auth = m_strAuthorization; + else + auth = m_strProxyAuthorization; + + int pos = auth.find("stale", 0, false); + if ( pos != -1 ) + { + pos += 5; + int len = auth.length(); + while( pos < len && (auth[pos] == ' ' || auth[pos] == '=') ) pos++; + if ( pos < len && auth.find("true", pos, false) != -1 ) + { + info.digestInfo = (m_responseCode == 401) ? m_strAuthorization : m_strProxyAuthorization; + kdDebug(7113) << "(" << m_pid << ") Just a stale nonce value! " + << "Retrying using the new nonce sent..." << endl; + } + } + } + } + + if (!result ) + { + // Do not prompt if the username & password + // is already supplied and the login attempt + // did not fail before. + if ( !repeatFailure && + !info.username.isNull() && + !info.password.isNull() ) + result = true; + else + { + if (Authentication == AUTH_Negotiate) + { + if (!repeatFailure) + result = true; + } + else if ( m_request.disablePassDlg == false ) + { + kdDebug( 7113 ) << "(" << m_pid << ") Prompting the user for authorization..." << endl; + promptInfo( info ); + result = openPassDlg( info, errorMsg ); + } + } + } + + if ( result ) + { + switch (m_responseCode) + { + case 401: // Request-Authentication + m_request.user = info.username; + m_request.passwd = info.password; + m_strRealm = info.realmValue; + m_strAuthorization = info.digestInfo; + break; + case 407: // Proxy-Authentication + m_proxyURL.setUser( info.username ); + m_proxyURL.setPass( info.password ); + m_strProxyRealm = info.realmValue; + m_strProxyAuthorization = info.digestInfo; + break; + default: + break; + } + return true; + } + + if (m_request.bErrorPage) + errorPage(); + else + error( ERR_USER_CANCELED, TQString::null ); + return false; +} + +void HTTPProtocol::saveAuthorization() +{ + AuthInfo info; + if ( m_prevResponseCode == 407 ) + { + if (!m_bUseProxy) + return; + m_bProxyAuthValid = true; + info.url = m_proxyURL; + info.username = m_proxyURL.user(); + info.password = m_proxyURL.pass(); + info.realmValue = m_strProxyRealm; + info.digestInfo = m_strProxyAuthorization; + cacheAuthentication( info ); + } + else + { + info.url = m_request.url; + info.username = m_request.user; + info.password = m_request.passwd; + info.realmValue = m_strRealm; + info.digestInfo = m_strAuthorization; + cacheAuthentication( info ); + } +} + +#ifdef HAVE_LIBGSSAPI +TQCString HTTPProtocol::gssError( int major_status, int minor_status ) +{ + OM_uint32 new_status; + OM_uint32 msg_ctx = 0; + gss_buffer_desc major_string; + gss_buffer_desc minor_string; + OM_uint32 ret; + TQCString errorstr; + + errorstr = ""; + + do { + ret = gss_display_status(&new_status, major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &major_string); + errorstr += (const char *)major_string.value; + errorstr += " "; + ret = gss_display_status(&new_status, minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &minor_string); + errorstr += (const char *)minor_string.value; + errorstr += " "; + } while (!GSS_ERROR(ret) && msg_ctx != 0); + + return errorstr; +} + +TQString HTTPProtocol::createNegotiateAuth() +{ + TQString auth; + TQCString servicename; + TQByteArray input; + OM_uint32 major_status, minor_status; + OM_uint32 req_flags = 0; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_name_t server; + gss_ctx_id_t ctx; + gss_OID mech_oid; + static gss_OID_desc krb5_oid_desc = {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + static gss_OID_desc spnego_oid_desc = {6, (void *) "\x2b\x06\x01\x05\x05\x02"}; + int found = 0; + unsigned int i; + gss_OID_set mech_set; + gss_OID tmp_oid; + + ctx = GSS_C_NO_CONTEXT; + mech_oid = &krb5_oid_desc; + + // see whether we can use the SPNEGO mechanism + major_status = gss_indicate_mechs(&minor_status, &mech_set); + if (GSS_ERROR(major_status)) { + kdDebug(7113) << "(" << m_pid << ") gss_indicate_mechs failed: " << gssError(major_status, minor_status) << endl; + } else { + for (i=0; icount && !found; i++) { + tmp_oid = &mech_set->elements[i]; + if (tmp_oid->length == spnego_oid_desc.length && + !memcmp(tmp_oid->elements, spnego_oid_desc.elements, tmp_oid->length)) { + kdDebug(7113) << "(" << m_pid << ") createNegotiateAuth: found SPNEGO mech" << endl; + found = 1; + mech_oid = &spnego_oid_desc; + break; + } + } + gss_release_oid_set(&minor_status, &mech_set); + } + + // the service name is "HTTP/f.q.d.n" + servicename = "HTTP@"; + servicename += m_state.hostname.ascii(); + + input_token.value = (void *)servicename.data(); + input_token.length = servicename.length() + 1; + + major_status = gss_import_name(&minor_status, &input_token, + GSS_C_NT_HOSTBASED_SERVICE, &server); + + input_token.value = NULL; + input_token.length = 0; + + if (GSS_ERROR(major_status)) { + kdDebug(7113) << "(" << m_pid << ") gss_import_name failed: " << gssError(major_status, minor_status) << endl; + // reset the auth string so that subsequent methods aren't confused + m_strAuthorization = TQString::null; + return TQString::null; + } + + major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, + &ctx, server, mech_oid, + req_flags, GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, NULL, &output_token, + NULL, NULL); + + + if (GSS_ERROR(major_status) || (output_token.length == 0)) { + kdDebug(7113) << "(" << m_pid << ") gss_init_sec_context failed: " << gssError(major_status, minor_status) << endl; + gss_release_name(&minor_status, &server); + if (ctx != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER); + ctx = GSS_C_NO_CONTEXT; + } + // reset the auth string so that subsequent methods aren't confused + m_strAuthorization = TQString::null; + return TQString::null; + } + + input.duplicate((const char *)output_token.value, output_token.length); + auth = "Authorization: Negotiate "; + auth += KCodecs::base64Encode( input ); + auth += "\r\n"; + + // free everything + gss_release_name(&minor_status, &server); + if (ctx != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER); + ctx = GSS_C_NO_CONTEXT; + } + gss_release_buffer(&minor_status, &output_token); + + return auth; +} +#else + +// Dummy +TQCString HTTPProtocol::gssError( int, int ) +{ + return ""; +} + +// Dummy +TQString HTTPProtocol::createNegotiateAuth() +{ + return TQString::null; +} +#endif + +TQString HTTPProtocol::createNTLMAuth( bool isForProxy ) +{ + uint len; + TQString auth, user, domain, passwd; + TQCString strauth; + TQByteArray buf; + + if ( isForProxy ) + { + auth = "Proxy-Connection: Keep-Alive\r\n"; + auth += "Proxy-Authorization: NTLM "; + user = m_proxyURL.user(); + passwd = m_proxyURL.pass(); + strauth = m_strProxyAuthorization.latin1(); + len = m_strProxyAuthorization.length(); + } + else + { + auth = "Authorization: NTLM "; + user = m_state.user; + passwd = m_state.passwd; + strauth = m_strAuthorization.latin1(); + len = m_strAuthorization.length(); + } + if ( user.contains('\\') ) { + domain = user.section( '\\', 0, 0); + user = user.section( '\\', 1 ); + } + + kdDebug(7113) << "(" << m_pid << ") NTLM length: " << len << endl; + if ( user.isEmpty() || passwd.isEmpty() || len < 4 ) + return TQString::null; + + if ( len > 4 ) + { + // create a response + TQByteArray challenge; + KCodecs::base64Decode( strauth.right( len - 5 ), challenge ); + KNTLM::getAuth( buf, challenge, user, passwd, domain, + KNetwork::KResolver::localHostName(), false, false ); + } + else + { + KNTLM::getNegotiate( buf ); + } + + // remove the challenge to prevent reuse + if ( isForProxy ) + m_strProxyAuthorization = "NTLM"; + else + m_strAuthorization = "NTLM"; + + auth += KCodecs::base64Encode( buf ); + auth += "\r\n"; + + return auth; +} + +TQString HTTPProtocol::createBasicAuth( bool isForProxy ) +{ + TQString auth; + TQCString user, passwd; + if ( isForProxy ) + { + auth = "Proxy-Authorization: Basic "; + user = m_proxyURL.user().latin1(); + passwd = m_proxyURL.pass().latin1(); + } + else + { + auth = "Authorization: Basic "; + user = m_state.user.latin1(); + passwd = m_state.passwd.latin1(); + } + + if ( user.isEmpty() ) + user = ""; + if ( passwd.isEmpty() ) + passwd = ""; + + user += ':'; + user += passwd; + auth += KCodecs::base64Encode( user ); + auth += "\r\n"; + + return auth; +} + +void HTTPProtocol::calculateResponse( DigestAuthInfo& info, TQCString& Response ) +{ + KMD5 md; + TQCString HA1; + TQCString HA2; + + // Calculate H(A1) + TQCString authStr = info.username; + authStr += ':'; + authStr += info.realm; + authStr += ':'; + authStr += info.password; + md.update( authStr ); + + if ( info.algorithm.lower() == "md5-sess" ) + { + authStr = md.hexDigest(); + authStr += ':'; + authStr += info.nonce; + authStr += ':'; + authStr += info.cnonce; + md.reset(); + md.update( authStr ); + } + HA1 = md.hexDigest(); + + kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A1 => " << HA1 << endl; + + // Calcualte H(A2) + authStr = info.method; + authStr += ':'; + authStr += m_request.url.encodedPathAndQuery(0, true).latin1(); + if ( info.qop == "auth-int" ) + { + authStr += ':'; + authStr += info.entityBody; + } + md.reset(); + md.update( authStr ); + HA2 = md.hexDigest(); + + kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A2 => " + << HA2 << endl; + + // Calcualte the response. + authStr = HA1; + authStr += ':'; + authStr += info.nonce; + authStr += ':'; + if ( !info.qop.isEmpty() ) + { + authStr += info.nc; + authStr += ':'; + authStr += info.cnonce; + authStr += ':'; + authStr += info.qop; + authStr += ':'; + } + authStr += HA2; + md.reset(); + md.update( authStr ); + Response = md.hexDigest(); + + kdDebug(7113) << "(" << m_pid << ") calculateResponse(): Response => " + << Response << endl; +} + +TQString HTTPProtocol::createDigestAuth ( bool isForProxy ) +{ + const char *p; + + TQString auth; + TQCString opaque; + TQCString Response; + + DigestAuthInfo info; + + opaque = ""; + if ( isForProxy ) + { + auth = "Proxy-Authorization: Digest "; + info.username = m_proxyURL.user().latin1(); + info.password = m_proxyURL.pass().latin1(); + p = m_strProxyAuthorization.latin1(); + } + else + { + auth = "Authorization: Digest "; + info.username = m_state.user.latin1(); + info.password = m_state.passwd.latin1(); + p = m_strAuthorization.latin1(); + } + if (!p || !*p) + return TQString::null; + + p += 6; // Skip "Digest" + + if ( info.username.isEmpty() || info.password.isEmpty() || !p ) + return TQString::null; + + // info.entityBody = p; // FIXME: send digest of data for POST action ?? + info.realm = ""; + info.algorithm = "MD5"; + info.nonce = ""; + info.qop = ""; + + // cnonce is recommended to contain about 64 bits of entropy + info.cnonce = TDEApplication::randomString(16).latin1(); + + // HACK: Should be fixed according to RFC 2617 section 3.2.2 + info.nc = "00000001"; + + // Set the method used... + switch ( m_request.method ) + { + case HTTP_GET: + info.method = "GET"; + break; + case HTTP_PUT: + info.method = "PUT"; + break; + case HTTP_POST: + info.method = "POST"; + break; + case HTTP_HEAD: + info.method = "HEAD"; + break; + case HTTP_DELETE: + info.method = "DELETE"; + break; + case DAV_PROPFIND: + info.method = "PROPFIND"; + break; + case DAV_PROPPATCH: + info.method = "PROPPATCH"; + break; + case DAV_MKCOL: + info.method = "MKCOL"; + break; + case DAV_COPY: + info.method = "COPY"; + break; + case DAV_MOVE: + info.method = "MOVE"; + break; + case DAV_LOCK: + info.method = "LOCK"; + break; + case DAV_UNLOCK: + info.method = "UNLOCK"; + break; + case DAV_SEARCH: + info.method = "SEARCH"; + break; + case DAV_SUBSCRIBE: + info.method = "SUBSCRIBE"; + break; + case DAV_UNSUBSCRIBE: + info.method = "UNSUBSCRIBE"; + break; + case DAV_POLL: + info.method = "POLL"; + break; + default: + error( ERR_UNSUPPORTED_ACTION, i18n("Unsupported method: authentication will fail. Please submit a bug report.")); + break; + } + + // Parse the Digest response.... + while (*p) + { + int i = 0; + while ( (*p == ' ') || (*p == ',') || (*p == '\t')) { p++; } + if (strncasecmp(p, "realm=", 6 )==0) + { + p+=6; + while ( *p == '"' ) p++; // Go past any number of " mark(s) first + while ( p[i] != '"' ) i++; // Read everything until the last " mark + info.realm = TQCString( p, i+1 ); + } + else if (strncasecmp(p, "algorith=", 9)==0) + { + p+=9; + while ( *p == '"' ) p++; // Go past any number of " mark(s) first + while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++; + info.algorithm = TQCString(p, i+1); + } + else if (strncasecmp(p, "algorithm=", 10)==0) + { + p+=10; + while ( *p == '"' ) p++; // Go past any " mark(s) first + while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++; + info.algorithm = TQCString(p,i+1); + } + else if (strncasecmp(p, "domain=", 7)==0) + { + p+=7; + while ( *p == '"' ) p++; // Go past any " mark(s) first + while ( p[i] != '"' ) i++; // Read everything until the last " mark + int pos; + int idx = 0; + TQCString uri = TQCString(p,i+1); + do + { + pos = uri.find( ' ', idx ); + if ( pos != -1 ) + { + KURL u (m_request.url, uri.mid(idx, pos-idx)); + if (u.isValid ()) + info.digestURI.append( u.url().latin1() ); + } + else + { + KURL u (m_request.url, uri.mid(idx, uri.length()-idx)); + if (u.isValid ()) + info.digestURI.append( u.url().latin1() ); + } + idx = pos+1; + } while ( pos != -1 ); + } + else if (strncasecmp(p, "nonce=", 6)==0) + { + p+=6; + while ( *p == '"' ) p++; // Go past any " mark(s) first + while ( p[i] != '"' ) i++; // Read everything until the last " mark + info.nonce = TQCString(p,i+1); + } + else if (strncasecmp(p, "opaque=", 7)==0) + { + p+=7; + while ( *p == '"' ) p++; // Go past any " mark(s) first + while ( p[i] != '"' ) i++; // Read everything until the last " mark + opaque = TQCString(p,i+1); + } + else if (strncasecmp(p, "qop=", 4)==0) + { + p+=4; + while ( *p == '"' ) p++; // Go past any " mark(s) first + while ( p[i] != '"' ) i++; // Read everything until the last " mark + info.qop = TQCString(p,i+1); + } + p+=(i+1); + } + + if (info.realm.isEmpty() || info.nonce.isEmpty()) + return TQString::null; + + // If the "domain" attribute was not specified and the current response code + // is authentication needed, add the current request url to the list over which + // this credential can be automatically applied. + if (info.digestURI.isEmpty() && (m_responseCode == 401 || m_responseCode == 407)) + info.digestURI.append (m_request.url.url().latin1()); + else + { + // Verify whether or not we should send a cached credential to the + // server based on the stored "domain" attribute... + bool send = true; + + // Determine the path of the request url... + TQString requestPath = m_request.url.directory(false, false); + if (requestPath.isEmpty()) + requestPath = "/"; + + int count = info.digestURI.count(); + + for (int i = 0; i < count; i++ ) + { + KURL u ( info.digestURI.at(i) ); + + send &= (m_request.url.protocol().lower() == u.protocol().lower()); + send &= (m_request.hostname.lower() == u.host().lower()); + + if (m_request.port > 0 && u.port() > 0) + send &= (m_request.port == u.port()); + + TQString digestPath = u.directory (false, false); + if (digestPath.isEmpty()) + digestPath = "/"; + + send &= (requestPath.startsWith(digestPath)); + + if (send) + break; + } + + kdDebug(7113) << "(" << m_pid << ") createDigestAuth(): passed digest " + "authentication credential test: " << send << endl; + + if (!send) + return TQString::null; + } + + kdDebug(7113) << "(" << m_pid << ") RESULT OF PARSING:" << endl; + kdDebug(7113) << "(" << m_pid << ") algorithm: " << info.algorithm << endl; + kdDebug(7113) << "(" << m_pid << ") realm: " << info.realm << endl; + kdDebug(7113) << "(" << m_pid << ") nonce: " << info.nonce << endl; + kdDebug(7113) << "(" << m_pid << ") opaque: " << opaque << endl; + kdDebug(7113) << "(" << m_pid << ") qop: " << info.qop << endl; + + // Calculate the response... + calculateResponse( info, Response ); + + auth += "username=\""; + auth += info.username; + + auth += "\", realm=\""; + auth += info.realm; + auth += "\""; + + auth += ", nonce=\""; + auth += info.nonce; + + auth += "\", uri=\""; + auth += m_request.url.encodedPathAndQuery(0, true); + + auth += "\", algorithm=\""; + auth += info.algorithm; + auth +="\""; + + if ( !info.qop.isEmpty() ) + { + auth += ", qop=\""; + auth += info.qop; + auth += "\", cnonce=\""; + auth += info.cnonce; + auth += "\", nc="; + auth += info.nc; + } + + auth += ", response=\""; + auth += Response; + if ( !opaque.isEmpty() ) + { + auth += "\", opaque=\""; + auth += opaque; + } + auth += "\"\r\n"; + + return auth; +} + +TQString HTTPProtocol::proxyAuthenticationHeader() +{ + TQString header; + + // We keep proxy authentication locally until they are changed. + // Thus, no need to check with the password manager for every + // connection. + if ( m_strProxyRealm.isEmpty() ) + { + AuthInfo info; + info.url = m_proxyURL; + info.username = m_proxyURL.user(); + info.password = m_proxyURL.pass(); + info.verifyPath = true; + + // If the proxy URL already contains username + // and password simply attempt to retrieve it + // without prompting the user... + if ( !info.username.isNull() && !info.password.isNull() ) + { + if( m_strProxyAuthorization.isEmpty() ) + ProxyAuthentication = AUTH_None; + else if( m_strProxyAuthorization.startsWith("Basic") ) + ProxyAuthentication = AUTH_Basic; + else if( m_strProxyAuthorization.startsWith("NTLM") ) + ProxyAuthentication = AUTH_NTLM; + else + ProxyAuthentication = AUTH_Digest; + } + else + { + if ( checkCachedAuthentication(info) && !info.digestInfo.isEmpty() ) + { + m_proxyURL.setUser( info.username ); + m_proxyURL.setPass( info.password ); + m_strProxyRealm = info.realmValue; + m_strProxyAuthorization = info.digestInfo; + if( m_strProxyAuthorization.startsWith("Basic") ) + ProxyAuthentication = AUTH_Basic; + else if( m_strProxyAuthorization.startsWith("NTLM") ) + ProxyAuthentication = AUTH_NTLM; + else + ProxyAuthentication = AUTH_Digest; + } + else + { + ProxyAuthentication = AUTH_None; + } + } + } + + /********* Only for debugging purpose... *********/ + if ( ProxyAuthentication != AUTH_None ) + { + kdDebug(7113) << "(" << m_pid << ") Using Proxy Authentication: " << endl; + kdDebug(7113) << "(" << m_pid << ") HOST= " << m_proxyURL.host() << endl; + kdDebug(7113) << "(" << m_pid << ") PORT= " << m_proxyURL.port() << endl; + kdDebug(7113) << "(" << m_pid << ") USER= " << m_proxyURL.user() << endl; + kdDebug(7113) << "(" << m_pid << ") PASSWORD= [protected]" << endl; + kdDebug(7113) << "(" << m_pid << ") REALM= " << m_strProxyRealm << endl; + kdDebug(7113) << "(" << m_pid << ") EXTRA= " << m_strProxyAuthorization << endl; + } + + switch ( ProxyAuthentication ) + { + case AUTH_Basic: + header += createBasicAuth( true ); + break; + case AUTH_Digest: + header += createDigestAuth( true ); + break; + case AUTH_NTLM: + if ( m_bFirstRequest ) header += createNTLMAuth( true ); + break; + case AUTH_None: + default: + break; + } + + return header; +} + +#include "http.moc" diff --git a/tdeioslave/http/http_cache_cleaner.cpp b/tdeioslave/http/http_cache_cleaner.cpp index aaf94d25a..1f2be7abf 100644 --- a/tdeioslave/http/http_cache_cleaner.cpp +++ b/tdeioslave/http/http_cache_cleaner.cpp @@ -77,7 +77,7 @@ public: }; // !START OF SYNC! -// Keep the following in sync with the cache code in http.cc +// Keep the following in sync with the cache code in http.cpp #define CACHE_REVISION "7\n" FileInfo *readEntry( const TQString &filename) @@ -158,7 +158,7 @@ FileInfo *readEntry( const TQString &filename) unlink( CEF.data()); return 0; } -// Keep the above in sync with the cache code in http.cc +// Keep the above in sync with the cache code in http.cpp // !END OF SYNC! void scanDirectory(FileInfoList &fileEntries, const TQString &name, const TQString &strDir) diff --git a/tdeioslave/iso/Makefile.am b/tdeioslave/iso/Makefile.am index ed8aaadfa..f0381203a 100644 --- a/tdeioslave/iso/Makefile.am +++ b/tdeioslave/iso/Makefile.am @@ -60,7 +60,7 @@ uninstall-local: # make messages.po. Move this one to ../po/ and "make merge" in po # the -x is for skipping messages already translated in tdelibs messages: - LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + LIST=`find . -name \*.h -o -name \*.cpp -o -name \*.c`; \ if test -n "$$LIST"; then \ $(XGETTEXT) -C -ki18n -x $(kde_includes)/tde.pot $$LIST -o ../po/iso.pot; \ fi diff --git a/tdeioslave/iso/iso.cpp b/tdeioslave/iso/iso.cpp index 8696b0c67..80e32b415 100644 --- a/tdeioslave/iso/iso.cpp +++ b/tdeioslave/iso/iso.cpp @@ -15,7 +15,7 @@ * * ***************************************************************************/ - /* This file is heavily based on tar.cc from tdebase + /* This file is heavily based on tar.cpp from tdebase * (c) David Faure */ diff --git a/tderandr/CMakeLists.txt b/tderandr/CMakeLists.txt index e52da4c17..fd269a65c 100644 --- a/tderandr/CMakeLists.txt +++ b/tderandr/CMakeLists.txt @@ -37,7 +37,7 @@ install( FILES set( target tderandr ) set( ${target}_SRCS - randr.cpp lowlevel_randr.c ktimerdialog.cpp libtderandr.cc + randr.cpp lowlevel_randr.c ktimerdialog.cpp libtderandr.cpp ) tde_add_library( ${target} SHARED AUTOMOC diff --git a/tderandr/Makefile.am b/tderandr/Makefile.am index 9a8e1cf37..433a30c57 100644 --- a/tderandr/Makefile.am +++ b/tderandr/Makefile.am @@ -9,7 +9,7 @@ libtderandrincludedir = $(includedir)/libtderandr libtderandrinclude_HEADERS = randr.h lowlevel_randr.h ktimerdialog.h libtderandr.h lib_LTLIBRARIES = libtderandr.la -libtderandr_la_SOURCES = randr.cpp lowlevel_randr.c ktimerdialog.cpp libtderandr.cc +libtderandr_la_SOURCES = randr.cpp lowlevel_randr.c ktimerdialog.cpp libtderandr.cpp METASOURCES = AUTO libtderandr_la_LDFLAGS = $(KDE_MT_LDFLAGS) -version-info 0:95 -no-undefined diff --git a/tderandr/libtderandr.cc b/tderandr/libtderandr.cc deleted file mode 100644 index 39e9c5b70..000000000 --- a/tderandr/libtderandr.cc +++ /dev/null @@ -1,1629 +0,0 @@ -/* libtderandr.cc - class KRandr that makes it easy to use XRandr in KDE - This file is part of KRandr 0.9.5 - Copyright (C) 2010 Timothy Pearson - LibKRandr's homepage : http://www.trinitydesktop.org - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Send comments and bug fixes to Timothy Pearson - -***************************************************************************/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "libtderandr.h" - -#include - -// FIXME -// For now, just use the standalone xrandr program to apply the display settings -#define USE_XRANDR_PROGRAM - -// This routine is courtsey of an answer on "Stack Overflow" -// It takes an LSB-first int and makes it an MSB-first int (or vice versa) -unsigned int reverse_bits(unsigned int x) -{ - x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); - x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); - x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); - x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); - return((x >> 16) | (x << 16)); -} - -// This routine returns the output of an arbitrary Bash command -TQString exec(const char * cmd) { - TQString bashcommand = cmd; - bashcommand = bashcommand.replace("\"", "\\\""); - bashcommand = TQString("/bin/bash -c \"%1\" 2>&1").arg(bashcommand); - FILE* pipe = popen(bashcommand.ascii(), "r"); - if (!pipe) return "ERROR"; - char buffer[128]; - TQString result = ""; - while(!feof(pipe)) { - if(fgets(buffer, 128, pipe) != NULL) { - result += buffer; - } - } - pclose(pipe); - result.remove(result.length(), 1); - return result; -} - -TQString capitalizeString(TQString in) { - return in.left(1).upper() + in.right(in.length()-1); -} - -TQString KRandrSimpleAPI::getIccFileName(TQString profileName, TQString screenName, TQString kde_confdir) { - KSimpleConfig *t_config = NULL; - KSimpleConfig *t_systemconfig = NULL; - int t_numberOfProfiles; - TQStringList t_cfgProfiles; - TQString retval; - - if ((profileName != NULL) && (profileName != "")) { - t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); - t_config->setGroup(NULL); - if (t_config->readBoolEntry("EnableICC", false) == true) { - t_config->setGroup(profileName); - retval = t_config->readEntry(screenName); - } - else { - retval = ""; - } - delete t_config; - } - else { - t_systemconfig = new KSimpleConfig( kde_confdir + TQString("/kicc/kiccconfigrc") ); - t_systemconfig->setGroup(NULL); - if (t_systemconfig->readBoolEntry("EnableICC", false) == true) { - retval = t_systemconfig->readEntry("ICCFile"); - } - else { - retval = ""; - } - delete t_systemconfig; - } - - return retval; -} - -TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) { - int i; - int j; - Display *randr_display; - ScreenInfo *randr_screen_info; - XRROutputInfo *output_info; - - int screenNumber = 0; - - if (fileName != "") { - // FIXME - // This should use the RRSetCrtcGamma function when available - // That is the only way to get proper setting when two output are active at the same time - // (otherwise in clone mode only one screen is available) - - // HACK - // For now, simply exit with no changes if screenName is not an active output - - if (isValid() == true) { - screenNumber = -1; - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - if (randr_screen_info == NULL) { - return ""; - } - j=0; - for (i = 0; i < randr_screen_info->n_output; i++) { - output_info = randr_screen_info->outputs[i]->info; - // Look for ON outputs... - if (!randr_screen_info->outputs[i]->cur_crtc) { - continue; - } - // ...that are connected - if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) { - continue; - } - if (output_info->name == screenName) { - screenNumber = j; - } - j++; - } - freeScreenInfoStructure(randr_screen_info); - } - - if (screenNumber >= 0) { - // Apply ICC settings with XCalib - TQString icc_command; - FILE *pipe_xcalib; - char xcalib_result[2048]; - int i; - xcalib_result[0]=0; - - icc_command = TQString("xcalib \"%1\"").arg(fileName); - if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) - { - printf("Xcalib pipe error\n [xcalib apply]"); - } - else { - if (fgets(xcalib_result, 2048, pipe_xcalib)) { - pclose(pipe_xcalib); - for (i=1;i<2048;i++) { - if (xcalib_result[i] == 0) { - xcalib_result[i-1]=0; - i=2048; - } - } - if (strlen(xcalib_result) > 2) { - return xcalib_result; - } - } - else { - return ""; - } - } - } - } - else { - // Reset ICC profile on this screen - - // FIXME - // This should use the RRSetCrtcGamma function when available - // That is the only way to get proper setting when two output are active at the same time - // (otherwise in clone mode only one screen is available) - - // HACK - // For now, simply exit with no changes if screenName is not an active output - - if (isValid() == true) { - screenNumber = -1; - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - if (randr_screen_info == NULL) { - return ""; - } - j=0; - for (i = 0; i < randr_screen_info->n_output; i++) { - output_info = randr_screen_info->outputs[i]->info; - // Look for ON outputs... - if (!randr_screen_info->outputs[i]->cur_crtc) { - continue; - } - // ...that are connected - if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) { - continue; - } - if (output_info->name == screenName) { - screenNumber = j; - } - j++; - } - freeScreenInfoStructure(randr_screen_info); - } - - if (screenNumber >= 0) { - // Apply ICC settings with XCalib - TQString icc_command; - FILE *pipe_xcalib; - char xcalib_result[2048]; - int i; - xcalib_result[0]=0; - - icc_command = TQString("xcalib -c"); - if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) - { - printf("Xcalib pipe error\n [xcalib clear]"); - } - else { - if (fgets(xcalib_result, 2048, pipe_xcalib)) { - pclose(pipe_xcalib); - for (i=1;i<2048;i++) { - if (xcalib_result[i] == 0) { - xcalib_result[i-1]=0; - i=2048; - } - } - if (strlen(xcalib_result) > 2) { - return xcalib_result; - } - } - else { - return ""; - } - } - } - } - return ""; -} - -TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString kde_confdir) { - int i; - Display *randr_display; - ScreenInfo *randr_screen_info; - XRROutputInfo *output_info; - KSimpleConfig *t_config; - - int screenNumber = 0; - TQString errorstr = ""; - - t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); - - // Find all screens - if (isValid() == true) { - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - if (randr_screen_info == NULL) { - return ""; - } - for (i = 0; i < randr_screen_info->n_output; i++) { - output_info = randr_screen_info->outputs[i]->info; - errorstr = applyIccFile(output_info->name, getIccFileName(profileName, output_info->name, kde_confdir)); - if (errorstr != "") { - return errorstr; - } - } - freeScreenInfoStructure(randr_screen_info); - } - else { - return applyIccFile(getIccFileName(profileName, "Default", kde_confdir), "Default"); - } - - t_config->writeEntry("CurrentProfile", profileName); - t_config->sync(); - delete t_config; - - return ""; -} - -TQString KRandrSimpleAPI::getEDIDMonitorName(int card, TQString displayname) { - TQString edid; - TQByteArray binaryedid = getEDID(card, displayname); - if (binaryedid.isNull()) - return TQString(); - - // Get the manufacturer ID - unsigned char letter_1 = ((binaryedid[8]>>2) & 0x1F) + 0x40; - unsigned char letter_2 = (((binaryedid[8] & 0x03) << 3) | ((binaryedid[9]>>5) & 0x07)) + 0x40; - unsigned char letter_3 = (binaryedid[9] & 0x1F) + 0x40; - TQChar qletter_1 = TQChar(letter_1); - TQChar qletter_2 = TQChar(letter_2); - TQChar qletter_3 = TQChar(letter_3); - TQString manufacturer_id = TQString("%1%2%3").arg(qletter_1).arg(qletter_2).arg(qletter_3); - - // Get the model ID - unsigned int raw_model_id = (((binaryedid[10] << 8) | binaryedid[11]) << 16) & 0xFFFF0000; - // Reverse the bit order - unsigned int model_id = reverse_bits(raw_model_id); - - // Try to get the model name - bool has_friendly_name = false; - unsigned char descriptor_block[18]; - int i; - for (i=72;i<90;i++) { - descriptor_block[i-72] = binaryedid[i] & 0xFF; - } - if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) { - for (i=90;i<108;i++) { - descriptor_block[i-90] = binaryedid[i] & 0xFF; - } - if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) { - for (i=108;i<126;i++) { - descriptor_block[i-108] = binaryedid[i] & 0xFF; - } - } - } - - TQString monitor_name; - if ((descriptor_block[0] == 0) && (descriptor_block[1] == 0) && (descriptor_block[3] == 0xFC)) { - char* pos = strchr((char *)(descriptor_block+5), '\n'); - if (pos) { - *pos = 0; - has_friendly_name = true; - monitor_name = TQString((char *)(descriptor_block+5)); - } - else { - has_friendly_name = false; - } - } - - // [FIXME] - // Look up manudacturer names if possible! - - if (has_friendly_name) - edid = TQString("%1 %2").arg(manufacturer_id).arg(monitor_name); - else - edid = TQString("%1 0x%2").arg(manufacturer_id).arg(model_id, 0, 16); - - return edid; -} - -TQByteArray KRandrSimpleAPI::getEDID(int card, TQString displayname) { - TQFile file(TQString("/sys/class/drm/card%1-%2/edid").arg(card).arg(displayname)); - if (!file.open (IO_ReadOnly)) - return TQByteArray(); - TQByteArray binaryedid = file.readAll(); - file.close(); - return binaryedid; -} - -TQString KRandrSimpleAPI::getCurrentProfile () { - TQString profileName; - KSimpleConfig *t_config; - - t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); - profileName = t_config->readEntry("CurrentProfile"); - delete t_config; - return profileName; -} - -TQString KRandrSimpleAPI::applySystemWideIccConfiguration(TQString kde_confdir) { - // Apply ICC settings with XCalib - TQString icc_command; - FILE *pipe_xcalib; - char xcalib_result[2048]; - int i; - xcalib_result[0]=0; - - icc_command = TQString("xcalib \"%1\"").arg(getIccFileName(NULL, "Default", kde_confdir)); - if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) - { - printf("Xcalib pipe error [xcalib apply]\n"); - } - else { - if (fgets(xcalib_result, 2048, pipe_xcalib)) { - pclose(pipe_xcalib); - for (i=1;i<2048;i++) { - if (xcalib_result[i] == 0) { - xcalib_result[i-1]=0; - i=2048; - } - } - if (strlen(xcalib_result) > 2) { - return xcalib_result; - } - } - else { - return ""; - } - } - return ""; -} - -TQStringList KRandrSimpleAPI::getDisplayConfigurationProfiles(TQString kde_confdir) { - TQStringList ret; - - TQDir d(kde_confdir + "/displayconfig/"); - d.setFilter(TQDir::Files); - d.setSorting(TQDir::Name); - - const TQFileInfoList *list = d.entryInfoList(); - if (list) { - TQFileInfoListIterator it(*list); - TQFileInfo *fi; - - while ((fi = it.current()) != 0) { - if (fi->fileName() != "default") { - ret.append(fi->fileName()); - } - ++it; - } - } - - return ret; -} - -bool KRandrSimpleAPI::deleteDisplayConfiguration(TQString profilename, TQString kde_confdir) { - TQString fileName = kde_confdir + "/displayconfig/"; - fileName.append(profilename); - return (!unlink(fileName.ascii())); -} - -bool KRandrSimpleAPI::renameDisplayConfiguration(TQString profilename, TQString newprofilename, TQString kde_confdir) { - TQString fileName = kde_confdir + "/displayconfig/"; - TQString newFileName = fileName; - fileName.append(profilename); - newFileName.append(newprofilename); - TQDir d(kde_confdir + "/displayconfig/"); - return (d.rename(fileName, newFileName)); -} - -void KRandrSimpleAPI::saveDisplayConfiguration(bool enable, bool applyonstart, TQString profilename, TQString defaultprofilename, TQString kde_confdir, TQPtrList screenInfoArray) { - int i; - - TQString filename; - - filename = "displayglobals"; - filename.prepend(kde_confdir.append("/")); - KSimpleConfig* display_config = new KSimpleConfig( filename ); - display_config->setGroup("General"); - display_config->writeEntry("EnableDisplayControl", enable); - display_config->writeEntry("ApplySettingsOnStart", applyonstart); - display_config->writeEntry("StartupProfileName", defaultprofilename); - display_config->sync(); - delete display_config; - - filename = profilename; - if (filename == "") { - filename = "default"; - } - filename.prepend(kde_confdir.append("/displayconfig/")); - - display_config = new KSimpleConfig( filename ); - - i=0; - SingleScreenData *screendata; - for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) { - display_config->setGroup(TQString("SCREEN %1").arg(i)); - display_config->writeEntry("ScreenUniqueName", screendata->screenUniqueName); - display_config->writeEntry("ScreenFriendlyName", screendata->screenFriendlyName); - display_config->writeEntry("GenericScreenDetected", screendata->generic_screen_detected); - display_config->writeEntry("ScreenConnected", screendata->screen_connected); - display_config->writeEntry("Resolutions", screendata->resolutions); - display_config->writeEntry("RefreshRates", screendata->refresh_rates); - display_config->writeEntry("ColorDepths", screendata->color_depths); - display_config->writeEntry("AvailableRotations", screendata->rotations); - display_config->writeEntry("CurrentResolution", screendata->current_resolution_index); - display_config->writeEntry("CurrentRefreshRate", screendata->current_refresh_rate_index); - display_config->writeEntry("CurrentColorDepth", screendata->current_color_depth_index); - display_config->writeEntry("CurrentRotation", screendata->current_rotation_index); - display_config->writeEntry("CurrentOrientiation", screendata->current_orientation_mask); - display_config->writeEntry("GammaRed", screendata->gamma_red); - display_config->writeEntry("GammaGreen", screendata->gamma_green); - display_config->writeEntry("GammaBlue", screendata->gamma_blue); - display_config->writeEntry("CurrentXFlip", screendata->has_x_flip); - display_config->writeEntry("CurrentYFlip", screendata->has_y_flip); - display_config->writeEntry("SupportsTransformation", screendata->supports_transformations); - display_config->writeEntry("IsPrimary", screendata->is_primary); - display_config->writeEntry("IsExtended", screendata->is_extended); - display_config->writeEntry("AbsXPos", screendata->absolute_x_position); - display_config->writeEntry("AbsYPos", screendata->absolute_y_position); - display_config->writeEntry("CurrentXPixelCount", screendata->current_x_pixel_count); - display_config->writeEntry("CurrentYPixelCount", screendata->current_y_pixel_count); - display_config->writeEntry("HasDPMS", screendata->has_dpms); - display_config->writeEntry("EnableDPMS", screendata->enable_dpms); - display_config->writeEntry("DPMSStandbyDelay", screendata->dpms_standby_delay); - display_config->writeEntry("DPMSSuspendDelay", screendata->dpms_suspend_delay); - display_config->writeEntry("DPMSPowerDownDelay", screendata->dpms_off_delay); - i++; - } - - display_config->sync(); - delete display_config; -} - -TQPoint KRandrSimpleAPI::applyStartupDisplayConfiguration(TQString kde_confdir) { - bool applyonstart = getDisplayConfigurationStartupAutoApplyEnabled(kde_confdir); - if (applyonstart) { - TQString profilename = getDisplayConfigurationStartupAutoApplyName(kde_confdir); - return applyDisplayConfiguration(profilename, kde_confdir); - } - else { - return TQPoint(); - } -} - -TQPoint KRandrSimpleAPI::applyDisplayConfiguration(TQString profilename, TQString kde_confdir) { - TQPoint ret; - - bool enabled = getDisplayConfigurationEnabled(kde_confdir); - if (profilename == "") { - profilename = "default"; - } - - if (enabled) { - TQPtrList screenInfoArray; - screenInfoArray = loadDisplayConfiguration(profilename, kde_confdir); - if (screenInfoArray.count() > 0) { - applyDisplayConfiguration(screenInfoArray, FALSE, kde_confdir); - } - destroyScreenInformationObject(screenInfoArray); - screenInfoArray = readCurrentDisplayConfiguration(); - ensureMonitorDataConsistency(screenInfoArray); - ret = primaryScreenOffsetFromTLC(screenInfoArray); - destroyScreenInformationObject(screenInfoArray); - } - - return ret; -} - -TQPtrList KRandrSimpleAPI::loadDisplayConfiguration(TQString profilename, TQString kde_confdir) { - int i; - - TQString filename; - filename = profilename; - if (filename == "") { - filename = "default"; - } - filename.prepend(kde_confdir.append("/displayconfig/")); - - KSimpleConfig* display_config = new KSimpleConfig( filename ); - - TQStringList grouplist = display_config->groupList(); - SingleScreenData *screendata; - TQPtrList screenInfoArray; - for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) { - if ((*it).startsWith("SCREEN ")) { - display_config->setGroup(*it); - i = ((*it).remove("SCREEN ")).toInt(); - screendata = new SingleScreenData; - screenInfoArray.append(screendata); - screendata->screenUniqueName = display_config->readEntry("ScreenUniqueName"); - screendata->screenFriendlyName = display_config->readEntry("ScreenFriendlyName"); - screendata->generic_screen_detected = display_config->readBoolEntry("GenericScreenDetected"); - screendata->screen_connected = display_config->readBoolEntry("ScreenConnected"); - screendata->resolutions = display_config->readListEntry("Resolutions"); - screendata->refresh_rates = display_config->readListEntry("RefreshRates"); - screendata->color_depths = display_config->readListEntry("ColorDepths"); - screendata->rotations = display_config->readListEntry("AvailableRotations"); - screendata->current_resolution_index = display_config->readNumEntry("CurrentResolution"); - screendata->current_refresh_rate_index = display_config->readNumEntry("CurrentRefreshRate"); - screendata->current_color_depth_index = display_config->readNumEntry("CurrentColorDepth"); - screendata->current_rotation_index = display_config->readNumEntry("CurrentRotation"); - screendata->current_orientation_mask = display_config->readNumEntry("CurrentOrientiation"); - screendata->gamma_red = display_config->readDoubleNumEntry("GammaRed"); - screendata->gamma_green = display_config->readDoubleNumEntry("GammaGreen"); - screendata->gamma_blue = display_config->readDoubleNumEntry("GammaBlue"); - screendata->has_x_flip = display_config->readBoolEntry("CurrentXFlip"); - screendata->has_y_flip = display_config->readBoolEntry("CurrentYFlip"); - screendata->supports_transformations = display_config->readBoolEntry("SupportsTransformation"); - screendata->is_primary = display_config->readBoolEntry("IsPrimary"); - screendata->is_extended = display_config->readBoolEntry("IsExtended"); - screendata->absolute_x_position = display_config->readNumEntry("AbsXPos"); - screendata->absolute_y_position = display_config->readNumEntry("AbsYPos"); - screendata->current_x_pixel_count = display_config->readNumEntry("CurrentXPixelCount"); - screendata->current_y_pixel_count = display_config->readNumEntry("CurrentYPixelCount"); - screendata->has_dpms = display_config->readBoolEntry("HasDPMS"); - screendata->enable_dpms = display_config->readBoolEntry("EnableDPMS"); - screendata->dpms_standby_delay = display_config->readNumEntry("DPMSStandbyDelay"); - screendata->dpms_suspend_delay = display_config->readNumEntry("DPMSSuspendDelay"); - screendata->dpms_off_delay = display_config->readNumEntry("DPMSPowerDownDelay"); - } - } - - delete display_config; - - return screenInfoArray; -} - -int KRandrSimpleAPI::getHardwareRotationFlags(SingleScreenData* screendata) { - int rotationFlags = 0; - if (screendata->current_rotation_index == ROTATION_0_DEGREES_INDEX) { - rotationFlags = rotationFlags | RandRScreen::Rotate0; - } - else if (screendata->current_rotation_index == ROTATION_90_DEGREES_INDEX) { - rotationFlags = rotationFlags | RandRScreen::Rotate90; - } - else if (screendata->current_rotation_index == ROTATION_180_DEGREES_INDEX) { - rotationFlags = rotationFlags | RandRScreen::Rotate180; - } - else if (screendata->current_rotation_index == ROTATION_270_DEGREES_INDEX) { - rotationFlags = rotationFlags | RandRScreen::Rotate270; - } - if (screendata->has_x_flip) { - rotationFlags = rotationFlags | RandRScreen::ReflectX; - } - if (screendata->has_y_flip) { - rotationFlags = rotationFlags | RandRScreen::ReflectY; - } - return rotationFlags; -} - -#define USE_XRANDR_PROGRAM - -bool KRandrSimpleAPI::applyDisplayConfiguration(TQPtrList screenInfoArray, bool test, TQString kde_confdir) { - int i; - int j; - bool accepted = true; - Display *randr_display; - XRROutputInfo *output_info; - ScreenInfo *randr_screen_info; - - SingleScreenData *screendata; - - TQPtrList oldconfig; - if (test == TRUE) { - oldconfig = readCurrentDisplayConfiguration(); - } - - if (isValid() == true) { -#ifdef USE_XRANDR_PROGRAM - // Assemble the command string for xrandr - TQString command; - command = "xrandr"; - - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - if (screendata) { - output_info = randr_screen_info->outputs[i]->info; - command.append(" --output ").append(output_info->name); - if (screendata->is_primary || screendata->is_extended) { - command.append(TQString(" --mode %1x%2").arg(screendata->current_x_pixel_count).arg(screendata->current_y_pixel_count)); - command.append(TQString(" --pos %1x%2").arg(screendata->absolute_x_position).arg(screendata->absolute_y_position)); - command.append(TQString(" --refresh %1").arg(atoi((*screendata->refresh_rates.at(screendata->current_refresh_rate_index)).ascii()))); - command.append(TQString(" --gamma %1:%2:%3").arg(screendata->gamma_red).arg(screendata->gamma_green).arg(screendata->gamma_blue)); - if (screendata->current_rotation_index == ROTATION_0_DEGREES_INDEX) command.append(" --rotate ").append("normal"); - if (screendata->current_rotation_index == ROTATION_90_DEGREES_INDEX) command.append(" --rotate ").append("left"); - if (screendata->current_rotation_index == ROTATION_180_DEGREES_INDEX) command.append(" --rotate ").append("inverted"); - if (screendata->current_rotation_index == ROTATION_270_DEGREES_INDEX) command.append(" --rotate ").append("right"); - if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("normal"); - if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("x"); - if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("y"); - if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("xy"); - if (screendata->is_primary) { - command.append(" --primary"); - } - } - else { - command.append(" --off"); - } - } - else { - printf("[WARNING] Unable to find configuration for monitor %d; settings may not be correctly applied...\n", i); fflush(stdout); - } - } - freeScreenInfoStructure(randr_screen_info); - - TQString xrandr_command_output = exec(command.ascii()); - xrandr_command_output = xrandr_command_output.stripWhiteSpace(); - if (test) { - // In case gamma settings is not supported, try again without '--gamma' parameter - if (xrandr_command_output == "xrandr: Gamma size is 0.") { - command = command.replace(TQRegExp("--gamma [0-9\\.]*:[0-9\\.]*:[0-9\\.]*"), ""); - xrandr_command_output = exec(command.ascii()); - xrandr_command_output = xrandr_command_output.stripWhiteSpace(); - } - - if(xrandr_command_output.startsWith("xrandr: Failed to get size of gamma for output")) { - KMessageBox::sorry(0, xrandr_command_output, i18n("Setting gamma failed.")); - } else if (xrandr_command_output != "") { - applyDisplayConfiguration(oldconfig, FALSE, kde_confdir); - accepted = false; - destroyScreenInformationObject(oldconfig); - KMessageBox::sorry(0, xrandr_command_output, i18n("XRandR encountered a problem")); - return accepted; - } - } -#else - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - // Turn off all displays - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - output_info = randr_screen_info->outputs[i]->info; - - randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; - randr_screen_info->cur_output = randr_screen_info->outputs[i]; - randr_screen_info->cur_output->auto_set = 0; - randr_screen_info->cur_output->off_set = 1; - output_off (randr_screen_info, randr_screen_info->cur_output); - j=main_low_apply(randr_screen_info); - } - freeScreenInfoStructure(randr_screen_info); - randr_screen_info = read_screen_info(randr_display); - // Turn on the primary display - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - output_info = randr_screen_info->outputs[i]->info; - - if (screendata->is_primary == true) { - randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; - randr_screen_info->cur_output = randr_screen_info->outputs[i]; - randr_screen_info->cur_output->auto_set = 1; - randr_screen_info->cur_output->off_set = 0; - output_auto (randr_screen_info, randr_screen_info->cur_output); - j=main_low_apply(randr_screen_info); - } - } - freeScreenInfoStructure(randr_screen_info); - // Handle the remaining displays - randr_screen_info = read_screen_info(randr_display); - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - output_info = randr_screen_info->outputs[i]->info; - - // Activate or deactivate the screens as necessary - randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; - randr_screen_info->cur_output = randr_screen_info->outputs[i]; - if (screendata->is_primary == false) { - if (screendata->is_primary || screendata->is_extended) { - randr_screen_info->cur_output->auto_set = 1; - randr_screen_info->cur_output->off_set = 0; - output_auto (randr_screen_info, randr_screen_info->cur_output); - j=main_low_apply(randr_screen_info); - } - else { - randr_screen_info->cur_output->auto_set = 0; - randr_screen_info->cur_output->off_set = 1; - output_off (randr_screen_info, randr_screen_info->cur_output); - j=main_low_apply(randr_screen_info); - } - } - } - freeScreenInfoStructure(randr_screen_info); - randr_screen_info = read_screen_info(randr_display); - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - output_info = randr_screen_info->outputs[i]->info; - - if (screendata->is_primary || screendata->is_extended) { - // Set rotation, refresh rate, and size - RandRScreen *cur_screen = new RandRScreen(i); - cur_screen->proposeSize(screendata->current_resolution_index); - cur_screen->proposeRefreshRate(screendata->current_refresh_rate_index); - cur_screen->proposeRotation(getHardwareRotationFlags(screendata)); - cur_screen->applyProposed(); - delete cur_screen; - - // Force data reload - randr_screen_info = read_screen_info(randr_display); - output_info = randr_screen_info->outputs[i]->info; - - // Finally, set the screen's position - randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; - if (randr_screen_info->cur_crtc) { - randr_screen_info->cur_crtc->cur_x = screendata->absolute_x_position; - randr_screen_info->cur_crtc->cur_y = screendata->absolute_y_position; - j=main_low_apply(randr_screen_info); - } - } - } - freeScreenInfoStructure(randr_screen_info); -#endif - } - - applyDisplayGamma(screenInfoArray); - applyDisplayDPMS(screenInfoArray); - TQString current_icc_profile = getCurrentProfile(); - applySystemWideIccConfiguration(kde_confdir); - applyIccConfiguration(current_icc_profile, kde_confdir); - - if (test == TRUE) { - int ret = showTestConfigurationDialog(); - if (!ret) { - applyDisplayConfiguration(oldconfig, FALSE, kde_confdir); - accepted = false; - } - destroyScreenInformationObject(oldconfig); - } - - return accepted; -} - -TQPtrList KRandrSimpleAPI::copyScreenInformationObject(TQPtrList screenInfoArray) { - SingleScreenData *origscreendata; - SingleScreenData *copyscreendata; - TQPtrList retArray; - for ( origscreendata = screenInfoArray.first(); origscreendata; origscreendata = screenInfoArray.next() ) { - copyscreendata = new SingleScreenData; - *copyscreendata = *origscreendata; - retArray.append(copyscreendata); - } - return retArray; -} - -void KRandrSimpleAPI::destroyScreenInformationObject(TQPtrList screenInfoArray) { - SingleScreenData *screendata; - for ( screendata = screenInfoArray.first(); screendata; screendata = screenInfoArray.next() ) { - screenInfoArray.remove(screendata); - delete screendata; - } -} - -void KRandrSimpleAPI::ensureMonitorDataConsistency(TQPtrList screenInfoArray) { - int i; - SingleScreenData *screendata; - - int numberOfScreens = screenInfoArray.count(); - - for (i=0;iscreen_connected) { - screendata->is_primary = false; - screendata->is_extended = false; - } - } - - bool has_primary_monitor = false; - for (i=0;iis_primary) { - has_primary_monitor = true; - } - } - if (!has_primary_monitor) { - for (i=0;iscreen_connected && screendata->is_extended) { - screendata->is_primary = true; - screendata->is_extended = true; - has_primary_monitor = true; - } - } - } - } - if (!has_primary_monitor) { - for (i=0;iscreen_connected) { - screendata->is_primary = true; - screendata->is_extended = true; - has_primary_monitor = true; - } - } - } - } - - bool found_first_primary_monitor = false; - for (i=0;iis_primary) { - if (!found_first_primary_monitor) { - found_first_primary_monitor = true; - } - else { - screendata->is_primary = false; - } - } - } - - for (i=0;iis_primary) { - screendata->is_extended = true; - } - } - - for (i=0;iresolutions[screendata->current_resolution_index]; - int separator_pos = resolutionstring.find(" x "); - TQString x_res_string = resolutionstring.left(separator_pos); - TQString y_res_string = resolutionstring.right(resolutionstring.length()-separator_pos-3); - screendata->current_x_pixel_count = x_res_string.toInt(); - screendata->current_y_pixel_count = y_res_string.toInt(); - screendata->current_orientation_mask = getHardwareRotationFlags(screendata); - } - - // Each screen's absolute position is given relative to the primary monitor - // Fix up the absolute positions - int primary_offset_x = 0; - int primary_offset_y = 0; - for (i=0;iis_primary) { - primary_offset_x = screendata->absolute_x_position; - primary_offset_y = screendata->absolute_y_position; - primary_offset_x = primary_offset_x * (-1); - primary_offset_y = primary_offset_y * (-1); - } - } - for (i=0;iabsolute_x_position = screendata->absolute_x_position + primary_offset_x; - screendata->absolute_y_position = screendata->absolute_y_position + primary_offset_y; - } -} - -TQPoint KRandrSimpleAPI::primaryScreenOffsetFromTLC(TQPtrList screenInfoArray) { - int i; - SingleScreenData *screendata; - int numberOfScreens = screenInfoArray.count(); - - int primary_offset_x = 0; - int primary_offset_y = 0; - for (i=0;iabsolute_x_position < primary_offset_x) { - primary_offset_x = screendata->absolute_x_position; - } - if (screendata->absolute_y_position < primary_offset_y) { - primary_offset_y = screendata->absolute_y_position; - } - } - primary_offset_x = primary_offset_x * (-1); - primary_offset_y = primary_offset_y * (-1); - - return TQPoint(primary_offset_x, primary_offset_y); -} - -HotPlugRulesList KRandrSimpleAPI::getHotplugRules(TQString kde_confdir) { - int i; - TQString filename; - HotPlugRulesList ret; - - filename = "displayglobals"; - filename.prepend(kde_confdir.append("/")); - KSimpleConfig* display_config = new KSimpleConfig( filename ); - - TQStringList grouplist = display_config->groupList(); - for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) { - if (!(*it).startsWith("Hotplug-Rule")) { - continue; - } - HotPlugRule rule; - display_config->setGroup(*it); - rule.outputs = display_config->readListEntry("Outputs"); - rule.states = display_config->readIntListEntry("States"); - rule.profileName = display_config->readEntry("Profile"); - ret.append(rule); - } - delete display_config; - - return ret; -} - -void KRandrSimpleAPI::saveHotplugRules(HotPlugRulesList rules, TQString kde_confdir) { - int i; - TQString filename; - - filename = "displayglobals"; - filename.prepend(kde_confdir.append("/")); - KSimpleConfig* display_config = new KSimpleConfig( filename ); - TQStringList grouplist = display_config->groupList(); - for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) { - if (!(*it).startsWith("Hotplug-Rule")) { - continue; - } - display_config->deleteGroup(*it, true, false); - } - HotPlugRulesList::Iterator it; - i=0; - for (it=rules.begin(); it != rules.end(); ++it) { - display_config->setGroup(TQString("Hotplug-Rule%1").arg(i)); - display_config->writeEntry("Outputs", (*it).outputs); - display_config->writeEntry("States", (*it).states); - display_config->writeEntry("Profile", (*it).profileName); - i++; - } - display_config->sync(); - delete display_config; -} - -bool KRandrSimpleAPI::getDisplayConfigurationEnabled(TQString kde_confdir) { - TQString filename = "displayglobals"; - filename.prepend(kde_confdir.append("/")); - KSimpleConfig* display_config = new KSimpleConfig( filename ); - display_config->setGroup("General"); - bool enabled = display_config->readBoolEntry("EnableDisplayControl", false); - delete display_config; - - return enabled; -} - -bool KRandrSimpleAPI::getDisplayConfigurationStartupAutoApplyEnabled(TQString kde_confdir) { - TQString filename = "displayglobals"; - filename.prepend(kde_confdir.append("/")); - KSimpleConfig* display_config = new KSimpleConfig( filename ); - display_config->setGroup("General"); - bool applyonstart = display_config->readBoolEntry("ApplySettingsOnStart", false); - delete display_config; - - return applyonstart; -} - -TQString KRandrSimpleAPI::getDisplayConfigurationStartupAutoApplyName(TQString kde_confdir) { - TQString filename = "displayglobals"; - filename.prepend(kde_confdir.append("/")); - KSimpleConfig* display_config = new KSimpleConfig( filename ); - display_config->setGroup("General"); - TQString profilename = display_config->readEntry("StartupProfileName", ""); - delete display_config; - - return profilename; -} - -void KRandrSimpleAPI::applyHotplugRules(TQString kde_confdir) { - bool enabled = getDisplayConfigurationEnabled(kde_confdir); - if (!enabled) { - return; - } - - HotPlugRulesList rules = getHotplugRules(kde_confdir); - TQPtrList screenInfoArray = readCurrentDisplayConfiguration(); - - int i; - int j; - TQString bestRule; - int bestRuleMatchCount = 0; - SingleScreenData *screendata = NULL; - HotPlugRulesList::Iterator it; - for (it=rules.begin(); it != rules.end(); ++it) { - // Compare each rule against the current display configuration - // It an output matches the state given in the rule, increment matchCount - HotPlugRule rule = *it; - int matchCount = 0; - int numberOfScreens = screenInfoArray.count(); - for (i=0;iscreenUniqueName) { - continue; - } - if ((*it).states[j] == HotPlugRule::Connected) { - if (screendata->screen_connected) { - matchCount++; - } - } - else if ((*it).states[j] == HotPlugRule::Disconnected) { - if (!screendata->screen_connected) { - matchCount++; - } - } - } - } - - if (matchCount > bestRuleMatchCount) { - bestRuleMatchCount = matchCount; - bestRule = rule.profileName; - } - } - - destroyScreenInformationObject(screenInfoArray); - - if (bestRuleMatchCount > 0) { - // At least one rule matched... - // Apply the profile name in bestRule to the display hardware - applyDisplayConfiguration(bestRule, kde_confdir); - } -} - -void KRandrSimpleAPI::applyDisplayGamma(TQPtrList screenInfoArray) { - int i; - Display *randr_display; - XRROutputInfo *output_info; - ScreenInfo *randr_screen_info; - XRRCrtcGamma *gamma; - - SingleScreenData *screendata; - - if (isValid() == true) { - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - output_info = randr_screen_info->outputs[i]->info; - CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; - if (!current_crtc) { - continue; - } - // vvvvvvvvv This chunk of code is borrowed from xrandr vvvvvvvvvv - int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id); - if (!size) { - continue; - } - gamma = XRRAllocGamma(size); - if (!gamma) { - continue; - } - for (i = 0; i < size; i++) { - if (screendata->gamma_red == 1.0) - gamma->red[i] = i << 8; - else - gamma->red[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_red) * (double)(size-1)*256); - - if (screendata->gamma_green == 1.0) - gamma->green[i] = i << 8; - else - gamma->green[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_green) * (double)(size-1)*256); - - if (screendata->gamma_blue == 1.0) - gamma->blue[i] = i << 8; - else - gamma->blue[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_blue) * (double)(size-1)*256); - } - XRRSetCrtcGamma(randr_display, current_crtc->id, gamma); - free(gamma); - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } - freeScreenInfoStructure(randr_screen_info); - } -} - -void KRandrSimpleAPI::applyDisplayDPMS(TQPtrList screenInfoArray) { - int i; - Display *randr_display; - XRROutputInfo *output_info; - ScreenInfo *randr_screen_info; - XRRCrtcGamma *gamma; - - SingleScreenData *screendata; - - if (isValid() == true) { - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - for (i = 0; i < screenInfoArray.count(); i++) { - screendata = screenInfoArray.at(i); - output_info = randr_screen_info->outputs[i]->info; - CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; - if (!current_crtc) { - continue; - } - if (!screendata->has_dpms) { - continue; - } - if (screendata->enable_dpms) { - DPMSSetTimeouts(randr_display, screendata->dpms_standby_delay, screendata->dpms_suspend_delay, screendata->dpms_off_delay); - DPMSEnable(randr_display); - } - else { - DPMSDisable(randr_display); - } - } - freeScreenInfoStructure(randr_screen_info); - } -} - -void KRandrSimpleAPI::freeScreenInfoStructure(ScreenInfo* screen_info) { - int i; - - for (i=0; in_crtc; i++) { - free(screen_info->crtcs[i]); - } - for (i=0; in_output; i++) { - free(screen_info->outputs[i]); - } - free(screen_info->outputs); - free(screen_info->crtcs); - free(screen_info); -} - -TQPtrList KRandrSimpleAPI::readCurrentDisplayConfiguration() { - // Discover display information - int i; - int j; - - XRROutputInfo *output_info; - SingleScreenData *screendata; - TQPtrList screenInfoArray; - - Display *randr_display; - ScreenInfo *randr_screen_info; - - // Clear existing info - destroyScreenInformationObject(screenInfoArray); - - int numberOfScreens = 0; - if (isValid() == true) { - randr_display = tqt_xdisplay(); - randr_screen_info = read_screen_info(randr_display); - for (i = 0; i < randr_screen_info->n_output; i++) { - output_info = randr_screen_info->outputs[i]->info; - CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; - - // Create new data object - screendata = new SingleScreenData; - screenInfoArray.append(screendata); - screendata->screenUniqueName = TQString(i18n("%1:%2")).arg(":0").arg(capitalizeString(output_info->name)); // [FIXME] How can I get the name of the Xorg graphics driver currently in use? - screendata->screenFriendlyName = TQString(i18n("%1. %2 output on %3")).arg(i+1).arg(capitalizeString(output_info->name)).arg(":0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use? - screendata->generic_screen_detected = false; - - // Attempt to use KMS to find screen EDID and name - TQString edid = getEDIDMonitorName(0, output_info->name); // [FIXME] Don't hardwire to card 0! - if (!edid.isNull()) { - screendata->screenFriendlyName = TQString(i18n("%1. %2 on %3 on card %4")).arg(i+1).arg(edid).arg(capitalizeString(output_info->name)).arg("0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use? - } - - // Get resolutions - bool screen_active; - RandRScreen *cur_screen = 0; - if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) { - // Output DISCONNECTED - screen_active = false; - } - else { - if (randr_screen_info->outputs[i]->cur_crtc) { - // Output CONNECTED and ON - screen_active = true; - cur_screen = new RandRScreen(i); - } - else { - // Output CONNECTED and OFF - screen_active = false; - cur_screen = new RandRScreen(i); - } - } - - // Get DPMS information - screendata->has_dpms = 1; // [FIXME] Master Xorg check for global DPMS support should go here if possible - if (screendata->has_dpms) { - CARD16 dpms_standby_delay; - CARD16 dpms_suspend_delay; - CARD16 dpms_off_delay; - screendata->has_dpms = DPMSGetTimeouts(randr_display, &dpms_standby_delay, &dpms_suspend_delay, &dpms_off_delay); - screendata->dpms_standby_delay = dpms_standby_delay; - screendata->dpms_suspend_delay = dpms_suspend_delay; - screendata->dpms_off_delay = dpms_off_delay; - if (screendata->has_dpms) { - CARD16 power_level; - BOOL enable_dpms; - screendata->has_dpms = DPMSInfo(randr_display, &power_level, &enable_dpms); - screendata->enable_dpms = enable_dpms; - } - } - if (!screendata->has_dpms) { - screendata->enable_dpms = false; - screendata->dpms_standby_delay = 0; - screendata->dpms_suspend_delay = 0; - screendata->dpms_off_delay = 0; - } - - if (cur_screen) { - screendata->screen_connected = true; - for (int j = 0; j < cur_screen->numSizes(); j++) { - screendata->resolutions.append(i18n("%1 x %2").arg(cur_screen->pixelSize(j).width()).arg(cur_screen->pixelSize(j).height())); - } - screendata->current_resolution_index = 0; - if (current_crtc) { - screendata->current_resolution_index = screendata->resolutions.findIndex(i18n("%1 x %2").arg(current_crtc->info->width).arg(current_crtc->info->height)); - } - if (screendata->current_resolution_index < 0) { - screendata->current_resolution_index = cur_screen->proposedSize(); - } - - // Get refresh rates - TQStringList rr = cur_screen->refreshRates(screendata->current_resolution_index); - for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it) { - screendata->refresh_rates.append(*it); - } - screendata->current_refresh_rate_index = cur_screen->proposedRefreshRate(); - - // Get color depths - // [FIXME] - screendata->color_depths.append(i18n("Default")); - screendata->current_color_depth_index = 0; - - // Get orientation flags - // RandRScreen::Rotate0 - // RandRScreen::Rotate90 - // RandRScreen::Rotate180 - // RandRScreen::Rotate270 - // RandRScreen::ReflectX - // RandRScreen::ReflectY - - screendata->rotations.append(i18n("0 degrees")); - screendata->rotations.append(i18n("90 degrees")); - screendata->rotations.append(i18n("180 degrees")); - screendata->rotations.append(i18n("270 degrees")); - screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0); - if (screendata->supports_transformations) { - screendata->current_orientation_mask = cur_screen->proposedRotation(); - switch (screendata->current_orientation_mask & RandRScreen::RotateMask) { - case RandRScreen::Rotate0: - screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; - break; - case RandRScreen::Rotate90: - screendata->current_rotation_index = ROTATION_90_DEGREES_INDEX; - break; - case RandRScreen::Rotate180: - screendata->current_rotation_index = ROTATION_180_DEGREES_INDEX; - break; - case RandRScreen::Rotate270: - screendata->current_rotation_index = ROTATION_270_DEGREES_INDEX; - break; - default: - // Shouldn't hit this one - Q_ASSERT(screendata->current_orientation_mask & RandRScreen::RotateMask); - screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; - break; - } - screendata->has_x_flip = (screendata->current_orientation_mask & RandRScreen::ReflectX); - screendata->has_y_flip = (screendata->current_orientation_mask & RandRScreen::ReflectY); - } - else { - screendata->has_x_flip = false; - screendata->has_y_flip = false; - screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; - } - - // Determine if this display is primary and/or extended - RROutput primaryoutput = XRRGetOutputPrimary(tqt_xdisplay(), DefaultRootWindow(tqt_xdisplay())); - if (primaryoutput == randr_screen_info->outputs[i]->id) { - screendata->is_primary = false; - } - else { - screendata->is_primary = true; - } - screendata->is_extended = screen_active; - if (!screendata->is_extended) { - screendata->is_primary = false; - } - - // Get this screen's absolute position - screendata->absolute_x_position = 0; - screendata->absolute_y_position = 0; - if (current_crtc) { - screendata->absolute_x_position = current_crtc->info->x; - screendata->absolute_y_position = current_crtc->info->y; - } - - // Get this screen's current resolution - screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width(); - screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height(); - - // Get this screen's current gamma values - // [FIXME] - // This attempts to guess a gamma value based on the LUT settings at 50% - // It may not always be 100% correct, or even anywhere close... - // Essentially it "undoes" the LUT gamma calculation from xrandr - // lut_gamma->green[i] = (pow(i/(size - 1), desired_gamma.green) * (size - 1) * 256); - screendata->gamma_red = 2.2; - screendata->gamma_green = 2.2; - screendata->gamma_blue = 2.2; - if (current_crtc) { - //int slot = 127; - int slot = 7; - int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id); - if(size>0) { - XRRCrtcGamma *gammastruct = XRRGetCrtcGamma (randr_display, current_crtc->id); - screendata->gamma_red = log(gammastruct->red[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); - screendata->gamma_green = log(gammastruct->green[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); - screendata->gamma_blue = log(gammastruct->blue[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); - } - } - // Round off the gamma to one decimal place - screendata->gamma_red = floorf(screendata->gamma_red * 10 + 0.5) / 10; - screendata->gamma_green = floorf(screendata->gamma_green * 10 + 0.5) / 10; - screendata->gamma_blue = floorf(screendata->gamma_blue * 10 + 0.5) / 10; - - delete cur_screen; - } - else { - // Fill in generic data for this disconnected output - screendata->screenFriendlyName = screendata->screenFriendlyName + TQString(" (") + i18n("disconnected") + TQString(")"); - screendata->screen_connected = false; - - screendata->resolutions = i18n("Default"); - screendata->refresh_rates = i18n("Default"); - screendata->color_depths = i18n("Default"); - screendata->rotations = i18n("N/A"); - - screendata->current_resolution_index = 0; - screendata->current_refresh_rate_index = 0; - screendata->current_color_depth_index = 0; - - screendata->gamma_red = 2.2; - screendata->gamma_green = 2.2; - screendata->gamma_blue = 2.2; - - screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; - screendata->current_orientation_mask = 0; - screendata->has_x_flip = false; - screendata->has_y_flip = false; - screendata->supports_transformations = false; - - screendata->is_primary = false; - screendata->is_extended = false; - screendata->absolute_x_position = 0; - screendata->absolute_y_position = 0; - screendata->current_x_pixel_count = 640; - screendata->current_y_pixel_count = 480; - } - - // Check for more screens... - numberOfScreens++; - } - - freeScreenInfoStructure(randr_screen_info); - } - else { - screendata = new SingleScreenData; - screenInfoArray.append(screendata); - - // Fill in a bunch of generic data - screendata->screenFriendlyName = i18n("Default output on generic video card"); - screendata->generic_screen_detected = true; - screendata->screen_connected = true; - - screendata->resolutions = i18n("Default"); - screendata->refresh_rates = i18n("Default"); - screendata->color_depths = i18n("Default"); - screendata->rotations = i18n("N/A"); - - screendata->current_resolution_index = 0; - screendata->current_refresh_rate_index = 0; - screendata->current_color_depth_index = 0; - - screendata->gamma_red = 2.2; - screendata->gamma_green = 2.2; - screendata->gamma_blue = 2.2; - - screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; - screendata->current_orientation_mask = 0; - screendata->has_x_flip = false; - screendata->has_y_flip = false; - screendata->supports_transformations = false; - - screendata->is_primary = true; - screendata->is_extended = true; - screendata->absolute_x_position = 0; - screendata->absolute_y_position = 0; - screendata->current_x_pixel_count = 640; - screendata->current_y_pixel_count = 480; - - numberOfScreens++; - } - - bool primary_set = false; - for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) { - if (screendata->is_primary) { - primary_set = true; - break; - } - } - // If there is no primary monitor set, xrandr is probably not functioning correctly! - Q_ASSERT(primary_set); - if (!primary_set) { - // [FIXME] - // Set this on the real primary monitor only! - screendata = screenInfoArray.at(0); - screendata->is_primary = true; - } - - return screenInfoArray; -} - -TQString KRandrSimpleAPI::clearIccConfiguration() { - // Clear ICC settings with XCalib - TQString icc_command; - FILE *pipe_xcalib; - char xcalib_result[2048]; - int i; - xcalib_result[0]=0; - - icc_command = TQString("xcalib -c"); - if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) - { - printf("Xcalib pipe error [xcalib clear]\n"); - } - else { - if (fgets(xcalib_result, 2048, pipe_xcalib)) { - pclose(pipe_xcalib); - for (i=1;i<2048;i++) { - if (xcalib_result[i] == 0) { - xcalib_result[i-1]=0; - i=2048; - } - } - if (strlen(xcalib_result) > 2) { - return xcalib_result; - } - } - else { - return ""; - } - } - return ""; -} - -ScreenInfo* KRandrSimpleAPI::read_screen_info (Display *display) -{ - return internal_read_screen_info(display); -} - -int KRandrSimpleAPI::set_screen_size (ScreenInfo *screen_info) -{ - return internal_set_screen_size(screen_info); -} - -void KRandrSimpleAPI::output_auto (ScreenInfo *screen_info, OutputInfo *output_info) -{ - internal_output_auto (screen_info, output_info); -} - -void KRandrSimpleAPI::output_off(ScreenInfo *screen_info, OutputInfo *output) -{ - internal_output_off(screen_info, output); -} - -CrtcInfo* KRandrSimpleAPI::auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info) -{ - return internal_auto_find_crtc (screen_info, output_info); -} - -XRRModeInfo *KRandrSimpleAPI::find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id) -{ - return internal_find_mode_by_xid (screen_info, mode_id); -} - -int KRandrSimpleAPI::mode_height (XRRModeInfo *mode_info, Rotation rotation) -{ - return internal_mode_height (mode_info, rotation); -} - -int KRandrSimpleAPI::mode_width (XRRModeInfo *mode_info, Rotation rotation) -{ - return internal_mode_width (mode_info, rotation); -} - -int KRandrSimpleAPI::get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id) -{ - return internal_get_width_by_output_id (screen_info, output_id); -} - -int KRandrSimpleAPI::get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id) -{ - return internal_get_height_by_output_id (screen_info, output_id); -} - -char *KRandrSimpleAPI::get_output_name (ScreenInfo *screen_info, RROutput id) -{ - return internal_get_output_name (screen_info, id); -} - -Status KRandrSimpleAPI::crtc_apply (CrtcInfo *crtc_info) -{ - return internal_crtc_apply (crtc_info); -} - -Status KRandrSimpleAPI::crtc_disable (CrtcInfo *crtc) -{ - return internal_crtc_disable (crtc); -} - -int KRandrSimpleAPI::main_low_apply (ScreenInfo *screen_info) -{ - return internal_main_low_apply (screen_info); -} - -void KRandrSimpleAPI::set_primary_output (ScreenInfo *screen_info, RROutput output_id) -{ - internal_output_set_primary(screen_info, output_id); -} - -bool KRandrSimpleAPI::kRandrHasRandr(void) -{ - return isValid(); -} - -const char *KRandrSimpleAPI::kRandrVersion(void) -{ - return "0.9.5"; -} - -const char *KRandrSimpleAPI::kRandrCopyright(void) -{ - return "LibKRandr 0.9.5 (C)2010 Timothy Pearson . U.S.A."; -} - -/* * * * * * - - Under this line (------) there's only a C wrapper for the KRandrSimpleAPI class - -* * * * * */ -const char *kRandrVersion(void) -{ - return KRandrSimpleAPI::kRandrVersion(); -} - -const char *kRandrCopyright(void) -{ - return KRandrSimpleAPI::kRandrCopyright(); -} - diff --git a/tderandr/libtderandr.cpp b/tderandr/libtderandr.cpp new file mode 100644 index 000000000..50c7a1673 --- /dev/null +++ b/tderandr/libtderandr.cpp @@ -0,0 +1,1629 @@ +/* libtderandr.cpp - class KRandr that makes it easy to use XRandr in KDE + This file is part of KRandr 0.9.5 + Copyright (C) 2010 Timothy Pearson + LibKRandr's homepage : http://www.trinitydesktop.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Send comments and bug fixes to Timothy Pearson + +***************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "libtderandr.h" + +#include + +// FIXME +// For now, just use the standalone xrandr program to apply the display settings +#define USE_XRANDR_PROGRAM + +// This routine is courtsey of an answer on "Stack Overflow" +// It takes an LSB-first int and makes it an MSB-first int (or vice versa) +unsigned int reverse_bits(unsigned int x) +{ + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + return((x >> 16) | (x << 16)); +} + +// This routine returns the output of an arbitrary Bash command +TQString exec(const char * cmd) { + TQString bashcommand = cmd; + bashcommand = bashcommand.replace("\"", "\\\""); + bashcommand = TQString("/bin/bash -c \"%1\" 2>&1").arg(bashcommand); + FILE* pipe = popen(bashcommand.ascii(), "r"); + if (!pipe) return "ERROR"; + char buffer[128]; + TQString result = ""; + while(!feof(pipe)) { + if(fgets(buffer, 128, pipe) != NULL) { + result += buffer; + } + } + pclose(pipe); + result.remove(result.length(), 1); + return result; +} + +TQString capitalizeString(TQString in) { + return in.left(1).upper() + in.right(in.length()-1); +} + +TQString KRandrSimpleAPI::getIccFileName(TQString profileName, TQString screenName, TQString kde_confdir) { + KSimpleConfig *t_config = NULL; + KSimpleConfig *t_systemconfig = NULL; + int t_numberOfProfiles; + TQStringList t_cfgProfiles; + TQString retval; + + if ((profileName != NULL) && (profileName != "")) { + t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); + t_config->setGroup(NULL); + if (t_config->readBoolEntry("EnableICC", false) == true) { + t_config->setGroup(profileName); + retval = t_config->readEntry(screenName); + } + else { + retval = ""; + } + delete t_config; + } + else { + t_systemconfig = new KSimpleConfig( kde_confdir + TQString("/kicc/kiccconfigrc") ); + t_systemconfig->setGroup(NULL); + if (t_systemconfig->readBoolEntry("EnableICC", false) == true) { + retval = t_systemconfig->readEntry("ICCFile"); + } + else { + retval = ""; + } + delete t_systemconfig; + } + + return retval; +} + +TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) { + int i; + int j; + Display *randr_display; + ScreenInfo *randr_screen_info; + XRROutputInfo *output_info; + + int screenNumber = 0; + + if (fileName != "") { + // FIXME + // This should use the RRSetCrtcGamma function when available + // That is the only way to get proper setting when two output are active at the same time + // (otherwise in clone mode only one screen is available) + + // HACK + // For now, simply exit with no changes if screenName is not an active output + + if (isValid() == true) { + screenNumber = -1; + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + if (randr_screen_info == NULL) { + return ""; + } + j=0; + for (i = 0; i < randr_screen_info->n_output; i++) { + output_info = randr_screen_info->outputs[i]->info; + // Look for ON outputs... + if (!randr_screen_info->outputs[i]->cur_crtc) { + continue; + } + // ...that are connected + if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) { + continue; + } + if (output_info->name == screenName) { + screenNumber = j; + } + j++; + } + freeScreenInfoStructure(randr_screen_info); + } + + if (screenNumber >= 0) { + // Apply ICC settings with XCalib + TQString icc_command; + FILE *pipe_xcalib; + char xcalib_result[2048]; + int i; + xcalib_result[0]=0; + + icc_command = TQString("xcalib \"%1\"").arg(fileName); + if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) + { + printf("Xcalib pipe error\n [xcalib apply]"); + } + else { + if (fgets(xcalib_result, 2048, pipe_xcalib)) { + pclose(pipe_xcalib); + for (i=1;i<2048;i++) { + if (xcalib_result[i] == 0) { + xcalib_result[i-1]=0; + i=2048; + } + } + if (strlen(xcalib_result) > 2) { + return xcalib_result; + } + } + else { + return ""; + } + } + } + } + else { + // Reset ICC profile on this screen + + // FIXME + // This should use the RRSetCrtcGamma function when available + // That is the only way to get proper setting when two output are active at the same time + // (otherwise in clone mode only one screen is available) + + // HACK + // For now, simply exit with no changes if screenName is not an active output + + if (isValid() == true) { + screenNumber = -1; + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + if (randr_screen_info == NULL) { + return ""; + } + j=0; + for (i = 0; i < randr_screen_info->n_output; i++) { + output_info = randr_screen_info->outputs[i]->info; + // Look for ON outputs... + if (!randr_screen_info->outputs[i]->cur_crtc) { + continue; + } + // ...that are connected + if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) { + continue; + } + if (output_info->name == screenName) { + screenNumber = j; + } + j++; + } + freeScreenInfoStructure(randr_screen_info); + } + + if (screenNumber >= 0) { + // Apply ICC settings with XCalib + TQString icc_command; + FILE *pipe_xcalib; + char xcalib_result[2048]; + int i; + xcalib_result[0]=0; + + icc_command = TQString("xcalib -c"); + if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) + { + printf("Xcalib pipe error\n [xcalib clear]"); + } + else { + if (fgets(xcalib_result, 2048, pipe_xcalib)) { + pclose(pipe_xcalib); + for (i=1;i<2048;i++) { + if (xcalib_result[i] == 0) { + xcalib_result[i-1]=0; + i=2048; + } + } + if (strlen(xcalib_result) > 2) { + return xcalib_result; + } + } + else { + return ""; + } + } + } + } + return ""; +} + +TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString kde_confdir) { + int i; + Display *randr_display; + ScreenInfo *randr_screen_info; + XRROutputInfo *output_info; + KSimpleConfig *t_config; + + int screenNumber = 0; + TQString errorstr = ""; + + t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); + + // Find all screens + if (isValid() == true) { + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + if (randr_screen_info == NULL) { + return ""; + } + for (i = 0; i < randr_screen_info->n_output; i++) { + output_info = randr_screen_info->outputs[i]->info; + errorstr = applyIccFile(output_info->name, getIccFileName(profileName, output_info->name, kde_confdir)); + if (errorstr != "") { + return errorstr; + } + } + freeScreenInfoStructure(randr_screen_info); + } + else { + return applyIccFile(getIccFileName(profileName, "Default", kde_confdir), "Default"); + } + + t_config->writeEntry("CurrentProfile", profileName); + t_config->sync(); + delete t_config; + + return ""; +} + +TQString KRandrSimpleAPI::getEDIDMonitorName(int card, TQString displayname) { + TQString edid; + TQByteArray binaryedid = getEDID(card, displayname); + if (binaryedid.isNull()) + return TQString(); + + // Get the manufacturer ID + unsigned char letter_1 = ((binaryedid[8]>>2) & 0x1F) + 0x40; + unsigned char letter_2 = (((binaryedid[8] & 0x03) << 3) | ((binaryedid[9]>>5) & 0x07)) + 0x40; + unsigned char letter_3 = (binaryedid[9] & 0x1F) + 0x40; + TQChar qletter_1 = TQChar(letter_1); + TQChar qletter_2 = TQChar(letter_2); + TQChar qletter_3 = TQChar(letter_3); + TQString manufacturer_id = TQString("%1%2%3").arg(qletter_1).arg(qletter_2).arg(qletter_3); + + // Get the model ID + unsigned int raw_model_id = (((binaryedid[10] << 8) | binaryedid[11]) << 16) & 0xFFFF0000; + // Reverse the bit order + unsigned int model_id = reverse_bits(raw_model_id); + + // Try to get the model name + bool has_friendly_name = false; + unsigned char descriptor_block[18]; + int i; + for (i=72;i<90;i++) { + descriptor_block[i-72] = binaryedid[i] & 0xFF; + } + if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) { + for (i=90;i<108;i++) { + descriptor_block[i-90] = binaryedid[i] & 0xFF; + } + if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) { + for (i=108;i<126;i++) { + descriptor_block[i-108] = binaryedid[i] & 0xFF; + } + } + } + + TQString monitor_name; + if ((descriptor_block[0] == 0) && (descriptor_block[1] == 0) && (descriptor_block[3] == 0xFC)) { + char* pos = strchr((char *)(descriptor_block+5), '\n'); + if (pos) { + *pos = 0; + has_friendly_name = true; + monitor_name = TQString((char *)(descriptor_block+5)); + } + else { + has_friendly_name = false; + } + } + + // [FIXME] + // Look up manudacturer names if possible! + + if (has_friendly_name) + edid = TQString("%1 %2").arg(manufacturer_id).arg(monitor_name); + else + edid = TQString("%1 0x%2").arg(manufacturer_id).arg(model_id, 0, 16); + + return edid; +} + +TQByteArray KRandrSimpleAPI::getEDID(int card, TQString displayname) { + TQFile file(TQString("/sys/class/drm/card%1-%2/edid").arg(card).arg(displayname)); + if (!file.open (IO_ReadOnly)) + return TQByteArray(); + TQByteArray binaryedid = file.readAll(); + file.close(); + return binaryedid; +} + +TQString KRandrSimpleAPI::getCurrentProfile () { + TQString profileName; + KSimpleConfig *t_config; + + t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); + profileName = t_config->readEntry("CurrentProfile"); + delete t_config; + return profileName; +} + +TQString KRandrSimpleAPI::applySystemWideIccConfiguration(TQString kde_confdir) { + // Apply ICC settings with XCalib + TQString icc_command; + FILE *pipe_xcalib; + char xcalib_result[2048]; + int i; + xcalib_result[0]=0; + + icc_command = TQString("xcalib \"%1\"").arg(getIccFileName(NULL, "Default", kde_confdir)); + if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) + { + printf("Xcalib pipe error [xcalib apply]\n"); + } + else { + if (fgets(xcalib_result, 2048, pipe_xcalib)) { + pclose(pipe_xcalib); + for (i=1;i<2048;i++) { + if (xcalib_result[i] == 0) { + xcalib_result[i-1]=0; + i=2048; + } + } + if (strlen(xcalib_result) > 2) { + return xcalib_result; + } + } + else { + return ""; + } + } + return ""; +} + +TQStringList KRandrSimpleAPI::getDisplayConfigurationProfiles(TQString kde_confdir) { + TQStringList ret; + + TQDir d(kde_confdir + "/displayconfig/"); + d.setFilter(TQDir::Files); + d.setSorting(TQDir::Name); + + const TQFileInfoList *list = d.entryInfoList(); + if (list) { + TQFileInfoListIterator it(*list); + TQFileInfo *fi; + + while ((fi = it.current()) != 0) { + if (fi->fileName() != "default") { + ret.append(fi->fileName()); + } + ++it; + } + } + + return ret; +} + +bool KRandrSimpleAPI::deleteDisplayConfiguration(TQString profilename, TQString kde_confdir) { + TQString fileName = kde_confdir + "/displayconfig/"; + fileName.append(profilename); + return (!unlink(fileName.ascii())); +} + +bool KRandrSimpleAPI::renameDisplayConfiguration(TQString profilename, TQString newprofilename, TQString kde_confdir) { + TQString fileName = kde_confdir + "/displayconfig/"; + TQString newFileName = fileName; + fileName.append(profilename); + newFileName.append(newprofilename); + TQDir d(kde_confdir + "/displayconfig/"); + return (d.rename(fileName, newFileName)); +} + +void KRandrSimpleAPI::saveDisplayConfiguration(bool enable, bool applyonstart, TQString profilename, TQString defaultprofilename, TQString kde_confdir, TQPtrList screenInfoArray) { + int i; + + TQString filename; + + filename = "displayglobals"; + filename.prepend(kde_confdir.append("/")); + KSimpleConfig* display_config = new KSimpleConfig( filename ); + display_config->setGroup("General"); + display_config->writeEntry("EnableDisplayControl", enable); + display_config->writeEntry("ApplySettingsOnStart", applyonstart); + display_config->writeEntry("StartupProfileName", defaultprofilename); + display_config->sync(); + delete display_config; + + filename = profilename; + if (filename == "") { + filename = "default"; + } + filename.prepend(kde_confdir.append("/displayconfig/")); + + display_config = new KSimpleConfig( filename ); + + i=0; + SingleScreenData *screendata; + for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) { + display_config->setGroup(TQString("SCREEN %1").arg(i)); + display_config->writeEntry("ScreenUniqueName", screendata->screenUniqueName); + display_config->writeEntry("ScreenFriendlyName", screendata->screenFriendlyName); + display_config->writeEntry("GenericScreenDetected", screendata->generic_screen_detected); + display_config->writeEntry("ScreenConnected", screendata->screen_connected); + display_config->writeEntry("Resolutions", screendata->resolutions); + display_config->writeEntry("RefreshRates", screendata->refresh_rates); + display_config->writeEntry("ColorDepths", screendata->color_depths); + display_config->writeEntry("AvailableRotations", screendata->rotations); + display_config->writeEntry("CurrentResolution", screendata->current_resolution_index); + display_config->writeEntry("CurrentRefreshRate", screendata->current_refresh_rate_index); + display_config->writeEntry("CurrentColorDepth", screendata->current_color_depth_index); + display_config->writeEntry("CurrentRotation", screendata->current_rotation_index); + display_config->writeEntry("CurrentOrientiation", screendata->current_orientation_mask); + display_config->writeEntry("GammaRed", screendata->gamma_red); + display_config->writeEntry("GammaGreen", screendata->gamma_green); + display_config->writeEntry("GammaBlue", screendata->gamma_blue); + display_config->writeEntry("CurrentXFlip", screendata->has_x_flip); + display_config->writeEntry("CurrentYFlip", screendata->has_y_flip); + display_config->writeEntry("SupportsTransformation", screendata->supports_transformations); + display_config->writeEntry("IsPrimary", screendata->is_primary); + display_config->writeEntry("IsExtended", screendata->is_extended); + display_config->writeEntry("AbsXPos", screendata->absolute_x_position); + display_config->writeEntry("AbsYPos", screendata->absolute_y_position); + display_config->writeEntry("CurrentXPixelCount", screendata->current_x_pixel_count); + display_config->writeEntry("CurrentYPixelCount", screendata->current_y_pixel_count); + display_config->writeEntry("HasDPMS", screendata->has_dpms); + display_config->writeEntry("EnableDPMS", screendata->enable_dpms); + display_config->writeEntry("DPMSStandbyDelay", screendata->dpms_standby_delay); + display_config->writeEntry("DPMSSuspendDelay", screendata->dpms_suspend_delay); + display_config->writeEntry("DPMSPowerDownDelay", screendata->dpms_off_delay); + i++; + } + + display_config->sync(); + delete display_config; +} + +TQPoint KRandrSimpleAPI::applyStartupDisplayConfiguration(TQString kde_confdir) { + bool applyonstart = getDisplayConfigurationStartupAutoApplyEnabled(kde_confdir); + if (applyonstart) { + TQString profilename = getDisplayConfigurationStartupAutoApplyName(kde_confdir); + return applyDisplayConfiguration(profilename, kde_confdir); + } + else { + return TQPoint(); + } +} + +TQPoint KRandrSimpleAPI::applyDisplayConfiguration(TQString profilename, TQString kde_confdir) { + TQPoint ret; + + bool enabled = getDisplayConfigurationEnabled(kde_confdir); + if (profilename == "") { + profilename = "default"; + } + + if (enabled) { + TQPtrList screenInfoArray; + screenInfoArray = loadDisplayConfiguration(profilename, kde_confdir); + if (screenInfoArray.count() > 0) { + applyDisplayConfiguration(screenInfoArray, FALSE, kde_confdir); + } + destroyScreenInformationObject(screenInfoArray); + screenInfoArray = readCurrentDisplayConfiguration(); + ensureMonitorDataConsistency(screenInfoArray); + ret = primaryScreenOffsetFromTLC(screenInfoArray); + destroyScreenInformationObject(screenInfoArray); + } + + return ret; +} + +TQPtrList KRandrSimpleAPI::loadDisplayConfiguration(TQString profilename, TQString kde_confdir) { + int i; + + TQString filename; + filename = profilename; + if (filename == "") { + filename = "default"; + } + filename.prepend(kde_confdir.append("/displayconfig/")); + + KSimpleConfig* display_config = new KSimpleConfig( filename ); + + TQStringList grouplist = display_config->groupList(); + SingleScreenData *screendata; + TQPtrList screenInfoArray; + for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) { + if ((*it).startsWith("SCREEN ")) { + display_config->setGroup(*it); + i = ((*it).remove("SCREEN ")).toInt(); + screendata = new SingleScreenData; + screenInfoArray.append(screendata); + screendata->screenUniqueName = display_config->readEntry("ScreenUniqueName"); + screendata->screenFriendlyName = display_config->readEntry("ScreenFriendlyName"); + screendata->generic_screen_detected = display_config->readBoolEntry("GenericScreenDetected"); + screendata->screen_connected = display_config->readBoolEntry("ScreenConnected"); + screendata->resolutions = display_config->readListEntry("Resolutions"); + screendata->refresh_rates = display_config->readListEntry("RefreshRates"); + screendata->color_depths = display_config->readListEntry("ColorDepths"); + screendata->rotations = display_config->readListEntry("AvailableRotations"); + screendata->current_resolution_index = display_config->readNumEntry("CurrentResolution"); + screendata->current_refresh_rate_index = display_config->readNumEntry("CurrentRefreshRate"); + screendata->current_color_depth_index = display_config->readNumEntry("CurrentColorDepth"); + screendata->current_rotation_index = display_config->readNumEntry("CurrentRotation"); + screendata->current_orientation_mask = display_config->readNumEntry("CurrentOrientiation"); + screendata->gamma_red = display_config->readDoubleNumEntry("GammaRed"); + screendata->gamma_green = display_config->readDoubleNumEntry("GammaGreen"); + screendata->gamma_blue = display_config->readDoubleNumEntry("GammaBlue"); + screendata->has_x_flip = display_config->readBoolEntry("CurrentXFlip"); + screendata->has_y_flip = display_config->readBoolEntry("CurrentYFlip"); + screendata->supports_transformations = display_config->readBoolEntry("SupportsTransformation"); + screendata->is_primary = display_config->readBoolEntry("IsPrimary"); + screendata->is_extended = display_config->readBoolEntry("IsExtended"); + screendata->absolute_x_position = display_config->readNumEntry("AbsXPos"); + screendata->absolute_y_position = display_config->readNumEntry("AbsYPos"); + screendata->current_x_pixel_count = display_config->readNumEntry("CurrentXPixelCount"); + screendata->current_y_pixel_count = display_config->readNumEntry("CurrentYPixelCount"); + screendata->has_dpms = display_config->readBoolEntry("HasDPMS"); + screendata->enable_dpms = display_config->readBoolEntry("EnableDPMS"); + screendata->dpms_standby_delay = display_config->readNumEntry("DPMSStandbyDelay"); + screendata->dpms_suspend_delay = display_config->readNumEntry("DPMSSuspendDelay"); + screendata->dpms_off_delay = display_config->readNumEntry("DPMSPowerDownDelay"); + } + } + + delete display_config; + + return screenInfoArray; +} + +int KRandrSimpleAPI::getHardwareRotationFlags(SingleScreenData* screendata) { + int rotationFlags = 0; + if (screendata->current_rotation_index == ROTATION_0_DEGREES_INDEX) { + rotationFlags = rotationFlags | RandRScreen::Rotate0; + } + else if (screendata->current_rotation_index == ROTATION_90_DEGREES_INDEX) { + rotationFlags = rotationFlags | RandRScreen::Rotate90; + } + else if (screendata->current_rotation_index == ROTATION_180_DEGREES_INDEX) { + rotationFlags = rotationFlags | RandRScreen::Rotate180; + } + else if (screendata->current_rotation_index == ROTATION_270_DEGREES_INDEX) { + rotationFlags = rotationFlags | RandRScreen::Rotate270; + } + if (screendata->has_x_flip) { + rotationFlags = rotationFlags | RandRScreen::ReflectX; + } + if (screendata->has_y_flip) { + rotationFlags = rotationFlags | RandRScreen::ReflectY; + } + return rotationFlags; +} + +#define USE_XRANDR_PROGRAM + +bool KRandrSimpleAPI::applyDisplayConfiguration(TQPtrList screenInfoArray, bool test, TQString kde_confdir) { + int i; + int j; + bool accepted = true; + Display *randr_display; + XRROutputInfo *output_info; + ScreenInfo *randr_screen_info; + + SingleScreenData *screendata; + + TQPtrList oldconfig; + if (test == TRUE) { + oldconfig = readCurrentDisplayConfiguration(); + } + + if (isValid() == true) { +#ifdef USE_XRANDR_PROGRAM + // Assemble the command string for xrandr + TQString command; + command = "xrandr"; + + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + if (screendata) { + output_info = randr_screen_info->outputs[i]->info; + command.append(" --output ").append(output_info->name); + if (screendata->is_primary || screendata->is_extended) { + command.append(TQString(" --mode %1x%2").arg(screendata->current_x_pixel_count).arg(screendata->current_y_pixel_count)); + command.append(TQString(" --pos %1x%2").arg(screendata->absolute_x_position).arg(screendata->absolute_y_position)); + command.append(TQString(" --refresh %1").arg(atoi((*screendata->refresh_rates.at(screendata->current_refresh_rate_index)).ascii()))); + command.append(TQString(" --gamma %1:%2:%3").arg(screendata->gamma_red).arg(screendata->gamma_green).arg(screendata->gamma_blue)); + if (screendata->current_rotation_index == ROTATION_0_DEGREES_INDEX) command.append(" --rotate ").append("normal"); + if (screendata->current_rotation_index == ROTATION_90_DEGREES_INDEX) command.append(" --rotate ").append("left"); + if (screendata->current_rotation_index == ROTATION_180_DEGREES_INDEX) command.append(" --rotate ").append("inverted"); + if (screendata->current_rotation_index == ROTATION_270_DEGREES_INDEX) command.append(" --rotate ").append("right"); + if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("normal"); + if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("x"); + if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("y"); + if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("xy"); + if (screendata->is_primary) { + command.append(" --primary"); + } + } + else { + command.append(" --off"); + } + } + else { + printf("[WARNING] Unable to find configuration for monitor %d; settings may not be correctly applied...\n", i); fflush(stdout); + } + } + freeScreenInfoStructure(randr_screen_info); + + TQString xrandr_command_output = exec(command.ascii()); + xrandr_command_output = xrandr_command_output.stripWhiteSpace(); + if (test) { + // In case gamma settings is not supported, try again without '--gamma' parameter + if (xrandr_command_output == "xrandr: Gamma size is 0.") { + command = command.replace(TQRegExp("--gamma [0-9\\.]*:[0-9\\.]*:[0-9\\.]*"), ""); + xrandr_command_output = exec(command.ascii()); + xrandr_command_output = xrandr_command_output.stripWhiteSpace(); + } + + if(xrandr_command_output.startsWith("xrandr: Failed to get size of gamma for output")) { + KMessageBox::sorry(0, xrandr_command_output, i18n("Setting gamma failed.")); + } else if (xrandr_command_output != "") { + applyDisplayConfiguration(oldconfig, FALSE, kde_confdir); + accepted = false; + destroyScreenInformationObject(oldconfig); + KMessageBox::sorry(0, xrandr_command_output, i18n("XRandR encountered a problem")); + return accepted; + } + } +#else + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + // Turn off all displays + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + + randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; + randr_screen_info->cur_output = randr_screen_info->outputs[i]; + randr_screen_info->cur_output->auto_set = 0; + randr_screen_info->cur_output->off_set = 1; + output_off (randr_screen_info, randr_screen_info->cur_output); + j=main_low_apply(randr_screen_info); + } + freeScreenInfoStructure(randr_screen_info); + randr_screen_info = read_screen_info(randr_display); + // Turn on the primary display + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + + if (screendata->is_primary == true) { + randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; + randr_screen_info->cur_output = randr_screen_info->outputs[i]; + randr_screen_info->cur_output->auto_set = 1; + randr_screen_info->cur_output->off_set = 0; + output_auto (randr_screen_info, randr_screen_info->cur_output); + j=main_low_apply(randr_screen_info); + } + } + freeScreenInfoStructure(randr_screen_info); + // Handle the remaining displays + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + + // Activate or deactivate the screens as necessary + randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; + randr_screen_info->cur_output = randr_screen_info->outputs[i]; + if (screendata->is_primary == false) { + if (screendata->is_primary || screendata->is_extended) { + randr_screen_info->cur_output->auto_set = 1; + randr_screen_info->cur_output->off_set = 0; + output_auto (randr_screen_info, randr_screen_info->cur_output); + j=main_low_apply(randr_screen_info); + } + else { + randr_screen_info->cur_output->auto_set = 0; + randr_screen_info->cur_output->off_set = 1; + output_off (randr_screen_info, randr_screen_info->cur_output); + j=main_low_apply(randr_screen_info); + } + } + } + freeScreenInfoStructure(randr_screen_info); + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + + if (screendata->is_primary || screendata->is_extended) { + // Set rotation, refresh rate, and size + RandRScreen *cur_screen = new RandRScreen(i); + cur_screen->proposeSize(screendata->current_resolution_index); + cur_screen->proposeRefreshRate(screendata->current_refresh_rate_index); + cur_screen->proposeRotation(getHardwareRotationFlags(screendata)); + cur_screen->applyProposed(); + delete cur_screen; + + // Force data reload + randr_screen_info = read_screen_info(randr_display); + output_info = randr_screen_info->outputs[i]->info; + + // Finally, set the screen's position + randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc; + if (randr_screen_info->cur_crtc) { + randr_screen_info->cur_crtc->cur_x = screendata->absolute_x_position; + randr_screen_info->cur_crtc->cur_y = screendata->absolute_y_position; + j=main_low_apply(randr_screen_info); + } + } + } + freeScreenInfoStructure(randr_screen_info); +#endif + } + + applyDisplayGamma(screenInfoArray); + applyDisplayDPMS(screenInfoArray); + TQString current_icc_profile = getCurrentProfile(); + applySystemWideIccConfiguration(kde_confdir); + applyIccConfiguration(current_icc_profile, kde_confdir); + + if (test == TRUE) { + int ret = showTestConfigurationDialog(); + if (!ret) { + applyDisplayConfiguration(oldconfig, FALSE, kde_confdir); + accepted = false; + } + destroyScreenInformationObject(oldconfig); + } + + return accepted; +} + +TQPtrList KRandrSimpleAPI::copyScreenInformationObject(TQPtrList screenInfoArray) { + SingleScreenData *origscreendata; + SingleScreenData *copyscreendata; + TQPtrList retArray; + for ( origscreendata = screenInfoArray.first(); origscreendata; origscreendata = screenInfoArray.next() ) { + copyscreendata = new SingleScreenData; + *copyscreendata = *origscreendata; + retArray.append(copyscreendata); + } + return retArray; +} + +void KRandrSimpleAPI::destroyScreenInformationObject(TQPtrList screenInfoArray) { + SingleScreenData *screendata; + for ( screendata = screenInfoArray.first(); screendata; screendata = screenInfoArray.next() ) { + screenInfoArray.remove(screendata); + delete screendata; + } +} + +void KRandrSimpleAPI::ensureMonitorDataConsistency(TQPtrList screenInfoArray) { + int i; + SingleScreenData *screendata; + + int numberOfScreens = screenInfoArray.count(); + + for (i=0;iscreen_connected) { + screendata->is_primary = false; + screendata->is_extended = false; + } + } + + bool has_primary_monitor = false; + for (i=0;iis_primary) { + has_primary_monitor = true; + } + } + if (!has_primary_monitor) { + for (i=0;iscreen_connected && screendata->is_extended) { + screendata->is_primary = true; + screendata->is_extended = true; + has_primary_monitor = true; + } + } + } + } + if (!has_primary_monitor) { + for (i=0;iscreen_connected) { + screendata->is_primary = true; + screendata->is_extended = true; + has_primary_monitor = true; + } + } + } + } + + bool found_first_primary_monitor = false; + for (i=0;iis_primary) { + if (!found_first_primary_monitor) { + found_first_primary_monitor = true; + } + else { + screendata->is_primary = false; + } + } + } + + for (i=0;iis_primary) { + screendata->is_extended = true; + } + } + + for (i=0;iresolutions[screendata->current_resolution_index]; + int separator_pos = resolutionstring.find(" x "); + TQString x_res_string = resolutionstring.left(separator_pos); + TQString y_res_string = resolutionstring.right(resolutionstring.length()-separator_pos-3); + screendata->current_x_pixel_count = x_res_string.toInt(); + screendata->current_y_pixel_count = y_res_string.toInt(); + screendata->current_orientation_mask = getHardwareRotationFlags(screendata); + } + + // Each screen's absolute position is given relative to the primary monitor + // Fix up the absolute positions + int primary_offset_x = 0; + int primary_offset_y = 0; + for (i=0;iis_primary) { + primary_offset_x = screendata->absolute_x_position; + primary_offset_y = screendata->absolute_y_position; + primary_offset_x = primary_offset_x * (-1); + primary_offset_y = primary_offset_y * (-1); + } + } + for (i=0;iabsolute_x_position = screendata->absolute_x_position + primary_offset_x; + screendata->absolute_y_position = screendata->absolute_y_position + primary_offset_y; + } +} + +TQPoint KRandrSimpleAPI::primaryScreenOffsetFromTLC(TQPtrList screenInfoArray) { + int i; + SingleScreenData *screendata; + int numberOfScreens = screenInfoArray.count(); + + int primary_offset_x = 0; + int primary_offset_y = 0; + for (i=0;iabsolute_x_position < primary_offset_x) { + primary_offset_x = screendata->absolute_x_position; + } + if (screendata->absolute_y_position < primary_offset_y) { + primary_offset_y = screendata->absolute_y_position; + } + } + primary_offset_x = primary_offset_x * (-1); + primary_offset_y = primary_offset_y * (-1); + + return TQPoint(primary_offset_x, primary_offset_y); +} + +HotPlugRulesList KRandrSimpleAPI::getHotplugRules(TQString kde_confdir) { + int i; + TQString filename; + HotPlugRulesList ret; + + filename = "displayglobals"; + filename.prepend(kde_confdir.append("/")); + KSimpleConfig* display_config = new KSimpleConfig( filename ); + + TQStringList grouplist = display_config->groupList(); + for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) { + if (!(*it).startsWith("Hotplug-Rule")) { + continue; + } + HotPlugRule rule; + display_config->setGroup(*it); + rule.outputs = display_config->readListEntry("Outputs"); + rule.states = display_config->readIntListEntry("States"); + rule.profileName = display_config->readEntry("Profile"); + ret.append(rule); + } + delete display_config; + + return ret; +} + +void KRandrSimpleAPI::saveHotplugRules(HotPlugRulesList rules, TQString kde_confdir) { + int i; + TQString filename; + + filename = "displayglobals"; + filename.prepend(kde_confdir.append("/")); + KSimpleConfig* display_config = new KSimpleConfig( filename ); + TQStringList grouplist = display_config->groupList(); + for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) { + if (!(*it).startsWith("Hotplug-Rule")) { + continue; + } + display_config->deleteGroup(*it, true, false); + } + HotPlugRulesList::Iterator it; + i=0; + for (it=rules.begin(); it != rules.end(); ++it) { + display_config->setGroup(TQString("Hotplug-Rule%1").arg(i)); + display_config->writeEntry("Outputs", (*it).outputs); + display_config->writeEntry("States", (*it).states); + display_config->writeEntry("Profile", (*it).profileName); + i++; + } + display_config->sync(); + delete display_config; +} + +bool KRandrSimpleAPI::getDisplayConfigurationEnabled(TQString kde_confdir) { + TQString filename = "displayglobals"; + filename.prepend(kde_confdir.append("/")); + KSimpleConfig* display_config = new KSimpleConfig( filename ); + display_config->setGroup("General"); + bool enabled = display_config->readBoolEntry("EnableDisplayControl", false); + delete display_config; + + return enabled; +} + +bool KRandrSimpleAPI::getDisplayConfigurationStartupAutoApplyEnabled(TQString kde_confdir) { + TQString filename = "displayglobals"; + filename.prepend(kde_confdir.append("/")); + KSimpleConfig* display_config = new KSimpleConfig( filename ); + display_config->setGroup("General"); + bool applyonstart = display_config->readBoolEntry("ApplySettingsOnStart", false); + delete display_config; + + return applyonstart; +} + +TQString KRandrSimpleAPI::getDisplayConfigurationStartupAutoApplyName(TQString kde_confdir) { + TQString filename = "displayglobals"; + filename.prepend(kde_confdir.append("/")); + KSimpleConfig* display_config = new KSimpleConfig( filename ); + display_config->setGroup("General"); + TQString profilename = display_config->readEntry("StartupProfileName", ""); + delete display_config; + + return profilename; +} + +void KRandrSimpleAPI::applyHotplugRules(TQString kde_confdir) { + bool enabled = getDisplayConfigurationEnabled(kde_confdir); + if (!enabled) { + return; + } + + HotPlugRulesList rules = getHotplugRules(kde_confdir); + TQPtrList screenInfoArray = readCurrentDisplayConfiguration(); + + int i; + int j; + TQString bestRule; + int bestRuleMatchCount = 0; + SingleScreenData *screendata = NULL; + HotPlugRulesList::Iterator it; + for (it=rules.begin(); it != rules.end(); ++it) { + // Compare each rule against the current display configuration + // It an output matches the state given in the rule, increment matchCount + HotPlugRule rule = *it; + int matchCount = 0; + int numberOfScreens = screenInfoArray.count(); + for (i=0;iscreenUniqueName) { + continue; + } + if ((*it).states[j] == HotPlugRule::Connected) { + if (screendata->screen_connected) { + matchCount++; + } + } + else if ((*it).states[j] == HotPlugRule::Disconnected) { + if (!screendata->screen_connected) { + matchCount++; + } + } + } + } + + if (matchCount > bestRuleMatchCount) { + bestRuleMatchCount = matchCount; + bestRule = rule.profileName; + } + } + + destroyScreenInformationObject(screenInfoArray); + + if (bestRuleMatchCount > 0) { + // At least one rule matched... + // Apply the profile name in bestRule to the display hardware + applyDisplayConfiguration(bestRule, kde_confdir); + } +} + +void KRandrSimpleAPI::applyDisplayGamma(TQPtrList screenInfoArray) { + int i; + Display *randr_display; + XRROutputInfo *output_info; + ScreenInfo *randr_screen_info; + XRRCrtcGamma *gamma; + + SingleScreenData *screendata; + + if (isValid() == true) { + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; + if (!current_crtc) { + continue; + } + // vvvvvvvvv This chunk of code is borrowed from xrandr vvvvvvvvvv + int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id); + if (!size) { + continue; + } + gamma = XRRAllocGamma(size); + if (!gamma) { + continue; + } + for (i = 0; i < size; i++) { + if (screendata->gamma_red == 1.0) + gamma->red[i] = i << 8; + else + gamma->red[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_red) * (double)(size-1)*256); + + if (screendata->gamma_green == 1.0) + gamma->green[i] = i << 8; + else + gamma->green[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_green) * (double)(size-1)*256); + + if (screendata->gamma_blue == 1.0) + gamma->blue[i] = i << 8; + else + gamma->blue[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_blue) * (double)(size-1)*256); + } + XRRSetCrtcGamma(randr_display, current_crtc->id, gamma); + free(gamma); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } + freeScreenInfoStructure(randr_screen_info); + } +} + +void KRandrSimpleAPI::applyDisplayDPMS(TQPtrList screenInfoArray) { + int i; + Display *randr_display; + XRROutputInfo *output_info; + ScreenInfo *randr_screen_info; + XRRCrtcGamma *gamma; + + SingleScreenData *screendata; + + if (isValid() == true) { + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < screenInfoArray.count(); i++) { + screendata = screenInfoArray.at(i); + output_info = randr_screen_info->outputs[i]->info; + CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; + if (!current_crtc) { + continue; + } + if (!screendata->has_dpms) { + continue; + } + if (screendata->enable_dpms) { + DPMSSetTimeouts(randr_display, screendata->dpms_standby_delay, screendata->dpms_suspend_delay, screendata->dpms_off_delay); + DPMSEnable(randr_display); + } + else { + DPMSDisable(randr_display); + } + } + freeScreenInfoStructure(randr_screen_info); + } +} + +void KRandrSimpleAPI::freeScreenInfoStructure(ScreenInfo* screen_info) { + int i; + + for (i=0; in_crtc; i++) { + free(screen_info->crtcs[i]); + } + for (i=0; in_output; i++) { + free(screen_info->outputs[i]); + } + free(screen_info->outputs); + free(screen_info->crtcs); + free(screen_info); +} + +TQPtrList KRandrSimpleAPI::readCurrentDisplayConfiguration() { + // Discover display information + int i; + int j; + + XRROutputInfo *output_info; + SingleScreenData *screendata; + TQPtrList screenInfoArray; + + Display *randr_display; + ScreenInfo *randr_screen_info; + + // Clear existing info + destroyScreenInformationObject(screenInfoArray); + + int numberOfScreens = 0; + if (isValid() == true) { + randr_display = tqt_xdisplay(); + randr_screen_info = read_screen_info(randr_display); + for (i = 0; i < randr_screen_info->n_output; i++) { + output_info = randr_screen_info->outputs[i]->info; + CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc; + + // Create new data object + screendata = new SingleScreenData; + screenInfoArray.append(screendata); + screendata->screenUniqueName = TQString(i18n("%1:%2")).arg(":0").arg(capitalizeString(output_info->name)); // [FIXME] How can I get the name of the Xorg graphics driver currently in use? + screendata->screenFriendlyName = TQString(i18n("%1. %2 output on %3")).arg(i+1).arg(capitalizeString(output_info->name)).arg(":0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use? + screendata->generic_screen_detected = false; + + // Attempt to use KMS to find screen EDID and name + TQString edid = getEDIDMonitorName(0, output_info->name); // [FIXME] Don't hardwire to card 0! + if (!edid.isNull()) { + screendata->screenFriendlyName = TQString(i18n("%1. %2 on %3 on card %4")).arg(i+1).arg(edid).arg(capitalizeString(output_info->name)).arg("0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use? + } + + // Get resolutions + bool screen_active; + RandRScreen *cur_screen = 0; + if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) { + // Output DISCONNECTED + screen_active = false; + } + else { + if (randr_screen_info->outputs[i]->cur_crtc) { + // Output CONNECTED and ON + screen_active = true; + cur_screen = new RandRScreen(i); + } + else { + // Output CONNECTED and OFF + screen_active = false; + cur_screen = new RandRScreen(i); + } + } + + // Get DPMS information + screendata->has_dpms = 1; // [FIXME] Master Xorg check for global DPMS support should go here if possible + if (screendata->has_dpms) { + CARD16 dpms_standby_delay; + CARD16 dpms_suspend_delay; + CARD16 dpms_off_delay; + screendata->has_dpms = DPMSGetTimeouts(randr_display, &dpms_standby_delay, &dpms_suspend_delay, &dpms_off_delay); + screendata->dpms_standby_delay = dpms_standby_delay; + screendata->dpms_suspend_delay = dpms_suspend_delay; + screendata->dpms_off_delay = dpms_off_delay; + if (screendata->has_dpms) { + CARD16 power_level; + BOOL enable_dpms; + screendata->has_dpms = DPMSInfo(randr_display, &power_level, &enable_dpms); + screendata->enable_dpms = enable_dpms; + } + } + if (!screendata->has_dpms) { + screendata->enable_dpms = false; + screendata->dpms_standby_delay = 0; + screendata->dpms_suspend_delay = 0; + screendata->dpms_off_delay = 0; + } + + if (cur_screen) { + screendata->screen_connected = true; + for (int j = 0; j < cur_screen->numSizes(); j++) { + screendata->resolutions.append(i18n("%1 x %2").arg(cur_screen->pixelSize(j).width()).arg(cur_screen->pixelSize(j).height())); + } + screendata->current_resolution_index = 0; + if (current_crtc) { + screendata->current_resolution_index = screendata->resolutions.findIndex(i18n("%1 x %2").arg(current_crtc->info->width).arg(current_crtc->info->height)); + } + if (screendata->current_resolution_index < 0) { + screendata->current_resolution_index = cur_screen->proposedSize(); + } + + // Get refresh rates + TQStringList rr = cur_screen->refreshRates(screendata->current_resolution_index); + for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it) { + screendata->refresh_rates.append(*it); + } + screendata->current_refresh_rate_index = cur_screen->proposedRefreshRate(); + + // Get color depths + // [FIXME] + screendata->color_depths.append(i18n("Default")); + screendata->current_color_depth_index = 0; + + // Get orientation flags + // RandRScreen::Rotate0 + // RandRScreen::Rotate90 + // RandRScreen::Rotate180 + // RandRScreen::Rotate270 + // RandRScreen::ReflectX + // RandRScreen::ReflectY + + screendata->rotations.append(i18n("0 degrees")); + screendata->rotations.append(i18n("90 degrees")); + screendata->rotations.append(i18n("180 degrees")); + screendata->rotations.append(i18n("270 degrees")); + screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0); + if (screendata->supports_transformations) { + screendata->current_orientation_mask = cur_screen->proposedRotation(); + switch (screendata->current_orientation_mask & RandRScreen::RotateMask) { + case RandRScreen::Rotate0: + screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; + break; + case RandRScreen::Rotate90: + screendata->current_rotation_index = ROTATION_90_DEGREES_INDEX; + break; + case RandRScreen::Rotate180: + screendata->current_rotation_index = ROTATION_180_DEGREES_INDEX; + break; + case RandRScreen::Rotate270: + screendata->current_rotation_index = ROTATION_270_DEGREES_INDEX; + break; + default: + // Shouldn't hit this one + Q_ASSERT(screendata->current_orientation_mask & RandRScreen::RotateMask); + screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; + break; + } + screendata->has_x_flip = (screendata->current_orientation_mask & RandRScreen::ReflectX); + screendata->has_y_flip = (screendata->current_orientation_mask & RandRScreen::ReflectY); + } + else { + screendata->has_x_flip = false; + screendata->has_y_flip = false; + screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; + } + + // Determine if this display is primary and/or extended + RROutput primaryoutput = XRRGetOutputPrimary(tqt_xdisplay(), DefaultRootWindow(tqt_xdisplay())); + if (primaryoutput == randr_screen_info->outputs[i]->id) { + screendata->is_primary = false; + } + else { + screendata->is_primary = true; + } + screendata->is_extended = screen_active; + if (!screendata->is_extended) { + screendata->is_primary = false; + } + + // Get this screen's absolute position + screendata->absolute_x_position = 0; + screendata->absolute_y_position = 0; + if (current_crtc) { + screendata->absolute_x_position = current_crtc->info->x; + screendata->absolute_y_position = current_crtc->info->y; + } + + // Get this screen's current resolution + screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width(); + screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height(); + + // Get this screen's current gamma values + // [FIXME] + // This attempts to guess a gamma value based on the LUT settings at 50% + // It may not always be 100% correct, or even anywhere close... + // Essentially it "undoes" the LUT gamma calculation from xrandr + // lut_gamma->green[i] = (pow(i/(size - 1), desired_gamma.green) * (size - 1) * 256); + screendata->gamma_red = 2.2; + screendata->gamma_green = 2.2; + screendata->gamma_blue = 2.2; + if (current_crtc) { + //int slot = 127; + int slot = 7; + int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id); + if(size>0) { + XRRCrtcGamma *gammastruct = XRRGetCrtcGamma (randr_display, current_crtc->id); + screendata->gamma_red = log(gammastruct->red[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); + screendata->gamma_green = log(gammastruct->green[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); + screendata->gamma_blue = log(gammastruct->blue[slot]/((size-1.0)*256.0))/log(slot/(size-1.0)); + } + } + // Round off the gamma to one decimal place + screendata->gamma_red = floorf(screendata->gamma_red * 10 + 0.5) / 10; + screendata->gamma_green = floorf(screendata->gamma_green * 10 + 0.5) / 10; + screendata->gamma_blue = floorf(screendata->gamma_blue * 10 + 0.5) / 10; + + delete cur_screen; + } + else { + // Fill in generic data for this disconnected output + screendata->screenFriendlyName = screendata->screenFriendlyName + TQString(" (") + i18n("disconnected") + TQString(")"); + screendata->screen_connected = false; + + screendata->resolutions = i18n("Default"); + screendata->refresh_rates = i18n("Default"); + screendata->color_depths = i18n("Default"); + screendata->rotations = i18n("N/A"); + + screendata->current_resolution_index = 0; + screendata->current_refresh_rate_index = 0; + screendata->current_color_depth_index = 0; + + screendata->gamma_red = 2.2; + screendata->gamma_green = 2.2; + screendata->gamma_blue = 2.2; + + screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; + screendata->current_orientation_mask = 0; + screendata->has_x_flip = false; + screendata->has_y_flip = false; + screendata->supports_transformations = false; + + screendata->is_primary = false; + screendata->is_extended = false; + screendata->absolute_x_position = 0; + screendata->absolute_y_position = 0; + screendata->current_x_pixel_count = 640; + screendata->current_y_pixel_count = 480; + } + + // Check for more screens... + numberOfScreens++; + } + + freeScreenInfoStructure(randr_screen_info); + } + else { + screendata = new SingleScreenData; + screenInfoArray.append(screendata); + + // Fill in a bunch of generic data + screendata->screenFriendlyName = i18n("Default output on generic video card"); + screendata->generic_screen_detected = true; + screendata->screen_connected = true; + + screendata->resolutions = i18n("Default"); + screendata->refresh_rates = i18n("Default"); + screendata->color_depths = i18n("Default"); + screendata->rotations = i18n("N/A"); + + screendata->current_resolution_index = 0; + screendata->current_refresh_rate_index = 0; + screendata->current_color_depth_index = 0; + + screendata->gamma_red = 2.2; + screendata->gamma_green = 2.2; + screendata->gamma_blue = 2.2; + + screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX; + screendata->current_orientation_mask = 0; + screendata->has_x_flip = false; + screendata->has_y_flip = false; + screendata->supports_transformations = false; + + screendata->is_primary = true; + screendata->is_extended = true; + screendata->absolute_x_position = 0; + screendata->absolute_y_position = 0; + screendata->current_x_pixel_count = 640; + screendata->current_y_pixel_count = 480; + + numberOfScreens++; + } + + bool primary_set = false; + for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) { + if (screendata->is_primary) { + primary_set = true; + break; + } + } + // If there is no primary monitor set, xrandr is probably not functioning correctly! + Q_ASSERT(primary_set); + if (!primary_set) { + // [FIXME] + // Set this on the real primary monitor only! + screendata = screenInfoArray.at(0); + screendata->is_primary = true; + } + + return screenInfoArray; +} + +TQString KRandrSimpleAPI::clearIccConfiguration() { + // Clear ICC settings with XCalib + TQString icc_command; + FILE *pipe_xcalib; + char xcalib_result[2048]; + int i; + xcalib_result[0]=0; + + icc_command = TQString("xcalib -c"); + if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL) + { + printf("Xcalib pipe error [xcalib clear]\n"); + } + else { + if (fgets(xcalib_result, 2048, pipe_xcalib)) { + pclose(pipe_xcalib); + for (i=1;i<2048;i++) { + if (xcalib_result[i] == 0) { + xcalib_result[i-1]=0; + i=2048; + } + } + if (strlen(xcalib_result) > 2) { + return xcalib_result; + } + } + else { + return ""; + } + } + return ""; +} + +ScreenInfo* KRandrSimpleAPI::read_screen_info (Display *display) +{ + return internal_read_screen_info(display); +} + +int KRandrSimpleAPI::set_screen_size (ScreenInfo *screen_info) +{ + return internal_set_screen_size(screen_info); +} + +void KRandrSimpleAPI::output_auto (ScreenInfo *screen_info, OutputInfo *output_info) +{ + internal_output_auto (screen_info, output_info); +} + +void KRandrSimpleAPI::output_off(ScreenInfo *screen_info, OutputInfo *output) +{ + internal_output_off(screen_info, output); +} + +CrtcInfo* KRandrSimpleAPI::auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info) +{ + return internal_auto_find_crtc (screen_info, output_info); +} + +XRRModeInfo *KRandrSimpleAPI::find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id) +{ + return internal_find_mode_by_xid (screen_info, mode_id); +} + +int KRandrSimpleAPI::mode_height (XRRModeInfo *mode_info, Rotation rotation) +{ + return internal_mode_height (mode_info, rotation); +} + +int KRandrSimpleAPI::mode_width (XRRModeInfo *mode_info, Rotation rotation) +{ + return internal_mode_width (mode_info, rotation); +} + +int KRandrSimpleAPI::get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id) +{ + return internal_get_width_by_output_id (screen_info, output_id); +} + +int KRandrSimpleAPI::get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id) +{ + return internal_get_height_by_output_id (screen_info, output_id); +} + +char *KRandrSimpleAPI::get_output_name (ScreenInfo *screen_info, RROutput id) +{ + return internal_get_output_name (screen_info, id); +} + +Status KRandrSimpleAPI::crtc_apply (CrtcInfo *crtc_info) +{ + return internal_crtc_apply (crtc_info); +} + +Status KRandrSimpleAPI::crtc_disable (CrtcInfo *crtc) +{ + return internal_crtc_disable (crtc); +} + +int KRandrSimpleAPI::main_low_apply (ScreenInfo *screen_info) +{ + return internal_main_low_apply (screen_info); +} + +void KRandrSimpleAPI::set_primary_output (ScreenInfo *screen_info, RROutput output_id) +{ + internal_output_set_primary(screen_info, output_id); +} + +bool KRandrSimpleAPI::kRandrHasRandr(void) +{ + return isValid(); +} + +const char *KRandrSimpleAPI::kRandrVersion(void) +{ + return "0.9.5"; +} + +const char *KRandrSimpleAPI::kRandrCopyright(void) +{ + return "LibKRandr 0.9.5 (C)2010 Timothy Pearson . U.S.A."; +} + +/* * * * * * + + Under this line (------) there's only a C wrapper for the KRandrSimpleAPI class + +* * * * * */ +const char *kRandrVersion(void) +{ + return KRandrSimpleAPI::kRandrVersion(); +} + +const char *kRandrCopyright(void) +{ + return KRandrSimpleAPI::kRandrCopyright(); +} + diff --git a/tdeui/ksharedpixmap.h b/tdeui/ksharedpixmap.h index c87196876..29b7821ff 100644 --- a/tdeui/ksharedpixmap.h +++ b/tdeui/ksharedpixmap.h @@ -40,7 +40,7 @@ class TDESharedPixmapPrivate; * * The server part of shared pixmaps is not implemented here. * That part is provided by KPixmapServer, in the source file: - * tdebase/kdesktop/pixmapserver.cc. + * tdebase/kdesktop/pixmapserver.cpp. * * An example: copy from a shared pixmap: * \code diff --git a/tdeui/tdetoolbarlabelaction.cpp b/tdeui/tdetoolbarlabelaction.cpp index c88f68434..07cfbb731 100644 --- a/tdeui/tdetoolbarlabelaction.cpp +++ b/tdeui/tdetoolbarlabelaction.cpp @@ -82,7 +82,7 @@ void TDEToolBarLabelAction::init() { d->m_label = static_cast(widget()); /* these lines were copied from Konqueror's KonqDraggableLabel class in - konq_misc.cc */ + konq_misc.cpp */ d->m_label->setBackgroundMode(TQt::PaletteButton); d->m_label->setAlignment((TQApplication::reverseLayout() ? Qt::AlignRight : Qt::AlignLeft) | diff --git a/tdewallet/backend/CMakeLists.txt b/tdewallet/backend/CMakeLists.txt index 57a1e77ac..db2f66994 100644 --- a/tdewallet/backend/CMakeLists.txt +++ b/tdewallet/backend/CMakeLists.txt @@ -30,9 +30,9 @@ link_directories( set( target tdewalletbackend ) set( ${target}_SRCS - blockcipher.cc blowfish.cc - cbc.cc sha1.cc tdewalletentry.cc - tdewalletbackend.cc + blockcipher.cpp blowfish.cpp + cbc.cpp sha1.cpp tdewalletentry.cpp + tdewalletbackend.cpp ) tde_add_library( ${target} SHARED diff --git a/tdewallet/backend/Makefile.am b/tdewallet/backend/Makefile.am index 487385eac..a53a0129f 100644 --- a/tdewallet/backend/Makefile.am +++ b/tdewallet/backend/Makefile.am @@ -5,12 +5,12 @@ lib_LTLIBRARIES = libtdewalletbackend.la libtdewalletbackend_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) -version-info 1:0 -no-undefined libtdewalletbackend_la_LIBADD = $(LIB_TQT) ../../tdecore/libtdecore.la -libtdewalletbackend_la_SOURCES = blockcipher.cc \ - blowfish.cc \ - cbc.cc \ - sha1.cc \ - tdewalletentry.cc \ - tdewalletbackend.cc +libtdewalletbackend_la_SOURCES = blockcipher.cpp \ + blowfish.cpp \ + cbc.cpp \ + sha1.cpp \ + tdewalletentry.cpp \ + tdewalletbackend.cpp libtdewalletbackend_la_METASOURCES = AUTO diff --git a/tdewallet/backend/blockcipher.cc b/tdewallet/backend/blockcipher.cc deleted file mode 100644 index 9d770098e..000000000 --- a/tdewallet/backend/blockcipher.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2001 George Staikos - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "blockcipher.h" - - - -BlockCipher::BlockCipher() { - _blksz = -1; -} - - -BlockCipher::~BlockCipher() { -} - - -int BlockCipher::blockSize() const { - return _blksz; -} - - diff --git a/tdewallet/backend/blockcipher.cpp b/tdewallet/backend/blockcipher.cpp new file mode 100644 index 000000000..9d770098e --- /dev/null +++ b/tdewallet/backend/blockcipher.cpp @@ -0,0 +1,37 @@ +/* This file is part of the KDE project + Copyright (C) 2001 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "blockcipher.h" + + + +BlockCipher::BlockCipher() { + _blksz = -1; +} + + +BlockCipher::~BlockCipher() { +} + + +int BlockCipher::blockSize() const { + return _blksz; +} + + diff --git a/tdewallet/backend/blowfish.cc b/tdewallet/backend/blowfish.cc deleted file mode 100644 index c708935de..000000000 --- a/tdewallet/backend/blowfish.cc +++ /dev/null @@ -1,259 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2001 George Staikos - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - - -// FIXME: should we unroll some loops? Optimization can be done here. - - -/* Implementation of 16 rounds blowfish as described in: - * _Applied_Cryptography_ (c) Bruce Schneier, 1996. - */ - -#include - -#include -#include -#include - -#include "blowfish.h" -#include "blowfishtables.h" - - -BlowFish::BlowFish() { - _blksz = 8; - _key = 0L; - _init = false; -} - - - -bool BlowFish::init() { - // Initialize the sboxes - for (int i = 0; i < 256; i++) { - _S[0][i] = ks0[i]; - _S[1][i] = ks1[i]; - _S[2][i] = ks2[i]; - _S[3][i] = ks3[i]; - } - - uint32_t datal = 0; - uint32_t datar = 0; - uint32_t data = 0; - int j = 0; - - - // Update the sboxes and pbox. - for (int i = 0; i < 18; i++) { - data = 0; - for (int k = 0; k < 4; ++k) { - data = (data << 8) | ((unsigned char *)_key)[j++]; - if (j >= _keylen / 8) { - j = 0; - } - } - _P[i] = P[i] ^ data; - } - - for (int i = 0; i < 18; i += 2) { - encipher(&datal, &datar); - _P[i] = datal; - _P[i+1] = datar; - } - - for (int j = 0; j < 4; j++) { - for (int i = 0; i < 256; i += 2) { - encipher(&datal, &datar); - _S[j][i] = datal; - _S[j][i+1] = datar; - } - } - - // Nice code from gpg's implementation... - // check to see if the key is weak and return error if so - for (int i = 0; i < 255; i++) { - for (int j = i + 1; j < 256; j++) { - if ((_S[0][i] == _S[0][j]) || (_S[1][i] == _S[1][j]) || - (_S[2][i] == _S[2][j]) || (_S[3][i] == _S[3][j])) { - return false; - } - } - } - - _init = true; - - return true; -} - - -BlowFish::~BlowFish() { - delete[] (unsigned char *)_key; - _key = 0L; -} - - -int BlowFish::keyLen() const { - return 448; -} - - -bool BlowFish::variableKeyLen() const { - return true; -} - - -bool BlowFish::readyToGo() const { - return _init; -} - - -bool BlowFish::setKey(void *key, int bitlength) { - if (bitlength <= 0 || bitlength > 448 || bitlength % 8 != 0) { - return false; - } - - delete[] (unsigned char *)_key; - - _key = new unsigned char[bitlength / 8]; - memcpy(_key, key, bitlength / 8); - _keylen = bitlength; - - return init(); -} - - -#ifdef WORDS_BIGENDIAN -#define shuffle(x) do { \ - uint32_t r = x; \ - x = (r & 0xff000000) >> 24; \ - x |= (r & 0x00ff0000) >> 8; \ - x |= (r & 0x0000ff00) << 8; \ - x |= (r & 0x000000ff) << 24; \ - } while (0) -#endif - -int BlowFish::encrypt(void *block, int len) { - uint32_t *d = (uint32_t *)block; - - if (!_init || len % _blksz != 0) { - return -1; - } - - for (int i = 0; i < len / _blksz; i++) { -#ifdef WORDS_BIGENDIAN - shuffle(*d); - shuffle(*(d + 1)); -#endif - encipher(d, d + 1); -#ifdef WORDS_BIGENDIAN - shuffle(*d); - shuffle(*(d + 1)); -#endif - d += 2; - } - - return len; -} - - -int BlowFish::decrypt(void *block, int len) { - uint32_t *d = (uint32_t *)block; - - if (!_init || len % _blksz != 0) { - return -1; - } - - for (int i = 0; i < len / _blksz; i++) { -#ifdef WORDS_BIGENDIAN - shuffle(*d); - shuffle(*(d + 1)); -#endif - decipher(d, d + 1); -#ifdef WORDS_BIGENDIAN - shuffle(*d); - shuffle(*(d + 1)); -#endif - d += 2; - } - - return len; -} - - -uint32_t BlowFish::F(uint32_t x) { - unsigned short a, b, c, d; - uint32_t y; - - d = x & 0x000000ff; - x >>= 8; - c = x & 0x000000ff; - x >>= 8; - b = x & 0x000000ff; - x >>= 8; - a = x & 0x000000ff; - - y = _S[0][a] + _S[1][b]; - y ^= _S[2][c]; - y += _S[3][d]; - - return y; -} - - -void BlowFish::encipher(uint32_t *xl, uint32_t *xr) { - uint32_t Xl = *xl, Xr = *xr, temp; - - for (int i = 0; i < 16; ++i) { - Xl ^= _P[i]; - Xr ^= F(Xl); - // Exchange - temp = Xl; Xl = Xr; Xr = temp; - } - - // Exchange - temp = Xl; Xl = Xr; Xr = temp; - - Xr ^= _P[16]; - Xl ^= _P[17]; - - *xl = Xl; - *xr = Xr; -} - - -void BlowFish::decipher(uint32_t *xl, uint32_t *xr) { - uint32_t Xl = *xl, Xr = *xr, temp; - - for (int i = 17; i > 1; --i) { - Xl ^= _P[i]; - Xr ^= F(Xl); - // Exchange - temp = Xl; Xl = Xr; Xr = temp; - } - - // Exchange - temp = Xl; Xl = Xr; Xr = temp; - - Xr ^= _P[1]; - Xl ^= _P[0]; - - *xl = Xl; - *xr = Xr; -} - - diff --git a/tdewallet/backend/blowfish.cpp b/tdewallet/backend/blowfish.cpp new file mode 100644 index 000000000..c708935de --- /dev/null +++ b/tdewallet/backend/blowfish.cpp @@ -0,0 +1,259 @@ +/* This file is part of the KDE project + Copyright (C) 2001 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +// FIXME: should we unroll some loops? Optimization can be done here. + + +/* Implementation of 16 rounds blowfish as described in: + * _Applied_Cryptography_ (c) Bruce Schneier, 1996. + */ + +#include + +#include +#include +#include + +#include "blowfish.h" +#include "blowfishtables.h" + + +BlowFish::BlowFish() { + _blksz = 8; + _key = 0L; + _init = false; +} + + + +bool BlowFish::init() { + // Initialize the sboxes + for (int i = 0; i < 256; i++) { + _S[0][i] = ks0[i]; + _S[1][i] = ks1[i]; + _S[2][i] = ks2[i]; + _S[3][i] = ks3[i]; + } + + uint32_t datal = 0; + uint32_t datar = 0; + uint32_t data = 0; + int j = 0; + + + // Update the sboxes and pbox. + for (int i = 0; i < 18; i++) { + data = 0; + for (int k = 0; k < 4; ++k) { + data = (data << 8) | ((unsigned char *)_key)[j++]; + if (j >= _keylen / 8) { + j = 0; + } + } + _P[i] = P[i] ^ data; + } + + for (int i = 0; i < 18; i += 2) { + encipher(&datal, &datar); + _P[i] = datal; + _P[i+1] = datar; + } + + for (int j = 0; j < 4; j++) { + for (int i = 0; i < 256; i += 2) { + encipher(&datal, &datar); + _S[j][i] = datal; + _S[j][i+1] = datar; + } + } + + // Nice code from gpg's implementation... + // check to see if the key is weak and return error if so + for (int i = 0; i < 255; i++) { + for (int j = i + 1; j < 256; j++) { + if ((_S[0][i] == _S[0][j]) || (_S[1][i] == _S[1][j]) || + (_S[2][i] == _S[2][j]) || (_S[3][i] == _S[3][j])) { + return false; + } + } + } + + _init = true; + + return true; +} + + +BlowFish::~BlowFish() { + delete[] (unsigned char *)_key; + _key = 0L; +} + + +int BlowFish::keyLen() const { + return 448; +} + + +bool BlowFish::variableKeyLen() const { + return true; +} + + +bool BlowFish::readyToGo() const { + return _init; +} + + +bool BlowFish::setKey(void *key, int bitlength) { + if (bitlength <= 0 || bitlength > 448 || bitlength % 8 != 0) { + return false; + } + + delete[] (unsigned char *)_key; + + _key = new unsigned char[bitlength / 8]; + memcpy(_key, key, bitlength / 8); + _keylen = bitlength; + + return init(); +} + + +#ifdef WORDS_BIGENDIAN +#define shuffle(x) do { \ + uint32_t r = x; \ + x = (r & 0xff000000) >> 24; \ + x |= (r & 0x00ff0000) >> 8; \ + x |= (r & 0x0000ff00) << 8; \ + x |= (r & 0x000000ff) << 24; \ + } while (0) +#endif + +int BlowFish::encrypt(void *block, int len) { + uint32_t *d = (uint32_t *)block; + + if (!_init || len % _blksz != 0) { + return -1; + } + + for (int i = 0; i < len / _blksz; i++) { +#ifdef WORDS_BIGENDIAN + shuffle(*d); + shuffle(*(d + 1)); +#endif + encipher(d, d + 1); +#ifdef WORDS_BIGENDIAN + shuffle(*d); + shuffle(*(d + 1)); +#endif + d += 2; + } + + return len; +} + + +int BlowFish::decrypt(void *block, int len) { + uint32_t *d = (uint32_t *)block; + + if (!_init || len % _blksz != 0) { + return -1; + } + + for (int i = 0; i < len / _blksz; i++) { +#ifdef WORDS_BIGENDIAN + shuffle(*d); + shuffle(*(d + 1)); +#endif + decipher(d, d + 1); +#ifdef WORDS_BIGENDIAN + shuffle(*d); + shuffle(*(d + 1)); +#endif + d += 2; + } + + return len; +} + + +uint32_t BlowFish::F(uint32_t x) { + unsigned short a, b, c, d; + uint32_t y; + + d = x & 0x000000ff; + x >>= 8; + c = x & 0x000000ff; + x >>= 8; + b = x & 0x000000ff; + x >>= 8; + a = x & 0x000000ff; + + y = _S[0][a] + _S[1][b]; + y ^= _S[2][c]; + y += _S[3][d]; + + return y; +} + + +void BlowFish::encipher(uint32_t *xl, uint32_t *xr) { + uint32_t Xl = *xl, Xr = *xr, temp; + + for (int i = 0; i < 16; ++i) { + Xl ^= _P[i]; + Xr ^= F(Xl); + // Exchange + temp = Xl; Xl = Xr; Xr = temp; + } + + // Exchange + temp = Xl; Xl = Xr; Xr = temp; + + Xr ^= _P[16]; + Xl ^= _P[17]; + + *xl = Xl; + *xr = Xr; +} + + +void BlowFish::decipher(uint32_t *xl, uint32_t *xr) { + uint32_t Xl = *xl, Xr = *xr, temp; + + for (int i = 17; i > 1; --i) { + Xl ^= _P[i]; + Xr ^= F(Xl); + // Exchange + temp = Xl; Xl = Xr; Xr = temp; + } + + // Exchange + temp = Xl; Xl = Xr; Xr = temp; + + Xr ^= _P[1]; + Xl ^= _P[0]; + + *xl = Xl; + *xr = Xr; +} + + diff --git a/tdewallet/backend/blowfishtables.h b/tdewallet/backend/blowfishtables.h index dae448f96..a41d7a7e3 100644 --- a/tdewallet/backend/blowfishtables.h +++ b/tdewallet/backend/blowfishtables.h @@ -17,7 +17,7 @@ Boston, MA 02110-1301, USA. */ -// This is also from _Applied_Cryptography_. See blowfish.cc for more details. +// This is also from _Applied_Cryptography_. See blowfish.cpp for more details. #ifndef __bfdefs_h #define __bfdefs_h diff --git a/tdewallet/backend/cbc.cc b/tdewallet/backend/cbc.cc deleted file mode 100644 index 7bc5f3891..000000000 --- a/tdewallet/backend/cbc.cc +++ /dev/null @@ -1,149 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2001 George Staikos - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - - -#include "cbc.h" -#include - - - -CipherBlockChain::CipherBlockChain(BlockCipher *cipher) : _cipher(cipher) { - _next = 0L; - _register = 0L; - _len = -1; - _reader = _writer = 0L; - if (cipher) { - _blksz = cipher->blockSize(); - } -} - - -CipherBlockChain::~CipherBlockChain() { - delete[] (char *)_register; - _register = 0L; - delete[] (char *)_next; - _next = 0L; -} - - -bool CipherBlockChain::setKey(void *key, int bitlength) { - if (_cipher) { - return _cipher->setKey(key, bitlength); - } - return false; -} - - -int CipherBlockChain::keyLen() const { - if (_cipher) { - return _cipher->keyLen(); - } - return -1; -} - - -bool CipherBlockChain::variableKeyLen() const { - if (_cipher) { - return _cipher->variableKeyLen(); - } - return false; -} - - -bool CipherBlockChain::readyToGo() const { - if (_cipher) { - return _cipher->readyToGo(); - } - return false; -} - - -int CipherBlockChain::encrypt(void *block, int len) { - if (_cipher && !_reader) { - int rc; - - _writer |= 1; - - if (!_register) { - _register = new unsigned char[len]; - _len = len; - memset(_register, 0, len); - } else if (len > _len) { - return -1; - } - - // This might be optimizable - char *tb = (char *)block; - for (int i = 0; i < len; i++) { - tb[i] ^= ((char *)_register)[i]; - } - - rc = _cipher->encrypt(block, len); - - if (rc != -1) { - memcpy(_register, block, len); - } - - return rc; - } - return -1; -} - - -int CipherBlockChain::decrypt(void *block, int len) { - if (_cipher && !_writer) { - int rc; - - _reader |= 1; - - if (!_register) { - _register = new unsigned char[len]; - _len = len; - memset(_register, 0, len); - } else if (len > _len) { - return -1; - } - - if (!_next) - _next = new unsigned char[_len]; - memcpy(_next, block, _len); - - rc = _cipher->decrypt(block, len); - - if (rc != -1) { - // This might be optimizable - char *tb = (char *)block; - for (int i = 0; i < len; i++) { - tb[i] ^= ((char *)_register)[i]; - } - } - - void *temp; - temp = _next; - _next = _register; - _register = temp; - - return rc; - } - return -1; -} - - - - diff --git a/tdewallet/backend/cbc.cpp b/tdewallet/backend/cbc.cpp new file mode 100644 index 000000000..7bc5f3891 --- /dev/null +++ b/tdewallet/backend/cbc.cpp @@ -0,0 +1,149 @@ +/* This file is part of the KDE project + Copyright (C) 2001 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "cbc.h" +#include + + + +CipherBlockChain::CipherBlockChain(BlockCipher *cipher) : _cipher(cipher) { + _next = 0L; + _register = 0L; + _len = -1; + _reader = _writer = 0L; + if (cipher) { + _blksz = cipher->blockSize(); + } +} + + +CipherBlockChain::~CipherBlockChain() { + delete[] (char *)_register; + _register = 0L; + delete[] (char *)_next; + _next = 0L; +} + + +bool CipherBlockChain::setKey(void *key, int bitlength) { + if (_cipher) { + return _cipher->setKey(key, bitlength); + } + return false; +} + + +int CipherBlockChain::keyLen() const { + if (_cipher) { + return _cipher->keyLen(); + } + return -1; +} + + +bool CipherBlockChain::variableKeyLen() const { + if (_cipher) { + return _cipher->variableKeyLen(); + } + return false; +} + + +bool CipherBlockChain::readyToGo() const { + if (_cipher) { + return _cipher->readyToGo(); + } + return false; +} + + +int CipherBlockChain::encrypt(void *block, int len) { + if (_cipher && !_reader) { + int rc; + + _writer |= 1; + + if (!_register) { + _register = new unsigned char[len]; + _len = len; + memset(_register, 0, len); + } else if (len > _len) { + return -1; + } + + // This might be optimizable + char *tb = (char *)block; + for (int i = 0; i < len; i++) { + tb[i] ^= ((char *)_register)[i]; + } + + rc = _cipher->encrypt(block, len); + + if (rc != -1) { + memcpy(_register, block, len); + } + + return rc; + } + return -1; +} + + +int CipherBlockChain::decrypt(void *block, int len) { + if (_cipher && !_writer) { + int rc; + + _reader |= 1; + + if (!_register) { + _register = new unsigned char[len]; + _len = len; + memset(_register, 0, len); + } else if (len > _len) { + return -1; + } + + if (!_next) + _next = new unsigned char[_len]; + memcpy(_next, block, _len); + + rc = _cipher->decrypt(block, len); + + if (rc != -1) { + // This might be optimizable + char *tb = (char *)block; + for (int i = 0; i < len; i++) { + tb[i] ^= ((char *)_register)[i]; + } + } + + void *temp; + temp = _next; + _next = _register; + _register = temp; + + return rc; + } + return -1; +} + + + + diff --git a/tdewallet/backend/sha1.cc b/tdewallet/backend/sha1.cc deleted file mode 100644 index 7420b5f16..000000000 --- a/tdewallet/backend/sha1.cc +++ /dev/null @@ -1,343 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2001 George Staikos - Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_STDINT_H -#include /* For uintXX_t on OSX */ -#endif -#ifdef HAVE_SYS_BITYPES_H -#include /* For uintXX_t on Tru64 */ -#endif -#ifdef HAVE_STDINT_H -#include -#endif - -#include "sha1.h" -#include - -// FIXME: this can be optimized to one instruction on most cpus. -#define rol(x,y) ((x << y) | (x >> (32-y))) - - -#define K1 0x5a827999L -#define K2 0x6ed9eba1L -#define K3 0x8f1bbcdcL -#define K4 0xca62c1d6L -#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) -#define F2(x,y,z) ( x ^ y ^ z ) -#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) -#define F4(x,y,z) ( x ^ y ^ z ) - -#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ - ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ - , (x[i&0x0f] = (tm << 1) | (tm >> 31))) - -#define R(a,b,c,d,e,f,k,m) do { e += rol(a, 5) \ - + f(b, c, d) \ - + k \ - + m; \ - b = rol(b, 30); \ - } while(0) - - -SHA1::SHA1() { - _hashlen = 160; - _init = false; - reset(); -} - - -int SHA1::reset() { - _h0 = 0x67452301; - _h1 = 0xefcdab89; - _h2 = 0x98badcfe; - _h3 = 0x10325476; - _h4 = 0xc3d2e1f0; - _nblocks = 0; - _count = 0; - memset(_buf, 0, 56); // clear the buffer - - _init = true; - return 0; -} - - -int SHA1::size() const { - return _hashlen; -} - - -SHA1::~SHA1() { - -} - - -void SHA1::transform(void *data) { - unsigned int a, b, c, d, e, tm; - unsigned int x[16]; - unsigned char *_data = (unsigned char *)data; - - a = _h0; - b = _h1; - c = _h2; - d = _h3; - e = _h4; - -#ifdef WORDS_BIGENDIAN - memcpy(x, _data, 64); -#else - int i; - unsigned char *p2; - for (i = 0, p2 = (unsigned char *)x; - i < 16; i++, p2 += 4) { - p2[3] = *_data++; - p2[2] = *_data++; - p2[1] = *_data++; - p2[0] = *_data++; - } -#endif - - R(a, b, c, d, e, F1, K1, x[ 0]); - R(e, a, b, c, d, F1, K1, x[ 1]); - R(d, e, a, b, c, F1, K1, x[ 2]); - R(c, d, e, a, b, F1, K1, x[ 3]); - R(b, c, d, e, a, F1, K1, x[ 4]); - R(a, b, c, d, e, F1, K1, x[ 5]); - R(e, a, b, c, d, F1, K1, x[ 6]); - R(d, e, a, b, c, F1, K1, x[ 7]); - R(c, d, e, a, b, F1, K1, x[ 8]); - R(b, c, d, e, a, F1, K1, x[ 9]); - R(a, b, c, d, e, F1, K1, x[10]); - R(e, a, b, c, d, F1, K1, x[11]); - R(d, e, a, b, c, F1, K1, x[12]); - R(c, d, e, a, b, F1, K1, x[13]); - R(b, c, d, e, a, F1, K1, x[14]); - R(a, b, c, d, e, F1, K1, x[15]); - R(e, a, b, c, d, F1, K1, M(16)); - R(d, e, a, b, c, F1, K1, M(17)); - R(c, d, e, a, b, F1, K1, M(18)); - R(b, c, d, e, a, F1, K1, M(19)); - R(a, b, c, d, e, F2, K2, M(20)); - R(e, a, b, c, d, F2, K2, M(21)); - R(d, e, a, b, c, F2, K2, M(22)); - R(c, d, e, a, b, F2, K2, M(23)); - R(b, c, d, e, a, F2, K2, M(24)); - R(a, b, c, d, e, F2, K2, M(25)); - R(e, a, b, c, d, F2, K2, M(26)); - R(d, e, a, b, c, F2, K2, M(27)); - R(c, d, e, a, b, F2, K2, M(28)); - R(b, c, d, e, a, F2, K2, M(29)); - R(a, b, c, d, e, F2, K2, M(30)); - R(e, a, b, c, d, F2, K2, M(31)); - R(d, e, a, b, c, F2, K2, M(32)); - R(c, d, e, a, b, F2, K2, M(33)); - R(b, c, d, e, a, F2, K2, M(34)); - R(a, b, c, d, e, F2, K2, M(35)); - R(e, a, b, c, d, F2, K2, M(36)); - R(d, e, a, b, c, F2, K2, M(37)); - R(c, d, e, a, b, F2, K2, M(38)); - R(b, c, d, e, a, F2, K2, M(39)); - R(a, b, c, d, e, F3, K3, M(40)); - R(e, a, b, c, d, F3, K3, M(41)); - R(d, e, a, b, c, F3, K3, M(42)); - R(c, d, e, a, b, F3, K3, M(43)); - R(b, c, d, e, a, F3, K3, M(44)); - R(a, b, c, d, e, F3, K3, M(45)); - R(e, a, b, c, d, F3, K3, M(46)); - R(d, e, a, b, c, F3, K3, M(47)); - R(c, d, e, a, b, F3, K3, M(48)); - R(b, c, d, e, a, F3, K3, M(49)); - R(a, b, c, d, e, F3, K3, M(50)); - R(e, a, b, c, d, F3, K3, M(51)); - R(d, e, a, b, c, F3, K3, M(52)); - R(c, d, e, a, b, F3, K3, M(53)); - R(b, c, d, e, a, F3, K3, M(54)); - R(a, b, c, d, e, F3, K3, M(55)); - R(e, a, b, c, d, F3, K3, M(56)); - R(d, e, a, b, c, F3, K3, M(57)); - R(c, d, e, a, b, F3, K3, M(58)); - R(b, c, d, e, a, F3, K3, M(59)); - R(a, b, c, d, e, F4, K4, M(60)); - R(e, a, b, c, d, F4, K4, M(61)); - R(d, e, a, b, c, F4, K4, M(62)); - R(c, d, e, a, b, F4, K4, M(63)); - R(b, c, d, e, a, F4, K4, M(64)); - R(a, b, c, d, e, F4, K4, M(65)); - R(e, a, b, c, d, F4, K4, M(66)); - R(d, e, a, b, c, F4, K4, M(67)); - R(c, d, e, a, b, F4, K4, M(68)); - R(b, c, d, e, a, F4, K4, M(69)); - R(a, b, c, d, e, F4, K4, M(70)); - R(e, a, b, c, d, F4, K4, M(71)); - R(d, e, a, b, c, F4, K4, M(72)); - R(c, d, e, a, b, F4, K4, M(73)); - R(b, c, d, e, a, F4, K4, M(74)); - R(a, b, c, d, e, F4, K4, M(75)); - R(e, a, b, c, d, F4, K4, M(76)); - R(d, e, a, b, c, F4, K4, M(77)); - R(c, d, e, a, b, F4, K4, M(78)); - R(b, c, d, e, a, F4, K4, M(79)); - - _h0 += a; - _h1 += b; - _h2 += c; - _h3 += d; - _h4 += e; - -} - - -bool SHA1::readyToGo() const { - return _init; -} - - -int SHA1::process(const void *block, int len) { - if (!_init) { - return -1; - } - - unsigned char *_block = (unsigned char *)block; - - int cnt = 0; - // Flush the buffer before proceeding - if (_count == 64) { - transform(_buf); - _count = 0; - _nblocks++; - } - - if (!_block) { - return 0; - } - - if (_count) { - for (; len && _count < 64; len--, cnt++) { - _buf[_count++] = *_block++; - } - process(0, 0); // flush the buffer if necessary - if (!len) { - return cnt; - } - } - - while (len >= 64) { - transform(_block); - _count = 0; - _nblocks++; - len -= 64; - cnt += 64; - _block += 64; - } - - for (; len && _count < 64; len--, cnt++) { - _buf[_count++] = *_block++; - } - - return cnt; -} - - -const unsigned char *SHA1::hash() { - unsigned int t, msb, lsb; - unsigned char *p; - - - if (!_init) { - return (unsigned char *)_buf; - } - - process(0, 0); - - msb = 0; - t = _nblocks; - - if ((lsb = t << 6) < t) { - msb++; - } - - msb += t >> 26; - t = lsb; - - if ((lsb = t + _count) < t) { - msb++; - } - - t = lsb; - - if ((lsb = t << 3) < t) { - msb++; - } - - msb += t >> 29; - - _buf[_count++] = 0x80; - - if (_count < 56) { - while (_count < 56) { - _buf[_count++] = 0; - } - } else { - while (_count < 64) { - _buf[_count++] = 0; - } - process(0, 0); - memset(_buf, 0, 56); - } - - _buf[56] = msb >> 24; - _buf[57] = msb >> 16; - _buf[58] = msb >> 8; - _buf[59] = msb; - _buf[60] = lsb >> 24; - _buf[61] = lsb >> 16; - _buf[62] = lsb >> 8; - _buf[63] = lsb; - - transform(_buf); - - p = _buf; - -#ifdef WORDS_BIGENDIAN -#define X( a ) do { *( uint32_t * )p = _h##a; p += 4; } while ( 0 ) -#else -#define X(a) do { *p++ = _h##a >> 24; *p++ = _h##a >> 16; \ - *p++ = _h##a >> 8; *p++ = _h##a; } while (0) -#endif - - X(0); - X(1); - X(2); - X(3); - X(4); - -#undef X - - _init = false; - - return (unsigned char *)_buf; -} - - - diff --git a/tdewallet/backend/sha1.cpp b/tdewallet/backend/sha1.cpp new file mode 100644 index 000000000..7420b5f16 --- /dev/null +++ b/tdewallet/backend/sha1.cpp @@ -0,0 +1,343 @@ +/* This file is part of the KDE project + Copyright (C) 2001 George Staikos + Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_STDINT_H +#include /* For uintXX_t on OSX */ +#endif +#ifdef HAVE_SYS_BITYPES_H +#include /* For uintXX_t on Tru64 */ +#endif +#ifdef HAVE_STDINT_H +#include +#endif + +#include "sha1.h" +#include + +// FIXME: this can be optimized to one instruction on most cpus. +#define rol(x,y) ((x << y) | (x >> (32-y))) + + +#define K1 0x5a827999L +#define K2 0x6ed9eba1L +#define K3 0x8f1bbcdcL +#define K4 0xca62c1d6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) + +#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ + ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ + , (x[i&0x0f] = (tm << 1) | (tm >> 31))) + +#define R(a,b,c,d,e,f,k,m) do { e += rol(a, 5) \ + + f(b, c, d) \ + + k \ + + m; \ + b = rol(b, 30); \ + } while(0) + + +SHA1::SHA1() { + _hashlen = 160; + _init = false; + reset(); +} + + +int SHA1::reset() { + _h0 = 0x67452301; + _h1 = 0xefcdab89; + _h2 = 0x98badcfe; + _h3 = 0x10325476; + _h4 = 0xc3d2e1f0; + _nblocks = 0; + _count = 0; + memset(_buf, 0, 56); // clear the buffer + + _init = true; + return 0; +} + + +int SHA1::size() const { + return _hashlen; +} + + +SHA1::~SHA1() { + +} + + +void SHA1::transform(void *data) { + unsigned int a, b, c, d, e, tm; + unsigned int x[16]; + unsigned char *_data = (unsigned char *)data; + + a = _h0; + b = _h1; + c = _h2; + d = _h3; + e = _h4; + +#ifdef WORDS_BIGENDIAN + memcpy(x, _data, 64); +#else + int i; + unsigned char *p2; + for (i = 0, p2 = (unsigned char *)x; + i < 16; i++, p2 += 4) { + p2[3] = *_data++; + p2[2] = *_data++; + p2[1] = *_data++; + p2[0] = *_data++; + } +#endif + + R(a, b, c, d, e, F1, K1, x[ 0]); + R(e, a, b, c, d, F1, K1, x[ 1]); + R(d, e, a, b, c, F1, K1, x[ 2]); + R(c, d, e, a, b, F1, K1, x[ 3]); + R(b, c, d, e, a, F1, K1, x[ 4]); + R(a, b, c, d, e, F1, K1, x[ 5]); + R(e, a, b, c, d, F1, K1, x[ 6]); + R(d, e, a, b, c, F1, K1, x[ 7]); + R(c, d, e, a, b, F1, K1, x[ 8]); + R(b, c, d, e, a, F1, K1, x[ 9]); + R(a, b, c, d, e, F1, K1, x[10]); + R(e, a, b, c, d, F1, K1, x[11]); + R(d, e, a, b, c, F1, K1, x[12]); + R(c, d, e, a, b, F1, K1, x[13]); + R(b, c, d, e, a, F1, K1, x[14]); + R(a, b, c, d, e, F1, K1, x[15]); + R(e, a, b, c, d, F1, K1, M(16)); + R(d, e, a, b, c, F1, K1, M(17)); + R(c, d, e, a, b, F1, K1, M(18)); + R(b, c, d, e, a, F1, K1, M(19)); + R(a, b, c, d, e, F2, K2, M(20)); + R(e, a, b, c, d, F2, K2, M(21)); + R(d, e, a, b, c, F2, K2, M(22)); + R(c, d, e, a, b, F2, K2, M(23)); + R(b, c, d, e, a, F2, K2, M(24)); + R(a, b, c, d, e, F2, K2, M(25)); + R(e, a, b, c, d, F2, K2, M(26)); + R(d, e, a, b, c, F2, K2, M(27)); + R(c, d, e, a, b, F2, K2, M(28)); + R(b, c, d, e, a, F2, K2, M(29)); + R(a, b, c, d, e, F2, K2, M(30)); + R(e, a, b, c, d, F2, K2, M(31)); + R(d, e, a, b, c, F2, K2, M(32)); + R(c, d, e, a, b, F2, K2, M(33)); + R(b, c, d, e, a, F2, K2, M(34)); + R(a, b, c, d, e, F2, K2, M(35)); + R(e, a, b, c, d, F2, K2, M(36)); + R(d, e, a, b, c, F2, K2, M(37)); + R(c, d, e, a, b, F2, K2, M(38)); + R(b, c, d, e, a, F2, K2, M(39)); + R(a, b, c, d, e, F3, K3, M(40)); + R(e, a, b, c, d, F3, K3, M(41)); + R(d, e, a, b, c, F3, K3, M(42)); + R(c, d, e, a, b, F3, K3, M(43)); + R(b, c, d, e, a, F3, K3, M(44)); + R(a, b, c, d, e, F3, K3, M(45)); + R(e, a, b, c, d, F3, K3, M(46)); + R(d, e, a, b, c, F3, K3, M(47)); + R(c, d, e, a, b, F3, K3, M(48)); + R(b, c, d, e, a, F3, K3, M(49)); + R(a, b, c, d, e, F3, K3, M(50)); + R(e, a, b, c, d, F3, K3, M(51)); + R(d, e, a, b, c, F3, K3, M(52)); + R(c, d, e, a, b, F3, K3, M(53)); + R(b, c, d, e, a, F3, K3, M(54)); + R(a, b, c, d, e, F3, K3, M(55)); + R(e, a, b, c, d, F3, K3, M(56)); + R(d, e, a, b, c, F3, K3, M(57)); + R(c, d, e, a, b, F3, K3, M(58)); + R(b, c, d, e, a, F3, K3, M(59)); + R(a, b, c, d, e, F4, K4, M(60)); + R(e, a, b, c, d, F4, K4, M(61)); + R(d, e, a, b, c, F4, K4, M(62)); + R(c, d, e, a, b, F4, K4, M(63)); + R(b, c, d, e, a, F4, K4, M(64)); + R(a, b, c, d, e, F4, K4, M(65)); + R(e, a, b, c, d, F4, K4, M(66)); + R(d, e, a, b, c, F4, K4, M(67)); + R(c, d, e, a, b, F4, K4, M(68)); + R(b, c, d, e, a, F4, K4, M(69)); + R(a, b, c, d, e, F4, K4, M(70)); + R(e, a, b, c, d, F4, K4, M(71)); + R(d, e, a, b, c, F4, K4, M(72)); + R(c, d, e, a, b, F4, K4, M(73)); + R(b, c, d, e, a, F4, K4, M(74)); + R(a, b, c, d, e, F4, K4, M(75)); + R(e, a, b, c, d, F4, K4, M(76)); + R(d, e, a, b, c, F4, K4, M(77)); + R(c, d, e, a, b, F4, K4, M(78)); + R(b, c, d, e, a, F4, K4, M(79)); + + _h0 += a; + _h1 += b; + _h2 += c; + _h3 += d; + _h4 += e; + +} + + +bool SHA1::readyToGo() const { + return _init; +} + + +int SHA1::process(const void *block, int len) { + if (!_init) { + return -1; + } + + unsigned char *_block = (unsigned char *)block; + + int cnt = 0; + // Flush the buffer before proceeding + if (_count == 64) { + transform(_buf); + _count = 0; + _nblocks++; + } + + if (!_block) { + return 0; + } + + if (_count) { + for (; len && _count < 64; len--, cnt++) { + _buf[_count++] = *_block++; + } + process(0, 0); // flush the buffer if necessary + if (!len) { + return cnt; + } + } + + while (len >= 64) { + transform(_block); + _count = 0; + _nblocks++; + len -= 64; + cnt += 64; + _block += 64; + } + + for (; len && _count < 64; len--, cnt++) { + _buf[_count++] = *_block++; + } + + return cnt; +} + + +const unsigned char *SHA1::hash() { + unsigned int t, msb, lsb; + unsigned char *p; + + + if (!_init) { + return (unsigned char *)_buf; + } + + process(0, 0); + + msb = 0; + t = _nblocks; + + if ((lsb = t << 6) < t) { + msb++; + } + + msb += t >> 26; + t = lsb; + + if ((lsb = t + _count) < t) { + msb++; + } + + t = lsb; + + if ((lsb = t << 3) < t) { + msb++; + } + + msb += t >> 29; + + _buf[_count++] = 0x80; + + if (_count < 56) { + while (_count < 56) { + _buf[_count++] = 0; + } + } else { + while (_count < 64) { + _buf[_count++] = 0; + } + process(0, 0); + memset(_buf, 0, 56); + } + + _buf[56] = msb >> 24; + _buf[57] = msb >> 16; + _buf[58] = msb >> 8; + _buf[59] = msb; + _buf[60] = lsb >> 24; + _buf[61] = lsb >> 16; + _buf[62] = lsb >> 8; + _buf[63] = lsb; + + transform(_buf); + + p = _buf; + +#ifdef WORDS_BIGENDIAN +#define X( a ) do { *( uint32_t * )p = _h##a; p += 4; } while ( 0 ) +#else +#define X(a) do { *p++ = _h##a >> 24; *p++ = _h##a >> 16; \ + *p++ = _h##a >> 8; *p++ = _h##a; } while (0) +#endif + + X(0); + X(1); + X(2); + X(3); + X(4); + +#undef X + + _init = false; + + return (unsigned char *)_buf; +} + + + diff --git a/tdewallet/backend/tdewalletbackend.cc b/tdewallet/backend/tdewalletbackend.cc deleted file mode 100644 index 83e37a49a..000000000 --- a/tdewallet/backend/tdewalletbackend.cc +++ /dev/null @@ -1,838 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001-2004 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "tdewalletbackend.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "blowfish.h" -#include "sha1.h" -#include "cbc.h" - -#include - -#define TDEWALLET_VERSION_MAJOR 0 -#define TDEWALLET_VERSION_MINOR 0 - -#define TDEWALLET_CIPHER_BLOWFISH_CBC 0 -#define TDEWALLET_CIPHER_3DES_CBC 1 // unsupported - -#define TDEWALLET_HASH_SHA1 0 -#define TDEWALLET_HASH_MD5 1 // unsupported - - -using namespace TDEWallet; - -#define KWMAGIC "KWALLET\n\r\0\r\n" -#define KWMAGIC_LEN 12 - -static void initTDEWalletDir() -{ - TDEGlobal::dirs()->addResourceType("tdewallet", "share/apps/tdewallet"); -} - -Backend::Backend(const TQString& name, bool isPath) : _name(name), _ref(0) { - initTDEWalletDir(); - if (isPath) { - _path = name; - } else { - _path = TDEGlobal::dirs()->saveLocation("tdewallet") + "/" + _name + ".kwl"; - } - - _open = false; -} - - -Backend::~Backend() { - if (_open) { - close(); - } -} - - -int Backend::close() { - for (FolderMap::ConstIterator i = _entries.begin(); i != _entries.end(); ++i) { - for (EntryMap::ConstIterator j = i.data().begin(); j != i.data().end(); ++j) { - delete j.data(); - } - } - _entries.clear(); - -return 0; -} - - -static int getRandomBlock(TQByteArray& randBlock) { - // First try /dev/urandom - if (TQFile::exists("/dev/urandom")) { - TQFile devrand("/dev/urandom"); - if (devrand.open(IO_ReadOnly)) { - unsigned int rc = devrand.readBlock(randBlock.data(), randBlock.size()); - - if (rc != randBlock.size()) { - return -3; // not enough data read - } - - return 0; - } - } - - // If that failed, try /dev/random - // FIXME: open in noblocking mode! - if (TQFile::exists("/dev/random")) { - TQFile devrand("/dev/random"); - if (devrand.open(IO_ReadOnly)) { - unsigned int rc = 0; - unsigned int cnt = 0; - - do { - int rc2 = devrand.readBlock(randBlock.data() + rc, randBlock.size()); - - if (rc2 < 0) { - return -3; // read error - } - - rc += rc2; - cnt++; - if (cnt > randBlock.size()) { - return -4; // reading forever?! - } - } while(rc < randBlock.size()); - - return 0; - } - } - - // EGD method - char *randFilename; - if ((randFilename = getenv("RANDFILE"))) { - if (TQFile::exists(randFilename)) { - TQFile devrand(randFilename); - if (devrand.open(IO_ReadOnly)) { - unsigned int rc = devrand.readBlock(randBlock.data(), randBlock.size()); - if (rc != randBlock.size()) { - return -3; // not enough data read - } - return 0; - } - } - } - - // Couldn't get any random data!! - - return -1; -} - - -// this should be SHA-512 for release probably -static int password2hash(const TQByteArray& password, TQByteArray& hash) { - SHA1 sha; - int shasz = sha.size() / 8; - - assert(shasz >= 20); - - TQByteArray block1(shasz); - - sha.process(password.data(), TQMIN(password.size(), 16)); - - // To make brute force take longer - for (int i = 0; i < 2000; i++) { - memcpy(block1.data(), sha.hash(), shasz); - sha.reset(); - sha.process(block1.data(), shasz); - } - - sha.reset(); - - if (password.size() > 16) { - sha.process(password.data() + 16, TQMIN(password.size() - 16, 16)); - TQByteArray block2(shasz); - // To make brute force take longer - for (int i = 0; i < 2000; i++) { - memcpy(block2.data(), sha.hash(), shasz); - sha.reset(); - sha.process(block2.data(), shasz); - } - - sha.reset(); - - if (password.size() > 32) { - sha.process(password.data() + 32, TQMIN(password.size() - 32, 16)); - - TQByteArray block3(shasz); - // To make brute force take longer - for (int i = 0; i < 2000; i++) { - memcpy(block3.data(), sha.hash(), shasz); - sha.reset(); - sha.process(block3.data(), shasz); - } - - sha.reset(); - - if (password.size() > 48) { - sha.process(password.data() + 48, password.size() - 48); - - TQByteArray block4(shasz); - // To make brute force take longer - for (int i = 0; i < 2000; i++) { - memcpy(block4.data(), sha.hash(), shasz); - sha.reset(); - sha.process(block4.data(), shasz); - } - - sha.reset(); - // split 14/14/14/14 - hash.resize(56); - memcpy(hash.data(), block1.data(), 14); - memcpy(hash.data() + 14, block2.data(), 14); - memcpy(hash.data() + 28, block3.data(), 14); - memcpy(hash.data() + 42, block4.data(), 14); - block4.fill(0); - } else { - // split 20/20/16 - hash.resize(56); - memcpy(hash.data(), block1.data(), 20); - memcpy(hash.data() + 20, block2.data(), 20); - memcpy(hash.data() + 40, block3.data(), 16); - } - block3.fill(0); - } else { - // split 20/20 - hash.resize(40); - memcpy(hash.data(), block1.data(), 20); - memcpy(hash.data() + 20, block2.data(), 20); - } - block2.fill(0); - } else { - // entirely block1 - hash.resize(20); - memcpy(hash.data(), block1.data(), 20); - } - - block1.fill(0); - - return 0; -} - - -bool Backend::exists(const TQString& wallet) { - initTDEWalletDir(); - TQString path = TDEGlobal::dirs()->saveLocation("tdewallet") + "/" + wallet + ".kwl"; - // Note: 60 bytes is presently the minimum size of a wallet file. - // Anything smaller is junk. -return TQFile::exists(path) && TQFileInfo(path).size() >= 60; -} - - -TQString Backend::openRCToString(int rc) { - switch (rc) { - case -255: - return i18n("Already open."); - case -2: - return i18n("Error opening file."); - case -3: - return i18n("Not a wallet file."); - case -4: - return i18n("Unsupported file format revision."); - case -42: - return i18n("Unknown encryption scheme."); - case -43: - return i18n("Corrupt file?"); - case -8: - return i18n("Error validating wallet integrity. Possibly corrupted."); - case -5: - case -7: - case -9: - return i18n("Read error - possibly incorrect password."); - case -6: - return i18n("Decryption error."); - default: - return TQString::null; - } -} - - -int Backend::open(const TQByteArray& password) { - - if (_open) { - return -255; // already open - } - - TQByteArray passhash; - - // No wallet existed. Let's create it. - // Note: 60 bytes is presently the minimum size of a wallet file. - // Anything smaller is junk and should be deleted. - if (!TQFile::exists(_path) || TQFileInfo(_path).size() < 60) { - TQFile newfile(_path); - if (!newfile.open(IO_ReadWrite)) { - return -2; // error opening file - } - newfile.close(); - _open = true; - sync(password); - return 1; // new file opened, but OK - } - - TQFile db(_path); - - if (!db.open(IO_ReadOnly)) { - return -2; // error opening file - } - - char magicBuf[KWMAGIC_LEN]; - db.readBlock(magicBuf, KWMAGIC_LEN); - if (memcmp(magicBuf, KWMAGIC, KWMAGIC_LEN) != 0) { - return -3; // bad magic - } - - db.readBlock(magicBuf, 4); - - // First byte is major version, second byte is minor version - if (magicBuf[0] != TDEWALLET_VERSION_MAJOR) { - return -4; // unknown version - } - - if (magicBuf[1] != TDEWALLET_VERSION_MINOR) { - return -4; // unknown version - } - - if (magicBuf[2] != TDEWALLET_CIPHER_BLOWFISH_CBC) { - return -42; // unknown cipher - } - - if (magicBuf[3] != TDEWALLET_HASH_SHA1) { - return -42; // unknown hash - } - - _hashes.clear(); - // Read in the hashes - TQDataStream hds(&db); - TQ_UINT32 n; - hds >> n; - if (n > 0xffff) { // sanity check - return -43; - } - - for (size_t i = 0; i < n; ++i) { - KMD5::Digest d, d2; // judgment day - MD5Digest ba; - TQMap >::iterator it; - TQ_UINT32 fsz; - if (hds.atEnd()) return -43; - hds.readRawBytes(reinterpret_cast(d), 16); - hds >> fsz; - ba.duplicate(reinterpret_cast(d), 16); - it = _hashes.insert(ba, TQValueList()); - for (size_t j = 0; j < fsz; ++j) { - hds.readRawBytes(reinterpret_cast(d2), 16); - ba.duplicate(reinterpret_cast(d2), 16); - (*it).append(ba); - } - } - - // Read in the rest of the file. - TQByteArray encrypted = db.readAll(); - assert(encrypted.size() < db.size()); - - BlowFish _bf; - CipherBlockChain bf(&_bf); - int blksz = bf.blockSize(); - if ((encrypted.size() % blksz) != 0) { - return -5; // invalid file structure - } - - // Decrypt the encrypted data - passhash.resize(bf.keyLen()/8); - password2hash(password, passhash); - - bf.setKey((void *)passhash.data(), passhash.size()*8); - - if (!encrypted.data()) { - passhash.fill(0); - encrypted.fill(0); - return -7; // file structure error - } - - int rc = bf.decrypt(encrypted.data(), encrypted.size()); - if (rc < 0) { - passhash.fill(0); - encrypted.fill(0); - return -6; // decrypt error - } - - passhash.fill(0); // passhash is UNUSABLE NOW - - const char *t = encrypted.data(); - - // strip the leading data - t += blksz; // one block of random data - - // strip the file size off - long fsize = 0; - - fsize |= (long(*t) << 24) & 0xff000000; - t++; - fsize |= (long(*t) << 16) & 0x00ff0000; - t++; - fsize |= (long(*t) << 8) & 0x0000ff00; - t++; - fsize |= long(*t) & 0x000000ff; - t++; - - if (fsize < 0 || fsize > long(encrypted.size()) - blksz - 4) { - //kdDebug() << "fsize: " << fsize << " encrypted.size(): " << encrypted.size() << " blksz: " << blksz << endl; - encrypted.fill(0); - return -9; // file structure error. - } - - // compute the hash ourself - SHA1 sha; - sha.process(t, fsize); - const char *testhash = (const char *)sha.hash(); - - // compare hashes - int sz = encrypted.size(); - for (int i = 0; i < 20; i++) { - if (testhash[i] != static_cast(encrypted.at(sz - 20 + i))) { - encrypted.fill(0); - sha.reset(); - return -8; // hash error. - } - } - - sha.reset(); - - // chop off the leading blksz+4 bytes - TQByteArray tmpenc; - tmpenc.duplicate(encrypted.data()+blksz+4, fsize); - encrypted.fill(0); - encrypted.duplicate(tmpenc.data(), tmpenc.size()); - tmpenc.fill(0); - - // Load the data structures up - TQDataStream eStream(encrypted, IO_ReadOnly); - - while (!eStream.atEnd()) { - TQString folder; - TQ_UINT32 n; - - eStream >> folder; - eStream >> n; - - // Force initialisation - _entries[folder].clear(); - - for (size_t i = 0; i < n; i++) { - TQString key; - TDEWallet::Wallet::EntryType et = TDEWallet::Wallet::Unknown; - Entry *e = new Entry; - eStream >> key; - TQ_INT32 x = 0; // necessary to read properly - eStream >> x; - et = static_cast(x); - - switch (et) { - case TDEWallet::Wallet::Password: - case TDEWallet::Wallet::Stream: - case TDEWallet::Wallet::Map: - break; - default: // Unknown entry - delete e; - continue; - } - - TQByteArray a; - eStream >> a; - e->setValue(a); - e->setType(et); - e->setKey(key); - _entries[folder][key] = e; - } - } - - _open = true; - return 0; -} - - -int Backend::sync(const TQByteArray& password) { - if (!_open) { - return -255; // not open yet - } - - KSaveFile sf(_path, 0600); - TQFile *qf = sf.file(); - - if (!qf) { - sf.abort(); - return -1; // error opening file - } - - qf->writeBlock(KWMAGIC, KWMAGIC_LEN); - - // Write the version number - TQByteArray version(4); - version[0] = TDEWALLET_VERSION_MAJOR; - version[1] = TDEWALLET_VERSION_MINOR; - version[2] = TDEWALLET_CIPHER_BLOWFISH_CBC; - version[3] = TDEWALLET_HASH_SHA1; - qf->writeBlock(version, 4); - - // Holds the hashes we write out - TQByteArray hashes; - TQDataStream hashStream(hashes, IO_WriteOnly); - KMD5 md5; - hashStream << static_cast(_entries.count()); - - // Holds decrypted data prior to encryption - TQByteArray decrypted; - - // FIXME: we should estimate the amount of data we will write in each - // buffer and resize them approximately in order to avoid extra - // resizes. - - // populate decrypted - TQDataStream dStream(decrypted, IO_WriteOnly); - for (FolderMap::ConstIterator i = _entries.begin(); i != _entries.end(); ++i) { - dStream << i.key(); - dStream << static_cast(i.data().count()); - - md5.reset(); - md5.update(i.key().utf8()); - hashStream.writeRawBytes(reinterpret_cast(&(md5.rawDigest()[0])), 16); - hashStream << static_cast(i.data().count()); - - for (EntryMap::ConstIterator j = i.data().begin(); j != i.data().end(); ++j) { - dStream << j.key(); - dStream << static_cast(j.data()->type()); - dStream << j.data()->value(); - - md5.reset(); - md5.update(j.key().utf8()); - hashStream.writeRawBytes(reinterpret_cast(&(md5.rawDigest()[0])), 16); - } - } - - qf->writeBlock(hashes, hashes.size()); - - // calculate the hash of the file - SHA1 sha; - BlowFish _bf; - CipherBlockChain bf(&_bf); - - sha.process(decrypted.data(), decrypted.size()); - - // prepend and append the random data - TQByteArray wholeFile; - long blksz = bf.blockSize(); - long newsize = decrypted.size() + - blksz + // encrypted block - 4 + // file size - 20; // size of the SHA hash - - int delta = (blksz - (newsize % blksz)); - newsize += delta; - wholeFile.resize(newsize); - - TQByteArray randBlock; - randBlock.resize(blksz+delta); - if (getRandomBlock(randBlock) < 0) { - sha.reset(); - decrypted.fill(0); - sf.abort(); - return -3; // Fatal error: can't get random - } - - for (int i = 0; i < blksz; i++) { - wholeFile[i] = randBlock[i]; - } - - for (int i = 0; i < 4; i++) { - wholeFile[(int)(i+blksz)] = (decrypted.size() >> 8*(3-i))&0xff; - } - - for (unsigned int i = 0; i < decrypted.size(); i++) { - wholeFile[(int)(i+blksz+4)] = decrypted[i]; - } - - for (int i = 0; i < delta; i++) { - wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)]; - } - - const char *hash = (const char *)sha.hash(); - for (int i = 0; i < 20; i++) { - wholeFile[(int)(newsize - 20 + i)] = hash[i]; - } - - sha.reset(); - decrypted.fill(0); - - // hash the passphrase - TQByteArray passhash; - password2hash(password, passhash); - - // encrypt the data - if (!bf.setKey(passhash.data(), passhash.size() * 8)) { - passhash.fill(0); - wholeFile.fill(0); - sf.abort(); - return -2; - } - - int rc = bf.encrypt(wholeFile.data(), wholeFile.size()); - if (rc < 0) { - passhash.fill(0); - wholeFile.fill(0); - sf.abort(); - return -2; // encrypt error - } - - passhash.fill(0); // passhash is UNUSABLE NOW - - // write the file - qf->writeBlock(wholeFile, wholeFile.size()); - if (!sf.close()) { - wholeFile.fill(0); - sf.abort(); - return -4; // write error - } - - wholeFile.fill(0); - -return 0; -} - - -int Backend::close(const TQByteArray& password) { - int rc = sync(password); - _open = false; - if (rc != 0) { - return rc; - } - return close(); -} - - -const TQString& Backend::walletName() const { - return _name; -} - - -bool Backend::isOpen() const { - return _open; -} - - -TQStringList Backend::folderList() const { - return _entries.keys(); -} - - -TQStringList Backend::entryList() const { - return _entries[_folder].keys(); -} - - -Entry *Backend::readEntry(const TQString& key) { -Entry *rc = 0L; - - if (_open && hasEntry(key)) { - rc = _entries[_folder][key]; - } - -return rc; -} - - -TQPtrList Backend::readEntryList(const TQString& key) { - TQPtrList rc; - - if (!_open) { - return rc; - } - - TQRegExp re(key, true, true); - - const EntryMap& map = _entries[_folder]; - for (EntryMap::ConstIterator i = map.begin(); i != map.end(); ++i) { - if (re.exactMatch(i.key())) { - rc.append(i.data()); - } - } - return rc; -} - - -bool Backend::createFolder(const TQString& f) { - if (_entries.contains(f)) { - return false; - } - - _entries.insert(f, EntryMap()); - - KMD5 folderMd5; - folderMd5.update(f.utf8()); - _hashes.insert(MD5Digest(folderMd5.rawDigest()), TQValueList()); - -return true; -} - - -int Backend::renameEntry(const TQString& oldName, const TQString& newName) { -EntryMap& emap = _entries[_folder]; -EntryMap::Iterator oi = emap.find(oldName); -EntryMap::Iterator ni = emap.find(newName); - - if (oi != emap.end() && ni == emap.end()) { - Entry *e = oi.data(); - emap.remove(oi); - emap[newName] = e; - - KMD5 folderMd5; - folderMd5.update(_folder.utf8()); - - HashMap::iterator i = _hashes.find(MD5Digest(folderMd5.rawDigest())); - if (i != _hashes.end()) { - KMD5 oldMd5, newMd5; - oldMd5.update(oldName.utf8()); - newMd5.update(newName.utf8()); - i.data().remove(MD5Digest(oldMd5.rawDigest())); - i.data().append(MD5Digest(newMd5.rawDigest())); - } - return 0; - } - -return -1; -} - - -void Backend::writeEntry(Entry *e) { - if (!_open) - return; - - if (!hasEntry(e->key())) { - _entries[_folder][e->key()] = new Entry; - } - _entries[_folder][e->key()]->copy(e); - - KMD5 folderMd5; - folderMd5.update(_folder.utf8()); - - HashMap::iterator i = _hashes.find(MD5Digest(folderMd5.rawDigest())); - if (i != _hashes.end()) { - KMD5 md5; - md5.update(e->key().utf8()); - i.data().append(MD5Digest(md5.rawDigest())); - } -} - - -bool Backend::hasEntry(const TQString& key) const { - return _entries.contains(_folder) && _entries[_folder].contains(key); -} - - -bool Backend::removeEntry(const TQString& key) { - if (!_open) { - return false; - } - - FolderMap::Iterator fi = _entries.find(_folder); - EntryMap::Iterator ei = fi.data().find(key); - - if (fi != _entries.end() && ei != fi.data().end()) { - delete ei.data(); - fi.data().remove(ei); - KMD5 folderMd5; - folderMd5.update(_folder.utf8()); - - HashMap::iterator i = _hashes.find(MD5Digest(folderMd5.rawDigest())); - if (i != _hashes.end()) { - KMD5 md5; - md5.update(key.utf8()); - i.data().remove(MD5Digest(md5.rawDigest())); - } - return true; - } - -return false; -} - - -bool Backend::removeFolder(const TQString& f) { - if (!_open) { - return false; - } - - FolderMap::Iterator fi = _entries.find(f); - - if (fi != _entries.end()) { - if (_folder == f) { - _folder = TQString::null; - } - - for (EntryMap::Iterator ei = fi.data().begin(); ei != fi.data().end(); ++ei) { - delete ei.data(); - } - - _entries.remove(fi); - - KMD5 folderMd5; - folderMd5.update(f.utf8()); - _hashes.erase(MD5Digest(folderMd5.rawDigest())); - return true; - } - -return false; -} - - -bool Backend::folderDoesNotExist(const TQString& folder) const { - KMD5 md5; - md5.update(folder.utf8()); - return !_hashes.contains(MD5Digest(md5.rawDigest())); -} - - -bool Backend::entryDoesNotExist(const TQString& folder, const TQString& entry) const { - KMD5 md5; - md5.update(folder.utf8()); - HashMap::const_iterator i = _hashes.find(MD5Digest(md5.rawDigest())); - if (i != _hashes.end()) { - md5.reset(); - md5.update(entry.utf8()); - return !i.data().contains(MD5Digest(md5.rawDigest())); - } - return true; -} - - diff --git a/tdewallet/backend/tdewalletbackend.cpp b/tdewallet/backend/tdewalletbackend.cpp new file mode 100644 index 000000000..83e37a49a --- /dev/null +++ b/tdewallet/backend/tdewalletbackend.cpp @@ -0,0 +1,838 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001-2004 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "tdewalletbackend.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "blowfish.h" +#include "sha1.h" +#include "cbc.h" + +#include + +#define TDEWALLET_VERSION_MAJOR 0 +#define TDEWALLET_VERSION_MINOR 0 + +#define TDEWALLET_CIPHER_BLOWFISH_CBC 0 +#define TDEWALLET_CIPHER_3DES_CBC 1 // unsupported + +#define TDEWALLET_HASH_SHA1 0 +#define TDEWALLET_HASH_MD5 1 // unsupported + + +using namespace TDEWallet; + +#define KWMAGIC "KWALLET\n\r\0\r\n" +#define KWMAGIC_LEN 12 + +static void initTDEWalletDir() +{ + TDEGlobal::dirs()->addResourceType("tdewallet", "share/apps/tdewallet"); +} + +Backend::Backend(const TQString& name, bool isPath) : _name(name), _ref(0) { + initTDEWalletDir(); + if (isPath) { + _path = name; + } else { + _path = TDEGlobal::dirs()->saveLocation("tdewallet") + "/" + _name + ".kwl"; + } + + _open = false; +} + + +Backend::~Backend() { + if (_open) { + close(); + } +} + + +int Backend::close() { + for (FolderMap::ConstIterator i = _entries.begin(); i != _entries.end(); ++i) { + for (EntryMap::ConstIterator j = i.data().begin(); j != i.data().end(); ++j) { + delete j.data(); + } + } + _entries.clear(); + +return 0; +} + + +static int getRandomBlock(TQByteArray& randBlock) { + // First try /dev/urandom + if (TQFile::exists("/dev/urandom")) { + TQFile devrand("/dev/urandom"); + if (devrand.open(IO_ReadOnly)) { + unsigned int rc = devrand.readBlock(randBlock.data(), randBlock.size()); + + if (rc != randBlock.size()) { + return -3; // not enough data read + } + + return 0; + } + } + + // If that failed, try /dev/random + // FIXME: open in noblocking mode! + if (TQFile::exists("/dev/random")) { + TQFile devrand("/dev/random"); + if (devrand.open(IO_ReadOnly)) { + unsigned int rc = 0; + unsigned int cnt = 0; + + do { + int rc2 = devrand.readBlock(randBlock.data() + rc, randBlock.size()); + + if (rc2 < 0) { + return -3; // read error + } + + rc += rc2; + cnt++; + if (cnt > randBlock.size()) { + return -4; // reading forever?! + } + } while(rc < randBlock.size()); + + return 0; + } + } + + // EGD method + char *randFilename; + if ((randFilename = getenv("RANDFILE"))) { + if (TQFile::exists(randFilename)) { + TQFile devrand(randFilename); + if (devrand.open(IO_ReadOnly)) { + unsigned int rc = devrand.readBlock(randBlock.data(), randBlock.size()); + if (rc != randBlock.size()) { + return -3; // not enough data read + } + return 0; + } + } + } + + // Couldn't get any random data!! + + return -1; +} + + +// this should be SHA-512 for release probably +static int password2hash(const TQByteArray& password, TQByteArray& hash) { + SHA1 sha; + int shasz = sha.size() / 8; + + assert(shasz >= 20); + + TQByteArray block1(shasz); + + sha.process(password.data(), TQMIN(password.size(), 16)); + + // To make brute force take longer + for (int i = 0; i < 2000; i++) { + memcpy(block1.data(), sha.hash(), shasz); + sha.reset(); + sha.process(block1.data(), shasz); + } + + sha.reset(); + + if (password.size() > 16) { + sha.process(password.data() + 16, TQMIN(password.size() - 16, 16)); + TQByteArray block2(shasz); + // To make brute force take longer + for (int i = 0; i < 2000; i++) { + memcpy(block2.data(), sha.hash(), shasz); + sha.reset(); + sha.process(block2.data(), shasz); + } + + sha.reset(); + + if (password.size() > 32) { + sha.process(password.data() + 32, TQMIN(password.size() - 32, 16)); + + TQByteArray block3(shasz); + // To make brute force take longer + for (int i = 0; i < 2000; i++) { + memcpy(block3.data(), sha.hash(), shasz); + sha.reset(); + sha.process(block3.data(), shasz); + } + + sha.reset(); + + if (password.size() > 48) { + sha.process(password.data() + 48, password.size() - 48); + + TQByteArray block4(shasz); + // To make brute force take longer + for (int i = 0; i < 2000; i++) { + memcpy(block4.data(), sha.hash(), shasz); + sha.reset(); + sha.process(block4.data(), shasz); + } + + sha.reset(); + // split 14/14/14/14 + hash.resize(56); + memcpy(hash.data(), block1.data(), 14); + memcpy(hash.data() + 14, block2.data(), 14); + memcpy(hash.data() + 28, block3.data(), 14); + memcpy(hash.data() + 42, block4.data(), 14); + block4.fill(0); + } else { + // split 20/20/16 + hash.resize(56); + memcpy(hash.data(), block1.data(), 20); + memcpy(hash.data() + 20, block2.data(), 20); + memcpy(hash.data() + 40, block3.data(), 16); + } + block3.fill(0); + } else { + // split 20/20 + hash.resize(40); + memcpy(hash.data(), block1.data(), 20); + memcpy(hash.data() + 20, block2.data(), 20); + } + block2.fill(0); + } else { + // entirely block1 + hash.resize(20); + memcpy(hash.data(), block1.data(), 20); + } + + block1.fill(0); + + return 0; +} + + +bool Backend::exists(const TQString& wallet) { + initTDEWalletDir(); + TQString path = TDEGlobal::dirs()->saveLocation("tdewallet") + "/" + wallet + ".kwl"; + // Note: 60 bytes is presently the minimum size of a wallet file. + // Anything smaller is junk. +return TQFile::exists(path) && TQFileInfo(path).size() >= 60; +} + + +TQString Backend::openRCToString(int rc) { + switch (rc) { + case -255: + return i18n("Already open."); + case -2: + return i18n("Error opening file."); + case -3: + return i18n("Not a wallet file."); + case -4: + return i18n("Unsupported file format revision."); + case -42: + return i18n("Unknown encryption scheme."); + case -43: + return i18n("Corrupt file?"); + case -8: + return i18n("Error validating wallet integrity. Possibly corrupted."); + case -5: + case -7: + case -9: + return i18n("Read error - possibly incorrect password."); + case -6: + return i18n("Decryption error."); + default: + return TQString::null; + } +} + + +int Backend::open(const TQByteArray& password) { + + if (_open) { + return -255; // already open + } + + TQByteArray passhash; + + // No wallet existed. Let's create it. + // Note: 60 bytes is presently the minimum size of a wallet file. + // Anything smaller is junk and should be deleted. + if (!TQFile::exists(_path) || TQFileInfo(_path).size() < 60) { + TQFile newfile(_path); + if (!newfile.open(IO_ReadWrite)) { + return -2; // error opening file + } + newfile.close(); + _open = true; + sync(password); + return 1; // new file opened, but OK + } + + TQFile db(_path); + + if (!db.open(IO_ReadOnly)) { + return -2; // error opening file + } + + char magicBuf[KWMAGIC_LEN]; + db.readBlock(magicBuf, KWMAGIC_LEN); + if (memcmp(magicBuf, KWMAGIC, KWMAGIC_LEN) != 0) { + return -3; // bad magic + } + + db.readBlock(magicBuf, 4); + + // First byte is major version, second byte is minor version + if (magicBuf[0] != TDEWALLET_VERSION_MAJOR) { + return -4; // unknown version + } + + if (magicBuf[1] != TDEWALLET_VERSION_MINOR) { + return -4; // unknown version + } + + if (magicBuf[2] != TDEWALLET_CIPHER_BLOWFISH_CBC) { + return -42; // unknown cipher + } + + if (magicBuf[3] != TDEWALLET_HASH_SHA1) { + return -42; // unknown hash + } + + _hashes.clear(); + // Read in the hashes + TQDataStream hds(&db); + TQ_UINT32 n; + hds >> n; + if (n > 0xffff) { // sanity check + return -43; + } + + for (size_t i = 0; i < n; ++i) { + KMD5::Digest d, d2; // judgment day + MD5Digest ba; + TQMap >::iterator it; + TQ_UINT32 fsz; + if (hds.atEnd()) return -43; + hds.readRawBytes(reinterpret_cast(d), 16); + hds >> fsz; + ba.duplicate(reinterpret_cast(d), 16); + it = _hashes.insert(ba, TQValueList()); + for (size_t j = 0; j < fsz; ++j) { + hds.readRawBytes(reinterpret_cast(d2), 16); + ba.duplicate(reinterpret_cast(d2), 16); + (*it).append(ba); + } + } + + // Read in the rest of the file. + TQByteArray encrypted = db.readAll(); + assert(encrypted.size() < db.size()); + + BlowFish _bf; + CipherBlockChain bf(&_bf); + int blksz = bf.blockSize(); + if ((encrypted.size() % blksz) != 0) { + return -5; // invalid file structure + } + + // Decrypt the encrypted data + passhash.resize(bf.keyLen()/8); + password2hash(password, passhash); + + bf.setKey((void *)passhash.data(), passhash.size()*8); + + if (!encrypted.data()) { + passhash.fill(0); + encrypted.fill(0); + return -7; // file structure error + } + + int rc = bf.decrypt(encrypted.data(), encrypted.size()); + if (rc < 0) { + passhash.fill(0); + encrypted.fill(0); + return -6; // decrypt error + } + + passhash.fill(0); // passhash is UNUSABLE NOW + + const char *t = encrypted.data(); + + // strip the leading data + t += blksz; // one block of random data + + // strip the file size off + long fsize = 0; + + fsize |= (long(*t) << 24) & 0xff000000; + t++; + fsize |= (long(*t) << 16) & 0x00ff0000; + t++; + fsize |= (long(*t) << 8) & 0x0000ff00; + t++; + fsize |= long(*t) & 0x000000ff; + t++; + + if (fsize < 0 || fsize > long(encrypted.size()) - blksz - 4) { + //kdDebug() << "fsize: " << fsize << " encrypted.size(): " << encrypted.size() << " blksz: " << blksz << endl; + encrypted.fill(0); + return -9; // file structure error. + } + + // compute the hash ourself + SHA1 sha; + sha.process(t, fsize); + const char *testhash = (const char *)sha.hash(); + + // compare hashes + int sz = encrypted.size(); + for (int i = 0; i < 20; i++) { + if (testhash[i] != static_cast(encrypted.at(sz - 20 + i))) { + encrypted.fill(0); + sha.reset(); + return -8; // hash error. + } + } + + sha.reset(); + + // chop off the leading blksz+4 bytes + TQByteArray tmpenc; + tmpenc.duplicate(encrypted.data()+blksz+4, fsize); + encrypted.fill(0); + encrypted.duplicate(tmpenc.data(), tmpenc.size()); + tmpenc.fill(0); + + // Load the data structures up + TQDataStream eStream(encrypted, IO_ReadOnly); + + while (!eStream.atEnd()) { + TQString folder; + TQ_UINT32 n; + + eStream >> folder; + eStream >> n; + + // Force initialisation + _entries[folder].clear(); + + for (size_t i = 0; i < n; i++) { + TQString key; + TDEWallet::Wallet::EntryType et = TDEWallet::Wallet::Unknown; + Entry *e = new Entry; + eStream >> key; + TQ_INT32 x = 0; // necessary to read properly + eStream >> x; + et = static_cast(x); + + switch (et) { + case TDEWallet::Wallet::Password: + case TDEWallet::Wallet::Stream: + case TDEWallet::Wallet::Map: + break; + default: // Unknown entry + delete e; + continue; + } + + TQByteArray a; + eStream >> a; + e->setValue(a); + e->setType(et); + e->setKey(key); + _entries[folder][key] = e; + } + } + + _open = true; + return 0; +} + + +int Backend::sync(const TQByteArray& password) { + if (!_open) { + return -255; // not open yet + } + + KSaveFile sf(_path, 0600); + TQFile *qf = sf.file(); + + if (!qf) { + sf.abort(); + return -1; // error opening file + } + + qf->writeBlock(KWMAGIC, KWMAGIC_LEN); + + // Write the version number + TQByteArray version(4); + version[0] = TDEWALLET_VERSION_MAJOR; + version[1] = TDEWALLET_VERSION_MINOR; + version[2] = TDEWALLET_CIPHER_BLOWFISH_CBC; + version[3] = TDEWALLET_HASH_SHA1; + qf->writeBlock(version, 4); + + // Holds the hashes we write out + TQByteArray hashes; + TQDataStream hashStream(hashes, IO_WriteOnly); + KMD5 md5; + hashStream << static_cast(_entries.count()); + + // Holds decrypted data prior to encryption + TQByteArray decrypted; + + // FIXME: we should estimate the amount of data we will write in each + // buffer and resize them approximately in order to avoid extra + // resizes. + + // populate decrypted + TQDataStream dStream(decrypted, IO_WriteOnly); + for (FolderMap::ConstIterator i = _entries.begin(); i != _entries.end(); ++i) { + dStream << i.key(); + dStream << static_cast(i.data().count()); + + md5.reset(); + md5.update(i.key().utf8()); + hashStream.writeRawBytes(reinterpret_cast(&(md5.rawDigest()[0])), 16); + hashStream << static_cast(i.data().count()); + + for (EntryMap::ConstIterator j = i.data().begin(); j != i.data().end(); ++j) { + dStream << j.key(); + dStream << static_cast(j.data()->type()); + dStream << j.data()->value(); + + md5.reset(); + md5.update(j.key().utf8()); + hashStream.writeRawBytes(reinterpret_cast(&(md5.rawDigest()[0])), 16); + } + } + + qf->writeBlock(hashes, hashes.size()); + + // calculate the hash of the file + SHA1 sha; + BlowFish _bf; + CipherBlockChain bf(&_bf); + + sha.process(decrypted.data(), decrypted.size()); + + // prepend and append the random data + TQByteArray wholeFile; + long blksz = bf.blockSize(); + long newsize = decrypted.size() + + blksz + // encrypted block + 4 + // file size + 20; // size of the SHA hash + + int delta = (blksz - (newsize % blksz)); + newsize += delta; + wholeFile.resize(newsize); + + TQByteArray randBlock; + randBlock.resize(blksz+delta); + if (getRandomBlock(randBlock) < 0) { + sha.reset(); + decrypted.fill(0); + sf.abort(); + return -3; // Fatal error: can't get random + } + + for (int i = 0; i < blksz; i++) { + wholeFile[i] = randBlock[i]; + } + + for (int i = 0; i < 4; i++) { + wholeFile[(int)(i+blksz)] = (decrypted.size() >> 8*(3-i))&0xff; + } + + for (unsigned int i = 0; i < decrypted.size(); i++) { + wholeFile[(int)(i+blksz+4)] = decrypted[i]; + } + + for (int i = 0; i < delta; i++) { + wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)]; + } + + const char *hash = (const char *)sha.hash(); + for (int i = 0; i < 20; i++) { + wholeFile[(int)(newsize - 20 + i)] = hash[i]; + } + + sha.reset(); + decrypted.fill(0); + + // hash the passphrase + TQByteArray passhash; + password2hash(password, passhash); + + // encrypt the data + if (!bf.setKey(passhash.data(), passhash.size() * 8)) { + passhash.fill(0); + wholeFile.fill(0); + sf.abort(); + return -2; + } + + int rc = bf.encrypt(wholeFile.data(), wholeFile.size()); + if (rc < 0) { + passhash.fill(0); + wholeFile.fill(0); + sf.abort(); + return -2; // encrypt error + } + + passhash.fill(0); // passhash is UNUSABLE NOW + + // write the file + qf->writeBlock(wholeFile, wholeFile.size()); + if (!sf.close()) { + wholeFile.fill(0); + sf.abort(); + return -4; // write error + } + + wholeFile.fill(0); + +return 0; +} + + +int Backend::close(const TQByteArray& password) { + int rc = sync(password); + _open = false; + if (rc != 0) { + return rc; + } + return close(); +} + + +const TQString& Backend::walletName() const { + return _name; +} + + +bool Backend::isOpen() const { + return _open; +} + + +TQStringList Backend::folderList() const { + return _entries.keys(); +} + + +TQStringList Backend::entryList() const { + return _entries[_folder].keys(); +} + + +Entry *Backend::readEntry(const TQString& key) { +Entry *rc = 0L; + + if (_open && hasEntry(key)) { + rc = _entries[_folder][key]; + } + +return rc; +} + + +TQPtrList Backend::readEntryList(const TQString& key) { + TQPtrList rc; + + if (!_open) { + return rc; + } + + TQRegExp re(key, true, true); + + const EntryMap& map = _entries[_folder]; + for (EntryMap::ConstIterator i = map.begin(); i != map.end(); ++i) { + if (re.exactMatch(i.key())) { + rc.append(i.data()); + } + } + return rc; +} + + +bool Backend::createFolder(const TQString& f) { + if (_entries.contains(f)) { + return false; + } + + _entries.insert(f, EntryMap()); + + KMD5 folderMd5; + folderMd5.update(f.utf8()); + _hashes.insert(MD5Digest(folderMd5.rawDigest()), TQValueList()); + +return true; +} + + +int Backend::renameEntry(const TQString& oldName, const TQString& newName) { +EntryMap& emap = _entries[_folder]; +EntryMap::Iterator oi = emap.find(oldName); +EntryMap::Iterator ni = emap.find(newName); + + if (oi != emap.end() && ni == emap.end()) { + Entry *e = oi.data(); + emap.remove(oi); + emap[newName] = e; + + KMD5 folderMd5; + folderMd5.update(_folder.utf8()); + + HashMap::iterator i = _hashes.find(MD5Digest(folderMd5.rawDigest())); + if (i != _hashes.end()) { + KMD5 oldMd5, newMd5; + oldMd5.update(oldName.utf8()); + newMd5.update(newName.utf8()); + i.data().remove(MD5Digest(oldMd5.rawDigest())); + i.data().append(MD5Digest(newMd5.rawDigest())); + } + return 0; + } + +return -1; +} + + +void Backend::writeEntry(Entry *e) { + if (!_open) + return; + + if (!hasEntry(e->key())) { + _entries[_folder][e->key()] = new Entry; + } + _entries[_folder][e->key()]->copy(e); + + KMD5 folderMd5; + folderMd5.update(_folder.utf8()); + + HashMap::iterator i = _hashes.find(MD5Digest(folderMd5.rawDigest())); + if (i != _hashes.end()) { + KMD5 md5; + md5.update(e->key().utf8()); + i.data().append(MD5Digest(md5.rawDigest())); + } +} + + +bool Backend::hasEntry(const TQString& key) const { + return _entries.contains(_folder) && _entries[_folder].contains(key); +} + + +bool Backend::removeEntry(const TQString& key) { + if (!_open) { + return false; + } + + FolderMap::Iterator fi = _entries.find(_folder); + EntryMap::Iterator ei = fi.data().find(key); + + if (fi != _entries.end() && ei != fi.data().end()) { + delete ei.data(); + fi.data().remove(ei); + KMD5 folderMd5; + folderMd5.update(_folder.utf8()); + + HashMap::iterator i = _hashes.find(MD5Digest(folderMd5.rawDigest())); + if (i != _hashes.end()) { + KMD5 md5; + md5.update(key.utf8()); + i.data().remove(MD5Digest(md5.rawDigest())); + } + return true; + } + +return false; +} + + +bool Backend::removeFolder(const TQString& f) { + if (!_open) { + return false; + } + + FolderMap::Iterator fi = _entries.find(f); + + if (fi != _entries.end()) { + if (_folder == f) { + _folder = TQString::null; + } + + for (EntryMap::Iterator ei = fi.data().begin(); ei != fi.data().end(); ++ei) { + delete ei.data(); + } + + _entries.remove(fi); + + KMD5 folderMd5; + folderMd5.update(f.utf8()); + _hashes.erase(MD5Digest(folderMd5.rawDigest())); + return true; + } + +return false; +} + + +bool Backend::folderDoesNotExist(const TQString& folder) const { + KMD5 md5; + md5.update(folder.utf8()); + return !_hashes.contains(MD5Digest(md5.rawDigest())); +} + + +bool Backend::entryDoesNotExist(const TQString& folder, const TQString& entry) const { + KMD5 md5; + md5.update(folder.utf8()); + HashMap::const_iterator i = _hashes.find(MD5Digest(md5.rawDigest())); + if (i != _hashes.end()) { + md5.reset(); + md5.update(entry.utf8()); + return !i.data().contains(MD5Digest(md5.rawDigest())); + } + return true; +} + + diff --git a/tdewallet/backend/tdewalletentry.cc b/tdewallet/backend/tdewalletentry.cc deleted file mode 100644 index d6b3aa84e..000000000 --- a/tdewallet/backend/tdewalletentry.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2001-2003 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "tdewalletentry.h" - - -using namespace TDEWallet; - - -Entry::Entry() { -} - -Entry::~Entry() { - _value.fill(0); -} - -const TQString& Entry::key() const { - return _key; -} - - -const TQByteArray& Entry::value() const { - return _value; -} - - -TQString Entry::password() const { -TQString x; - TQDataStream qds(_value, IO_ReadOnly); - qds >> x; - return x; -} - - -void Entry::setValue(const TQByteArray& val) { - // do a direct copy from one into the other without - // temporary variables - _value.fill(0); - _value.duplicate(val); -} - - -void Entry::setValue(const TQString& val) { - _value.fill(0); - TQDataStream qds(_value, IO_WriteOnly); - qds << val; -} - - -void Entry::setKey(const TQString& key) { - _key = key; -} - - -Wallet::EntryType Entry::type() const { - return _type; -} - - -void Entry::setType(Wallet::EntryType type) { - _type = type; -} - - -void Entry::copy(const Entry* x) { - _type = x->_type; - _key = x->_key; - _value.fill(0); - _value.duplicate(x->_value); -} - - diff --git a/tdewallet/backend/tdewalletentry.cpp b/tdewallet/backend/tdewalletentry.cpp new file mode 100644 index 000000000..d6b3aa84e --- /dev/null +++ b/tdewallet/backend/tdewalletentry.cpp @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001-2003 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "tdewalletentry.h" + + +using namespace TDEWallet; + + +Entry::Entry() { +} + +Entry::~Entry() { + _value.fill(0); +} + +const TQString& Entry::key() const { + return _key; +} + + +const TQByteArray& Entry::value() const { + return _value; +} + + +TQString Entry::password() const { +TQString x; + TQDataStream qds(_value, IO_ReadOnly); + qds >> x; + return x; +} + + +void Entry::setValue(const TQByteArray& val) { + // do a direct copy from one into the other without + // temporary variables + _value.fill(0); + _value.duplicate(val); +} + + +void Entry::setValue(const TQString& val) { + _value.fill(0); + TQDataStream qds(_value, IO_WriteOnly); + qds << val; +} + + +void Entry::setKey(const TQString& key) { + _key = key; +} + + +Wallet::EntryType Entry::type() const { + return _type; +} + + +void Entry::setType(Wallet::EntryType type) { + _type = type; +} + + +void Entry::copy(const Entry* x) { + _type = x->_type; + _key = x->_key; + _value.fill(0); + _value.duplicate(x->_value); +} + + diff --git a/tdewallet/backend/tests/CMakeLists.txt b/tdewallet/backend/tests/CMakeLists.txt index abc703a7c..129377791 100644 --- a/tdewallet/backend/tests/CMakeLists.txt +++ b/tdewallet/backend/tests/CMakeLists.txt @@ -31,8 +31,8 @@ add_test( NAME "tdewallet/backed/backendtest" COMMAND sh -x "${CMAKE_CURRENT_SOURCE_DIR}/backendtest.sh" ) set_tests_properties( "tdewallet/backed/backendtest" PROPERTIES TIMEOUT 30) tde_add_check_executable( testbf AUTOMOC - SOURCES testbf.cpp ../blockcipher.cc ../blowfish.cc + SOURCES testbf.cpp ../blockcipher.cpp ../blowfish.cpp LINK tdewalletbackend-shared tdewalletclient-shared TEST ) tde_add_check_executable( testsha AUTOMOC - SOURCES testsha.cpp ../sha1.cc + SOURCES testsha.cpp ../sha1.cpp LINK tdewalletbackend-shared tdewalletclient-shared TEST ) diff --git a/tdewallet/client/CMakeLists.txt b/tdewallet/client/CMakeLists.txt index ac56830e8..87c77132b 100644 --- a/tdewallet/client/CMakeLists.txt +++ b/tdewallet/client/CMakeLists.txt @@ -34,7 +34,7 @@ install( FILES set( target tdewalletclient ) set( ${target}_SRCS - tdewallet.skel tdewallet.cc + tdewallet.skel tdewallet.cpp ) tde_add_library( ${target} SHARED AUTOMOC diff --git a/tdewallet/client/Makefile.am b/tdewallet/client/Makefile.am index 4fe262f76..51fdd4161 100644 --- a/tdewallet/client/Makefile.am +++ b/tdewallet/client/Makefile.am @@ -6,7 +6,7 @@ lib_LTLIBRARIES = libtdewalletclient.la libtdewalletclient_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) -version-info 1:1 -no-undefined libtdewalletclient_la_LIBADD = $(LIB_TDECORE) $(LIB_TQT) $(top_builddir)/dcop/libDCOP.la libtdewalletclient_la_SOURCES = tdewallet.skel \ - tdewallet.cc + tdewallet.cpp libtdewalletclient_la_METASOURCES = AUTO diff --git a/tdewallet/client/tdewallet.cc b/tdewallet/client/tdewallet.cc deleted file mode 100644 index c730f10d4..000000000 --- a/tdewallet/client/tdewallet.cc +++ /dev/null @@ -1,713 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2002-2004 George Staikos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "tdewallettypes.h" -#include "tdewallet.h" -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace TDEWallet; - - -const TQString Wallet::LocalWallet() { - TDEConfig cfg("tdewalletrc", true); - cfg.setGroup("Wallet"); - if (!cfg.readBoolEntry("Use One Wallet", true)) { - TQString tmp = cfg.readEntry("Local Wallet", "localwallet"); - if (tmp.isEmpty()) { - return "localwallet"; - } - return tmp; - } - - TQString tmp = cfg.readEntry("Default Wallet", "kdewallet"); - if (tmp.isEmpty()) { - return "kdewallet"; - } - return tmp; -} - -const TQString Wallet::NetworkWallet() { - TDEConfig cfg("tdewalletrc", true); - cfg.setGroup("Wallet"); - - TQString tmp = cfg.readEntry("Default Wallet", "kdewallet"); - if (tmp.isEmpty()) { - return "kdewallet"; - } - return tmp; -} - -const TQString Wallet::PasswordFolder() { - return "Passwords"; -} - -const TQString Wallet::FormDataFolder() { - return "Form Data"; -} - - - -Wallet::Wallet(int handle, const TQString& name) -: TQObject(0L), DCOPObject(), d(0L), _name(name), _handle(handle) { - - _dcopRef = new DCOPRef("kded", "tdewalletd"); - - _dcopRef->dcopClient()->setNotifications(true); - connect(_dcopRef->dcopClient(), - TQT_SIGNAL(applicationRemoved(const TQCString&)), - this, - TQT_SLOT(slotAppUnregistered(const TQCString&))); - - connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "walletClosed(int)", "slotWalletClosed(int)", false); - connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "folderListUpdated(TQString)", "slotFolderListUpdated(TQString)", false); - connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "folderUpdated(TQString, TQString)", "slotFolderUpdated(TQString, TQString)", false); - connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "applicationDisconnected(TQString, TQCString)", "slotApplicationDisconnected(TQString, TQCString)", false); - - // Verify that the wallet is still open - if (_handle != -1) { - DCOPReply r = _dcopRef->call("isOpen", _handle); - if (r.isValid()) { - bool rc = false; - r.get(rc); - if (!rc) { - _handle = -1; - _name = TQString::null; - } - } - } -} - - -Wallet::~Wallet() { - if (_handle != -1) { - _dcopRef->call("close", _handle, false); - _handle = -1; - _folder = TQString::null; - _name = TQString::null; - } - - delete _dcopRef; - _dcopRef = 0L; -} - - -TQStringList Wallet::walletList() { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("wallets"); - TQStringList rc; - if (r.isValid()) { - r.get(rc); - } - return rc; -} - - -void Wallet::changePassword(const TQString& name, WId w) { - DCOPRef("kded", "tdewalletd").send("changePassword", name, uint(w)); -} - - -bool Wallet::isEnabled() { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("isEnabled"); - bool rc = false; - if (r.isValid()) { - r.get(rc); - } - return rc; -} - - -bool Wallet::isOpen(const TQString& name) { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("isOpen", name); - bool rc = false; - if (r.isValid()) { - r.get(rc); - } - return rc; -} - - -int Wallet::closeWallet(const TQString& name, bool force) { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("close", name, force); - int rc = -1; - if (r.isValid()) { - r.get(rc); - } - return rc; -} - - -int Wallet::deleteWallet(const TQString& name) { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("deleteWallet", name); - int rc = -1; - if (r.isValid()) { - r.get(rc); - } - return rc; -} - - -Wallet *Wallet::openWallet(const TQString& name, WId w, OpenType ot) { - if (ot == Asynchronous) { - Wallet *wallet = new Wallet(-1, name); - DCOPRef("kded", "tdewalletd").send("openAsynchronous", name, wallet->objId(), uint(w)); - return wallet; - } - - // avoid deadlock if the app has some popup open (#65978/#71048) - while( TQWidget* widget = TQT_TQWIDGET(tqApp->activePopupWidget())) - widget->close(); - - bool isPath = ot == Path; - DCOPReply r; - - if (isPath) { - r = DCOPRef("kded", "tdewalletd").call("openPath", name, uint(w)); - } else { - r = DCOPRef("kded", "tdewalletd").call("open", name, uint(w)); - } - - if (r.isValid()) { - int drc = -1; - r.get(drc); - if (drc != -1) { - return new Wallet(drc, name); - } - } - - return 0; -} - - -bool Wallet::disconnectApplication(const TQString& wallet, const TQCString& app) { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("disconnectApplication", wallet, app); - bool rc = false; - if (r.isValid()) { - r.get(rc); - } - return rc; -} - - -TQStringList Wallet::users(const TQString& name) { - DCOPReply r = DCOPRef("kded", "tdewalletd").call("users", name); - TQStringList drc; - if (r.isValid()) { - r.get(drc); - } - return drc; -} - - -int Wallet::sync() { - if (_handle == -1) { - return -1; - } - - _dcopRef->call("sync", _handle); - return 0; -} - - -int Wallet::lockWallet() { - if (_handle == -1) { - return -1; - } - - DCOPReply r = _dcopRef->call("close", _handle, true); - _handle = -1; - _folder = TQString::null; - _name = TQString::null; - if (r.isValid()) { - int drc = -1; - r.get(drc); - return drc; - } - return -1; -} - - -const TQString& Wallet::walletName() const { - return _name; -} - - -bool Wallet::isOpen() const { - return _handle != -1; -} - - -void Wallet::requestChangePassword(WId w) { - if (_handle == -1) { - return; - } - - _dcopRef->send("changePassword", _name, uint(w)); -} - - -void Wallet::slotWalletClosed(int handle) { - if (_handle == handle) { - _handle = -1; - _folder = TQString::null; - _name = TQString::null; - emit walletClosed(); - } -} - - -TQStringList Wallet::folderList() { - TQStringList rc; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("folderList", _handle); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -TQStringList Wallet::entryList() { - TQStringList rc; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("entryList", _handle, _folder); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -bool Wallet::hasFolder(const TQString& f) { - bool rc = false; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("hasFolder", _handle, f); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -bool Wallet::createFolder(const TQString& f) { - bool rc = true; - - if (_handle == -1) { - return false; - } - - if (!hasFolder(f)) { - DCOPReply r = _dcopRef->call("createFolder", _handle, f); - if (r.isValid()) { - r.get(rc); - } - } - - return rc; -} - - -bool Wallet::setFolder(const TQString& f) { - bool rc = false; - - if (_handle == -1) { - return rc; - } - - // Don't do this - the folder could have disappeared? -#if 0 - if (f == _folder) { - return true; - } -#endif - - if (hasFolder(f)) { - _folder = f; - rc = true; - } - - return rc; -} - - -bool Wallet::removeFolder(const TQString& f) { - bool rc = false; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("removeFolder", _handle, f); - if (r.isValid()) { - r.get(rc); - } - - if (_folder == f) { - setFolder(TQString::null); - } - - return rc; -} - - -const TQString& Wallet::currentFolder() const { - return _folder; -} - - -int Wallet::readEntry(const TQString& key, TQByteArray& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("readEntry", _handle, _folder, key); - if (r.isValid()) { - r.get(value); - rc = 0; - } - - return rc; -} - - -int Wallet::readEntryList(const TQString& key, TQMap& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("readEntryList", _handle, _folder, key); - if (r.isValid()) { - r.get(value); - rc = 0; - } - - return rc; -} - - -int Wallet::renameEntry(const TQString& oldName, const TQString& newName) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("renameEntry", _handle, _folder, oldName, newName); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -int Wallet::readMap(const TQString& key, TQMap& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("readMap", _handle, _folder, key); - if (r.isValid()) { - TQByteArray v; - r.get(v); - if (!v.isEmpty()) { - TQDataStream ds(v, IO_ReadOnly); - ds >> value; - } - rc = 0; - } - - return rc; -} - - -int Wallet::readMapList(const TQString& key, TQMap >& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("readMapList", _handle, _folder, key); - if (r.isValid()) { - TQMap unparsed; - r.get(unparsed); - for (TQMap::ConstIterator i = unparsed.begin(); i != unparsed.end(); ++i) { - if (!i.data().isEmpty()) { - TQDataStream ds(i.data(), IO_ReadOnly); - TQMap v; - ds >> v; - value.insert(i.key(), v); - } - } - rc = 0; - } - - return rc; -} - - -int Wallet::readPassword(const TQString& key, TQString& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("readPassword", _handle, _folder, key); - if (r.isValid()) { - r.get(value); - rc = 0; - } - - return rc; -} - - -int Wallet::readPasswordList(const TQString& key, TQMap& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("readPasswordList", _handle, _folder, key); - if (r.isValid()) { - r.get(value); - rc = 0; - } - - return rc; -} - - -int Wallet::writeEntry(const TQString& key, const TQByteArray& value, EntryType entryType) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("writeEntry", _handle, _folder, key, value, int(entryType)); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -int Wallet::writeEntry(const TQString& key, const TQByteArray& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("writeEntry", _handle, _folder, key, value); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -int Wallet::writeMap(const TQString& key, const TQMap& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - TQByteArray a; - TQDataStream ds(a, IO_WriteOnly); - ds << value; - DCOPReply r = _dcopRef->call("writeMap", _handle, _folder, key, a); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -int Wallet::writePassword(const TQString& key, const TQString& value) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("writePassword", _handle, _folder, key, value); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -bool Wallet::hasEntry(const TQString& key) { - bool rc = false; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("hasEntry", _handle, _folder, key); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -int Wallet::removeEntry(const TQString& key) { - int rc = -1; - - if (_handle == -1) { - return rc; - } - - DCOPReply r = _dcopRef->call("removeEntry", _handle, _folder, key); - if (r.isValid()) { - r.get(rc); - } - - return rc; -} - - -Wallet::EntryType Wallet::entryType(const TQString& key) { - int rc = 0; - - if (_handle == -1) { - return Wallet::Unknown; - } - - DCOPReply r = _dcopRef->call("entryType", _handle, _folder, key); - if (r.isValid()) { - r.get(rc); - } - - return static_cast(rc); -} - - -void Wallet::slotAppUnregistered(const TQCString& app) { - if (_handle >= 0 && app == "kded") { - slotWalletClosed(_handle); - } -} - - -void Wallet::slotFolderUpdated(const TQString& wallet, const TQString& folder) { - if (_name == wallet) { - emit folderUpdated(folder); - } -} - - -void Wallet::slotFolderListUpdated(const TQString& wallet) { - if (_name == wallet) { - emit folderListUpdated(); - } -} - - -void Wallet::slotApplicationDisconnected(const TQString& wallet, const TQCString& application) { - if (_handle >= 0 - && _name == wallet - && application == _dcopRef->dcopClient()->appId()) { - slotWalletClosed(_handle); - } -} - - -void Wallet::walletOpenResult(int id) { - if (_handle != -1) { - // This is BAD. - return; - } - - if (id > 0) { - _handle = id; - emit walletOpened(true); - } else if (id < 0) { - emit walletOpened(false); - } // id == 0 => wait -} - - -bool Wallet::folderDoesNotExist(const TQString& wallet, const TQString& folder) { -DCOPReply r = DCOPRef("kded", "tdewalletd").call("folderDoesNotExist", wallet, folder); -bool rc = true; - if (r.isValid()) { - r.get(rc); - } -return rc; -} - - -bool Wallet::keyDoesNotExist(const TQString& wallet, const TQString& folder, const TQString& key) { -DCOPReply r = DCOPRef("kded", "tdewalletd").call("keyDoesNotExist", wallet, folder, key); -bool rc = true; - if (r.isValid()) { - r.get(rc); - } -return rc; -} - - -void Wallet::virtual_hook(int, void*) { - //BASE::virtual_hook( id, data ); -} - -#include "tdewallet.moc" diff --git a/tdewallet/client/tdewallet.cpp b/tdewallet/client/tdewallet.cpp new file mode 100644 index 000000000..c730f10d4 --- /dev/null +++ b/tdewallet/client/tdewallet.cpp @@ -0,0 +1,713 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2002-2004 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "tdewallettypes.h" +#include "tdewallet.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace TDEWallet; + + +const TQString Wallet::LocalWallet() { + TDEConfig cfg("tdewalletrc", true); + cfg.setGroup("Wallet"); + if (!cfg.readBoolEntry("Use One Wallet", true)) { + TQString tmp = cfg.readEntry("Local Wallet", "localwallet"); + if (tmp.isEmpty()) { + return "localwallet"; + } + return tmp; + } + + TQString tmp = cfg.readEntry("Default Wallet", "kdewallet"); + if (tmp.isEmpty()) { + return "kdewallet"; + } + return tmp; +} + +const TQString Wallet::NetworkWallet() { + TDEConfig cfg("tdewalletrc", true); + cfg.setGroup("Wallet"); + + TQString tmp = cfg.readEntry("Default Wallet", "kdewallet"); + if (tmp.isEmpty()) { + return "kdewallet"; + } + return tmp; +} + +const TQString Wallet::PasswordFolder() { + return "Passwords"; +} + +const TQString Wallet::FormDataFolder() { + return "Form Data"; +} + + + +Wallet::Wallet(int handle, const TQString& name) +: TQObject(0L), DCOPObject(), d(0L), _name(name), _handle(handle) { + + _dcopRef = new DCOPRef("kded", "tdewalletd"); + + _dcopRef->dcopClient()->setNotifications(true); + connect(_dcopRef->dcopClient(), + TQT_SIGNAL(applicationRemoved(const TQCString&)), + this, + TQT_SLOT(slotAppUnregistered(const TQCString&))); + + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "walletClosed(int)", "slotWalletClosed(int)", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "folderListUpdated(TQString)", "slotFolderListUpdated(TQString)", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "folderUpdated(TQString, TQString)", "slotFolderUpdated(TQString, TQString)", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "applicationDisconnected(TQString, TQCString)", "slotApplicationDisconnected(TQString, TQCString)", false); + + // Verify that the wallet is still open + if (_handle != -1) { + DCOPReply r = _dcopRef->call("isOpen", _handle); + if (r.isValid()) { + bool rc = false; + r.get(rc); + if (!rc) { + _handle = -1; + _name = TQString::null; + } + } + } +} + + +Wallet::~Wallet() { + if (_handle != -1) { + _dcopRef->call("close", _handle, false); + _handle = -1; + _folder = TQString::null; + _name = TQString::null; + } + + delete _dcopRef; + _dcopRef = 0L; +} + + +TQStringList Wallet::walletList() { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("wallets"); + TQStringList rc; + if (r.isValid()) { + r.get(rc); + } + return rc; +} + + +void Wallet::changePassword(const TQString& name, WId w) { + DCOPRef("kded", "tdewalletd").send("changePassword", name, uint(w)); +} + + +bool Wallet::isEnabled() { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("isEnabled"); + bool rc = false; + if (r.isValid()) { + r.get(rc); + } + return rc; +} + + +bool Wallet::isOpen(const TQString& name) { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("isOpen", name); + bool rc = false; + if (r.isValid()) { + r.get(rc); + } + return rc; +} + + +int Wallet::closeWallet(const TQString& name, bool force) { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("close", name, force); + int rc = -1; + if (r.isValid()) { + r.get(rc); + } + return rc; +} + + +int Wallet::deleteWallet(const TQString& name) { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("deleteWallet", name); + int rc = -1; + if (r.isValid()) { + r.get(rc); + } + return rc; +} + + +Wallet *Wallet::openWallet(const TQString& name, WId w, OpenType ot) { + if (ot == Asynchronous) { + Wallet *wallet = new Wallet(-1, name); + DCOPRef("kded", "tdewalletd").send("openAsynchronous", name, wallet->objId(), uint(w)); + return wallet; + } + + // avoid deadlock if the app has some popup open (#65978/#71048) + while( TQWidget* widget = TQT_TQWIDGET(tqApp->activePopupWidget())) + widget->close(); + + bool isPath = ot == Path; + DCOPReply r; + + if (isPath) { + r = DCOPRef("kded", "tdewalletd").call("openPath", name, uint(w)); + } else { + r = DCOPRef("kded", "tdewalletd").call("open", name, uint(w)); + } + + if (r.isValid()) { + int drc = -1; + r.get(drc); + if (drc != -1) { + return new Wallet(drc, name); + } + } + + return 0; +} + + +bool Wallet::disconnectApplication(const TQString& wallet, const TQCString& app) { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("disconnectApplication", wallet, app); + bool rc = false; + if (r.isValid()) { + r.get(rc); + } + return rc; +} + + +TQStringList Wallet::users(const TQString& name) { + DCOPReply r = DCOPRef("kded", "tdewalletd").call("users", name); + TQStringList drc; + if (r.isValid()) { + r.get(drc); + } + return drc; +} + + +int Wallet::sync() { + if (_handle == -1) { + return -1; + } + + _dcopRef->call("sync", _handle); + return 0; +} + + +int Wallet::lockWallet() { + if (_handle == -1) { + return -1; + } + + DCOPReply r = _dcopRef->call("close", _handle, true); + _handle = -1; + _folder = TQString::null; + _name = TQString::null; + if (r.isValid()) { + int drc = -1; + r.get(drc); + return drc; + } + return -1; +} + + +const TQString& Wallet::walletName() const { + return _name; +} + + +bool Wallet::isOpen() const { + return _handle != -1; +} + + +void Wallet::requestChangePassword(WId w) { + if (_handle == -1) { + return; + } + + _dcopRef->send("changePassword", _name, uint(w)); +} + + +void Wallet::slotWalletClosed(int handle) { + if (_handle == handle) { + _handle = -1; + _folder = TQString::null; + _name = TQString::null; + emit walletClosed(); + } +} + + +TQStringList Wallet::folderList() { + TQStringList rc; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("folderList", _handle); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +TQStringList Wallet::entryList() { + TQStringList rc; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("entryList", _handle, _folder); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +bool Wallet::hasFolder(const TQString& f) { + bool rc = false; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("hasFolder", _handle, f); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +bool Wallet::createFolder(const TQString& f) { + bool rc = true; + + if (_handle == -1) { + return false; + } + + if (!hasFolder(f)) { + DCOPReply r = _dcopRef->call("createFolder", _handle, f); + if (r.isValid()) { + r.get(rc); + } + } + + return rc; +} + + +bool Wallet::setFolder(const TQString& f) { + bool rc = false; + + if (_handle == -1) { + return rc; + } + + // Don't do this - the folder could have disappeared? +#if 0 + if (f == _folder) { + return true; + } +#endif + + if (hasFolder(f)) { + _folder = f; + rc = true; + } + + return rc; +} + + +bool Wallet::removeFolder(const TQString& f) { + bool rc = false; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("removeFolder", _handle, f); + if (r.isValid()) { + r.get(rc); + } + + if (_folder == f) { + setFolder(TQString::null); + } + + return rc; +} + + +const TQString& Wallet::currentFolder() const { + return _folder; +} + + +int Wallet::readEntry(const TQString& key, TQByteArray& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("readEntry", _handle, _folder, key); + if (r.isValid()) { + r.get(value); + rc = 0; + } + + return rc; +} + + +int Wallet::readEntryList(const TQString& key, TQMap& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("readEntryList", _handle, _folder, key); + if (r.isValid()) { + r.get(value); + rc = 0; + } + + return rc; +} + + +int Wallet::renameEntry(const TQString& oldName, const TQString& newName) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("renameEntry", _handle, _folder, oldName, newName); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +int Wallet::readMap(const TQString& key, TQMap& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("readMap", _handle, _folder, key); + if (r.isValid()) { + TQByteArray v; + r.get(v); + if (!v.isEmpty()) { + TQDataStream ds(v, IO_ReadOnly); + ds >> value; + } + rc = 0; + } + + return rc; +} + + +int Wallet::readMapList(const TQString& key, TQMap >& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("readMapList", _handle, _folder, key); + if (r.isValid()) { + TQMap unparsed; + r.get(unparsed); + for (TQMap::ConstIterator i = unparsed.begin(); i != unparsed.end(); ++i) { + if (!i.data().isEmpty()) { + TQDataStream ds(i.data(), IO_ReadOnly); + TQMap v; + ds >> v; + value.insert(i.key(), v); + } + } + rc = 0; + } + + return rc; +} + + +int Wallet::readPassword(const TQString& key, TQString& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("readPassword", _handle, _folder, key); + if (r.isValid()) { + r.get(value); + rc = 0; + } + + return rc; +} + + +int Wallet::readPasswordList(const TQString& key, TQMap& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("readPasswordList", _handle, _folder, key); + if (r.isValid()) { + r.get(value); + rc = 0; + } + + return rc; +} + + +int Wallet::writeEntry(const TQString& key, const TQByteArray& value, EntryType entryType) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("writeEntry", _handle, _folder, key, value, int(entryType)); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +int Wallet::writeEntry(const TQString& key, const TQByteArray& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("writeEntry", _handle, _folder, key, value); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +int Wallet::writeMap(const TQString& key, const TQMap& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + TQByteArray a; + TQDataStream ds(a, IO_WriteOnly); + ds << value; + DCOPReply r = _dcopRef->call("writeMap", _handle, _folder, key, a); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +int Wallet::writePassword(const TQString& key, const TQString& value) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("writePassword", _handle, _folder, key, value); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +bool Wallet::hasEntry(const TQString& key) { + bool rc = false; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("hasEntry", _handle, _folder, key); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +int Wallet::removeEntry(const TQString& key) { + int rc = -1; + + if (_handle == -1) { + return rc; + } + + DCOPReply r = _dcopRef->call("removeEntry", _handle, _folder, key); + if (r.isValid()) { + r.get(rc); + } + + return rc; +} + + +Wallet::EntryType Wallet::entryType(const TQString& key) { + int rc = 0; + + if (_handle == -1) { + return Wallet::Unknown; + } + + DCOPReply r = _dcopRef->call("entryType", _handle, _folder, key); + if (r.isValid()) { + r.get(rc); + } + + return static_cast(rc); +} + + +void Wallet::slotAppUnregistered(const TQCString& app) { + if (_handle >= 0 && app == "kded") { + slotWalletClosed(_handle); + } +} + + +void Wallet::slotFolderUpdated(const TQString& wallet, const TQString& folder) { + if (_name == wallet) { + emit folderUpdated(folder); + } +} + + +void Wallet::slotFolderListUpdated(const TQString& wallet) { + if (_name == wallet) { + emit folderListUpdated(); + } +} + + +void Wallet::slotApplicationDisconnected(const TQString& wallet, const TQCString& application) { + if (_handle >= 0 + && _name == wallet + && application == _dcopRef->dcopClient()->appId()) { + slotWalletClosed(_handle); + } +} + + +void Wallet::walletOpenResult(int id) { + if (_handle != -1) { + // This is BAD. + return; + } + + if (id > 0) { + _handle = id; + emit walletOpened(true); + } else if (id < 0) { + emit walletOpened(false); + } // id == 0 => wait +} + + +bool Wallet::folderDoesNotExist(const TQString& wallet, const TQString& folder) { +DCOPReply r = DCOPRef("kded", "tdewalletd").call("folderDoesNotExist", wallet, folder); +bool rc = true; + if (r.isValid()) { + r.get(rc); + } +return rc; +} + + +bool Wallet::keyDoesNotExist(const TQString& wallet, const TQString& folder, const TQString& key) { +DCOPReply r = DCOPRef("kded", "tdewalletd").call("keyDoesNotExist", wallet, folder, key); +bool rc = true; + if (r.isValid()) { + r.get(rc); + } +return rc; +} + + +void Wallet::virtual_hook(int, void*) { + //BASE::virtual_hook( id, data ); +} + +#include "tdewallet.moc" diff --git a/win/common.pro b/win/common.pro index f5c2f1af7..985c45268 100644 --- a/win/common.pro +++ b/win/common.pro @@ -172,7 +172,7 @@ QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_EXCEPTIONS_ON # /GX for msvc QMAKE_LFLAGS += /FORCE:MULTIPLE # Specify that filename is a C++ source file, even if it doesn’t have -# a .cpp or .cxx extension, thus .cc files are compiled properly with msvc +# a .cpp or .cxx extension, thus files are compiled properly with msvc QMAKE_CXXFLAGS += /TP INCLUDEPATH += moc $(KDELIBS)/win $(KDELIBS) diff --git a/win/pro_files/dcop/dcopidl/dcopidl.pro b/win/pro_files/dcop/dcopidl/dcopidl.pro index 2febfaa2c..df3e48a19 100644 --- a/win/pro_files/dcop/dcopidl/dcopidl.pro +++ b/win/pro_files/dcop/dcopidl/dcopidl.pro @@ -15,7 +15,7 @@ DEFINES += YY_ALWAYS_INTERACTIVE SOURCES = \ main.cpp \ -scanner.cc \ -yacc.cc +scanner.cpp \ +yacc.cpp HEADERS = diff --git a/win/pro_files/tdeio/tdeio.pro b/win/pro_files/tdeio/tdeio.pro index 706208b2a..9d92be52c 100644 --- a/win/pro_files/tdeio/tdeio.pro +++ b/win/pro_files/tdeio/tdeio.pro @@ -102,19 +102,19 @@ tdeio/statusbarprogress.cpp \ tdeio/tcpslavebase.cpp \ tdeio/yacc.c \ \ -bookmarks/kbookmark.cc \ -bookmarks/kbookmarkbar.cc \ -bookmarks/kbookmarkdombuilder.cc \ -bookmarks/kbookmarkdrag.cc \ -bookmarks/kbookmarkexporter.cc \ -bookmarks/kbookmarkimporter.cc \ -bookmarks/kbookmarkimporter_crash.cc \ -bookmarks/kbookmarkimporter_ie.cc \ -bookmarks/kbookmarkimporter_kde1.cc \ -bookmarks/kbookmarkimporter_ns.cc \ -bookmarks/kbookmarkimporter_opera.cc \ -bookmarks/kbookmarkmanager.cc \ -bookmarks/kbookmarkmenu.cc \ +bookmarks/kbookmark.cpp \ +bookmarks/kbookmarkbar.cpp \ +bookmarks/kbookmarkdombuilder.cpp \ +bookmarks/kbookmarkdrag.cpp \ +bookmarks/kbookmarkexporter.cpp \ +bookmarks/kbookmarkimporter.cpp \ +bookmarks/kbookmarkimporter_crash.cpp \ +bookmarks/kbookmarkimporter_ie.cpp \ +bookmarks/kbookmarkimporter_kde1.cpp \ +bookmarks/kbookmarkimporter_ns.cpp \ +bookmarks/kbookmarkimporter_opera.cpp \ +bookmarks/kbookmarkmanager.cpp \ +bookmarks/kbookmarkmenu.cpp \ \ tdefile/kcombiview.cpp \ tdefile/kcustommenueditor.cpp \ @@ -154,27 +154,27 @@ tdefile/kurlrequesterdlg.cpp \ \ misc/uiserver.cpp \ \ -kssl/ksslcertdlg.cc \ -kssl/ksslinfodlg.cc \ -kssl/ksslcsessioncache.cc \ -kssl/ksslsession.cc \ -kssl/ksslsettings.cc \ -kssl/ksslcertchain.cc \ -kssl/ksslcertificate.cc \ -kssl/ksslcertificatecache.cc \ -kssl/ksslcertificatehome.cc \ -kssl/ksslcertificatefactory.cc \ -kssl/kssl.cc \ -kssl/ksslconnectioninfo.cc \ -kssl/ksslkeygen.cc \ -kssl/ksslpkcs7.cc \ -kssl/ksslpkcs12.cc \ -kssl/ksslx509v3.cc \ -kssl/ksslx509map.cc \ -kssl/ksslsigners.cc \ -kssl/ksslpeerinfo.cc \ -kssl/kopenssl.cc \ -kssl/ksmimecrypto.cc +kssl/ksslcertdlg.cpp \ +kssl/ksslinfodlg.cpp \ +kssl/ksslcsessioncache.cpp \ +kssl/ksslsession.cpp \ +kssl/ksslsettings.cpp \ +kssl/ksslcertchain.cpp \ +kssl/ksslcertificate.cpp \ +kssl/ksslcertificatecache.cpp \ +kssl/ksslcertificatehome.cpp \ +kssl/ksslcertificatefactory.cpp \ +kssl/kssl.cpp \ +kssl/ksslconnectioninfo.cpp \ +kssl/ksslkeygen.cpp \ +kssl/ksslpkcs7.cpp \ +kssl/ksslpkcs12.cpp \ +kssl/ksslx509v3.cpp \ +kssl/ksslx509map.cpp \ +kssl/ksslsigners.cpp \ +kssl/ksslpeerinfo.cpp \ +kssl/kopenssl.cpp \ +kssl/ksmimecrypto.cpp #removed tdeio/kautomount.cpp \ -- cgit v1.2.1