73 files changed, 8602 insertions, 0 deletions
diff --git a/noncore/unsupported/mail2/LICENSE b/noncore/unsupported/mail2/LICENSE new file mode 100644 index 0000000..b1e3f5a --- a/dev/null +++ b/noncore/unsupported/mail2/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/noncore/unsupported/mail2/README b/noncore/unsupported/mail2/README new file mode 100644 index 0000000..85fc951 --- a/dev/null +++ b/noncore/unsupported/mail2/README @@ -0,0 +1,23 @@ +Mail README +----------------------------------------------------------------------------- + +!! !! !! !! !! +This program does not yet work. You can send email, but IMAP inbox viewing +isn't posible due some bugs. Please don't complain. If you want to send mail, +look for another program (Which does not exist yet.) +!! !! !! !! !! + +About: +Mail is divided into three parts: libmail, mail and bend. +libmail is a library containing all classes needed both by mail and +bend. This includes for example the IMAP classes, the plugin structure, and +configfile management. +mail is the mailer itself. You could say it is a gui to libmail. +bend is the messagenotifier tool. It runs as an applet in the Opie taskbar. + +Compilation: +To compile, you have to set $QTDIR and $TMAKEPATH to the appropriate +directories. Then simply make in the toplevel directory of the distribution. + +Have fun, Constantin <cbergemann@lisa.de>. + diff --git a/noncore/unsupported/mail2/TODO b/noncore/unsupported/mail2/TODO new file mode 100644 index 0000000..ef596dc --- a/dev/null +++ b/noncore/unsupported/mail2/TODO @@ -0,0 +1,31 @@ +LISAmail TODO +----------------------------------------------------------------------------- + +General stuff: + - If password is empty, ask for it during fetch. + - Check if all necessary fields in AccoundEditor are filled. + +Protocol related: + - The IMAP implentation is kinda strange and slow. + - The SMTP implentation is goddamn strange. + - POP3 support would be nice. + - NNTP would be kinda neat, too. + - Implent a plugin system. + +Security related: + - GnuPG support. This will require a seperate gpg managing utility in + the settings tab. + - sMIME? maybe in the distant future. + +Mail management: + - Header caching + - Sieve filtering support? + - Enqueueing/Draft support both on the IMAP server and local. + +Testing: + I'm using the courier-imap server at my developement site. I didn't have + much opportunity to test on other servers. Giving me test-accounts on other + servers would be helpfull. + +If you want something added, drop a mail. Comments are allways welcome. + diff --git a/noncore/unsupported/mail2/accounteditor.cpp b/noncore/unsupported/mail2/accounteditor.cpp new file mode 100644 index 0000000..8230a69 --- a/dev/null +++ b/noncore/unsupported/mail2/accounteditor.cpp @@ -0,0 +1,82 @@ +#include <qmultilineedit.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qmessagebox.h> +#include <qtabwidget.h> +#include <qlineedit.h> +#include <qcheckbox.h> + +#include "accounteditor.h" +#include "miscfunctions.h" + +AccountEditor::AccountEditor(Account account, QWidget *parent, const char *name, bool modal, WFlags fl) + : AccountEditorBase(parent, name, modal, fl), _account(account) +{ + TabWidget2->removePage(sslTab); + + fillValues(); +} + +void AccountEditor::accept() +{ + int numLf = 0; + for (unsigned int i = 0; i <= signature->text().length(); i++) { + if (signature->text()[i] == '\n') numLf++; + } + if (numLf >= 4) { + int ret = QMessageBox::warning(this, tr("Warning"), tr("<p>Your signature is longer than 4 lines. This is considered inpolite by many people. You should shorten your signature.</p>"), tr("Change"), tr("Continue")); + if (ret == 0) return; + } + + _account.setAccountName(_account.accountName() ? _account.accountName() : MiscFunctions::uniqueString()); + _account.setRealName(realname->text()); + _account.setEmail(email->text()); + _account.setOrg(org->text()); + _account.setImapServer(imapServer->text()); + _account.setImapPort(imapPort->text()); + _account.setSmtpServer(smtpServer->text()); + _account.setSmtpPort(smtpPort->text()); + _account.setUser(user->text()); + _account.setPass(pass->text()); + _account.setSmtpSsl(smtpssl->isChecked()); + _account.setSmtpSslPort(smtpsPort->text()); + _account.setImapSsl(imapssl->isChecked()); + _account.setImapSslPort(imapsPort->text()); + _account.setDefaultCc(addCc->isChecked()); + _account.setDefaultBcc(addBcc->isChecked()); + _account.setDefaultReplyTo(addReplyTo->isChecked()); + _account.setCc(cc->text()); + _account.setBcc(bcc->text()); + _account.setReplyTo(replyTo->text()); + _account.setSignature(signature->text()); + + QDialog::accept(); +} + +void AccountEditor::fillValues() +{ + realname->setText(_account.realName()); + email->setText(_account.email()); + org->setText(_account.org()); + imapServer->setText(_account.imapServer()); + imapPort->setText(!_account.imapPort().isEmpty() ? _account.imapPort() : QString("143")); + smtpServer->setText(_account.smtpServer()); + smtpPort->setText(!_account.smtpPort().isEmpty() ? _account.smtpPort() : QString("25")); + user->setText(_account.user()); + pass->setText(_account.pass()); + smtpssl->setChecked(_account.smtpSsl()); + smtpsPort->setText(_account.smtpSslPort()); + imapssl->setChecked(_account.imapSsl()); + imapsPort->setText(!_account.imapSslPort().isEmpty() ? _account.imapSslPort() : QString("993")); + addCc->setChecked(_account.defaultCc()); + if (_account.defaultCc()) cc->setEnabled(true); + addBcc->setChecked(_account.defaultBcc()); + if (_account.defaultBcc()) bcc->setEnabled(true); + addReplyTo->setChecked(_account.defaultReplyTo()); + if (_account.defaultReplyTo()) replyTo->setEnabled(true); + cc->setText(_account.cc()); + bcc->setText(_account.bcc()); + replyTo->setText(_account.replyTo()); + signature->setText(_account.signature()); +} + diff --git a/noncore/unsupported/mail2/accounteditor.h b/noncore/unsupported/mail2/accounteditor.h new file mode 100644 index 0000000..4a2bda3 --- a/dev/null +++ b/noncore/unsupported/mail2/accounteditor.h @@ -0,0 +1,24 @@ +#ifndef ACCOUNTEDITOR_H +#define ACCOUNTEDITOR_H + +#include "accounteditorbase.h" +#include "configfile.h" + +class AccountEditor : public AccountEditorBase +{ + Q_OBJECT + +public: + AccountEditor(Account account = Account(), QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags fl = 0); + + Account _account; + +protected slots: + void accept(); + +protected: + void fillValues(); + +}; + +#endif diff --git a/noncore/unsupported/mail2/accounteditorbase.ui b/noncore/unsupported/mail2/accounteditorbase.ui new file mode 100644 index 0000000..fe9f2a4 --- a/dev/null +++ b/noncore/unsupported/mail2/accounteditorbase.ui @@ -0,0 +1,751 @@ +<!DOCTYPE UI><UI> +<class>AccountEditorBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>AccountEditorBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>243</width> + <height>320</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Account Editor</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>0</number> + </property> + <widget row="0" column="0" > + <class>QTabWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>TabWidget2</cstring> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Server</string> + </attribute> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel2</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>IMAP:</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>imapServer</cstring> + </property> + </widget> + <widget row="1" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel3</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Port:</string> + </property> + </widget> + <widget row="1" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>imapPort</cstring> + </property> + </widget> + <spacer row="8" column="1" > + <property> + <name>name</name> + <cstring>Spacer2</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget row="7" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>smtpPort</cstring> + </property> + </widget> + <widget row="6" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>smtpServer</cstring> + </property> + </widget> + <widget row="6" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel6</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>SMTP:</string> + </property> + </widget> + <widget row="7" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel7</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Port:</string> + </property> + </widget> + <widget row="3" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel4</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>User:</string> + </property> + </widget> + <widget row="4" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel5</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Pass:</string> + </property> + </widget> + <widget row="4" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>pass</cstring> + </property> + <property stdset="1"> + <name>echoMode</name> + <enum>Password</enum> + </property> + </widget> + <widget row="3" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>user</cstring> + </property> + </widget> + <widget row="2" column="0" rowspan="1" colspan="2" > + <class>Line</class> + <property stdset="1"> + <name>name</name> + <cstring>Line1</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Horizontal</enum> + </property> + </widget> + <widget row="5" column="0" rowspan="1" colspan="2" > + <class>Line</class> + <property stdset="1"> + <name>name</name> + <cstring>Line2</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Horizontal</enum> + </property> + </widget> + </grid> + </widget> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Identity</string> + </attribute> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel8</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Name:</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>realname</cstring> + </property> + </widget> + <widget row="1" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>email</cstring> + </property> + </widget> + <widget row="1" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel9</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>E-Mail:</string> + </property> + </widget> + <widget row="2" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel10</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Org:</string> + </property> + </widget> + <widget row="2" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>org</cstring> + </property> + </widget> + <spacer row="3" column="1" > + <property> + <name>name</name> + <cstring>Spacer1</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Advanced</string> + </attribute> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>addCc</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Cc</string> + </property> + </widget> + <widget row="1" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>addBcc</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Bcc</string> + </property> + </widget> + <widget row="2" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>addReplyTo</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Reply-To</string> + </property> + </widget> + <widget row="2" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>replyTo</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + </widget> + <widget row="1" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>bcc</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + </widget> + <widget row="0" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>cc</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + </widget> + <widget row="3" column="0" rowspan="1" colspan="2" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel12</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Signature:</string> + </property> + </widget> + <widget row="4" column="0" rowspan="1" colspan="2" > + <class>QMultiLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>signature</cstring> + </property> + </widget> + <spacer row="5" column="1" > + <property> + <name>name</name> + <cstring>Spacer3</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>sslTab</cstring> + </property> + <attribute> + <name>title</name> + <string>SSL</string> + </attribute> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <spacer row="2" column="0" > + <property> + <name>name</name> + <cstring>Spacer4</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget row="0" column="0" > + <class>QButtonGroup</class> + <property stdset="1"> + <name>name</name> + <cstring>ButtonGroup1</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>IMAP</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>imapssl</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Use SSL</string> + </property> + </widget> + <widget row="1" column="0" > + <class>QFrame</class> + <property stdset="1"> + <name>name</name> + <cstring>Frame11</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>frameShape</name> + <enum>NoFrame</enum> + </property> + <property stdset="1"> + <name>frameShadow</name> + <enum>Raised</enum> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel13</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Port:</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>imapsPort</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>text</name> + <string>993</string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget row="1" column="0" > + <class>QButtonGroup</class> + <property stdset="1"> + <name>name</name> + <cstring>smtpSslGroup</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>SMTP</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>smtpssl</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Use SSL</string> + </property> + </widget> + <widget row="1" column="0" > + <class>QFrame</class> + <property stdset="1"> + <name>name</name> + <cstring>Frame6</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>frameShape</name> + <enum>NoFrame</enum> + </property> + <property stdset="1"> + <name>frameShadow</name> + <enum>Raised</enum> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel14</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Port:</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>smtpsPort</cstring> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + </grid> + </widget> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>addCc</sender> + <signal>toggled(bool)</signal> + <receiver>cc</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>addBcc</sender> + <signal>toggled(bool)</signal> + <receiver>bcc</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>addReplyTo</sender> + <signal>toggled(bool)</signal> + <receiver>replyTo</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>smtpssl</sender> + <signal>toggled(bool)</signal> + <receiver>Frame6</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>imapssl</sender> + <signal>toggled(bool)</signal> + <receiver>Frame11</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>imapssl</sender> + <signal>toggled(bool)</signal> + <receiver>imapsPort</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>imapssl</sender> + <signal>toggled(bool)</signal> + <receiver>TextLabel13</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>TabWidget2</tabstop> + <tabstop>imapServer</tabstop> + <tabstop>imapPort</tabstop> + <tabstop>user</tabstop> + <tabstop>pass</tabstop> + <tabstop>smtpServer</tabstop> + <tabstop>smtpPort</tabstop> + <tabstop>realname</tabstop> + <tabstop>email</tabstop> + <tabstop>org</tabstop> + <tabstop>addCc</tabstop> + <tabstop>cc</tabstop> + <tabstop>addBcc</tabstop> + <tabstop>bcc</tabstop> + <tabstop>addReplyTo</tabstop> + <tabstop>replyTo</tabstop> + <tabstop>signature</tabstop> + <tabstop>imapsPort</tabstop> + <tabstop>smtpsPort</tabstop> +</tabstops> +</UI> diff --git a/noncore/unsupported/mail2/addresspicker.cpp b/noncore/unsupported/mail2/addresspicker.cpp new file mode 100644 index 0000000..178fe27 --- a/dev/null +++ b/noncore/unsupported/mail2/addresspicker.cpp @@ -0,0 +1,117 @@ +#include <qpushbutton.h> +#include <qmessagebox.h> +#include <qtextstream.h> +#include <qlistbox.h> +#include <qfile.h> + +#include <qpe/resource.h> + +#include <stdlib.h> + +#include "addresspicker.h" + +AddressPicker::AddressPicker(QWidget *parent, const char *name, bool modal, + WFlags fl) : AddressPickerBase(parent, name, modal, fl) +{ + okButton->setIconSet(Resource::loadPixmap("enter")); + cancelButton->setIconSet(Resource::loadPixmap("editdelete")); + + connect(okButton, SIGNAL(clicked()), SLOT(accept())); + connect(cancelButton, SIGNAL(clicked()), SLOT(close())); + + QFile f((QString) getenv("HOME") + "/Applications/" + + "addressbook/addressbook.xml"); + + if (f.open(IO_ReadOnly)) { + QTextStream stream(&f); + QString content; + while (!f.atEnd()) content += stream.readLine() + "\n"; + QStringList lines = QStringList::split(QRegExp("\\n"), content); + QStringList::Iterator it; + for (it = lines.begin(); it != lines.end(); it++) { + if ((*it).find(QRegExp("^<Contact.*")) != -1) { + int pos = (*it).find("FirstName=\""); + QString fname; + if (pos != -1) { + int i = 1; + QChar c; + while (c != '"') { + c = (*it)[pos + 10 + i]; + if (c != '"') fname += c; + i++; + } + } + pos = (*it).find("LastName=\""); + QString lname; + if (pos != -1) { + int i = 1; + QChar c; + while (c != '"') { + c = (*it)[pos + 9 + i]; + if (c != '"') lname += c; + i++; + } + } + pos = (*it).find("DefaultEmail=\""); + QString email; + if (pos != -1) { + int i = 1; + QChar c; + while (c != '"') { + c = (*it)[pos + 13 + i]; + if (c != '"') email += c; + i++; + } + } + QString tname, temail; + if (!fname.isEmpty()) tname += fname; + if (!lname.isEmpty()) tname += fname.isEmpty() ? lname : (" " + lname); + if (!email.isEmpty()) temail += tname.isEmpty() ? email : (" <" + email + ">"); + if (!email.isEmpty()) addressList->insertItem(tname + temail); + } + } + } + if (addressList->count() <= 0) { + addressList->insertItem(tr("There are no entries in the addressbook.")); + addressList->setEnabled(false); + okButton->setEnabled(false); + } +} + +void AddressPicker::accept() +{ + QListBoxItem *item = addressList->firstItem(); + QString names; + + while (item) { + if (item->selected()) + names += item->text() + ", "; + item = item->next(); + } + names.replace(names.length() - 2, 2, ""); + + if (names.isEmpty()) { + QMessageBox::information(this, tr("Error"), tr("<p>You have to select" + " at least one address entry.</p>"), tr("Ok")); + return; + } + + selectedNames = names; + QDialog::accept(); +} + +QString AddressPicker::getNames() +{ + QString names = 0; + + AddressPicker *picker = new AddressPicker(0, 0, true); + picker->showMaximized(); + picker->show(); + + int ret = picker->exec(); + if (QDialog::Accepted == ret) { + return picker->selectedNames; + } + return 0; +} + diff --git a/noncore/unsupported/mail2/addresspicker.h b/noncore/unsupported/mail2/addresspicker.h new file mode 100644 index 0000000..7d21915 --- a/dev/null +++ b/noncore/unsupported/mail2/addresspicker.h @@ -0,0 +1,24 @@ +#ifndef ADDRESSPICKER_H +#define ADDRESSPICKER_H + +#include "addresspickerbase.h" + +class AddressPicker : public AddressPickerBase +{ + Q_OBJECT + +public: + static QString getNames(); + +protected: + AddressPicker(QWidget *parent = 0, const char *name = 0, + bool modal = false, WFlags fl = 0); + + QString selectedNames; + + void accept(); + +}; + +#endif + diff --git a/noncore/unsupported/mail2/addresspickerbase.ui b/noncore/unsupported/mail2/addresspickerbase.ui new file mode 100644 index 0000000..8eb288d --- a/dev/null +++ b/noncore/unsupported/mail2/addresspickerbase.ui @@ -0,0 +1,86 @@ +<!DOCTYPE UI><UI> +<class>AddressPickerBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>AddressPickerBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>286</width> + <height>320</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Address Picker</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" rowspan="1" colspan="2" > + <class>QListBox</class> + <property stdset="1"> + <name>name</name> + <cstring>addressList</cstring> + </property> + <property stdset="1"> + <name>selectionMode</name> + <enum>Multi</enum> + </property> + </widget> + <widget row="1" column="0" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>okButton</cstring> + </property> + <property stdset="1"> + <name>minimumSize</name> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property stdset="1"> + <name>text</name> + <string>Ok</string> + </property> + </widget> + <widget row="1" column="1" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>cancelButton</cstring> + </property> + <property stdset="1"> + <name>minimumSize</name> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property stdset="1"> + <name>text</name> + <string>Cancel</string> + </property> + </widget> + </grid> +</widget> +</UI> diff --git a/noncore/unsupported/mail2/attachdiag.cpp b/noncore/unsupported/mail2/attachdiag.cpp new file mode 100644 index 0000000..6e6c3d4 --- a/dev/null +++ b/noncore/unsupported/mail2/attachdiag.cpp @@ -0,0 +1,71 @@ +#include <qmessagebox.h> +#include <qpushbutton.h> +#include <qlistbox.h> +#include <qlayout.h> + +#include <qpe/fileselector.h> +#include <qpe/resource.h> + +#include <stdlib.h> + +#include "attachdiag.h" + +AttachDiag::AttachDiag(QWidget* parent = 0, const char* name = 0, bool modal, WFlags fl = 0) + : QDialog(parent, name, modal, fl) +{ + setCaption(tr("Attach File")); + + QGridLayout *layout = new QGridLayout(this); + layout->setSpacing(3); + layout->setMargin(4); + + FileSelector *fileSelector = new FileSelector("*", this, "FileSelector"); + fileSelector->setCloseVisible(false); + fileSelector->setNewVisible(false); + + layout->addMultiCellWidget(fileSelector, 0, 0, 0, 1); + + QPushButton *attachButton = new QPushButton(this); + attachButton->setText(tr("Ok")); + attachButton->setIconSet(Resource::loadPixmap("enter")); + + layout->addWidget(attachButton, 1, 0); + + QPushButton *cancelButton = new QPushButton(this); + cancelButton->setText(tr("Cancel")); + cancelButton->setIconSet(Resource::loadPixmap("editdelete")); + + layout->addWidget(cancelButton, 1, 1); + + connect(fileSelector, SIGNAL(fileSelected(const DocLnk &)), SLOT(fileSelected(const DocLnk &))); + connect(attachButton, SIGNAL(clicked()), SLOT(accept())); + connect(cancelButton, SIGNAL(clicked()), SLOT(close())); + + if (fileSelector->selected() != NULL) + currentFile = *fileSelector->selected(); + + if (fileSelector->fileCount() == 0) { + attachButton->setEnabled(false); + fileSelector->setEnabled(false); + } +} + +void AttachDiag::fileSelected(const DocLnk &file) +{ + currentFile = file; +} + +DocLnk AttachDiag::getFile() +{ + AttachDiag *attach = new AttachDiag(0, 0, true); + attach->showMaximized(); + attach->show(); + + if (QDialog::Accepted == attach->exec()) { + return attach->currentFile; + } + + return DocLnk(); +} + + diff --git a/noncore/unsupported/mail2/attachdiag.h b/noncore/unsupported/mail2/attachdiag.h new file mode 100644 index 0000000..c673cfc --- a/dev/null +++ b/noncore/unsupported/mail2/attachdiag.h @@ -0,0 +1,27 @@ +#ifndef ATTACHDIAG_H +#define ATTACHDIAG_H + +#include <qdialog.h> + +#include <qpe/applnk.h> + +class AttachDiag : public QDialog +{ + Q_OBJECT + +public: + static DocLnk getFile(); + +protected: + AttachDiag(QWidget *parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0); + +private slots: + void fileSelected(const DocLnk &); + +private: + DocLnk currentFile; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/bend/bend.cpp b/noncore/unsupported/mail2/bend/bend.cpp new file mode 100644 index 0000000..b4da3ac --- a/dev/null +++ b/noncore/unsupported/mail2/bend/bend.cpp @@ -0,0 +1,116 @@ +#include <qlayout.h> +#include <qpixmap.h> +#include <qlabel.h> +#include <qtimer.h> +#include <qdir.h> + +#include <qpe/qcopenvelope_qws.h> +#include <qpe/resource.h> +#include <qpe/config.h> + +#include <stdlib.h> + +#include "configfile.h" +#include "imapresponse.h" +#include "imaphandler.h" +#include "zaurusstuff.h" +#include "bend.h" + +BenD::BenD(QWidget *parent, const char *name, WFlags fl) + : QButton(parent, name, fl) +{ + _config = new Config("mail"); + _config->setGroup("Settings"); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addItem(new QSpacerItem(0,0)); + + QLabel *pixmap = new QLabel(this); + pixmap->setPixmap(Resource::loadPixmap("mail/mailchecker")); + layout->addWidget(pixmap); + + layout->addItem(new QSpacerItem(0,0)); + + hide(); + + connect(this, SIGNAL(clicked()), SLOT(slotClicked())); + + if (!_config->readBoolEntry("Disabled", false)) { + _intervalMs = _config->readNumEntry("CheckEvery", 5) * 60000; + _intervalTimer = new QTimer(); + _intervalTimer->start(_intervalMs); + connect(_intervalTimer, SIGNAL(timeout()), SLOT(slotCheck())); + + QTimer::singleShot(0, this, SLOT(slotCheck())); + } +} + +void BenD::drawButton(QPainter *) { } +void BenD::drawButtonText(QPainter *) { } + +void BenD::slotClicked() +{ + QCopEnvelope e("QPE/System", "execute(QString)"); + e << QString("mail"); + + if (_ledOn) { + ZaurusStuff::blinkLedOff(); + _ledOn = false; + } +} + +void BenD::slotCheck() +{ + // Check wether the check interval has been changed. + int newIntervalMs = _config->readNumEntry("CheckEvery", 5) * 60000; + if (newIntervalMs != _intervalMs) { + _intervalTimer->changeInterval(newIntervalMs); + _intervalMs = newIntervalMs; + } + + QValueList<Account> acList = ConfigFile::getAccounts(); + QValueList<Account>::Iterator ot; + for (ot = acList.begin(); ot != acList.end(); ot++) { + if (!((*ot).imapServer().isEmpty() || + (*ot).imapPort().isEmpty() || + (*ot).user().isEmpty() || + (*ot).pass().isEmpty())) { + if (!((*ot).imapSsl() && + (*ot).imapSslPort().isEmpty())) { + IMAPHandler *handler = new IMAPHandler(*ot); + handler->iStatus("INBOX", "RECENT"); + connect(handler, SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPStatus(IMAPResponse &))); + } + } + } +} + +void BenD::slotIMAPStatus(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPStatus(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + if (response.STATUS()[0].recent().toInt() > 0) { + if (isHidden()) show(); + if (_config->readBoolEntry("BlinkLed", true)) + ZaurusStuff::blinkLedOn(); + if (_config->readBoolEntry("PlaySound", false)) { + ZaurusStuff::buzzerOn(); + QTimer::singleShot(3000, this, SLOT(slotSoundOff())); + } + } else { + if (!isHidden()) hide(); + if (!_ledOn) { + ZaurusStuff::blinkLedOff(); + _ledOn = false; + } + } + response.imapHandler()->iLogout(); + } else qWarning("BenD: WARNING: Couldn't retrieve INBOX status."); +} + +void BenD::slotSoundOff() +{ + ZaurusStuff::buzzerOff(); +} + diff --git a/noncore/unsupported/mail2/bend/bend.h b/noncore/unsupported/mail2/bend/bend.h new file mode 100644 index 0000000..cf50bc5 --- a/dev/null +++ b/noncore/unsupported/mail2/bend/bend.h @@ -0,0 +1,38 @@ +#ifndef BEND_H +#define BEND_H + +#include <qbutton.h> + +class Config; +class QTimer; +class IMAPResponse; + +class BenD : public QButton +{ + Q_OBJECT + +public: + BenD(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected: + void drawButton(QPainter *); + void drawButtonText(QPainter *); + void gotNewMail(); + QString rot13(const QString &input); + +protected slots: + void slotCheck(); + void slotClicked(); + void slotSoundOff(); + void slotIMAPStatus(IMAPResponse &response); + +private: + Config *_config; + QTimer *_intervalTimer; + int _intervalMs; + bool _ledOn; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/bend/bend.pro b/noncore/unsupported/mail2/bend/bend.pro new file mode 100644 index 0000000..fe7b22c --- a/dev/null +++ b/noncore/unsupported/mail2/bend/bend.pro @@ -0,0 +1,10 @@ +TEMPLATE = lib +CONFIG += qt warn_on release +HEADERS += bend.h \ + bendimpl.h +SOURCES += bend.cpp \ + bendimpl.cpp +INCLUDEPATH += $(OPIEDIR)/include ../libmail +LIBS += -lmail -lqpe +TARGET = bend +DESTDIR += $(OPIEDIR)/plugins/applets/ diff --git a/noncore/unsupported/mail2/bend/bendimpl.cpp b/noncore/unsupported/mail2/bend/bendimpl.cpp new file mode 100644 index 0000000..e616c68 --- a/dev/null +++ b/noncore/unsupported/mail2/bend/bendimpl.cpp @@ -0,0 +1,39 @@ +#include "bendimpl.h" +#include "bend.h" + +BenDImpl::BenDImpl() + : _benD(0), ref(0) +{ + +} + +BenDImpl::~BenDImpl() +{ + delete _benD; +} + +QWidget *BenDImpl::applet(QWidget *parent) +{ + if (!_benD) _benD = new BenD(parent); + return _benD; +} + +int BenDImpl::position() const +{ + return 4; +} + +QRESULT BenDImpl::queryInterface(const QUuid &uuid, QUnknownInterface **iface) +{ + *iface = 0; + if (uuid == IID_QUnknown) *iface = this; + else if (uuid == IID_TaskbarApplet) *iface = this; + + if (*iface) (*iface)->addRef(); + return QS_OK; +} + +Q_EXPORT_INTERFACE() +{ + Q_CREATE_INSTANCE(BenDImpl) +} diff --git a/noncore/unsupported/mail2/bend/bendimpl.h b/noncore/unsupported/mail2/bend/bendimpl.h new file mode 100644 index 0000000..c883f1b --- a/dev/null +++ b/noncore/unsupported/mail2/bend/bendimpl.h @@ -0,0 +1,27 @@ +#ifndef BENDIMPL_H +#define BENDIMPL_H + +#include <qpe/taskbarappletinterface.h> + +class BenD; + +class BenDImpl : public TaskbarAppletInterface +{ +public: + BenDImpl(); + virtual ~BenDImpl(); + + QRESULT queryInterface(const QUuid &uuid, QUnknownInterface **iface); + Q_REFCOUNT + + virtual QWidget *applet(QWidget *parent); + virtual int position() const; + +private: + BenD *_benD; + ulong ref; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/composer.cpp b/noncore/unsupported/mail2/composer.cpp new file mode 100644 index 0000000..2f13604 --- a/dev/null +++ b/noncore/unsupported/mail2/composer.cpp @@ -0,0 +1,215 @@ +#include <qmultilineedit.h> +#include <qmessagebox.h> +#include <qpopupmenu.h> +#include <qcombobox.h> +#include <qlineedit.h> +#include <qaction.h> +#include <qtimer.h> +#include <qlabel.h> + +#include <qpe/resource.h> + +#include "addresspicker.h" +#include "listviewplus.h" +#include "smtphandler.h" +#include "attachdiag.h" +#include "composer.h" +#include "rename.h" + +AttachViewItem::AttachViewItem(QListView *parent, Attachment &attachment) + : QListViewItem(parent), _attachment(attachment) +{ + setPixmap(0, _attachment.docLnk()->pixmap().isNull() ? Resource::loadPixmap("UnknownDocument-14") : _attachment.docLnk()->pixmap()); + setText(0, _attachment.newName().isEmpty() ? _attachment.fileName() : _attachment.newName()); + setText(1, _attachment.description()); +} + +Composer::Composer(QWidget *parent, const char *name, WFlags fl) + : ComposerBase(parent, name, fl) +{ + abort->setEnabled(false); + to->setFocus(); + + connect(sendmail, SIGNAL(activated()), SLOT(slotSendMail())); + connect(addressbook, SIGNAL(activated()), SLOT(slotOpenAddressPicker())); + connect(addattach, SIGNAL(activated()), SLOT(slotAddAttach())); + connect(delattach, SIGNAL(activated()), SLOT(slotDelAttach())); + + connect(from, SIGNAL(activated(int)), SLOT(slotFromChanged(int))); + + connect(attachPopup, SIGNAL(activated(int)), SLOT(slotPopupHandler(int))); + + QTimer::singleShot(0, this, SLOT(slotFillStuff())); + QTimer::singleShot(0, this, SLOT(slotResizing())); +} + +void Composer::setSendMail(SendMail &sendMail) +{ + to->setText(sendMail.to()); + cc->setText(sendMail.cc()); + bcc->setText(sendMail.bcc()); + subject->setText(sendMail.subject()); + message->setText(sendMail.message()); + _inReplyTo = sendMail.inReplyTo(); + + QValueList<Attachment> attachments = sendMail.attachments(); + QValueList<Attachment>::Iterator it; + for (it = attachments.begin(); it != attachments.end(); it++) { + (void) new AttachViewItem(attachView, *it); + if (attachView->isHidden()) attachView->show(); + } +} + +void Composer::slotResizing() +{ + from->setMaximumWidth(width() - fromBox->width()); + from->resize(width() - fromBox->width(), y()); +} + +void Composer::slotPopupHandler(int itemid) +{ + if (attachView->currentItem() == NULL) { + QMessageBox::information(this, tr("Error"), tr("Please select an entry first."), tr("Ok")); + return; + } + + if (itemid == POPUP_ATTACH_RENAME) { + QString tmp = Rename::rename(attachView->currentItem()->text(0), this); + if (tmp != QString(0)) attachView->currentItem()->setText(0, tmp); + } else if (itemid == POPUP_ATTACH_DESC) { + QString tmp = Rename::getText(tr("Set Description"), tr("<div align=center>Description"), this); + if (tmp != QString(0)) attachView->currentItem()->setText(1, tmp); + } else if (itemid == POPUP_ATTACH_REMOVE) { + attachView->takeItem(attachView->currentItem()); + } +} + +void Composer::slotSendMail() +{ + if (to->text().find(QRegExp(".*\\@.*\\..*")) == -1) { + QMessageBox::information(this, tr("Error"), tr("<p>You have to specify a recipient.<br>(eg: foo@bar.org)</p>"), tr("Ok")); + return; + } + + SendMail smail; + smail.setFrom(from->currentText()); + smail.setReplyTo(replyto->text()); + smail.setTo(to->text()); + smail.setCc(cc->text()); + smail.setBcc(bcc->text()); + smail.setSubject(subject->text()); + smail.setMessage(message->text()); + smail.setNeedsMime(attachView->childCount() == 0 ? false : true); + smail.setAccount(accountsLoaded[from->currentItem()]); + + if (priority->currentItem() == POPUP_PRIO_LOW) { + smail.setPriority("Low"); // No i18n on purpose + } else if (priority->currentItem() == POPUP_PRIO_NORMAL) { + smail.setPriority("Normal"); // No i18n on purpose + } else if (priority->currentItem() == POPUP_PRIO_HIGH) { + smail.setPriority("High"); // No i18n on purpose + } + + QValueList<Attachment> attachments; + QListViewItem *item; + for (item = attachView->firstChild(); item != 0; item = item->itemBelow()) { + attachments.append(((AttachViewItem *)item)->attachment()); + } + + smail.setAttachments(attachments); + + QString header, message; + MailFactory::genMail(header, message, smail, this); + + abort->setEnabled(true); + + SmtpHandler *handler = new SmtpHandler(header, message, accountsLoaded[from->currentItem()], to->text()); + connect(handler, SIGNAL(finished()), SLOT(slotSendFinished())); + connect(handler, SIGNAL(error(const QString &)), SLOT(slotSendError(const QString &))); + connect(handler, SIGNAL(status(const QString &)), status, SLOT(setText(const QString &))); +} + +void Composer::slotSendError(const QString &error) +{ + status->setText(tr("<font color=#ff0000>Error occoured during sending.</font>")); + QMessageBox::warning(this, tr("Error"), tr("<p>%1</p").arg(error), tr("Ok")); +} + +void Composer::slotSendFinished() +{ + status->setText(QString(0)); + abort->setEnabled(false); +} + +void Composer::slotFillStuff() +{ + QValueList<Account> accounts = ConfigFile::getAccounts(); + int i = 0; + + QValueList<Account>::Iterator it; + for (it = accounts.begin(); it != accounts.end(); it++) { + if (!(*it).email().isEmpty() && !(*it).smtpServer().isEmpty() && !(*it).smtpPort().isEmpty()) { + if (!(*it).realName().isEmpty()) + from->insertItem((*it).realName() + " <" + (*it).email() + ">", i); + else + from->insertItem((*it).email()); + + accountsLoaded.append(*it); + i++; + } + } +} + +void Composer::slotFromChanged(int id) +{ + Account account = accountsLoaded[id]; + + if (account.defaultCc()) cc->setText(account.cc()); + if (account.defaultBcc()) bcc->setText(account.bcc()); + if (account.defaultReplyTo()) replyto->setText(account.replyTo()); + if (!account.signature().isEmpty()) + message->setText(message->text() + "\n\n-- \n" + account.signature()); +} + +void Composer::slotOpenAddressPicker() +{ + if (!to->isHidden() && cc->isHidden() && bcc->isHidden()) { + if (to->text().isEmpty()) { + to->setText(AddressPicker::getNames()); + } else { + to->setText(to->text() + ", " + AddressPicker::getNames()); + } + } else if (to->isHidden() && !cc->isHidden() && bcc->isHidden()) { + if (cc->text().isEmpty()) { + cc->setText(AddressPicker::getNames()); + } else { + cc->setText(cc->text() + ", " + AddressPicker::getNames()); + } + } else if (to->isHidden() && cc->isHidden() && !bcc->isHidden()) { + if (bcc->text().isEmpty()) { + bcc->setText(AddressPicker::getNames()); + } else { + bcc->setText(bcc->text() + ", " + AddressPicker::getNames()); + } + } +} + +void Composer::slotAddAttach() +{ + DocLnk lnk = AttachDiag::getFile(); + if (lnk.name().isEmpty()) return; + + Attachment attachment; + attachment.setFileName(lnk.file()); + attachment.setNewName(lnk.name()); + attachment.setDocLnk(&lnk); + + (void) new AttachViewItem(attachView, attachment); +} + +void Composer::slotDelAttach() +{ + if (attachView->currentItem() == NULL) return; + attachView->takeItem(attachView->currentItem()); +} + diff --git a/noncore/unsupported/mail2/composer.h b/noncore/unsupported/mail2/composer.h new file mode 100644 index 0000000..a1af121 --- a/dev/null +++ b/noncore/unsupported/mail2/composer.h @@ -0,0 +1,52 @@ +#ifndef COMPOSER_H +#define COMPOSER_H + +#include <qlistview.h> +#include <qpe/applnk.h> + +#include "mailfactory.h" +#include "composerbase.h" +#include "configfile.h" + +class AttachViewItem : public QListViewItem +{ +public: + AttachViewItem(QListView *parent, Attachment &attachment); + + Attachment attachment() { return _attachment; } + +private: + Attachment _attachment; + +}; + +class Composer : public ComposerBase +{ + Q_OBJECT + +public: + Composer(QWidget *parent = 0, const char *name = 0, WFlags fl = Qt::WType_Modal); + + void setSendMail(SendMail &sendMail); + +protected slots: + void slotPopupHandler(int itemid); + void slotSendMail(); + void slotSendError(const QString &); + void slotSendFinished(); + void slotResizing(); + void slotFillStuff(); + void slotFromChanged(int id); + void slotOpenAddressPicker(); + void slotAddAttach(); + void slotDelAttach(); + +protected: + QValueList<Account> accountsLoaded; + +private: + QString _inReplyTo; + +}; + +#endif diff --git a/noncore/unsupported/mail2/composerbase.cpp b/noncore/unsupported/mail2/composerbase.cpp new file mode 100644 index 0000000..7754863 --- a/dev/null +++ b/noncore/unsupported/mail2/composerbase.cpp @@ -0,0 +1,199 @@ +#include <qmultilineedit.h> +#include <qpopupmenu.h> +#include <qcombobox.h> +#include <qlineedit.h> +#include <qtoolbar.h> +#include <qlayout.h> +#include <qaction.h> +#include <qlabel.h> +#include <qvbox.h> + +#include <qpe/resource.h> + +#include "listviewplus.h" +#include "composerbase.h" + +ComposerBase::ComposerBase(QWidget *parent, const char *name, WFlags fl) + : QMainWindow(parent, name, fl) +{ + setCaption(tr("Compose Message")); + setToolBarsMovable(false); + + toolbar = new QToolBar(this); + addToolBar(toolbar); + toolbar->setHorizontalStretchable(true); + + sendmail = new QAction(tr("Send the mail"), QIconSet(Resource::loadPixmap("mail/sendmail")), 0, 0, this); + sendmail->addTo(toolbar); + + attachfile = new QAction(tr("Attach a file"), QIconSet(Resource::loadPixmap("mail/attach")), 0, 0, this, 0, true); + attachfile->addTo(toolbar); + connect(attachfile, SIGNAL(toggled(bool)), SLOT(slotAttachfileChanged(bool))); + + addressbook = new QAction(tr("Addressbook"), QIconSet(Resource::loadPixmap("mail/addbook")), 0, 0, this); + addressbook->addTo(toolbar); + + QLabel *spacer = new QLabel(toolbar); + spacer->setBackgroundMode(QWidget::PaletteButton); + toolbar->setStretchableWidget(spacer); + + abort = new QAction(tr("Abort sending"), QIconSet(Resource::loadPixmap("mail/abort")), 0, 0, this); + abort->addTo(toolbar); + + QWidget *main = new QWidget(this); + setCentralWidget(main); + + QGridLayout *layout = new QGridLayout(main); + + fromBox = new QComboBox(main); + fromBox->insertItem(tr("From"), POPUP_FROM_FROM); + fromBox->insertItem(tr("Reply"), POPUP_FROM_REPLYTO); + layout->addWidget(fromBox, 0, 0); + + connect(fromBox, SIGNAL(activated(int)), SLOT(slotFromMenuChanged(int))); + + QHBoxLayout *fromLayout = new QHBoxLayout(); + layout->addLayout(fromLayout, 0, 1); + + from = new QComboBox(main); + fromLayout->addWidget(from); + + replyto = new QLineEdit(main); + replyto->hide(); + fromLayout->addWidget(replyto); + + receiversBox = new QComboBox(main); + receiversBox->insertItem(tr("To"), POPUP_RECV_TO); + receiversBox->insertItem(tr("Cc"), POPUP_RECV_CC); + receiversBox->insertItem(tr("Bcc"), POPUP_RECV_BCC); + layout->addWidget(receiversBox, 1, 0); + + connect(receiversBox, SIGNAL(activated(int)), SLOT(slotReceiverMenuChanged(int))); + + QHBoxLayout *receiverLayout = new QHBoxLayout(); + layout->addLayout(receiverLayout, 1, 1); + + to = new QLineEdit(main); + receiverLayout->addWidget(to); + + cc = new QLineEdit(main); + cc->hide(); + receiverLayout->addWidget(cc); + + bcc = new QLineEdit(main); + bcc->hide(); + receiverLayout->addWidget(bcc); + + subjectBox = new QComboBox(main); + subjectBox->insertItem(tr("Subj."), POPUP_SUBJ_SUBJECT); + subjectBox->insertItem(tr("Prio."), POPUP_SUBJ_PRIORITY); + layout->addWidget(subjectBox, 2, 0); + connect(subjectBox, SIGNAL(activated(int)), SLOT(slotSubjectMenuChanged(int))); + + QHBoxLayout *subjectLayout = new QHBoxLayout(); + layout->addLayout(subjectLayout, 2, 1); + + subject = new QLineEdit(main); + subjectLayout->addWidget(subject); + + priority = new QComboBox(main); + priority->insertItem(tr("Low"), POPUP_PRIO_LOW); + priority->insertItem(tr("Normal"), POPUP_PRIO_NORMAL); + priority->insertItem(tr("High"), POPUP_PRIO_HIGH); + priority->setCurrentItem(POPUP_PRIO_NORMAL); + priority->hide(); + subjectLayout->addWidget(priority); + + QVBox *view = new QVBox(main); + layout->addMultiCellWidget(view, 3, 3, 0, 1); + + message = new QMultiLineEdit(view); + message->setMinimumHeight(30); + + attachWindow = new QMainWindow(view, 0, 0); + attachWindow->setMinimumHeight(100); + attachWindow->setMaximumHeight(100); + attachWindow->setToolBarsMovable(false); + attachWindow->hide(); + + attachToolbar = new QToolBar(attachWindow); + attachToolbar->setVerticalStretchable(true); + + addattach = new QAction(tr("Add an Attachement"), QIconSet(Resource::loadPixmap("mail/newmail")), 0, 0, this); + addattach->addTo(attachToolbar); + + delattach = new QAction(tr("Remove Attachement"), QIconSet(Resource::loadPixmap("mail/delete")), 0, 0, this); + delattach->addTo(attachToolbar); + + QLabel *attachSpacer = new QLabel(attachToolbar); + attachSpacer->setBackgroundMode(QWidget::PaletteButton); + attachToolbar->setStretchableWidget(attachSpacer); + + attachWindow->addToolBar(attachToolbar, QMainWindow::Left); + + attachView = new ListViewPlus(attachWindow); + attachView->addColumn(tr("Name"), 80); + attachView->addColumn(tr("Description"), 110); + attachView->setAllColumnsShowFocus(true); + attachWindow->setCentralWidget(attachView); + + attachPopup = new QPopupMenu(attachView); + attachPopup->insertItem(tr("Rename"), POPUP_ATTACH_RENAME); + attachPopup->insertItem(tr("Change Description"), POPUP_ATTACH_DESC); + attachPopup->insertSeparator(); + attachPopup->insertItem(tr("Remove"), POPUP_ATTACH_REMOVE); + attachView->setPopup(attachPopup); + + status = new QLabel(view); + QFont tmpFont = status->font(); + tmpFont.setPixelSize(8); + status->setFont(tmpFont); +} + +void ComposerBase::slotAttachfileChanged(bool toggled) +{ + if (toggled) { + if (attachWindow->isHidden()) attachWindow->show(); + } else { + if (!attachWindow->isHidden()) attachWindow->hide(); + } +} + +void ComposerBase::slotFromMenuChanged(int id) +{ + if (POPUP_FROM_FROM == id) { + if (from->isHidden()) from->show(); + if (!replyto->isHidden()) replyto->hide(); + } else if (POPUP_FROM_REPLYTO == id) { + if (!from->isHidden()) from->hide(); + if (replyto->isHidden()) replyto->show(); + } +} + +void ComposerBase::slotReceiverMenuChanged(int id) +{ + if (POPUP_RECV_TO == id) { + if (to->isHidden()) to->show(); + if (!cc->isHidden()) cc->hide(); + if (!bcc->isHidden()) bcc->hide(); + } else if (POPUP_RECV_CC == id) { + if (!to->isHidden()) to->hide(); + if (cc->isHidden()) cc->show(); + if (!bcc->isHidden()) bcc->hide(); + } else if (POPUP_RECV_BCC == id) { + if (!to->isHidden()) to->hide(); + if (!cc->isHidden()) cc->hide(); + if (bcc->isHidden()) bcc->show(); + } +} + +void ComposerBase::slotSubjectMenuChanged(int id) +{ + if (POPUP_SUBJ_SUBJECT == id) { + if (subject->isHidden()) subject->show(); + if (!priority->isHidden()) priority->hide(); + } else if (POPUP_SUBJ_PRIORITY == id) { + if (!subject->isHidden()) subject->hide(); + if (priority->isHidden()) priority->show(); + } +} diff --git a/noncore/unsupported/mail2/composerbase.h b/noncore/unsupported/mail2/composerbase.h new file mode 100644 index 0000000..e5fab67 --- a/dev/null +++ b/noncore/unsupported/mail2/composerbase.h @@ -0,0 +1,55 @@ +#ifndef COMPOSERBASE_H +#define COMPOSERBASE_H + +#include <qmainwindow.h> + +class QMultiLineEdit; +class ListViewPlus; +class QPopupMenu; +class QComboBox; +class QLineEdit; +class QToolBar; +class QAction; +class QLabel; + +class ComposerBase : public QMainWindow +{ + Q_OBJECT + +public: + ComposerBase(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected: + static const int POPUP_FROM_FROM = 0; + static const int POPUP_FROM_REPLYTO = 1; + static const int POPUP_RECV_TO = 0; + static const int POPUP_RECV_CC = 1; + static const int POPUP_RECV_BCC = 2; + static const int POPUP_SUBJ_SUBJECT = 0; + static const int POPUP_SUBJ_PRIORITY = 1; + static const int POPUP_PRIO_LOW = 0; + static const int POPUP_PRIO_NORMAL = 1; + static const int POPUP_PRIO_HIGH = 2; + static const int POPUP_ATTACH_RENAME = 0; + static const int POPUP_ATTACH_DESC = 1; + static const int POPUP_ATTACH_REMOVE = 2; + + QMultiLineEdit *message; + ListViewPlus *attachView; + QMainWindow *attachWindow; + QPopupMenu *attachPopup; + QComboBox *fromBox, *from, *receiversBox, *subjectBox, *priority; + QLineEdit *replyto, *to, *cc, *bcc, *subject; + QToolBar *toolbar, *attachToolbar; + QAction *sendmail, *attachfile, *addressbook, *abort, *addattach, *delattach; + QLabel *fromLabel, *status; + +protected slots: + void slotAttachfileChanged(bool toggled); + void slotFromMenuChanged(int id); + void slotReceiverMenuChanged(int id); + void slotSubjectMenuChanged(int id); + +}; + +#endif diff --git a/noncore/unsupported/mail2/configdiag.cpp b/noncore/unsupported/mail2/configdiag.cpp new file mode 100644 index 0000000..be1f1f4 --- a/dev/null +++ b/noncore/unsupported/mail2/configdiag.cpp @@ -0,0 +1,144 @@ +#include <qmessagebox.h> +#include <qpushbutton.h> +#include <qtoolbutton.h> +#include <qgroupbox.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qheader.h> +#include <qtimer.h> +#include <qlabel.h> + +#include <qpe/resource.h> +#include <qpe/config.h> + +#include "accounteditor.h" +#include "zaurusstuff.h" +#include "configdiag.h" +#include "defines.h" + +AccountListItem::AccountListItem(QListView *parent, Account &account) + : QListViewItem(parent), _account(account) +{ + QString displayText; + if (!_account.realName().isEmpty() && !_account.email().isEmpty()) + setText(0, _account.realName() + " <" + _account.email() + ">"); + else if (_account.realName().isEmpty() && !_account.email().isEmpty()) + setText(0, _account.email()); + else if (!_account.realName().isEmpty() && _account.email().isEmpty()) + setText(0, _account.realName()); + else + setText(0, QObject::tr("(no name)")); + + setPixmap(0, Resource::loadPixmap("mail/inbox")); +} + +ConfigDiag::ConfigDiag(QWidget *parent, const char *name, bool modal, WFlags fl) + : ConfigDiagBase(parent, name, modal, fl) +{ + _configBenD = new Config("mail"); + _configBenD->setGroup("Settings"); + disabled->setChecked(_configBenD->readBoolEntry("Disabled", false)); + playSound->setChecked(_configBenD->readBoolEntry("PlaySound", false)); + blinkLed->setChecked(_configBenD->readBoolEntry("BlinkLed", true)); + checkDelay->setValue(_configBenD->readNumEntry("CheckDelay", 5)); + + accountList->header()->hide(); + disclaimer->setText(disclaimer->text().arg(VERSION)); + + connect(accountNew, SIGNAL(clicked()), SLOT(slotNewAccount())); + connect(accountEdit, SIGNAL(clicked()), SLOT(slotEditAccount())); + connect(accountDelete, SIGNAL(clicked()), SLOT(slotDelAccount())); + + connect(testbutton, SIGNAL(clicked()), SLOT(slotTestSettings())); + + slotFillLists(); +} + +void ConfigDiag::accept() +{ + _configBenD->setGroup("Settings"); + _configBenD->writeEntry("Disabled", disabled->isChecked()); + _configBenD->writeEntry("PlaySound", playSound->isChecked()); + _configBenD->writeEntry("BlinkLed", blinkLed->isChecked()); + _configBenD->writeEntry("CheckDelay", checkDelay->value()); + _configBenD->write(); + + QDialog::accept(); +} + +void ConfigDiag::slotFillLists() +{ + accountList->clear(); + + QValueList<Account> accounts = ConfigFile::getAccounts(); + + QValueList<Account>::Iterator it; + for (it = accounts.begin(); it != accounts.end(); it++) + (void) new AccountListItem(accountList, *it); +} + +void ConfigDiag::slotNewAccount() +{ + AccountEditor *editor = new AccountEditor(Account(), 0, 0, true); + editor->showMaximized(); + editor->show(); + + if (QDialog::Accepted == editor->exec()) { + ConfigFile::updateAccount(editor->_account); + slotFillLists(); + emit changed(); + } +} + +void ConfigDiag::slotEditAccount() +{ + if (!accountList->currentItem()) { + QMessageBox::information(this, tr("Error"), tr("<p>You have to select an account first.</p>"), tr("Ok")); + return; + } + Account account = ((AccountListItem *)accountList->currentItem())->account(); + + AccountEditor *editor = new AccountEditor(account, 0, 0, true); + editor->showMaximized(); + editor->show(); + + if (QDialog::Accepted == editor->exec()) { + ConfigFile::updateAccount(editor->_account); + slotFillLists(); + emit changed(); + } +} + +void ConfigDiag::slotDelAccount() +{ + if (!accountList->currentItem()) { + QMessageBox::information(this, tr("Error"), tr("<p>You have to select an account first.</p>"), tr("Ok")); + return; + } + Account account = ((AccountListItem *)accountList->currentItem())->account(); + + int ret = QMessageBox::information(this, tr("Question"), tr("<p>Do you relly want to delete the selected account?</p>"), tr("Yes"), tr("No")); + if (1 == ret) return; + + ConfigFile::deleteAccount(account); + slotFillLists(); + emit changed(); +} + +void ConfigDiag::slotTestSettings() +{ + testbutton->setEnabled(false); + + if (blinkLed->isChecked()) ZaurusStuff::blinkLedOn(); + if (playSound->isChecked()) ZaurusStuff::buzzerOn(); + QTimer::singleShot(3000, this, SLOT(slotEndTest())); +} + +void ConfigDiag::slotEndTest() +{ + if (playSound->isChecked()) ZaurusStuff::buzzerOff(); + if (blinkLed->isChecked()) ZaurusStuff::blinkLedOff(); + + testbutton->setEnabled(true); +} + diff --git a/noncore/unsupported/mail2/configdiag.h b/noncore/unsupported/mail2/configdiag.h new file mode 100644 index 0000000..f70ba7f --- a/dev/null +++ b/noncore/unsupported/mail2/configdiag.h @@ -0,0 +1,48 @@ +#ifndef CONFIGDIAG_H +#define CONFIGDIAG_H + +#include <qlistview.h> + +#include "configdiagbase.h" +#include "configfile.h" + +class Config; +class Account; + +class AccountListItem : public QListViewItem +{ +public: + AccountListItem(QListView *parent, Account &account); + + Account account() { return _account; } + +protected: + Account _account; + +}; + +class ConfigDiag : public ConfigDiagBase +{ + Q_OBJECT + +public: + ConfigDiag(QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags fl = 0); + +signals: + void changed(); + +protected slots: + void accept(); + void slotFillLists(); + void slotNewAccount(); + void slotEditAccount(); + void slotDelAccount(); + void slotTestSettings(); + void slotEndTest(); + +private: + Config *_configBenD; + +}; + +#endif diff --git a/noncore/unsupported/mail2/configdiagbase.ui b/noncore/unsupported/mail2/configdiagbase.ui new file mode 100644 index 0000000..754458a --- a/dev/null +++ b/noncore/unsupported/mail2/configdiagbase.ui @@ -0,0 +1,352 @@ +<!DOCTYPE UI><UI> +<class>ConfigDiagBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>ConfigDiagBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>260</width> + <height>344</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Configuration</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>0</number> + </property> + <widget row="0" column="0" > + <class>QTabWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>TabWidget2</cstring> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Accounts</string> + </attribute> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="1" column="1" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>accountEdit</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Edit</string> + </property> + </widget> + <widget row="1" column="2" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>accountDelete</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Delete</string> + </property> + </widget> + <widget row="0" column="0" rowspan="1" colspan="3" > + <class>QListView</class> + <column> + <property> + <name>text</name> + <string>[Hidden]</string> + </property> + <property> + <name>clickable</name> + <bool>true</bool> + </property> + <property> + <name>resizeable</name> + <bool>true</bool> + </property> + </column> + <property stdset="1"> + <name>name</name> + <cstring>accountList</cstring> + </property> + </widget> + <widget row="1" column="0" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>accountNew</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>New</string> + </property> + </widget> + </grid> + </widget> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>General</string> + </attribute> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <spacer row="1" column="0" > + <property> + <name>name</name> + <cstring>Spacer5</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget row="0" column="0" > + <class>QGroupBox</class> + <property stdset="1"> + <name>name</name> + <cstring>notificationGroup</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>Mail notification</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="1" column="0" > + <class>QFrame</class> + <property stdset="1"> + <name>name</name> + <cstring>Frame3</cstring> + </property> + <property stdset="1"> + <name>frameShape</name> + <enum>NoFrame</enum> + </property> + <property stdset="1"> + <name>frameShadow</name> + <enum>Raised</enum> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="1" column="0" rowspan="1" colspan="3" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>blinkLed</cstring> + </property> + <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + </sizepolicy> + </property> + <property stdset="1"> + <name>text</name> + <string>Blink LED (Zaurus only)</string> + </property> + </widget> + <widget row="2" column="2" > + <class>QToolButton</class> + <property stdset="1"> + <name>name</name> + <cstring>testbutton</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string> Test </string> + </property> + </widget> + <widget row="0" column="0" rowspan="1" colspan="3" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>playSound</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Play sound (Zaurus only)</string> + </property> + </widget> + <widget row="2" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Check&nbsp;every</string> + </property> + </widget> + <widget row="2" column="1" > + <class>QSpinBox</class> + <property stdset="1"> + <name>name</name> + <cstring>checkDelay</cstring> + </property> + <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + </sizepolicy> + </property> + <property stdset="1"> + <name>suffix</name> + <string> min</string> + </property> + <property stdset="1"> + <name>maxValue</name> + <number>30</number> + </property> + <property stdset="1"> + <name>minValue</name> + <number>1</number> + </property> + <property stdset="1"> + <name>value</name> + <number>1</number> + </property> + </widget> + </grid> + </widget> + <widget row="0" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>disabled</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Disable mail notification</string> + </property> + </widget> + </grid> + </widget> + <widget row="2" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>disclaimer</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><p><b>Mail version %1</b><hr> +Sponsored and Programmed by LISAsystems<br> +Visit http://www.lisa.de/ for Information. + </string> + </property> + </widget> + </grid> + </widget> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>disabled</sender> + <signal>toggled(bool)</signal> + <receiver>Frame3</receiver> + <slot>setDisabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>TabWidget2</tabstop> + <tabstop>accountList</tabstop> + <tabstop>accountNew</tabstop> + <tabstop>accountEdit</tabstop> + <tabstop>accountDelete</tabstop> + <tabstop>disabled</tabstop> + <tabstop>playSound</tabstop> + <tabstop>blinkLed</tabstop> + <tabstop>checkDelay</tabstop> +</tabstops> +</UI> diff --git a/noncore/unsupported/mail2/folderwidget.cpp b/noncore/unsupported/mail2/folderwidget.cpp new file mode 100644 index 0000000..ca2bb5a --- a/dev/null +++ b/noncore/unsupported/mail2/folderwidget.cpp @@ -0,0 +1,314 @@ +#include <qmessagebox.h> +#include <qtextstream.h> +#include <qpopupmenu.h> +#include <qheader.h> +#include <qfile.h> +#include <qdir.h> + +#include <qpe/resource.h> + +#include <stdlib.h> + +#include "folderwidget.h" +#include "imaphandler.h" +#include "imapbase.h" +#include "rename.h" + +FolderWidgetItem::FolderWidgetItem(Folder &folder, QListView *parent) + : QListViewItem(parent), _folder(folder) +{ + setPixmap(0, QPixmap(Resource::loadPixmap("mail/inbox"))); + setText(0, _folder.topFolder().account().user() + " (" + _folder.topFolder().account().imapServer() + ")"); + setOpen(true); +} + +FolderWidgetItem::FolderWidgetItem(Folder &folder, FolderWidgetItem *parent) + : QListViewItem(parent), _folder(folder) +{ + if (_folder.noCache()) { + setText(0, QObject::tr("<Foldertree not known.>")); + } else { + if (folder.fullName().upper() == "INBOX") { + setPixmap(0, QPixmap(Resource::loadPixmap("mail/inbox"))); + setText(0, QObject::tr("Inbox")); + } else { + setPixmap(0, QPixmap(Resource::loadPixmap("mail/folder"))); + setText(0, folder.fullName()); + } + setOpen(true); + } +} + +FolderWidget::FolderWidget(QWidget *parent, const char *name, WFlags fl) + : ListViewPlus(parent, name, fl) +{ + header()->hide(); + addColumn(""); + setSorting(-1); + + QPopupMenu *menu = new QPopupMenu(); + menu->insertItem(tr("Rename"), MENU_RENAME); + menu->insertItem(tr("Delete"), MENU_DELETE); + menu->insertItem(tr("Move"), MENU_MOVE); + menu->insertItem(tr("Copy"), MENU_COPY); + menu->insertSeparator(); + menu->insertItem(tr("Create folder"), MENU_CREATE); + menu->insertSeparator(); + menu->insertItem(tr("Rescan folder list"), MENU_RESCAN); + setPopup(menu); + + getAccounts(); + + connect(menu, SIGNAL(activated(int)), SLOT(slotMenuActivated(int))); + connect(this, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *))); +} + +FolderWidget::~FolderWidget() +{ + // TODO: Save folder tree. +} + +void FolderWidget::update() +{ + getAccounts(); +} + +void FolderWidget::getAccounts() +{ + clear(); + + QValueList<Account> accounts = ConfigFile::getAccounts(); + QValueList<Account>::Iterator it; + for (it = accounts.begin(); it != accounts.end(); it++) { + FolderWidgetItem *item = addAccount(*it); + QFile f((QString) getenv("HOME") + "/Applications/mail/foldercache/foldercache-" + (*it).accountName()); + if (!f.open(IO_ReadOnly)) { + Folder folder; + folder.setNoCache(true); + addFolder(folder, item); + } else { + QTextStream t(&f); + while (!t.atEnd()) { + QString separator = t.readLine(); + QString fullname = t.readLine(); + Folder folder; + folder.setSeparator(separator); + folder.setFullName(fullname); + folder.setTopFolder(item->folder().topFolder()); + addFolder(folder, item); + } + f.close(); + } + } +} + +FolderWidgetItem *FolderWidget::addAccount(Account &account) +{ + TopFolder tf; + tf.setAccount(account); + + // XXX This has to change!!! The folderwidget may not create an + // XXX IMAPHandler!!!! Do this in IMAPHandler! + tf.setIMAPHandler(new IMAPHandler(account)); + + Folder folder; + folder.setTopFolder(tf); + + connect(tf.handler(), SIGNAL(IMAPLookingUpHost()), SLOT(slotIMAPLookingUpHost())); + connect(tf.handler(), SIGNAL(IMAPHostFound()), SLOT(slotIMAPHostFound())); + connect(tf.handler(), SIGNAL(IMAPConnected()), SLOT(slotIMAPConnected())); + connect(tf.handler(), SIGNAL(IMAPDisconnected()), SLOT(slotIMAPDisconnected())); + connect(tf.handler(), SIGNAL(IMAPError(int)), SLOT(slotIMAPError(int))); + + return new FolderWidgetItem(folder, this); +} + +FolderWidgetItem *FolderWidget::addFolder(Folder &folder, FolderWidgetItem *folderWidgetItem) +{ + return new FolderWidgetItem(folder, folderWidgetItem); +} + +void FolderWidget::slotMenuActivated(int itemid) +{ + if (currentItem() == NULL) { + QMessageBox::information(this, tr("Error"), tr("<p>Please select an item first.</p>"), tr("Ok")); + return; + } + + if (itemid == MENU_RENAME) { + if (((FolderWidgetItem *)currentItem())->folder().fullName().isEmpty()) return; + + Folder folder = ((FolderWidgetItem *)currentItem())->folder(); + QString newName = Rename::rename(folder.fullName(), this); + if (newName.isNull()) return; + + folder.topFolder().handler()->iRename(folder.fullName(), newName); + connect(folder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPRename(IMAPResponse &))); + } else if (itemid == MENU_DELETE) { + if (((FolderWidgetItem *)currentItem())->folder().fullName().isEmpty()) return; + + Folder folder = ((FolderWidgetItem *)currentItem())->folder(); + + int ret = QMessageBox::information(this, tr("Question"), tr("<p>Do you really want to delete <pre>%1</pre>?").arg(folder.fullName()), tr("Yes"), tr("No")); + if (ret == 1) return; + + _createFolder = folder; + + folder.topFolder().handler()->iDelete(folder.fullName()); + connect(folder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPDelete(IMAPResponse &))); + } else if (itemid == MENU_MOVE) { + + } else if (itemid == MENU_COPY) { + + } else if (itemid == MENU_CREATE) { + Folder folder = (((FolderWidgetItem *)currentItem())->folder()); + _createFolder = folder; + + QString folderName = Rename::getText(tr("Foldername"), tr("<p>Please enter the name of the new folder.</p>"), this); + if (folderName.isNull()) return; + + folder.topFolder().handler()->iCreate(folder.fullName() + folder.separator() + folderName); + connect(folder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPCreate(IMAPResponse &))); + } else if (itemid == MENU_RESCAN) { + Folder folder = (((FolderWidgetItem *)currentItem())->folder()); + _rescanAccount = folder.topFolder().account(); + + folder.topFolder().handler()->iList(".", "*"); + connect(folder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPList(IMAPResponse &))); + } +} + +void FolderWidget::slotItemClicked(QListViewItem *item) +{ + if (item == NULL) return; + Folder folder = ((FolderWidgetItem *)item)->folder(); + if (folder.fullName().isEmpty()) return; + + emit folderSelected(folder); +} + +void FolderWidget::slotIMAPLookingUpHost() +{ + emit status(tr("Looking up host...")); + emit connecting(); +} + +void FolderWidget::slotIMAPHostFound() +{ + emit status(tr("Host found.")); +} + +void FolderWidget::slotIMAPConnected() +{ + emit status(tr("Connected to host.")); + emit connected(); +} + +void FolderWidget::slotIMAPError(int error) +{ + if (error == IMAPBase::IMAPErrConnectionRefused) { + QMessageBox::warning(this, tr("Error"), tr("<p>The IMAP connection was refused.</p>"), tr("Ok")); + } else if (error == IMAPBase::IMAPErrHostNotFound) { + QMessageBox::warning(this, tr("Error"), tr("<p>The host was not found.</p>"), tr("Ok")); + } else if (error == IMAPBase::IMAPErrSocketRead) { + QMessageBox::warning(this, tr("Error"), tr("<p>There was an error while reading from the socket.</p>"), tr("Ok")); + } else if (error == IMAPBase::IMAPErrLoginFailed) { + QMessageBox::warning(this, tr("Error"), tr("<p>Login failed. Check your password/username.</p>"), tr("Ok")); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>An unknown error was encountered.</p>"), tr("Ok")); + } +} + +void FolderWidget::slotIMAPDisconnected() +{ + emit status(tr("Disconnected.")); + emit disconnected(); +} + +void FolderWidget::slotIMAPLogin(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPLogin(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + emit status(tr("Login successfull!")); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Login failed. Go away.</p>"), tr("Ok")); + } +} + +void FolderWidget::slotIMAPRename(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPRename(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + emit status(tr("Renaming successfull!")); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Renaming failed. (Server said: %1)</p>").arg(response.statusResponse().comment()), tr("Ok")); + } +} + +void FolderWidget::slotIMAPDelete(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPDelete(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + emit status(tr("Deletion successfull!")); + + _rescanAccount = _createFolder.topFolder().account(); + + _createFolder.topFolder().handler()->iList(".", "*"); + connect(_createFolder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPList(IMAPResponse &))); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Delete failed. (Server said: %1)</p>").arg(response.statusResponse().comment()), tr("Ok")); + } +} + +void FolderWidget::slotIMAPCreate(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPCreate(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + emit status(tr("Folder created. Rescanning...")); + + _rescanAccount = _createFolder.topFolder().account(); + + _createFolder.topFolder().handler()->iList(".", "*"); + connect(_createFolder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPList(IMAPResponse &))); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>The folder could not be created. (Server said: %1)</p>").arg(response.statusResponse().comment()), tr("Ok")); + } +} + +void FolderWidget::slotIMAPList(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPList(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + QDir d((QString) getenv("HOME") + "/Applications/mail/foldercache"); + if (!d.exists()) { + system("mkdir -p $HOME/Applications/mail/foldercache"); + qWarning("Created $HOME/Applications/mail/foldercache."); + } + QFile f((QString) getenv("HOME") + "/Applications/mail/foldercache/foldercache-" + _rescanAccount.accountName()); + if (!f.open(IO_WriteOnly)) { + QMessageBox::critical(this, tr("Error"), tr("<p>Couldn't open folder cache file for writing!</p>"), tr("Ok")); + return; + } + QTextStream t(&f); + + QValueList<IMAPResponseLIST>::Iterator it; + QValueList<IMAPResponseLIST> lists = response.LIST(); + for (it = lists.begin(); it != lists.end(); it++) { + t << (*it).folderSeparator() << "\n"; + t << (*it).folder() << "\n"; + } + + f.close(); + + emit status(tr("Got folder list.")); + getAccounts(); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Couldn't retrieve the folder list. (Server said: %1)</p>").arg(response.statusResponse().comment()), tr("Ok")); + } +} + diff --git a/noncore/unsupported/mail2/folderwidget.h b/noncore/unsupported/mail2/folderwidget.h new file mode 100644 index 0000000..bb10319 --- a/dev/null +++ b/noncore/unsupported/mail2/folderwidget.h @@ -0,0 +1,123 @@ +#ifndef FOLDERWIDGET_H +#define FOLDERWIDGET_H + +#include "imapresponse.h" +#include "listviewplus.h" +#include "configfile.h" + +class IMAPHandler; + +class TopFolder +{ +public: + TopFolder() + { + _valid = true; + } + + bool isValid() { return _valid; } + void setAccount(Account account) { _account = account; } + Account account() { return _account; } + void setIMAPHandler(IMAPHandler *handler) { _handler = handler; } + IMAPHandler *handler() { return _handler; } + +private: + bool _valid; + Account _account; + IMAPHandler *_handler; + +}; + +class Folder +{ +public: + Folder() + { + _valid = true; + _noCache = false; + } + + bool isValid() { return _valid; } + void setNoCache(bool noCache) { _noCache = noCache; } + bool noCache() { return _noCache; } + void setFullName(QString fullName) { _fullName = fullName; } + QString fullName() { return _fullName; } + void setSeparator(QString separator) { _separator = separator; } + QString separator() { return _separator; } + void setTopFolder(TopFolder topFolder) { _topFolder = topFolder; } + TopFolder topFolder() { return _topFolder; } + +private: + bool _valid, _noCache; + QString _fullName, _separator; + TopFolder _topFolder; + +}; + +class FolderWidgetItem : public QListViewItem +{ +public: + FolderWidgetItem(Folder &folder, QListView *parent); + FolderWidgetItem(Folder &folder, FolderWidgetItem *parent); + + Folder folder() { return _folder; } + +private: + Folder _folder; + +}; + +class FolderWidget : public ListViewPlus +{ + Q_OBJECT + +public: + FolderWidget(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + ~FolderWidget(); + +public slots: + void update(); + +signals: + void folderSelected(Folder folder); + void status(const QString &text); + void connecting(); + void connected(); + void disconnected(); + +protected: + void getAccounts(); + FolderWidgetItem *addFolder(Folder &folder, FolderWidgetItem *folderWidgetItem); + FolderWidgetItem *addAccount(Account &account); + + static const int MENU_RENAME = 0; + static const int MENU_DELETE = 1; + static const int MENU_MOVE = 2; + static const int MENU_COPY = 3; + static const int MENU_CREATE = 4; + static const int MENU_RESCAN = 5; + +protected slots: + void slotMenuActivated(int itemid); + void slotItemClicked(QListViewItem *item); + + void slotIMAPLookingUpHost(); + void slotIMAPHostFound(); + void slotIMAPConnected(); + void slotIMAPError(int error); + void slotIMAPDisconnected(); + + void slotIMAPLogin(IMAPResponse &response); + void slotIMAPRename(IMAPResponse &response); + void slotIMAPDelete(IMAPResponse &response); + void slotIMAPCreate(IMAPResponse &response); + void slotIMAPList(IMAPResponse &response); + +private: + Account _rescanAccount; + Folder _createFolder; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/libmail/configfile.cpp b/noncore/unsupported/mail2/libmail/configfile.cpp new file mode 100644 index 0000000..a5c2b49 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/configfile.cpp @@ -0,0 +1,112 @@ +#include <qdir.h> + +#include <qpe/config.h> + +#include <stdlib.h> + +#include "configfile.h" + +ConfigFile::ConfigFile() : QObject() +{ + checkDirectory(); + + QDir dir((QString) getenv("HOME") + "/Applications/mail/accounts"); + QStringList entries = dir.entryList("account-*"); + + QStringList::Iterator it; + for (it = entries.begin(); it != entries.end(); it++) { + Account account; + + Config *config = new Config((QString) getenv("HOME") + "/Applications/mail/accounts/" + *it, Config::File); + config->setGroup("Account"); + account.setAccountName((*it).replace(0, 8, "")); + account.setRealName(config->readEntry("RealName")); + account.setEmail(config->readEntry("Email")); + account.setOrg(config->readEntry("Organization")); + account.setImapServer(config->readEntry("ImapServer")); + account.setImapPort(config->readEntry("ImapPort")); + account.setSmtpServer(config->readEntry("SmtpServer")); + account.setSmtpPort(config->readEntry("SmtpPort")); + account.setUser(config->readEntry("User")); + account.setPass(rot13(config->readEntryCrypt("Pass"))); + account.setSmtpSsl(config->readBoolEntry("SmtpSsl")); + account.setSmtpSslPort(config->readEntry("SmtpSslPort")); + account.setImapSsl(config->readBoolEntry("ImapSsl")); + account.setImapSslPort(config->readEntry("ImapSslPort")); + account.setDefaultCc(config->readBoolEntry("DefaultCc")); + account.setDefaultBcc(config->readBoolEntry("DefaultBcc")); + account.setDefaultReplyTo(config->readBoolEntry("DefaultReplyTo")); + account.setCc(config->readEntry("Cc")); + account.setBcc(config->readEntry("Bcc")); + account.setReplyTo(config->readEntry("ReplyTo")); + account.setSignature(config->readEntry("Signature").replace(QRegExp("<br>"), "\n")); + + _accounts.append(account); + } +} + +QValueList<Account> ConfigFile::getAccounts() +{ + ConfigFile *configFile = new ConfigFile(); + return configFile->_accounts; +} + +void ConfigFile::updateAccount(Account account) +{ + checkDirectory(); + Config *config = new Config((QString) getenv("HOME") + "/Applications/mail/accounts/account-" + account.accountName(), Config::File); + + config->setGroup("Account"); + config->writeEntry("RealName", account.realName()); + config->writeEntry("Email", account.email()); + config->writeEntry("Organization", account.org()); + config->writeEntry("ImapServer", account.imapServer()); + config->writeEntry("ImapPort", account.imapPort()); + config->writeEntry("SmtpServer", account.smtpServer()); + config->writeEntry("SmtpPort", account.smtpPort()); + config->writeEntry("User", account.user()); + config->writeEntryCrypt("Pass", rot13(account.pass())); + config->writeEntry("SmtpSsl", account.smtpSsl()); + config->writeEntry("SmtpSslPort", account.smtpSslPort()); + config->writeEntry("ImapSsl", account.imapSsl()); + config->writeEntry("ImapSslPort", account.imapSslPort()); + config->writeEntry("DefaultCc", account.defaultCc()); + config->writeEntry("DefaultBcc", account.defaultBcc()); + config->writeEntry("DefaultReplyTo", account.defaultReplyTo()); + config->writeEntry("Cc", account.cc()); + config->writeEntry("Bcc", account.bcc()); + config->writeEntry("ReplyTo", account.replyTo()); + config->writeEntry("Signature", account.signature().replace(QRegExp("\\n"), "<br>")); + + config->write(); +} + +void ConfigFile::deleteAccount(Account account) +{ + QFile f((QString) getenv("HOME") + "/Applications/mail/accounts/account-" + account.accountName()); + f.remove(); +} + +void ConfigFile::checkDirectory() +{ + if (!QDir((QString) getenv("HOME") + "/Applications/mail/accounts").exists()) { + system("mkdir -p $HOME/Applications/mail/accounts"); + qWarning("mail: $HOME/Applications/mail/accounts created"); + } +} + +QString ConfigFile::rot13(const QString &input) +{ + QString i = input; + int l = i.length(); + while(l--) { + if (i[l] >= QChar('A') && i[l] <= QChar('M') || + i[l] >= QChar('a') && i[l] <= QChar('m')) + i[l] = (char)((int)QChar(l[i])+13); + else if (i[l] >= QChar('N') && i[l] <= QChar('Z') || + i[l] >= QChar('n') && i[l] <= QChar('z')) + i[l] = (char)((int)QChar(l[i])-13); + } + return i; +} + diff --git a/noncore/unsupported/mail2/libmail/configfile.h b/noncore/unsupported/mail2/libmail/configfile.h new file mode 100644 index 0000000..84b57d5 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/configfile.h @@ -0,0 +1,97 @@ +#ifndef CONFIGFILE_H +#define CONFIGFILE_H + +#include <qobject.h> + +class Config; + +class Account +{ +public: + Account() + { + _smtpssl = false; + _imapssl = false; + _dateField = false; + _msgIdField = false; + _defaultCc = false; + _defaultBcc = false; + _defaultRep = false; + } + + void setAccountName(QString accountName) { _accountName = accountName; } + + void setRealName(QString name) { _name = name; } + void setEmail(QString email) { _email = email; } + void setOrg(QString org) { _org = org; } + void setImapServer(QString imapServer) { _imapServer = imapServer; } + void setImapPort(QString imapPort) { _imapPort = imapPort; } + void setSmtpServer(QString smtpServer) { _smtpServer = smtpServer; } + void setSmtpPort(QString smtpPort) { _smtpPort = smtpPort; } + void setUser(QString user) { _user = user; } + void setPass(QString pass) { _pass = pass; } + void setSmtpSsl(bool smtpssl) { _smtpssl = smtpssl; } + void setSmtpSslPort(QString smtpSslPort) { _smtpSslPort = smtpSslPort; } + void setImapSsl(bool imapssl) { _imapssl = imapssl; } + void setImapSslPort(QString imapSslPort) { _imapSslPort = imapSslPort; } + void setDateField(bool dateField) { _dateField = dateField; } + void setMsgIdField(bool msgIdField) { _msgIdField = msgIdField; } + void setDefaultCc(bool defaultCc) { _defaultCc = defaultCc; } + void setDefaultBcc(bool defaultBcc) { _defaultBcc = defaultBcc; } + void setDefaultReplyTo(bool defaultRep) { _defaultRep = defaultRep; } + void setCc(QString cc) { _cc = cc; } + void setBcc(QString bcc) { _bcc = bcc; } + void setReplyTo(QString replyTo) { _replyTo = replyTo; } + void setSignature(QString signature) { _signature = signature; } + + QString accountName() { return _accountName; } + + QString realName() { return _name; } + QString email() { return _email; } + QString org() { return _org; } + QString imapServer() { return _imapServer; } + QString imapPort() { return _imapPort; } + QString smtpServer() { return _smtpServer; } + QString smtpPort() { return _smtpPort; } + QString user() { return _user; } + QString pass() { return _pass; } + bool smtpSsl() { return _smtpssl; } + QString smtpSslPort() { return _smtpSslPort; } + bool imapSsl() { return _imapssl; } + QString imapSslPort() { return _imapSslPort; } + bool dateField() { return _dateField; } + bool msgIdField() { return _msgIdField; } + bool defaultCc() { return _defaultCc; } + bool defaultBcc() { return _defaultBcc; } + bool defaultReplyTo() { return _defaultRep; } + QString cc() { return _cc; } + QString bcc() { return _bcc; } + QString replyTo() { return _replyTo; } + QString signature() { return _signature; } + +private: + QString _accountName, _name, _email, _org, _imapServer, _smtpServer, _user, _pass, _cc, _bcc, _replyTo, _imapPort, _smtpPort, _signature, _smtpSslPort, _imapSslPort; + bool _dateField, _msgIdField, _defaultCc, _defaultBcc, _defaultRep, _smtpssl, _imapssl; + +}; + +class ConfigFile : public QObject +{ + Q_OBJECT + +public: + static QValueList<Account> getAccounts(); + static void updateAccount(Account account); + static void deleteAccount(Account account); + +protected: + static void checkDirectory(); + static QString rot13(const QString &input); + + ConfigFile(); + + QValueList<Account> _accounts; + +}; + +#endif diff --git a/noncore/unsupported/mail2/libmail/defines.h b/noncore/unsupported/mail2/libmail/defines.h new file mode 100644 index 0000000..489cb0e --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/defines.h @@ -0,0 +1,8 @@ +#ifndef DEFINES_H +#define DEFINES_H + +#define VERSION "0.0.9" + +#define USERAGENT "LISAMail/" + VERSION + +#endif diff --git a/noncore/unsupported/mail2/libmail/imapbase.cpp b/noncore/unsupported/mail2/libmail/imapbase.cpp new file mode 100644 index 0000000..9a2ba47 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/imapbase.cpp @@ -0,0 +1,110 @@ +#include <qsocket.h> +#include <qtimer.h> + +#include "imapbase.h" + +IMAPBase::IMAPBase(const Account &account) + : QObject(), _account(account) +{ + _connected = false; + _writingAllowed = false; + _socket = new QSocket(this); + + connect(_socket, SIGNAL(readyRead()), SLOT(slotDataAvailiable())); + connect(_socket, SIGNAL(hostFound()), SLOT(slotHostFound())); + connect(_socket, SIGNAL(connected()), SLOT(slotConnected())); + connect(_socket, SIGNAL(connectionClosed()), SLOT(slotDisconnected())); + connect(_socket, SIGNAL(error(int)), SLOT(slotError(int))); + + QTimer *commandTimer = new QTimer(this); + commandTimer->start(200); + connect(commandTimer, SIGNAL(timeout()), SLOT(writeCommands())); +} + +void IMAPBase::sendCommand(const QString &command) +{ + if (!_connected) makeConnect(); + _commandQueue.append(command); +} + +void IMAPBase::disconnect() +{ + _connected = false; + delete _socket; + emit disconnected(); +} + +void IMAPBase::makeConnect() +{ + emit lookingUpHost(); + if (_socket == NULL) _socket = new QSocket(this); + + Q_UINT16 port = _account.imapPort().toUInt(); + _socket->connectToHost(_account.imapServer(), port); +} + +void IMAPBase::writeCommands() +{ + if (!_connected) return; + if (_commandQueue.isEmpty()) return; + if (!_writingAllowed) return; + + QStringList::Iterator it; + for (it = _commandQueue.begin(); it != _commandQueue.end(); it++) { + if (!(*it).isEmpty() && _writingAllowed) { +#ifndef QT_NO_DEBUG + qDebug("IMAP > " + (*it).stripWhiteSpace()); +#endif + _socket->writeBlock((*it).latin1(), (*it).length()); + _writingAllowed = false; + _commandQueue.remove(it); + break; + } + } +} + +void IMAPBase::slotError(int err) +{ + if (err == QSocket::ErrConnectionRefused) { + emit error(IMAPErrConnectionRefused); + } else if (err == QSocket::ErrHostNotFound) { + emit error(IMAPErrHostNotFound); + } else if (err == QSocket::ErrSocketRead) { + emit error(IMAPErrSocketRead); + } else { + emit error(IMAPErrUnknownError); + } +} + +void IMAPBase::slotHostFound() +{ + emit hostFound(); +} + +void IMAPBase::slotConnected() +{ + _connected = true; + emit connected(); +} + +void IMAPBase::slotDisconnected() +{ + _connected = false; + emit disconnected(); +} + +void IMAPBase::slotDataAvailiable() +{ + while (_socket->canReadLine()) { + _data += _socket->readLine(); + if (_socket->atEnd()) { +#ifndef QT_NO_DEBUG + qDebug("IMAP < " + _data.stripWhiteSpace()); +#endif + emit dataReceived(_data); + _writingAllowed = true; + _data = QString(0); + } + } +} + diff --git a/noncore/unsupported/mail2/libmail/imapbase.h b/noncore/unsupported/mail2/libmail/imapbase.h new file mode 100644 index 0000000..e4a0b97 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/imapbase.h @@ -0,0 +1,52 @@ +#ifndef IMAPBASE_H +#define IMAPBASE_H + +#include <qobject.h> + +#include "configfile.h" + +class QSocket; + +class IMAPBase : public QObject +{ + Q_OBJECT + +public: + IMAPBase(const Account &account); + + enum Error { IMAPErrConnectionRefused, IMAPErrHostNotFound, + IMAPErrSocketRead, IMAPErrUnknownError, + IMAPErrLoginFailed }; + + void sendCommand(const QString &command); + void disconnect(); + +signals: + void dataReceived(const QString &data); + void lookingUpHost(); + void hostFound(); + void connected(); + void disconnected(); + void error(int err); + +protected: + void makeConnect(); + +protected slots: + void writeCommands(); + void slotError(int error); + void slotHostFound(); + void slotConnected(); + void slotDisconnected(); + void slotDataAvailiable(); + +private: + Account _account; + QString _data; + QSocket *_socket; + QStringList _commandQueue; + bool _connected, _writingAllowed; + +}; + +#endif diff --git a/noncore/unsupported/mail2/libmail/imaphandler.cpp b/noncore/unsupported/mail2/libmail/imaphandler.cpp new file mode 100644 index 0000000..66c92c5 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/imaphandler.cpp @@ -0,0 +1,334 @@ +#include "imapresponse.h" +#include "imaphandler.h" +#include "imapbase.h" + +IMAPHandler::IMAPHandler(const Account &account) + : QObject(), _account(account) +{ + _loggingin = false; + _loggedin = false; + _tag = 0; + _ibase = new IMAPBase(account); + + connect(_ibase, SIGNAL(dataReceived(const QString &)), SLOT(slotDataReceived(const QString &))); + connect(_ibase, SIGNAL(lookingUpHost()), SLOT(slotLookingUpHost())); + connect(_ibase, SIGNAL(hostFound()), SLOT(slotHostFound())); + connect(_ibase, SIGNAL(connected()), SLOT(slotConnected())); + connect(_ibase, SIGNAL(disconnected()), SLOT(slotDisconnected())); + connect(_ibase, SIGNAL(error(int)), SLOT(slotError(int))); +} + +void IMAPHandler::doLogin() +{ + if (_loggedin) return; + if (_loggingin) return; + + _loggingin = true; + iLogin(_account.user(), _account.pass()); +} + +QString IMAPHandler::iCapability() +{ + _ibase->sendCommand(QString("%1 CAPABILITY\r\n") + .arg(tag())); + return tag(false); +} + +QString IMAPHandler::iNoop() +{ + _ibase->sendCommand(QString("%1 NOOP\r\n") + .arg(tag())); + return tag(false); +} + +QString IMAPHandler::iLogout() +{ + _ibase->sendCommand(QString("%1 LOGOUT\r\n") + .arg(tag())); + return tag(false); +} + +QString IMAPHandler::iAuthenticate(const QString &mechanism) +{ + _ibase->sendCommand(QString("%1 AUTHENTICATE \"%2\"\r\n") + .arg(tag()) + .arg(escape(mechanism))); + return tag(false); +} + +QString IMAPHandler::iLogin(const QString &user, const QString &pass) +{ + _ibase->sendCommand(QString("%1 LOGIN \"%2\" \"%3\"\r\n") + .arg(tag()) + .arg(escape(user)) + .arg(escape(pass))); + return tag(false); +} + +QString IMAPHandler::iSelect(const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 SELECT \"%2\"\r\n") + .arg(tag()) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iExamine(const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 EXAMINE \"%2\"\r\n") + .arg(tag()) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iCreate(const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 CREATE \"%2\"\r\n") + .arg(tag()) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iDelete(const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 DELETE \"%2\"\r\n") + .arg(tag()) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iRename(const QString &mailbox, const QString &newMailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 RENAME \"%2\" \"%3\"\r\n") + .arg(tag()) + .arg(escape(mailbox)) + .arg(escape(newMailbox))); + return tag(false); +} + +QString IMAPHandler::iSubscribe(const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 SUBSCRIBE \"%2\"\r\n") + .arg(tag()) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iUnsubscribe(const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 UNSUBSCRIBE \"%2\"\r\n") + .arg(tag()) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iList(const QString &reference, const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 LIST \"%2\" \"%3\"\r\n") + .arg(tag()) + .arg(escape(reference)) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iLsub(const QString &reference, const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 LSUB \"%2\" \"%3\"\r\n") + .arg(tag()) + .arg(escape(reference)) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iStatus(const QString &mailbox, const QString &items) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 STATUS \"%2\" (%3)\r\n") + .arg(tag()) + .arg(escape(mailbox)) + .arg(escape(items))); + return tag(false); +} + +QString IMAPHandler::iAppend(const QString &mailbox, const QString &literal, const QString &flags, const QString &datetime = 0) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 APPEND \"%2\" (%3) \"%4\" {%5}\r\n%6\r\n") + .arg(tag()) + .arg(escape(mailbox)) + .arg(flags) + .arg(escape(datetime)) + .arg(literal.length()) + .arg(literal)); + return tag(false); +} + +QString IMAPHandler::iCheck() +{ + doLogin(); + + _ibase->sendCommand(QString("%1 CHECK\r\n") + .arg(tag())); + return tag(false); +} + +QString IMAPHandler::iClose() +{ + doLogin(); + + _ibase->sendCommand(QString("%1 CLOSE\r\n") + .arg(tag())); + return tag(false); +} + +QString IMAPHandler::iExpunge() +{ + doLogin(); + + _ibase->sendCommand(QString("%1 EXPUNGE\r\n") + .arg(tag())); + return tag(false); +} + +QString IMAPHandler::iSearch(const QString &search, const QString &charset) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 SEARCH %2 %3\r\n") + .arg(tag()) + .arg(charset.isEmpty() ? QString(0) : escape(charset)) + .arg(search)); + return tag(false); +} + +QString IMAPHandler::iFetch(const QString &message, const QString &items) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 FETCH %2 (%3)\r\n") + .arg(tag()) + .arg(message) + .arg(items)); + return tag(false); +} + +QString IMAPHandler::iStore(const QString &message, const QString &items) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 STORE %2 %3\r\n") + .arg(tag()) + .arg(message) + .arg(items)); + return tag(false); +} + +QString IMAPHandler::iCopy(const QString &message, const QString &mailbox) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 COPY %2 \"%3\"\r\n") + .arg(tag()) + .arg(message) + .arg(escape(mailbox))); + return tag(false); +} + +QString IMAPHandler::iUid(const QString &command, const QString &arguments) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 UID %2 %3\r\n") + .arg(tag()) + .arg(command) + .arg(arguments)); + return tag(false); +} + +QString IMAPHandler::iX(const QString &commandAtom, const QString &arguments) +{ + doLogin(); + + _ibase->sendCommand(QString("%1 X%2 %3\r\n") + .arg(tag()) + .arg(commandAtom) + .arg(arguments)); + return tag(false); +} + +QString IMAPHandler::escape(const QString &in) +{ + QString in_ = in; + return in_.replace(QRegExp("\""), "\\\""); +} + +QString IMAPHandler::tag(bool count) +{ + return QString("a%1").arg(count ? _tag++ : _tag); +} + +void IMAPHandler::slotDataReceived(const QString &data) +{ + IMAPResponseParser parser(data); + IMAPResponse response = parser.response(); + response.setImapHandler(this); + + if (!_loggingin) emit gotResponse(response); + else { + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + _loggingin = false; + _loggedin = true; + qWarning("OK. Logged in. Leaving loggingin state."); + } else { + _loggingin = false; + emit IMAPError(IMAPBase::IMAPErrLoginFailed); + } + } +} + +void IMAPHandler::slotLookingUpHost() +{ + emit IMAPLookingUpHost(); +} + +void IMAPHandler::slotHostFound() +{ + emit IMAPHostFound(); +} + +void IMAPHandler::slotConnected() +{ + emit IMAPConnected(); +} + +void IMAPHandler::slotDisconnected() +{ + _loggedin = false; + emit IMAPDisconnected(); +} + +void IMAPHandler::slotError(int err) +{ + emit IMAPError(err); +} + diff --git a/noncore/unsupported/mail2/libmail/imaphandler.h b/noncore/unsupported/mail2/libmail/imaphandler.h new file mode 100644 index 0000000..8cb42db --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/imaphandler.h @@ -0,0 +1,86 @@ +#ifndef IMAPHANDLER_H +#define IMAPHANDLER_H + +#include <qobject.h> + +#include "configfile.h" + +class IMAPBase; +class IMAPResponse; + +class IMAPHandler : public QObject +{ + Q_OBJECT + +public: + IMAPHandler(const Account &account); + + QString iCapability(); + QString iNoop(); + QString iLogout(); + + QString iAuthenticate(const QString &mechanism); + QString iLogin(const QString &user, const QString &pass); + + QString iSelect(const QString &mailbox); + QString iExamine(const QString &mailbox); + QString iCreate(const QString &mailbox); + QString iDelete(const QString &mailbox); + QString iRename(const QString &mailbox, const QString &newMailbox); + + QString iSubscribe(const QString &mailbox); + QString iUnsubscribe(const QString &mailbox); + + QString iList(const QString &reference, const QString &mailbox); + QString iLsub(const QString &reference, const QString &mailbox); + + QString iStatus(const QString &mailbox, const QString &items); + + QString iAppend(const QString &mailbox, const QString &literal, const QString &flags = 0, const QString &datetime = 0); + + QString iCheck(); + QString iClose(); + QString iExpunge(); + + QString iSearch(const QString &search, const QString &charset = 0); + + QString iFetch(const QString &message, const QString &items); + + QString iStore(const QString &message, const QString &items); + QString iCopy(const QString &message, const QString &mailbox); + + QString iUid(const QString &command, const QString &arguments); + + QString iX(const QString &commandAtom, const QString &arguments); + +signals: + void gotResponse(IMAPResponse &response); + + void IMAPLookingUpHost(); + void IMAPHostFound(); + void IMAPConnected(); + void IMAPDisconnected(); + void IMAPError(int err); + +protected: + void doLogin(); + QString escape(const QString &in); + QString tag(bool count = true); + +protected slots: + void slotDataReceived(const QString &data); + void slotLookingUpHost(); + void slotHostFound(); + void slotConnected(); + void slotDisconnected(); + void slotError(int err); + +private: + Account _account; + IMAPBase *_ibase; + unsigned int _tag; + bool _loggingin, _loggedin; + +}; + +#endif diff --git a/noncore/unsupported/mail2/libmail/imapresponse.cpp b/noncore/unsupported/mail2/libmail/imapresponse.cpp new file mode 100644 index 0000000..06dca33 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/imapresponse.cpp @@ -0,0 +1,448 @@ +#include "imapresponse.h" + +static QString _previousData; +static unsigned int _neededData; + +IMAPResponseParser::IMAPResponseParser(const QString &data) +{ + QString _data = data, more; + _data.replace((QString)"\r\n", "\n"); + + QStringList lines = QStringList::split('\n', _data); + QStringList::Iterator it; + for (it = lines.begin(); it != lines.end(); it++) { + QString tag, lineData; + + if (!_previousData.isNull()) { + qDebug(QString("IMAPResponseParser: got additional data. (%1/%2)").arg(_previousData.length()).arg(_neededData)); + _previousData += *it + "\n"; + if (_previousData.length() >= _neededData) { + _previousData += ")"; + qDebug("IMAPResponseParser: got ALL additional data."); + qDebug("Data is: " + _previousData); + parseResponse(_previousData); + _previousData = QString(0); + _neededData = 0; + } + } else { + splitTagData(*it, tag, lineData); + if (tag == "*") { + int pos; + if ((pos = data.find(QRegExp("\\{\\d*\\}"))) != -1) { + qDebug("IMAPResponseParser: waiting for additional data..."); + _previousData = lineData + "\n"; + + QString tmp = data.right(data.length() - pos - 1).stripWhiteSpace(); + tmp.truncate(tmp.length() - 1); + + _neededData = tmp.toUInt(); + if (_previousData.length() >= _neededData) { + qDebug("IMAPResponseParser: got ALL additional data. (1st)"); + parseResponse(_previousData); + _previousData = QString(0); + _neededData = 0; + } else { + break; + } + } else { + parseResponse(lineData); + } + } else if (tag == "+") { + emit needMoreData(_data); + } else { + _iresponse.setTag(tag); + parseResponse(_data, true); + } + } + } +} + +IMAPResponse IMAPResponseParser::response() +{ + return _iresponse; +} + +void IMAPResponseParser::parseResponse(const QString &data, bool tagged) +{ + QString response, line; + int pos; + bool isNum = false; + if ((pos = data.find(' ')) != -1) { + response = data.left(pos).upper(); + response.toInt(&isNum); + line = data.right(data.length() - pos - 1); + } else { + qWarning("IMAPResponseParser: parseResponse: No response found."); + return; + } + + if (response == "OK" && tagged) { + IMAPResponseStatusResponse status(OK, line); + status.setResponseCode(getResponseCode(status.comment())); + _iresponse.setStatusResponse(status); + } else if (response == "OK" && !tagged) { + IMAPResponseOK ok(line, getResponseCode(line)); + _iresponse.addOK(ok); + } else if (response == "NO" && tagged) { + IMAPResponseStatusResponse status(NO, line); + status.setResponseCode(getResponseCode(status.comment())); + _iresponse.setStatusResponse(status); + } else if (response == "NO" && !tagged) { + IMAPResponseNO no(line, getResponseCode(line)); + _iresponse.addNO(no); + } else if (response == "BAD" && tagged) { + IMAPResponseStatusResponse status(BAD, line); + status.setResponseCode(getResponseCode(status.comment())); + _iresponse.setStatusResponse(status); + } else if (response == "BAD" && !tagged) { + IMAPResponseBAD bad(line, getResponseCode(line)); + _iresponse.addBAD(bad); + } else if (response == "PREAUTH" && tagged) { + IMAPResponseStatusResponse status(PREAUTH, line); + _iresponse.setStatusResponse(status); + } else if (response == "PREAUTH" && !tagged) { + qDebug("IMAPResponseParser: responseParser: got untagged PREAUTH response."); + // XXX + } else if (response == "BYE") { + IMAPResponseStatusResponse status(BYE, line); + if (!tagged) status.setExitedUnexpected(true); + _iresponse.setStatusResponse(status); + } else if (response == "CAPABILITY") { + IMAPResponseCAPABILITY capability(QStringList::split(' ', line)); + _iresponse.addCAPABILITY(capability); + } else if (response == "LIST") { + QStringList list = splitData(line, true); + + QStringList flags; + parseParenthesizedList(list[0], flags); + + removeLimiters(list[1]); + removeLimiters(list[2]); + IMAPResponseLIST rlist(parseFlagList(flags), list[1], list[2]); + _iresponse.addLIST(rlist); + } else if (response == "LSUB") { + QStringList list = splitData(line, true); + + QStringList flags; + parseParenthesizedList(list[0], flags); + + removeLimiters(list[1]); + removeLimiters(list[2]); + IMAPResponseLSUB lsub(parseFlagList(flags), list[1], list[2]); + _iresponse.addLSUB(lsub); + } else if (response == "STATUS") { + QStringList list = splitData(line, true); + + removeLimiters(list[0]); + IMAPResponseSTATUS status(list[0]); + + QStringList flags; + parseParenthesizedList(list[1], flags); + QStringList::Iterator it; + for (it = flags.begin(); it != flags.end(); it++) { + if (*it == "MESSAGES") status.setMessages(*(++it)); + else if (*it == "RECENT") status.setRecent(*(++it)); + else if (*it == "UIDNEXT") status.setUidnext(*(++it)); + else if (*it == "UIDVALIDITY") status.setUidvalidity(*(++it)); + else if (*it == "UNSEEN") status.setUnseen(*(++it)); + else qWarning("IMAPResponseParser: parseResponse: Unknown status data: " + *(it++) + "|"); + } + _iresponse.addSTATUS(status); + } else if (response == "SEARCH") { + IMAPResponseSEARCH search(QStringList::split(' ', line)); + _iresponse.addSEARCH(search); + } else if (response == "FLAGS") { + QStringList list; + parseParenthesizedList(line, list); + + IMAPResponseFLAGS flags(parseFlagList(list)); + _iresponse.addFLAGS(flags); + } else if (isNum) { + QStringList list = QStringList::split(' ', line); + if (list[0] == "EXISTS") { + IMAPResponseEXISTS exists(response); + _iresponse.addEXISTS(exists); + } else if (list[0] == "RECENT") { + IMAPResponseRECENT recent(response); + _iresponse.addRECENT(recent); + } else if (list[0] == "EXPUNGE") { + IMAPResponseEXPUNGE expunge(response); + _iresponse.addEXPUNGE(expunge); + } else if (list[0] == "FETCH") { + IMAPResponseFETCH fetch; + QStringList::Iterator it; + + QStringList fetchList = splitData(line, true); + QStringList list; + parseParenthesizedList(fetchList[1], list); + + for (it = list.begin(); it != list.end(); it++) { + if (*it == "BODY") { + qDebug("IMAPResponseParser: responseParser: got FETCH::BODY"); + // XXX + } else if ((*it).find(QRegExp("BODY\\[\\d+\\]")) != -1) { + QString bodydata = *(++it); + qDebug("IMAPResponseParser: responseParser: got FETCH::BODY[x]"); + + QStringList blist; + parseParenthesizedList(bodydata, blist); + + IMAPResponseBodyPart bodypart; + QString tmp; + for (unsigned int i = 2; i < blist.count(); i++) { + if (i != 2) tmp += " " + blist[i]; + else tmp += blist[i]; + } + bodypart.setData(tmp); + + tmp = list[0]; + tmp.replace(0, 5, ""); + tmp.truncate(blist[0].length() - 1); + bodypart.setPart(tmp); + + fetch.addBodyPart(bodypart); + } else if (*it == "BODYSTRUCTURE") { + qDebug("IMAPResponseParser: responseParser: got FETCH::BODYSTRUCTURE"); +/* + QString bsdata = *(++it); + QStringList bsList; + parseParenthesizedList(bsdata, bsList); + + IMAPResponseBodystructure bodystructure; + QStringList attachml; + + for (int i = 0; i < bsList.count() - 1; i++) { + parseParenthesizedList(bsList[0], attachml); + + IMAPResponseBodypart bodypart; + bodypart.setMimeTypeMain(attachml[0] == "NIL" ? QString(0) : attachml[0]); + bodypart.setMimeTypeSub(attachml[1] == "NIL" ? QString(0) : attachml[1]); + bodypart.setAddData(attachml[2] == "NIL" ? QString(0) : attachml[2]); + // 3 (NIL) + // 4 (NIL) + bodypart.setEncoding(attachml[5] == "NIL" ? QString(0) : attachml[5]); + bodypart.setSize(attachml[6] == "NIL" ? QString(0) : attachml[6]); + bodypart.setLength(attachml[7] == "NIL" ? QString(0) : attachml[7]); + bodypart.setAttachInfo(attachml[8] == "NIL" ? QString(0) : attachml[8]); + // 9 (NIL) + // 10 (NIL) + + bodystructure.addBodyPart(bodypart); + } +*/ + } else if (*it == "ENVELOPE") { + QString envdata = *(++it); + QStringList envList; + parseParenthesizedList(envdata, envList); + + IMAPResponseEnvelope envelope; + envelope.setMailDate(envList[0] == "NIL" ? QString(0) : removeLimiters(envList[0])); + envelope.setSubject(envList[1] == "NIL" ? QString(0) : removeLimiters(envList[1])); + + QStringList froml, senderl, replytol, tol, ccl, bccl; + QStringList froma, sendera, replytoa, toa, cca, bcca; + parseParenthesizedList(envList[2], froml); + parseParenthesizedList(envList[3], senderl); + parseParenthesizedList(envList[4], replytol); + parseParenthesizedList(envList[5], tol); + parseParenthesizedList(envList[6], ccl); + parseParenthesizedList(envList[7], bccl); + + QStringList::Iterator it; + for (it = froml.begin(); it != froml.end(); it++) { + parseParenthesizedList(*it, froma); + if (froml[0] != "NIL") + envelope.addFrom(IMAPResponseAddress( + removeLimiters(froma[0]), + removeLimiters(froma[1]), + removeLimiters(froma[2]), + removeLimiters(froma[3]))); + } + + for (it = senderl.begin(); it != senderl.end(); it++) { + parseParenthesizedList(*it, sendera); + if (senderl[0] != "NIL") + envelope.addSender(IMAPResponseAddress( + removeLimiters(sendera[0]), + removeLimiters(sendera[1]), + removeLimiters(sendera[2]), + removeLimiters(sendera[3]))); + } + + for (it = replytol.begin(); it != replytol.end(); it++) { + parseParenthesizedList(*it, replytoa); + if (replytol[0] != "NIL") + envelope.addReplyTo(IMAPResponseAddress( + removeLimiters(replytoa[0]), + removeLimiters(replytoa[1]), + removeLimiters(replytoa[2]), + removeLimiters(replytoa[3]))); + } + + for (it = tol.begin(); it != tol.end(); it++) { + parseParenthesizedList(*it, toa); + if (tol[0] != "NIL") + envelope.addTo(IMAPResponseAddress( + removeLimiters(toa[0]), + removeLimiters(toa[1]), + removeLimiters(toa[2]), + removeLimiters(toa[3]))); + } + + for (it = ccl.begin(); it != ccl.end(); it++) { + parseParenthesizedList(*it, cca); + if (ccl[0] != "NIL") + envelope.addCc(IMAPResponseAddress( + removeLimiters(cca[0]), + removeLimiters(cca[1]), + removeLimiters(cca[2]), + removeLimiters(cca[3]))); + } + + for (it = bccl.begin(); it != bccl.end(); it++) { + parseParenthesizedList(*it, bcca); + if (bccl[0] != "NIL") + envelope.addBcc(IMAPResponseAddress( + removeLimiters(bcca[0]), + removeLimiters(bcca[1]), + removeLimiters(bcca[2]), + removeLimiters(bcca[3]))); + } + + envelope.setInReplyTo(envList[7] == "NIL" ? QString(0) : removeLimiters(envList[7])); + envelope.setMessageId(envList[8] == "NIL" ? QString(0) : removeLimiters(envList[8])); + + fetch.setEnvelope(envelope); + } else if (*it == "FLAGS") { + QString flagdata = *(++it); + QStringList flags; + parseParenthesizedList(flagdata, flags); + fetch.setFlags(parseFlagList(flags)); + } else if (*it == "INTERNALDATE") { + fetch.setInternalDate(removeLimiters(*(++it))); + } else if (*it == "RFC822" || *it == "BODY[]") { + qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822"); + // XXX + } else if (*it == "RFC822.HEADER" || *it == "BODY.PEEK[HEADER]") { + qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822.HEADER"); + // XXX + } else if (*it == "RFC822.SIZE") { + fetch.setRFC822Size(*(++it)); + } else if (*it == "RFC822.TEXT" || *it == "BODY[TEXT]") { + qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822.TEXT"); + // XXX + } else if (*it == "UID") { + fetch.setUid(*(++it)); + } + } + _iresponse.addFETCH(fetch); + } + } else qWarning("IMAPResponseParser: parseResponse: Unknown response: " + response + "|"); +} + +QStringList IMAPResponseParser::splitData(const QString &data, bool withBrackets) +{ + int b = 0; + bool a = false, noappend = false, escaped = false; + QString temp; + QStringList list; + + for (unsigned int i = 0; i <= data.length(); i++) { + if (withBrackets && data[i] == '(' && !a) b++; + else if (withBrackets && data[i] == ')' && !a) b--; + + if (data[i] == '"' && !escaped) a = !a; + else escaped = false; + + if (data[i] == '\\' && data[i + 1] == '"') escaped = true; + + if ((data[i] == ' ' || i == data.length()) && b == 0 && !a) { + list.append(temp); + temp = QString(0); + if (data[i] == ' ') noappend = true; + } + + if (!noappend) temp += data[i]; + noappend = false; + } + + return list; +} + +void IMAPResponseParser::parseParenthesizedList(const QString &data, QStringList &parsed) +{ + QString data_(data); + removeLimiters(data_, '(', ')'); + parsed = splitData(data_, true); +} + +void IMAPResponseParser::splitTagData(const QString &line, QString &tag, QString &data) +{ + int pos; + if ((pos = line.find(' ')) != -1) { + tag = line.left(pos); + data = line.right(line.length() - pos - 1); + } else qWarning("IMAPResponseParser: splitTagData: tag not found. Line was " + line + "|"); +} + +QString IMAPResponseParser::removeLimiters(QString &string, const QChar &sl, const QChar &el) +{ + QString tmpString; + if (string[0] == sl && string[string.length() - 1] == el) { + string.truncate(string.length() - 1); + string.replace(0, 1, ""); + + for (unsigned int i = 1; i <= string.length(); i++) { + if (string[i - 1] == '\\' && sl == '"') ++i; + tmpString += string[i - 1]; + } + } + + return tmpString; +} + +IMAPResponseEnums::IMAPResponseCode IMAPResponseParser::getResponseCode(const QString &line) +{ + if (line.find(QRegExp((QString) "^\\[.*\\]" + ' ' + ".*")) != -1) { + int pos = line.find("] "); + QString code = line.left(pos + 1).upper(); + + if (code.find(QRegExp("[ALERT]")) != -1) return ALERT; + else if (code.find(QRegExp("[NEWNAME .* .*]")) != -1) return NEWNAME; // XXX + else if (code.find(QRegExp("[PARSE]")) != -1) return PARSE; + else if (code.find(QRegExp("[PERMANENTFLAGS \\d*]")) != -1) return PERMANENTFLAGS; // XXX + else if (code.find(QRegExp("[READ-ONLY]")) != -1) return READONLY; + else if (code.find(QRegExp("[READ-WRITE]")) != -1) return READWRITE; + else if (code.find(QRegExp("[TRYCREATE]")) != -1) return TRYCREATE; + else if (code.find(QRegExp("[UIDVALIDITY \\d*]")) != -1) return UIDVALIDITY; // XXX + else if (code.find(QRegExp("[UNSEEN \\d*]")) != -1) return UNSEEN; // XXX + else { + qWarning("IMAPResponseParser: getResponseCode: Unknown code: " + code + "|"); + return UnknownCode; + } + } + return NoCode; +} + +QValueList<IMAPResponseEnums::IMAPResponseFlags> IMAPResponseParser::parseFlagList(const QStringList &flagList) +{ + QValueList<IMAPResponseFlags> flags; + QStringList::ConstIterator it; + for (it = flagList.begin(); it != flagList.end(); it++) { + QString flag = (*it).lower(); + if (flag == "\\seen") flags.append(Seen); + else if (flag == "\\answered") flags.append(Answered); + else if (flag == "\\flagged") flags.append(Flagged); + else if (flag == "\\deleted") flags.append(Deleted); + else if (flag == "\\draft") flags.append(Draft); + else if (flag == "\\recent") flags.append(Recent); + else if (flag == "\\noinferiors") flags.append(Noinferiors); + else if (flag == "\\noselect") flags.append(Noselect); + else if (flag == "\\marked") flags.append(Marked); + else if (flag == "\\unmarked") flags.append(Unmarked); + else if (flag.isEmpty()) { } + else qWarning("IMAPResponseParser: parseFlagList: Unknown flag: " + *it + "|"); + } + return flags; +} + diff --git a/noncore/unsupported/mail2/libmail/imapresponse.h b/noncore/unsupported/mail2/libmail/imapresponse.h new file mode 100644 index 0000000..73435ee --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/imapresponse.h @@ -0,0 +1,531 @@ +#ifndef IMAPRESPONSE_H +#define IMAPRESPONSE_H + +#include <qobject.h> + +#define MAX_BODYPARTS 50 + +class IMAPHandler; + +class IMAPResponseEnums +{ +public: + enum IMAPResponseStatus { + OK, NO, BAD, PREAUTH, BYE, UnknownStatus = 0 + }; + + enum IMAPResponseFlags { + Seen, Answered, Flagged, Deleted, Draft, Recent, + Noinferiors, Noselect, Marked, Unmarked, UnknownFlag = 0 + }; + + enum IMAPResponseCode { + ALERT, NEWNAME, PARSE, PERMANENTFLAGS, READONLY, READWRITE, + TRYCREATE, UIDVALIDITY, UNSEEN, NoCode, UnknownCode = 0 + }; + +}; + +class IMAPResponseAddress +{ +public: + IMAPResponseAddress(QString name = 0, QString adl = 0, QString mailbox = 0, QString host = 0) + { + _name = name; + _adl = adl; + _mailbox = mailbox; + _host = host; + } + + void setName(QString name) { _name = name; } + QString name() { return _name; } + void setAdl(QString adl) { _adl = adl; } + QString adl() { return _adl; } + void setMailbox(QString mailbox) { _mailbox = mailbox; } + QString mailbox() { return _mailbox; } + void setHost(QString host) { _host = host; } + QString host() { return _host; } + + QString toString() + { + if (_name.isNull() && _mailbox.isNull() && _host.isNull()) + return QString(0); + if (_name != _mailbox + "@" + _host) + return _name + " <" + _mailbox + "@" + _host + ">"; + else + return _name; + } + + QString email() + { + if (_host.isEmpty()) return _mailbox; + else return _mailbox + "@" + _host; + } + +private: + QString _name, _adl, _mailbox, _host; + +}; + +class IMAPResponseAddressList : public QValueList<IMAPResponseAddress> +{ +public: + IMAPResponseAddressList() + : QValueList<IMAPResponseAddress>() + { + + } + + QString toString() + { + QString string; + IMAPResponseAddressList::Iterator it; + for (it = this->begin(); it != this->end(); it++) { + QString tmp = (*it).toString(); + if (!tmp.isNull() && string.isEmpty()) string = tmp; + else if (!tmp.isNull()) string += ", " + tmp; + } + return string; + } + +}; + +class IMAPResponseBody +{ +public: + void setData(QString data) { _data = data; } + QString data() { return _data; } + +private: + QString _data; + +}; + +class IMAPResponseBodyPart : public IMAPResponseBody +{ +public: + void setPart(QString part) { _part = part; } + QString part() { return _part; } + +private: + QString _part; + +}; + +class IMAPResponseEnvelope +{ +public: + void setMailDate(QString date) { _date = date; } + QString mailDate() { return _date; } + void setSubject(QString subject) { _subject = subject; } + QString subject() { return _subject; } + void addFrom(IMAPResponseAddress from) { _from.append(from); } + IMAPResponseAddressList from() { return _from; } + void addSender(IMAPResponseAddress sender) { _sender.append(sender); } + IMAPResponseAddressList sender() { return _sender; } + void addReplyTo(IMAPResponseAddress replyTo) { _replyTo.append(replyTo); } + IMAPResponseAddressList replyTo() { return _replyTo; } + void addTo(IMAPResponseAddress to) { _to.append(to); } + IMAPResponseAddressList to() { return _to; } + void addCc(IMAPResponseAddress cc) { _cc.append(cc); } + IMAPResponseAddressList cc() { return _cc; } + void addBcc(IMAPResponseAddress bcc) { _bcc.append(bcc); } + IMAPResponseAddressList bcc() { return _bcc; } + void setInReplyTo(QString inReplyTo) { _inReplyTo = inReplyTo; } + QString inReplyTo() { return _inReplyTo; } + void setMessageId(QString messageId) { _messageId = messageId; } + QString messageId() { return _messageId; } + +private: + QString _date, _subject, _inReplyTo, _messageId; + IMAPResponseAddressList _from, _sender, _replyTo, _to, _cc, _bcc; + +}; + +class IMAPResponseStatusResponse : public IMAPResponseEnums +{ +public: + IMAPResponseStatusResponse(IMAPResponseStatus status = (IMAPResponseStatus)0, QString comment = 0, IMAPResponseCode code = (IMAPResponseCode)0) + { + _status = status; + _comment = comment; + _code = code; + } + + void setStatus(IMAPResponseStatus status) { _status = status; } + IMAPResponseStatus status() { return _status; } + void setComment(QString comment) { _comment = comment; } + QString comment() { return _comment; } + void setResponseCode(IMAPResponseCode code) { _code = code; } + IMAPResponseCode responseCode() { return _code; } + + void setExitedUnexpected(bool exitu) { _exitu = exitu; } + bool exitedUnexpected() { return _exitu; } + +private: + IMAPResponseStatus _status; + QString _comment; + IMAPResponseCode _code; + bool _exitu; + +}; + +class IMAPResponseOK : public IMAPResponseEnums +{ +public: + IMAPResponseOK(QString comment = 0, IMAPResponseCode code = (IMAPResponseCode)0) + { + _comment = comment; + _code = code; + } + + void setComment(QString comment) { _comment = comment; } + QString comment() { return _comment; } + void setResponseCode(IMAPResponseCode code) { _code = code; } + IMAPResponseCode responseCode() { return _code; } + +private: + QString _comment; + IMAPResponseCode _code; + +}; + +class IMAPResponseNO : public IMAPResponseEnums +{ +public: + IMAPResponseNO(QString comment = 0, IMAPResponseCode code = (IMAPResponseCode)0) + { + _comment = comment; + _code = code; + } + + void setComment(QString comment) { _comment = comment; } + QString comment() { return _comment; } + void setResponseCode(IMAPResponseCode code) { _code = code; } + IMAPResponseCode responseCode() { return _code; } + +private: + QString _comment; + IMAPResponseCode _code; + +}; + +class IMAPResponseBAD : public IMAPResponseEnums +{ +public: + IMAPResponseBAD(QString comment = 0, IMAPResponseCode code = (IMAPResponseCode)0) + { + _comment = comment; + _code = code; + } + + void setComment(QString comment) { _comment = comment; } + QString comment() { return _comment; } + void setResponseCode(IMAPResponseCode code) { _code = code; } + IMAPResponseCode responseCode() { return _code; } + +private: + QString _comment; + IMAPResponseCode _code; + +}; + +class IMAPResponseCAPABILITY +{ +public: + IMAPResponseCAPABILITY(QStringList capabilities = 0) + { + _capabilities = capabilities; + } + + void setCapabilities(QStringList capabilities) { _capabilities = capabilities; } + QStringList capabilities() { return _capabilities; } + +private: + QStringList _capabilities; + +}; + +class IMAPResponseLIST : public IMAPResponseEnums +{ +public: + IMAPResponseLIST(QValueList<IMAPResponseFlags> flags = QValueList<IMAPResponseFlags>(), QString folderSeparator = 0, QString folder = 0) + { + _flags = flags; + _folderSeparator = folderSeparator; + _folder = folder; + } + + void setFlags(QValueList<IMAPResponseFlags> flags) { _flags = flags; } + QValueList<IMAPResponseFlags> flags() { return _flags; } + void setFolderSeparator(QString folderSeparator) { _folderSeparator = folderSeparator; } + QString folderSeparator() { return _folderSeparator; } + void setFolder(QString folder) { _folder = folder; } + QString folder() { return _folder; } + +private: + QValueList<IMAPResponseFlags> _flags; + QString _folderSeparator, _folder; + +}; + +class IMAPResponseLSUB : public IMAPResponseEnums +{ +public: + IMAPResponseLSUB(QValueList<IMAPResponseFlags> flags = QValueList<IMAPResponseFlags>(), QString folderSeperator = 0, QString folder = 0) + { + _flags = flags; + _folderSeperator = folderSeperator; + _folder = folder; + } + + void setFlags(QValueList<IMAPResponseFlags> flags) { _flags = flags; } + QValueList<IMAPResponseFlags> flags() { return _flags; } + void setFolderSeperator(QString folderSeperator) { _folderSeperator = folderSeperator; } + QString folderSeperator() { return _folderSeperator; } + void setFolder(QString folder) { _folder = folder; } + QString folder() { return _folder; } + +private: + QValueList<IMAPResponseFlags> _flags; + QString _folderSeperator, _folder; + +}; + +class IMAPResponseSTATUS +{ +public: + IMAPResponseSTATUS(QString mailbox = 0, QString messages = 0, QString recent = 0, QString uidnext = 0, QString uidvalidity = 0, QString unseen = 0) + { + _mailbox = mailbox; + _messages = messages; + _recent = recent; + _uidnext = uidnext; + _uidvalidity = uidvalidity; + _unseen = unseen; + } + + void setMailbox(QString &mailbox) { _mailbox = mailbox; } + QString mailbox() { return _mailbox; } + void setMessages(QString &messages) { _messages = messages; } + QString messages() { return _messages; } + void setRecent(QString &recent) { _recent = recent; } + QString recent() { return _recent; } + void setUidnext(QString &uidnext) { _uidnext = uidnext; } + QString uidnext() { return _uidnext; } + void setUidvalidity(QString &uidvalidity) { _uidvalidity = uidvalidity; } + QString uidvalidity() { return _uidvalidity; } + void setUnseen(QString &unseen) { _unseen = unseen; } + QString unseen() { return _unseen; } + +private: + QString _mailbox, _messages, _recent, _uidnext, _uidvalidity, _unseen; + +}; + +class IMAPResponseSEARCH +{ +public: + IMAPResponseSEARCH(QStringList mails = 0) + { + _mails = mails; + } + + void setMails(QStringList mails) { _mails = mails; } + QStringList mails() { return _mails; } + +private: + QStringList _mails; + +}; + +class IMAPResponseFLAGS : public IMAPResponseEnums +{ +public: + IMAPResponseFLAGS(QValueList<IMAPResponseFlags> flags = QValueList<IMAPResponseFlags>()) + { + _flags = flags; + } + + void setFlags(QValueList<IMAPResponseFlags> flags) { _flags = flags; } + QValueList<IMAPResponseFlags> flags() { return _flags; } + +private: + QValueList<IMAPResponseFlags> _flags; + +}; + +class IMAPResponseEXISTS +{ +public: + IMAPResponseEXISTS(QString mails = 0) + { + _mails = mails; + } + + void setMails(QString mails) { _mails = mails; } + QString mails() { return _mails; } + +private: + QString _mails; + +}; + +class IMAPResponseRECENT +{ +public: + IMAPResponseRECENT(QString mails = 0) + { + _mails = mails; + } + + void setMails(QString mails) { _mails = mails; } + QString mails() { return _mails; } + +private: + QString _mails; + +}; + +class IMAPResponseEXPUNGE +{ +public: + IMAPResponseEXPUNGE(QString mails = 0) + { + _mails = mails; + } + + void setMails(QString mails) { _mails = mails; } + QString mails() { return _mails; } + +private: + QString _mails; + +}; + +class IMAPResponseFETCH : public IMAPResponseEnums +{ +public: + void setEnvelope(IMAPResponseEnvelope envelope) { _envelope = envelope; } + IMAPResponseEnvelope envelope() { return _envelope; } + void setFlags(QValueList<IMAPResponseFlags> flags) { _flags = flags; } + QValueList<IMAPResponseFlags> flags() { return _flags; } + void setInternalDate(QString idate) { _idate = idate; } + QString internalDate() { return _idate; } + void setRFC822Size(QString rfc822size) { _rfc822size = rfc822size; } + QString RFC822Size() { return _rfc822size; } + void setUid(QString uid) { _uid = uid; } + QString uid() { return _uid; } + + void setBody(QString body) { _body = body; } + QString body() { return _body; } + void addBodyPart(IMAPResponseBodyPart part) { _bodyParts.append(part); } + void setBodyParts(QValueList<IMAPResponseBodyPart> parts) { _bodyParts = parts; } + QValueList<IMAPResponseBodyPart> bodyParts() { return _bodyParts; } + IMAPResponseBodyPart bodyPart(int part) { return _bodyParts[part]; } + void setRfc822(QString rfc822) { _rfc822 = rfc822; } + QString rfc822() { return _rfc822; } + void setRfc822Header(QString rfc822Header) { _rfc822Header = rfc822Header; } + QString rfc822Header() { return _rfc822Header; } + void setRfc822Text(QString rfc822Text) { _rfc822Text = rfc822Text; } + QString rfc822Text() { return _rfc822Text; } + +private: + IMAPResponseEnvelope _envelope; + QValueList<IMAPResponseFlags> _flags; + QString _idate, _rfc822size, _uid, _body, _rfc822, _rfc822Header, _rfc822Text; + QValueList<IMAPResponseBodyPart> _bodyParts; + +}; + +class IMAPResponse : public IMAPResponseEnums +{ +public: + void setTag(QString tag) { _tag = tag; } + QString tag() { return _tag; } + + void setImapHandler(IMAPHandler *handler) { _handler = handler; } + IMAPHandler *imapHandler() { return _handler; } + + void setStatusResponse(IMAPResponseStatusResponse response) { _response = response; } + IMAPResponseStatusResponse statusResponse() { return _response; } + + void addOK(IMAPResponseOK ok) { _okl.append(ok); } + void addNO(IMAPResponseNO no) { _nol.append(no); } + void addBAD(IMAPResponseBAD bad) { _badl.append(bad); } + void addCAPABILITY(IMAPResponseCAPABILITY capability) { _capabilityl.append(capability); } + void addLIST(IMAPResponseLIST list) { _listl.append(list); } + void addLSUB(IMAPResponseLSUB lsub) { _lsubl.append(lsub); } + void addSTATUS(IMAPResponseSTATUS status) { _statusl.append(status); } + void addSEARCH(IMAPResponseSEARCH search) { _searchl.append(search); } + void addFLAGS(IMAPResponseFLAGS flags) { _flagsl.append(flags); } + void addEXISTS(IMAPResponseEXISTS exists) { _existsl.append(exists); } + void addRECENT(IMAPResponseRECENT recent) { _recentl.append(recent); } + void addEXPUNGE(IMAPResponseEXPUNGE expunge) { _expungel.append(expunge); } + void addFETCH(IMAPResponseFETCH fetch) { _fetchl.append(fetch); } + + QValueList<IMAPResponseOK> OK() { return _okl; } + QValueList<IMAPResponseNO> NO() { return _nol; } + QValueList<IMAPResponseBAD> BAD() { return _badl; } + QValueList<IMAPResponseCAPABILITY> CAPABILITY() { return _capabilityl; } + QValueList<IMAPResponseLIST> LIST() { return _listl; } + QValueList<IMAPResponseLSUB> LSUB() { return _lsubl; } + QValueList<IMAPResponseSTATUS> STATUS() { return _statusl; } + QValueList<IMAPResponseSEARCH> SEARCH() { return _searchl; } + QValueList<IMAPResponseFLAGS> FLAGS() { return _flagsl; } + QValueList<IMAPResponseEXISTS> EXISTS() { return _existsl; } + QValueList<IMAPResponseRECENT> RECENT() { return _recentl; } + QValueList<IMAPResponseEXPUNGE> EXPUNGE() { return _expungel; } + QValueList<IMAPResponseFETCH> FETCH() { return _fetchl; } + +private: + QString _tag; + IMAPResponseStatusResponse _response; + + IMAPHandler *_handler; + + QValueList<IMAPResponseOK> _okl; + QValueList<IMAPResponseNO> _nol; + QValueList<IMAPResponseBAD> _badl; + QValueList<IMAPResponseCAPABILITY> _capabilityl; + QValueList<IMAPResponseLIST> _listl; + QValueList<IMAPResponseLSUB> _lsubl; + QValueList<IMAPResponseSTATUS> _statusl; + QValueList<IMAPResponseSEARCH> _searchl; + QValueList<IMAPResponseFLAGS> _flagsl; + QValueList<IMAPResponseEXISTS> _existsl; + QValueList<IMAPResponseRECENT> _recentl; + QValueList<IMAPResponseEXPUNGE> _expungel; + QValueList<IMAPResponseFETCH> _fetchl; + +}; + +class IMAPResponseParser : public QObject, public IMAPResponseEnums +{ + Q_OBJECT + +public: + IMAPResponseParser(const QString &data); + + IMAPResponse response(); + +signals: + void needMoreData(const QString &comment); + +protected: + void parseResponse(const QString &data, bool tagged = false); + + QStringList splitData(const QString &data, bool withBrackets); + void parseParenthesizedList(const QString &data, QStringList &parsed); + void splitTagData(const QString &line, QString &tag, QString &data); + QString removeLimiters(QString &string, const QChar &sl = '"', const QChar &el = '"'); + IMAPResponseCode getResponseCode(const QString &line); + QValueList<IMAPResponseFlags> parseFlagList(const QStringList &flags); + +private: + IMAPResponse _iresponse; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/libmail/libmail.pro b/noncore/unsupported/mail2/libmail/libmail.pro new file mode 100644 index 0000000..662af90 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/libmail.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +HEADERS = configfile.h \ + defines.h \ + imapbase.h \ + imaphandler.h \ + imapresponse.h \ + mailfactory.h \ + md5.cpp \ + miscfunctions.h \ + sharp_char.h \ + smtphandler.h \ + zaurusstuff.h +SOURCES = configfile.cpp \ + imapbase.cpp \ + imaphandler.cpp \ + imapresponse.cpp \ + mailfactory.cpp \ + md5.h \ + miscfunctions.cpp \ + smtphandler.cpp \ + zaurusstuff.cpp +INCLUDEPATH += $(OPIEDIR)/include +LIBS += -L$(OPIEDIR)/lib -lqpe +TARGET = mail +DESTDIR = $(QTDIR)/lib diff --git a/noncore/unsupported/mail2/libmail/mailfactory.cpp b/noncore/unsupported/mail2/libmail/mailfactory.cpp new file mode 100644 index 0000000..58cf5f8 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/mailfactory.cpp @@ -0,0 +1,173 @@ +#include <qmessagebox.h> +#include <qtextstream.h> +#include <qfile.h> + +#include <qpe/mimetype.h> + +#include "miscfunctions.h" +#include "mailfactory.h" +#include "defines.h" + +MailFactory::MailFactory(SendMail &smail, QWidget *parent) + : QObject(), _smail(smail), _parent(parent) +{ + _abort = false; + Account account = _smail.account(); + + if (!_smail.from().isEmpty()) + _header += "From: " + _smail.from() + "\n"; + if (!_smail.replyTo().isEmpty()) + _header += "Reply-To: " + _smail.replyTo() + "\n"; + if (!_smail.to().isEmpty()) + _header += "To: " + _smail.to() + "\n"; + if (!_smail.cc().isEmpty()) + _header += "Cc: " + _smail.cc() + "\n"; + if (!_smail.bcc().isEmpty()) + _header += "Bcc: " + _smail.bcc() + "\n"; + if (!_smail.subject().isEmpty()) + _header += "Subject: " + _smail.subject() + "\n"; + if (!_smail.priority().isEmpty() || (_smail.priority() != "Normal")) + _header += "Priority: " + _smail.priority() + "\n"; + _header += "Date: " + MiscFunctions::rfcDate() + "\n"; + if (!_smail.account().org().isEmpty()) + _header += "Organization: " + _smail.account().org() + "\n"; + if (_smail.needsMime()) + _header += "Mime-Version: 1.0\n"; + _header += "Message-Id: <" + MiscFunctions::uniqueString() + "." + account.email() + ">\n"; + if (!_smail.inReplyTo().isEmpty()) + _header += "In-Reply-To: " + _smail.inReplyTo() + "\n"; + if (!QString((QString) USERAGENT).isEmpty()) + _header += (QString) "User-Agent: " + USERAGENT + "\n"; + + if (!_smail.needsMime()) { +// if (_smail.encrypt() && !_smail.sign()) { +// openPgpEncrypt(_smail.message(), _header, _body); +// } else if (!_smail.encrypt() && _smail.sign()) { +// openPgpSign(_smail.message(), _header, _body); +// } else if (_smail.encrypt() && _smail.sign()) { +// openPgpSignEncrypt(_smail.message(), _header, _body); +// } else { + _body += _smail.message(); +// } + } else { + QString boundary = MiscFunctions::uniqueString(); + + _header += "Content-Type: multipart/mixed; boundary=\"" + boundary + "\"\n"; + + _body += "This is a multi-part message in MIME format.\n\n"; + _body += "--" + boundary + "\n"; + +// if (_smail.encrypt() && !_smail.sign()) { +// QString header, body; +// openPgpEncrypt(_smail.message(), header, body); +// _body += header + "\n" + body + "\n"; +// } else if (!_smail.encrypt() && _smail.sign()) { +// QString header, body; +// openPgpSign(_smail.message(), header, body); +// _body += header + "\n" + body + "\n"; +// } else if (_smail.encrypt() && _smail.sign()) { +// QString header, body; +// openPgpSignEncrypt(_smail.message(), header, body); +// _body += header + "\n" + body + "\n"; +// } else { + + // TODO: Do proper charset handling! + _body += "Content-Type: text/plain; charset=\"iso-8859-1\"\n"; + _body += "Content-Transfer-Encoding: 8bit\n\n"; + _body += _smail.message() + "\n"; +// } + + QValueList<Attachment> attachments = _smail.attachments(); + QValueList<Attachment>::Iterator it; + for (it = attachments.begin(); it != attachments.end(); it++) { + QFile f((*it).fileName()); + if (f.open(IO_ReadOnly)) { + QTextStream t(&f); + QString file; + while (!t.atEnd()) file += t.readLine() + "\n"; + f.close(); + QString mimetype = (new MimeType(*(*it).docLnk()))->id(); + + _body += "\n--" + boundary + "\n"; + _body += "Content-Type: " + mimetype + "; name=\"" + (*it).newName() + "\"\n"; + + // TODO: Decide which content transfer encoding is best. B64 for binary, QP for text. + _body += "Content-Transfer-Encoding: base64\n"; + + _body += "Content-Disposition: attachment; filename=\"" + (*it).newName() + "\"\n"; + if (!(*it).description().isEmpty()) + _body += "Content-Description: " + (*it).description() + "\n"; + + _body += "\n" + MiscFunctions::encodeBase64(file) + "\n"; + } else { + int ret = QMessageBox::critical(_parent, tr("Error"), tr("<p>Couldn't attach file '%1'. Continue anyway or abort?</p>"), tr("Continue"), tr("Abort")); + if (ret == 1) { + it = attachments.end(); + _abort = true; + } + } + } + _body += "\n--" + boundary + "--"; + } + + if (_abort) { + _body = QString(0); + _header = QString(0); + } +} + +// Unfinished GPG code. +/* +void MailFactory::openPgpEncrypt(const QString &text, QString &header, QString &body) +{ + QString boundary = MiscFunctions::uniqueString(); + + header += "Content-Type: multipart/encrypted; boundary=\"" + boundary + "\"; protocol=\"application/pgp-encrypted\"\n"; + + body += "--" + boundary + "\n"; + body += "Content-Type: application/pgp-encrypted\n\n"; + body += "Version: 1\n\n"; + body += "--" + boundary + "\n"; + body += "Content-Type: application/octet-stream\n\n"; + body += GpgHandling::encrypt(_smail.gpgReceivers(), text); + body += "\n--" + boundary + "--\n"; +} + +void MailFactory::openPgpSign(const QString &text, QString &header, QString &body) +{ + QString boundary = MiscFunctions::uniqueString(); + + header += "Content-Type: multipart/signed; boundary=\"" + boundary + "\"; protocol=\"application/pgp-signature\"\n"; + + body += "--" + boundary + "\n"; + + QString temp; + temp += "Content-Type: text/plain; charset=\"iso-8859-1\"\n"; + temp += "Content-Transfer-Encoding: quoted-printable\n\n"; + temp += MiscFunctions::encodeQPrintable(text) + "\n"; + body += temp; + + temp.replace(QRegExp("\n"), "\r\n"); + QString signature = GpgHandling::sign(temp, _parent); + + body += "\n--" + boundary + "\n"; + body += "Content-Type: application/pgp-signature\n\n"; + body += signature + "\n"; + body += "\n--" + boundary + "--\n"; +} + +void MailFactory::openPgpSignEncrypt(const QString &text, QString &header, QString &message) +{ + QString header_, message_; + openPgpSign(text, header_, message_); + openPgpEncrypt(header_ + "\n" + message_, header, message); +} +*/ +void MailFactory::genMail(QString &header, QString &message, SendMail &smail, QWidget *parent) +{ + MailFactory factory(smail, parent); + + header = factory._header; + message = factory._body; +} + diff --git a/noncore/unsupported/mail2/libmail/mailfactory.h b/noncore/unsupported/mail2/libmail/mailfactory.h new file mode 100644 index 0000000..8f67447 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/mailfactory.h @@ -0,0 +1,109 @@ +#ifndef MAILFACTORY_H +#define MAILFACTORY_H + +#include <qobject.h> + +#include <qpe/applnk.h> + +#include "configfile.h" + +class Attachment +{ +public: + void setFileName(QString fileName) { _fileName = fileName; } + void setNewName(QString newName) { _newName = newName; } + void setDescription(QString description) { _description = description; } + void setDocLnk(DocLnk *docLnk) { _docLnk = docLnk; } + + QString fileName() { return _fileName; } + QString newName() { return _newName; } + QString description() { return _description; } + DocLnk *docLnk() { return _docLnk; } + +protected: + QString _fileName, _newName, _description; + DocLnk *_docLnk; + +}; + +class SendMail +{ +public: + SendMail() { _needsMime = false; } + + void setAccount(Account account) { _account = account; } + + void setFrom(QString from) { _from = from; } + void setReplyTo(QString replyTo) { _replyTo = replyTo; } + void setTo(QString to) { _to = to; } + void setCc(QString cc) { _cc = cc; } + void setBcc(QString bcc) { _bcc = bcc; } + void setSubject(QString subject) { _subject = subject; } + void setPriority(QString priority) { _priority = priority; } + void setMessage(QString message) { _message = message; } + void setInReplyTo(QString inReplyTo) { _inReplyTo = inReplyTo; } + + void setNeedsMime(bool needsMime) { _needsMime = needsMime; } + + //void setEncrypt(bool encrypt) { _encrypt = encrypt; } + //void setSign(bool sign) { _sign = sign; } + //void setGpgReceivers(QValueList<GpgKey> receivers) { _receivers = receivers; } + //void setGpgPassphrase(QString passphrase) { _passphrase = passphrase; } + + void setAttachments(QValueList<Attachment> attachments) { _attachments = attachments; } + void addAttachment(Attachment attachment) { _attachments.append(attachment); } + + Account account() { return _account; } + + QString from() { return _from; } + QString replyTo() { return _replyTo; } + QString to() { return _to; } + QString cc() { return _cc; } + QString bcc() { return _bcc; } + QString subject() { return _subject; } + QString priority() { return _priority; } + QString message() { return _message; } + QString inReplyTo() { return _inReplyTo; } + + bool needsMime() { return _needsMime; } + + //bool encrypt() { return _encrypt; } + //bool sign() { return _sign; } + //QValueList<GpgKey> gpgReceivers() { return _receivers; } + //QString gpgPassphrase() { return _passphrase; } + + QValueList<Attachment> attachments() { return _attachments; } + +protected: + Account _account; + QString _from, _replyTo, _to, _cc, _bcc, _subject, _priority, _message, _inReplyTo; + bool _needsMime; + //bool _encrypt, _sign; + //QValueList<GpgKey> _receivers; + //QString _passphrase; + QValueList<Attachment> _attachments; + +}; + +class MailFactory : public QObject +{ + Q_OBJECT + +public: + static void genMail(QString &header, QString &message, SendMail &smail, QWidget *parent); + +protected: + MailFactory(SendMail &smail, QWidget *parent); + +// void openPgpEncrypt(const QString &text, QString &header, QString &message); +// void openPgpSign(const QString &text, QString &header, QString &message); +// void openPgpSignEncrypt(const QString &text, QString &header, QString &message); + + bool _abort; + SendMail _smail; + QWidget *_parent; + QString _header, _body; + +}; + +#endif diff --git a/noncore/unsupported/mail2/libmail/md5.cpp b/noncore/unsupported/mail2/libmail/md5.cpp new file mode 100644 index 0000000..4ee2c42 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/md5.cpp @@ -0,0 +1,242 @@ +// This code was written by Colin Plumb. I've made some small changes. +// (Constantin Bergemann) + +#ifdef __cplusplus +extern "C" { +#endif + +#include <string.h> /* for memcpy() */ +#include "md5.h" + +#if __BYTE_ORDER == 1234 +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); + +/* + * Note: this code is harmless on little-endian machines. + */ +void byteReverse(unsigned char *buf, unsigned longs) +{ + u_int32_t t; + do { + t = (u_int32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(u_int32_t *) buf = t; + buf += 4; + } while (--longs); +} +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5_Init(MD5_CTX *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5_Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) +{ + u_int32_t t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((u_int32_t) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u_int32_t *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u_int32_t *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u_int32_t *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((u_int32_t *) ctx->in)[14] = ctx->bits[0]; + ((u_int32_t *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (u_int32_t *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5Transform(u_int32_t buf[4], u_int32_t const in[16]) +{ + register u_int32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/noncore/unsupported/mail2/libmail/md5.h b/noncore/unsupported/mail2/libmail/md5.h new file mode 100644 index 0000000..221dd09 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/md5.h @@ -0,0 +1,35 @@ +// This code was written by Colin Plumb. I've made some small changes. +// (Constantin Bergemann) + +#ifndef _MD5_H_ +#define _MD5_H_ + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MD5_HASHBYTES 16 + +typedef struct MD5Context { + u_int32_t buf[4]; + u_int32_t bits[2]; + unsigned char in[64]; +} MD5_CTX; + +extern void MD5_Init(MD5_CTX *context); +extern void MD5_Update(MD5_CTX *context, unsigned char const *buf, + unsigned len); +extern void MD5_Final(unsigned char digest[MD5_HASHBYTES], MD5_CTX *context); +extern void MD5Transform(u_int32_t buf[4], u_int32_t const in[16]); +extern char * MD5End(MD5_CTX *, char *); +extern char * MD5File(const char *, char *); +extern char * MD5Data (const unsigned char *, unsigned int, char *); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* !_MD5_H_ */ + diff --git a/noncore/unsupported/mail2/libmail/miscfunctions.cpp b/noncore/unsupported/mail2/libmail/miscfunctions.cpp new file mode 100644 index 0000000..0edbfa8 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/miscfunctions.cpp @@ -0,0 +1,295 @@ +#include <qdatetime.h> + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#include <openssl/md5.h> + +#include "miscfunctions.h" + +QString MiscFunctions::encodeQPrintable(const QString &src) +{ + // TODO: implent encodeQPrintable + return src; +} + +QString MiscFunctions::decodeQPrintable(const QString &src) +{ + QString out; + + for (unsigned int i = 0; i <= src.length(); i++) { + if (src[i] == '=') { + if (src[i+1] == "\n") { + i += 1; + } else { + QString temp = QString("%1%2").arg(src[i+1]).arg(src[i+2]); + int number = temp.toInt(0, 16); + + out += QChar(number); + i += 2; + } + } else { + out += src[i]; + } + } + return out; +} + +QString MiscFunctions::encodeBase64(const QString &src) +{ + char *dataPtr = (char *) src.latin1(); + int len = src.length(); + int count = 0; + QString temp = ""; + + while (len > 0) { + if (len < 3) { + encodeBase64Base(dataPtr, &temp, len); + len = 0; + } else { + encodeBase64Base(dataPtr, &temp, 3); + len -= 3; + dataPtr += 3; + count += 4; + } + if (count > 72) { + count = 0; + temp += "\n"; + } + } + + return temp; +} + +void MiscFunctions::encodeBase64Base(char *src, QString *dest, int len) +{ + QString temp; + uchar c; + uchar bufOut[4]; + + bufOut[0] = src[0]; + bufOut[0] >>= 2; + + bufOut[1] = src[0]; + bufOut[1] = bufOut[1] & (1 + 2); + bufOut[1] <<= 4; + if (len > 1) c = src[1]; + else c = 0; + + c = c & (16 + 32 + 64 + 128); + c >>= 4; + bufOut[1] = bufOut[1] | c; + + bufOut[2] = src[1]; + bufOut[2] = bufOut[2] & (1 + 2 + 4 + 8); + bufOut[2] <<= 2; + if (len > 2) c = src[2]; + else c = 0; + + c >>= 6; + bufOut[2] = bufOut[2] | c; + + bufOut[3] = src[2]; + bufOut[3] = bufOut[3] & (1 + 2 + 4 + 8 + 16 + 32); + + if (len == 1) { + bufOut[2] = 64; + bufOut[3] = 64; + } + if (len == 2) { + bufOut[3] = 64; + } + for (int x = 0; x < 4; x++) { + if (bufOut[x] <= 25) + bufOut[x] += (uint) 'A'; + else if (bufOut[x] >= 26 && bufOut[x] <= 51) + bufOut[x] += (uint) 'a' - 26; + else if (bufOut[x] >= 52 && bufOut[x] <= 61) + bufOut[x] += (uint) '0' - 52; + else if (bufOut[x] == 62) + bufOut[x] = '+'; + else if (bufOut[x] == 63) + bufOut[x] = '/'; + else if (bufOut[x] == 64) + bufOut[x] = '='; + + dest->append(bufOut[x]); + } +} + +QString MiscFunctions::decodeBase64(const QString &src) +{ + char plain[4]; + char *destPtr; + QByteArray buffer; + uint bufCount = 0, pos = 0, decodedCount, x; + + buffer.resize(src.length() * 3 / 4); + destPtr = buffer.data(); + + while (pos < src.length()) { + decodedCount = 4; + x = 0; + while ((x < 4) && (pos < src.length())) { + plain[x] = src[pos].latin1(); + pos++; + if (plain[x] == '\r' || plain[x] == '\n' || plain[x] == ' ') + x--; + x++; + } + if (x > 1) { + decodedCount = decodeBase64Base(plain, destPtr); + destPtr += decodedCount; + bufCount += decodedCount; + } + } + + buffer.resize(bufCount); + return QString(buffer); +} + +int MiscFunctions::decodeBase64Base(char *src, char *bufOut) +{ + char c, z; + char li[4]; + int processed; + + for (int x = 0; x < 4; x++) { + c = src[x]; + + if ( (int) c >= 'A' && (int) c <= 'Z') + li[x] = (int) c - (int) 'A'; + if ( (int) c >= 'a' && (int) c <= 'z') + li[x] = (int) c - (int) 'a' + 26; + if ( (int) c >= '0' && (int) c <= '9') + li[x] = (int) c - (int) '0' + 52; + if (c == '+') + li[x] = 62; + if (c == '/') + li[x] = 63; + } + + processed = 1; + bufOut[0] = (char) li[0] & (32+16+8+4+2+1); + bufOut[0] <<= 2; + z = li[1] >> 4; + bufOut[0] = bufOut[0] | z; + + if (src[2] != '=') { + bufOut[1] = (char) li[1] & (8+4+2+1); + bufOut[1] <<= 4; + z = li[2] >> 2; + bufOut[1] = bufOut[1] | z; + processed++; + + if (src[3] != '=') { + bufOut[2] = (char) li[2] & (2+1); + bufOut[2] <<= 6; + z = li[3]; + bufOut[2] = bufOut[2] | z; + processed++; + } + } + return processed; +} + +QString MiscFunctions::uniqueString() +{ + QString uniqueString = QDate::currentDate().toString(); + uniqueString += QTime::currentTime().toString(); + uniqueString += QString("%1").arg(rand()); + + unsigned char md[16]; + + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, (unsigned char *)uniqueString.latin1(), uniqueString.length()); + MD5_Final(md, &ctx); + + char hash[16]; + for (unsigned int i = 0; i < sizeof(md); i++) + sprintf(hash + 2 * i, "%02x", md[i]); + + return hash; +} + +QString MiscFunctions::rfcDate() +{ + time_t t = time(NULL); + tm *time = localtime(&t); + QString pm, tzh, tzm, ths, tms, tss; + + time->tm_gmtoff < 0 ? pm = "-" : pm = "+"; + int h = abs(time->tm_gmtoff) / 3600; + int m = (abs(time->tm_gmtoff) - h * 3600) / 60; + h < 10 ? tzh = QString("0%1").arg(h) : tzh = QString("%1").arg(h); + m < 10 ? tzm = QString("0%1").arg(m) : tzm = QString("%1").arg(m); + + int th = time->tm_hour; + int tm = time->tm_min; + int ts = time->tm_sec; + th < 10 ? ths = QString("0%1").arg(th) : ths = QString("%1").arg(th); + tm < 10 ? tms = QString("0%1").arg(tm) : tms = QString("%1").arg(tm); + ts < 10 ? tss = QString("0%1").arg(ts) : tss = QString("%1").arg(ts); + + QString month = QDate().monthName(time->tm_mon + 1); + QString dayna = QDate().dayName(time->tm_wday); + QString tzone = pm + tzh + tzm; + + return QString("%1, %2 %3 %4 %5:%6:%7 %8") + .arg(dayna) + .arg(time->tm_mday) + .arg(month) + .arg(time->tm_year + 1900) + .arg(ths) + .arg(tms) + .arg(tss) + .arg(tzone); +} + +QString MiscFunctions::smtpAuthCramMd5(const QString &data, const QString &key) +{ + MD5_CTX context; + unsigned char k_ipad[65]; + unsigned char k_opad[65]; + unsigned char tk[16]; + unsigned char digest[16]; + unsigned char *key_int = (unsigned char *)key.latin1(); + char hash[33]; + + if (key.length() > 64) { + MD5_CTX tctx; + MD5_Init(&tctx); + MD5_Update(&tctx, key_int, sizeof(key_int)); + MD5_Final(tk, &tctx); + + key_int = tk; + } + + bzero(k_ipad, sizeof k_ipad); + bzero(k_opad, sizeof k_opad); + bcopy(key_int, k_ipad, sizeof(key_int)); + bcopy(key_int, k_opad, sizeof(key_int)); + + for (int i = 0; i < 64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + MD5_Init(&context); + MD5_Update(&context, k_ipad, 64); + MD5_Update(&context, (unsigned char *)data.latin1(), data.length()); + MD5_Final(digest, &context); + + MD5_Init(&context); + MD5_Update(&context, k_opad, 64); + MD5_Update(&context, digest, 16); + MD5_Final(digest, &context); + + for (unsigned int i = 0; i < sizeof(digest); i++) + sprintf (hash + 2 * i, "%02x", digest[i]); + + return hash; +} + diff --git a/noncore/unsupported/mail2/libmail/miscfunctions.h b/noncore/unsupported/mail2/libmail/miscfunctions.h new file mode 100644 index 0000000..a13e1e3 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/miscfunctions.h @@ -0,0 +1,27 @@ +#ifndef MISCFUNCTIONS_H +#define MISCFUNCTIONS_H + +#include <qobject.h> + +class MiscFunctions : public QObject +{ + Q_OBJECT + +public: + static QString encodeQPrintable(const QString &src); + static QString decodeQPrintable(const QString &src); + static QString encodeBase64(const QString &src); + static QString decodeBase64(const QString &src); + static QString uniqueString(); + static QString rfcDate(); + static QString smtpAuthCramMd5(const QString &data, const QString &key); + +protected: + MiscFunctions() : QObject() { } + + static void encodeBase64Base(char *src, QString *dest, int len); + static int decodeBase64Base(char *src, char *bufOut); + +}; + +#endif diff --git a/noncore/unsupported/mail2/libmail/sharp_char.h b/noncore/unsupported/mail2/libmail/sharp_char.h new file mode 100644 index 0000000..8bd8beb --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/sharp_char.h @@ -0,0 +1,241 @@ +/* + * linux/include/asm/sharp_char.h + */ + +#ifndef __ASM_SHARP_CHAR_H_INCLUDED +#define __ASM_SHARP_CHAR_H_INCLUDED + +/* + * If SHARPCHAR_USE_MISCDEV defined , misc driver architecture used instead of sharp_char + */ + +#define SHARPCHAR_USE_MISCDEV + +/* + * devices defines... + */ + +#ifndef SHARP_DEV_MAJOR +#define SHARP_DEV_MAJOR 11 +#endif + +#ifndef SHARP_DEV_MINOR_START +#define SHARP_DEV_MINOR_START 210 +#endif + +#define SHARP_DEV_MINOR_MAX 4 /* defines last minor number of SHARP device */ + +#define SHARP_LED_MINOR (SHARP_DEV_MINOR_START+0) +#define SHARP_BUZZER_MINOR (SHARP_DEV_MINOR_START+1) +#define SHARP_GSM_MINOR (SHARP_DEV_MINOR_START+2) +#define SHARP_AUDIOCTL_MINOR (SHARP_DEV_MINOR_START+3) +#define SHARP_KBDCTL_MINOR (SHARP_DEV_MINOR_START+4) + +/* + * ioctl defines... + */ + +#define SHARP_DEV_IOCTL_COMMAND_START 0x5680 + +/* --- for SHARP_LED device --- */ +#define SHARP_LED_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_LED_GETSTATUS (SHARP_LED_IOCTL_START) +#define SHARP_LED_SETSTATUS (SHARP_LED_IOCTL_START+1) +#define SHARP_LED_ISUPPORTED (SHARP_LED_IOCTL_START+2) + +typedef struct sharp_led_status { + int which; /* select which LED status is wanted. */ + int status; /* set new led status if you call SHARP_LED_SETSTATUS */ +} sharp_led_status; + +#define SHARP_LED_WHICH_MAX 15 /* last number of LED */ + +/* parameters for 'which' member */ +#define SHARP_LED_PDA 0 /* PDA status */ +#define SHARP_LED_DALARM 1 /* daily alarm */ +#define SHARP_LED_SALARM 2 /* schedule alarm */ +#define SHARP_LED_BATTERY 3 /* main battery status */ +#define SHARP_LED_ACSTATUS 4 /* AC line status */ +#define SHARP_LED_CHARGER 5 /* charger status */ +#define SHARP_LED_PHONE_RSSI 6 /* phone status (RSSI...) */ +#define SHARP_LED_PHONE_DIAL 7 /* phone status (dialing...) */ +#define SHARP_LED_PHONE_IN 8 /* phone status (incoming..) */ +#define SHARP_LED_MAIL_EXISTS 9 /* mail status (exists or not) */ +#define SHARP_LED_MAIL_SEND 10 /* mail status (sending...) */ +#define SHARP_LED_MAIL_QUEUE 11 /* mail to send is in queue */ +#define SHARP_LED_COLLIE_0 12 /* 1st pri. battery LED control */ +#define SHARP_LED_COLLIE_1 13 /* 1st pri. mail LED control */ +#define SHARP_LED_COLLIE_2 14 /* reserved */ +#define SHARP_LED_COLLIE_3 15 /* reserved */ + +/* parameters for 'status' member */ +#define LED_PDA_RUNNING 0 /* for SHARP_LED_RUN */ +#define LED_PDA_SUSPENDED 1 /* for SHARP_LED_RUN */ +#define LED_PDA_OFF 2 /* for SHARP_LED_RUN */ +#define LED_PDA_ERROR 3 /* for SHARP_LED_RUN */ + +#define LED_DALARM_OFF 0 /* for SHARP_LED_DALARM */ +#define LED_DALARM_ON 1 /* for SHARP_LED_DALARM */ + +#define LED_SALARM_OFF 0 /* for SHARP_LED_SALARM */ +#define LED_SALARM_ON 1 /* for SHARP_LED_SALARM */ + +#define LED_BATTERY_GOOD 0 /* for SHARP_LED_BATTERY */ +#define LED_BATTERY_LOW 1 /* for SHARP_LED_BATTERY */ +#define LED_BATTERY_VERY_LOW 2 /* for SHARP_LED_BATTERY */ +#define LED_BATTERY_CRITICAL 3 /* for SHARP_LED_BATTERY */ + +#define LED_CHARGER_OFF 0 /* for SHARP_LED_CHARGER */ +#define LED_CHARGER_CHARGING 1 /* for SHARP_LED_CHARGER */ +#define LED_CHARGER_ERROR 2 /* for SHARP_LED_CHARGER */ + +#define LED_AC_NOT_CONNECTED 0 /* for SHARP_LED_ACSTATUS */ +#define LED_AC_CONNECTED 1 /* for SHARP_LED_ACSTATUS */ + +#define LED_RSSI_OUT 0 /* for SHARP_LED_PHONE_RSSI */ +#define LED_RSSI_IN 1 /* for SHARP_LED_PHONE_RSSI */ + +#define LED_DIAL_OFF 0 /* for SHARP_LED_PHONE_DIAL */ +#define LED_DIAL_DIALING 1 /* for SHARP_LED_PHONE_DIAL */ +#define LED_DIAL_HOLDING 2 /* for SHARP_LED_PHONE_DIAL */ + +#define LED_PHONE_WAITING 0 /* for SHARP_LED_PHONE_IN */ +#define LED_PHONE_INCOMING 1 /* for SHARP_LED_PHONE_IN */ + +#define LED_MAIL_NO_UNREAD_MAIL 0 /* for SHARP_LED_MAIL_EXISTS */ +#define LED_MAIL_NEWMAIL_EXISTS 1 /* for SHARP_LED_MAIL_EXISTS */ +#define LED_MAIL_UNREAD_MAIL_EX 2 /* for SHARP_LED_MAIL_EXISTS */ + +#define LED_SENDMAIL_OFF 0 /* for SHARP_LED_MAIL_SEND */ +#define LED_SENDMAIL_SENDING 1 /* for SHARP_LED_MAIL_SEND */ +#define LED_SENDMAIL_ERROR 2 /* for SHARP_LED_MAIL_SEND */ + +#define LED_MAILQUEUE_NOUNREAD 0 /* for SHARP_LED_MAIL_QUEUE */ +#define LED_MAILQUEUE_NEWMAIL 1 /* for SHARP_LED_MAIL_QUEUE */ +#define LED_MAILQUEUE_UNREAD 2 /* for SHARP_LED_MAIL_QUEUE */ + +#define LED_COLLIE_0_DEFAULT 0 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_OFF 1 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_ON 2 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_FASTBLINK 3 /* for SHARP_LED_COLLIE_0 */ +#define LED_COLLIE_0_SLOWBLINK 4 /* for SHARP_LED_COLLIE_0 */ + + +#define LED_COLLIE_1_DEFAULT 0 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_OFF 1 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_ON 2 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_FLASHON 3 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_FLASHOFF 4 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_VFSTBLINK 5 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_FASTBLINK 6 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_NORMBLINK 7 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_SLOWBLINK 8 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_SOFTBLINK 9 /* for SHARP_LED_COLLIE_1 */ +#define LED_COLLIE_1_SOFTFLASH 10 /* for SHARP_LED_COLLIE_1 */ + +/* --- for SHARP_BUZZER device --- */ +#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START) +#define SHARP_BUZZER_SETVOLUME (SHARP_BUZZER_IOCTL_START+1) +#define SHARP_BUZZER_GETVOLUME (SHARP_BUZZER_IOCTL_START+2) +#define SHARP_BUZZER_ISSUPPORTED (SHARP_BUZZER_IOCTL_START+3) +#define SHARP_BUZZER_SETMUTE (SHARP_BUZZER_IOCTL_START+4) +#define SHARP_BUZZER_STOPSOUND (SHARP_BUZZER_IOCTL_START+5) + +typedef struct sharp_buzzer_status { /* this struct is used for setvolume/getvolume */ + int which; /* select which LED status is wanted. */ + int volume; /* set new buzzer volume if you call SHARP_BUZZER_SETVOLUME */ + int mute; /* set 1 to MUTE if you call SHARP_BUZZER_SETMUTE */ +} sharp_buzzer_status; + +#define SHARP_BUZ_WHICH_MAX 14 /* last number of buzzer */ + +#define SHARP_BUZ_ALL_SOUNDS -1 /* for setting volumes of ALL sounds at a time */ + +#define SHARP_BUZ_WRITESOUND 0 /* for sound datas through 'write' calls */ +#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */ +#define SHARP_BUZ_KEYSOUND 2 /* key sound */ +#define SHARP_PDA_ILLCLICKSOUND 3 /* illegal click */ +#define SHARP_PDA_WARNSOUND 4 /* warning occurred */ +#define SHARP_PDA_ERRORSOUND 5 /* error occurred */ +#define SHARP_PDA_CRITICALSOUND 6 /* critical error occurred */ +#define SHARP_PDA_SYSSTARTSOUND 7 /* system start */ +#define SHARP_PDA_SYSTEMENDSOUND 8 /* system shutdown */ +#define SHARP_PDA_APPSTART 9 /* application start */ +#define SHARP_PDA_APPQUIT 10 /* application ends */ +#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */ +#define SHARP_BUZ_DAILY_ALARM 12 /* daily alarm */ +#define SHARP_BUZ_GOT_PHONE_CALL 13 /* phone call sound */ +#define SHARP_BUZ_GOT_MAIL 14 /* mail sound */ + +#define SHARP_BUZ_VOLUME_OFF 0 +#define SHARP_BUZ_VOLUME_LOW 33 +#define SHARP_BUZ_VOLUME_MEDIUM 67 +#define SHARP_BUZ_VOLUME_HIGH 100 /* currentry , this is the maximum ... */ +#define SHARP_BUZ_VOLUME_MAX (SHARP_BUZ_VOLUME_HIGH) + +/* --- for SHARP_GSM device --- */ +#define SHARP_GSM_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_GSM_GETEXTSTATUS (SHARP_GSM_IOCTL_START+16) +#define SHARP_GSM_INFO_TELL_MODE (SHARP_GSM_IOCTL_START+17) + +#define GSM_PHONE_NO_POWER 0 /* for SHARP_GSM_INFO_TELL_MODE */ +#define GSM_PHONE_NO_CONNECTION 1 /* for SHARP_GSM_INFO_TELL_MODE */ +#define GSM_PHONE_IN_ANALOG_MODE 2 /* for SHARP_GSM_INFO_TELL_MODE */ +#define GSM_PHONE_IN_DATA_MODE 3 /* for SHARP_GSM_INFO_TELL_MODE */ + +typedef struct sharp_gsmext_status { + int carkit; /* be set as 1 , if car-kit is connected */ + int headphone_mic; /* be set as 1 , if head-phone-microphone is inserted */ +} sharp_gsmext_status; + +/* --- for SHARP_AUDIOCTL device --- */ +#define SHARP_AUDIOCTL_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_AUDIOCTL_ARCH_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START+0x10) +#define SHARP_IRIS_AUFIL_GETVAL (SHARP_AUDIOCTL_ARCH_IOCTL_START+0) +#define SHARP_IRIS_AUFIL_SETVAL (SHARP_AUDIOCTL_ARCH_IOCTL_START+1) +#define SHARP_IRIS_AMP_EXT_ON (SHARP_AUDIOCTL_ARCH_IOCTL_START+2) +#define SHARP_IRIS_AMP_EXT_OFF (SHARP_AUDIOCTL_ARCH_IOCTL_START+3) + + +#define SHARP_IRIS_AUFIL_FILTERON 0x01 /* Iris AudioCtl Specific. Enable Audio Filter */ + +/* --- for SHARP_AUDIOCTL device --- */ +#define SHARP_KBDCTL_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) +#define SHARP_KBDCTL_GETMODIFSTAT (SHARP_KBDCTL_IOCTL_START+0) +#define SHARP_KBDCTL_TOGGLEMODIFSTAT (SHARP_KBDCTL_IOCTL_START+1) +#define SHARP_KBDCTL_SETHOLDTH (SHARP_KBDCTL_IOCTL_START+2) +#define SHARP_KBDCTL_SETHOLDTH_GR (SHARP_KBDCTL_IOCTL_START+3) +#define SHARP_KBDCTL_HOLDINFO_SETHD (SHARP_KBDCTL_IOCTL_START+4) +#define SHARP_KBDCTL_HOLDINFO_SETSL (SHARP_KBDCTL_IOCTL_START+5) +#define SHARP_KBDCTL_HOLDINFO_DELHD (SHARP_KBDCTL_IOCTL_START+6) +#define SHARP_KBDCTL_HOLDINFO_DELSL (SHARP_KBDCTL_IOCTL_START+7) +#define SHARP_KBDCTL_HOLDINFO_RESTHD (SHARP_KBDCTL_IOCTL_START+8) +#define SHARP_KBDCTL_HOLDINFO_RESTSL (SHARP_KBDCTL_IOCTL_START+9) +#define SHARP_KBDCTL_HOLDINFO_RESTFULL (SHARP_KBDCTL_IOCTL_START+10) + +typedef struct sharp_kbdctl_modifstat { + int which; + int stat; +} sharp_kbdctl_modifstat; + +typedef struct sharp_kbdctl_holdstat { + int group; + int timeout; +} sharp_kbdctl_holdstat; + +typedef struct sharp_kbdctl_holdcustom { + int normal_hardcode; + int normal_slcode; + int hold_slcode; +} sharp_kbdctl_holdcustom; + +#define SHARP_EXTMODIF_2ND 0x01 +#define SHARP_EXTMODIF_CAPS 0x02 +#define SHARP_EXTMODIF_NUMLOCK 0x03 + +#define HOLDKEY_GROUP_NORMAL 0 +#define HOLDKEY_GROUP_POWER 1 + +#endif /* __ASM_SHARP_CHAR_H_INCLUDED */ + diff --git a/noncore/unsupported/mail2/libmail/smtphandler.cpp b/noncore/unsupported/mail2/libmail/smtphandler.cpp new file mode 100644 index 0000000..1bbad8b --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/smtphandler.cpp @@ -0,0 +1,172 @@ +#warning "TODO: XXX This class needs to be rewritten. XXX" + +#include <qsocket.h> +#include <qtimer.h> +#include <qfile.h> +#include <qdatetime.h> +#include <qdir.h> +#include <qregexp.h> + +#include <qpe/mimetype.h> +#include <qpe/config.h> + +#include <stdlib.h> + +#include "smtphandler.h" +#include "miscfunctions.h" + +SmtpHandler::SmtpHandler(const QString &header, const QString &message, Account &account, const QString &to) + : QObject(), _header(header), _message(message), _account(account), _to(to) +{ + _header.replace(QRegExp("\\n"), "\r\n"); + _message.replace(QRegExp("\\n"), "\r\n"); + _message.replace(QRegExp("\\r\\n\\.\\r\\n"), "\r\n..\r\n"); + +// _state = account.esmtpAuth() ? Ehlo : Helo; + _state = Helo; + + _socket = new QSocket(this); + connect(_socket, SIGNAL(hostFound()), this, SLOT(hostFound())); + connect(_socket, SIGNAL(connected()), this, SLOT(connected())); + connect(_socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(_socket, SIGNAL(error(int)), this, SLOT(errorHandling(int))); + + _socket->connectToHost(account.smtpServer(), account.smtpPort().toUInt()); + emit status(tr("Looking up host...")); +} + +void SmtpHandler::errorHandling(int err) +{ + if (err == QSocket::ErrConnectionRefused) { + emit error(tr("The server refused the connection.")); + } else if (err == QSocket::ErrHostNotFound) { + emit error(tr("Host lookup failed.")); + } else if (err == QSocket::ErrSocketRead) { + emit error(tr("The read from the socket failed for an unknown reason.")); + } else { + emit error(tr("The sending failed for an unknown reason.")); + } + stop(); +} + +void SmtpHandler::hostFound() +{ + emit status(tr("Host found.")); +} + +void SmtpHandler::connected() +{ + emit status(tr("Connected to %1").arg(_socket->peerName())); +} + +void SmtpHandler::readyRead() +{ + if (!_socket->canReadLine()) return; + if (_state == Close) stop(); + + QString response = _socket->readLine(); + QString temp = response; + temp.truncate(3); + int responseCode = temp.toInt(); + +#ifndef QT_NO_DEBUG + qDebug(tr("SMTP > %3").arg(response.stripWhiteSpace())); +#endif + + response.replace(0, 4, ""); + response.stripWhiteSpace(); + + if (_state == Ehlo && responseCode == 220) { + QString hostname = getenv("HOSTNAME"); + if (hostname.stripWhiteSpace().isEmpty()) + hostname = "opiemail"; + + emit status(tr("SMTP> EHLO *")); + sendToSocket(QString("EHLO %1\r\n").arg(hostname)); + _state = Auth; + } else if (_state == Auth && responseCode == 250) { + QStringList capabilities; + while (_socket->canReadLine()) { + QString line = _socket->readLine().stripWhiteSpace(); + capabilities.append(line); + } + + // FIXME: Dirty, quick hack! + if (!capabilities.grep(QRegExp("^250-AUTH=LOGIN.*CRAM-MD5.*$")).isEmpty()) { +// emit errorOccourred(ErrAuthNotSupported); + _state = Mail; + } else { + emit status(tr("SMTP> AUTH CRAM-MD5")); + sendToSocket("AUTH CRAM-MD5\r\n"); + _state = ReadAuth; + } + } else if (_state == ReadAuth && responseCode == 334) { + QString msgId = MiscFunctions::decodeBase64(response); + + QString authString; + authString = _account.user() + " " + + MiscFunctions::smtpAuthCramMd5(msgId, _account.pass()); + authString = MiscFunctions::encodeBase64(authString); + + emit status(tr("SMTP> Authenticating")); + sendToSocket(authString + "\r\n"); + + _state = Mail; + } else if (_state == Helo && responseCode == 220) { + QString hostname = getenv("HOSTNAME"); + if (hostname.stripWhiteSpace().isEmpty()) + hostname = "opiemail"; + + emit status(tr("SMTP> HELO *")); + sendToSocket(QString("HELO %1\r\n").arg(hostname)); + _state = Mail; + } else if (_state == Mail && responseCode == 250) { + emit status(tr("SMTP> MAIL FROM: *")); + sendToSocket("MAIL FROM: " + _account.email() + "\r\n"); + _state = Rcpt; + } else if (_state == Rcpt && responseCode == 250) { + emit status(tr("SMTP> RCPT TO: *")); + sendToSocket("RCPT TO: " + _to + "\r\n"); + _state = Data; + } else if (_state == Data && responseCode == 250) { + emit status(tr("SMTP> DATA")); + sendToSocket("DATA\r\n"); + _state = Body; + } else if (_state == Body && responseCode == 354) { + emit status(tr("SMTP> Sending data...")); + sendToSocket(_header + "\r\n" + _message + "\r\n.\r\n", false); + _state = Quit; + } else if (_state == Quit) { + emit status(tr("SMTP> QUIT (Done)")); + sendToSocket("QUIT\r\n"); + _state = Close; + } else if (_state == Close) { + + } else { + emit error(tr("The server returned an error. This is the message:<br>%1").arg(response)); + stop(); + } +} + +void SmtpHandler::sendToSocket(const QString &text, bool log) +{ + _socket->writeBlock(text.latin1(), text.length()); + + if (log) { +#ifndef QT_NO_DEBUG + qDebug(tr("SMTP < %3").arg(text.stripWhiteSpace())); +#endif + } +} + +void SmtpHandler::stop() +{ + emit finished(); + QTimer::singleShot(0, this, SLOT(deleteMe())); +} + +void SmtpHandler::deleteMe() +{ + delete this; +} + diff --git a/noncore/unsupported/mail2/libmail/smtphandler.h b/noncore/unsupported/mail2/libmail/smtphandler.h new file mode 100644 index 0000000..abbcbcd --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/smtphandler.h @@ -0,0 +1,55 @@ +#ifndef SMTPHANDLER_H +#define SMTPHANDLER_H + +#include <qobject.h> +#include <qstring.h> + +#include "configfile.h" + +class QSocket; + +class SmtpHandler : public QObject +{ + Q_OBJECT + +public: + SmtpHandler(const QString &header, const QString &message, Account &account, const QString &to); + + enum SmtpError { + ErrConnectionRefused, + ErrHostNotFound, + ErrUnknownResponse, + ErrAuthNotSupported + }; + +public slots: + void stop(); + +signals: + void finished(); + void error(const QString &); + void status(const QString &); + +private slots: + void readyRead(); + void hostFound(); + void connected(); + void deleteMe(); + void errorHandling(int); + +private: + void sendToSocket(const QString &text, bool log = true); + + enum State { Ehlo, Auth, ReadAuth, Helo, Mail, Rcpt, + Data, Body, Quit, Close }; + + QString _header, _message; + Account _account; + QString _to; + QSocket *_socket; + int _state; +}; + +#endif + + diff --git a/noncore/unsupported/mail2/libmail/zaurusstuff.cpp b/noncore/unsupported/mail2/libmail/zaurusstuff.cpp new file mode 100644 index 0000000..bbf1541 --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/zaurusstuff.cpp @@ -0,0 +1,38 @@ +#include <sys/ioctl.h> +#include <fcntl.h> +#include <stdio.h> + +#include "zaurusstuff.h" +#include "sharp_char.h" + +ZaurusStuff::ZaurusStuff() : QObject() +{ + +} + +void ZaurusStuff::blinkLedOn() +{ + sharp_led_status st; + st.which = SHARP_LED_COLLIE_1; + st.status = LED_COLLIE_1_FLASHON; + ioctl(open("/dev/sharp_led", O_WRONLY), SHARP_LED_SETSTATUS, &st); +} + +void ZaurusStuff::blinkLedOff() +{ + sharp_led_status st; + st.which = SHARP_LED_COLLIE_1; + st.status = LED_COLLIE_1_DEFAULT; + ioctl(open("/dev/sharp_led", O_WRONLY), SHARP_LED_SETSTATUS, &st); +} + +void ZaurusStuff::buzzerOn() +{ + ioctl(open("/dev/sharp_buz", O_WRONLY), SHARP_BUZZER_MAKESOUND, 4); +} + +void ZaurusStuff::buzzerOff() +{ + +} + diff --git a/noncore/unsupported/mail2/libmail/zaurusstuff.h b/noncore/unsupported/mail2/libmail/zaurusstuff.h new file mode 100644 index 0000000..33c65da --- a/dev/null +++ b/noncore/unsupported/mail2/libmail/zaurusstuff.h @@ -0,0 +1,23 @@ +#ifndef ZAURUSSTUFF_H +#define ZAURUSSTUFF_H + +#include <qobject.h> + +class ZaurusStuff : public QObject +{ + Q_OBJECT + +public: + static void blinkLedOn(); + static void blinkLedOff(); + static void buzzerOn(); + static void buzzerOff(); + +protected: + ZaurusStuff(); + + +}; + +#endif + diff --git a/noncore/unsupported/mail2/listviewplus.cpp b/noncore/unsupported/mail2/listviewplus.cpp new file mode 100644 index 0000000..ce5f35f --- a/dev/null +++ b/noncore/unsupported/mail2/listviewplus.cpp @@ -0,0 +1,54 @@ +#include <qpopupmenu.h> +#include <qtimer.h> + +#include "listviewplus.h" + +ListViewPlus::ListViewPlus(QWidget *parent, const char *name, WFlags fl) + : QListView(parent, name, fl) +{ + +} + +void ListViewPlus::keyPressEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_Space: // FALLTHROUGH + case Qt::Key_Enter: + if (currentItem() != 0) + emit clicked(currentItem()); + break; + default: break; + } + + QListView::keyPressEvent(event); +} + +void ListViewPlus::setPopup(QPopupMenu *popup, int delay) +{ + _popup = popup; + _delay = delay; + + connect(this, SIGNAL(pressed(QListViewItem *, const QPoint &, int)), SLOT(_initPopup(QListViewItem *, const QPoint &, int))); + connect(this, SIGNAL(clicked(QListViewItem *, const QPoint &, int)), SLOT(_cancelPopup(QListViewItem *, const QPoint &, int))); +} + +void ListViewPlus::_initPopup(QListViewItem *, const QPoint &point, int) +{ + _point = point; + + _timer = new QTimer(); + _timer->start(_delay, true); + + connect(_timer, SIGNAL(timeout()), this, SLOT(_showPopup())); +} + +void ListViewPlus::_cancelPopup(QListViewItem *, const QPoint &, int) +{ + delete _timer; +} + +void ListViewPlus::_showPopup() +{ + _popup->popup(_point); +} + diff --git a/noncore/unsupported/mail2/listviewplus.h b/noncore/unsupported/mail2/listviewplus.h new file mode 100644 index 0000000..519bc39 --- a/dev/null +++ b/noncore/unsupported/mail2/listviewplus.h @@ -0,0 +1,37 @@ +#ifndef LISTVIEWPLUS_H +#define LISTVIEWPLUS_H + +#include <qlistview.h> + +class QPopupMenu; +class QPoint; +class QTimer; + +class ListViewPlus : public QListView +{ + Q_OBJECT + +public: + ListViewPlus(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + + void setPopup(QPopupMenu *popup, int delay = 800); + QPopupMenu *popup() { return _popup; } + +protected: + void keyPressEvent(QKeyEvent *event); + +private slots: + void _initPopup(QListViewItem *, const QPoint &point, int); + void _cancelPopup(QListViewItem *, const QPoint &, int); + void _showPopup(); + +private: + QPopupMenu *_popup; + QPoint _point; + QTimer *_timer; + int _delay; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/mail.pro b/noncore/unsupported/mail2/mail.pro new file mode 100644 index 0000000..6e498fd --- a/dev/null +++ b/noncore/unsupported/mail2/mail.pro @@ -0,0 +1,48 @@ +TEMPLATE = app +CONFIG = qt warn_on release +HEADERS = accounteditor.h \ + addresspicker.h \ + attachdiag.h \ + composer.h \ + composerbase.h \ + configdiag.h \ + folderwidget.h \ + listviewplus.h \ + mailtable.h \ + mainwindow.h \ + mainwindowbase.h \ + opendiag.h \ + passdiag.h \ + rename.h \ + searchdiag.h \ + viewmail.h \ + viewmailbase.h +SOURCES = accounteditor.cpp \ + addresspicker.cpp \ + attachdiag.cpp \ + composer.cpp \ + composerbase.cpp \ + configdiag.cpp \ + folderwidget.cpp \ + listviewplus.cpp \ + mailtable.cpp \ + main.cpp \ + mainwindow.cpp \ + mainwindowbase.cpp \ + opendiag.cpp \ + passdiag.cpp \ + rename.cpp \ + searchdiag.cpp \ + viewmail.cpp \ + viewmailbase.cpp +INTERFACES = accounteditorbase.ui \ + addresspickerbase.ui \ + configdiagbase.ui \ + opendiagbase.ui \ + passdiagbase.ui \ + renamebase.ui \ + searchdiagbase.ui +INCLUDEPATH += $(OPIEDIR)/include libmail +LIBS += -lmail -lqpe +TARGET = mail +DESTDIR = $(OPIEDIR)/bin diff --git a/noncore/unsupported/mail2/mailtable.cpp b/noncore/unsupported/mail2/mailtable.cpp new file mode 100644 index 0000000..fd179f0 --- a/dev/null +++ b/noncore/unsupported/mail2/mailtable.cpp @@ -0,0 +1,171 @@ +#include <qmessagebox.h> +#include <qpopupmenu.h> +#include <qheader.h> +#include <qtimer.h> + +#include "folderwidget.h" +#include "imaphandler.h" +#include "mailtable.h" + +MailTableItem::MailTableItem(QListView *parent, IMAPResponseFETCH fetch) + : QListViewItem(parent), _fetch(fetch) +{ + _draft = false; + _new = false; + _unseen = true; + + QValueList<IMAPResponseEnums::IMAPResponseFlags>::Iterator it; + QValueList<IMAPResponseEnums::IMAPResponseFlags> flags = fetch.flags(); + for (it = flags.begin(); it != flags.end(); it++) { + if (*it == IMAPResponseEnums::Draft) _draft = true; + else if (*it == IMAPResponseEnums::Recent) _new = true; + else if (*it == IMAPResponseEnums::Seen) _unseen = false; + } + + setText(0, fetch.envelope().from()[0].name().isEmpty() ? QObject::tr("(no from)") : fetch.envelope().from()[0].name()); + setText(1, fetch.envelope().subject().isEmpty() ? QObject::tr("(no subject)") : fetch.envelope().subject()); + setText(2, fetch.envelope().mailDate().isEmpty() ? QObject::tr("(no date)") : fetch.envelope().mailDate()); +} + +void MailTableItem::paintCell(QPainter *painter, const QColorGroup &cg, int col, int width, int align) +{ + QColor color = cg.color(QColorGroup::Text); + QFont font = painter->font(); + if (_draft) { + color = QColor("#707070"); + } else if (_new) { + color = QColor("#ff0000"); + font.setBold(true); + } else if (_unseen) { + font.setBold(true); + } + + painter->setFont(font); + QColorGroup cg_(cg); + cg_.setColor(QColorGroup::Text, color); + + QListViewItem::paintCell(painter, cg_, col, width, align); +} + +MailTable::MailTable(QWidget *parent, const char *name, WFlags fl) + : ListViewPlus(parent, name, fl), _parent(parent) +{ + _stopped = false; + + setSorting(-1); + + setAllColumnsShowFocus(true); + addColumn(tr("From"), 100); + addColumn(tr("Subject"), 100); + addColumn(tr("Date"), 100); + + QPopupMenu *menu = new QPopupMenu(this); + menu->insertItem(tr("Copy"), MENU_COPY); + + QPopupMenu *markMenu = new QPopupMenu(this); + markMenu->insertItem(tr("Seen"), MENU_MARK_READ); + markMenu->insertItem(tr("Unseen"), MENU_MARK_UNREAD); + markMenu->insertSeparator(); + markMenu->insertItem(tr("Marked"), MENU_MARK_MARKED); + markMenu->insertItem(tr("Unmarked"), MENU_MARK_UNMARKED); + + menu->insertItem(tr("Mark as..."), markMenu, MENU_MARK); + menu->insertSeparator(); + menu->insertItem(tr("Delete Mail"), MENU_DELETE); + setPopup(menu); + + connect(this, SIGNAL(clicked(QListViewItem *)), SLOT(itemClicked(QListViewItem *))); +} + +void MailTable::setFolder(Folder folder) +{ + folder.topFolder().handler()->iSelect(folder.fullName()); + _handler = folder.topFolder().handler(); + connect(folder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPSelect(IMAPResponse &))); +} + +void MailTable::setHeaders(QValueList<IMAPResponseFETCH> response) +{ + clear(); + QValueList<IMAPResponseFETCH>::Iterator it; + for (it = response.begin(); it != response.end(); it++) { + (void) new MailTableItem(this, *it); + } +} + +void MailTable::slotIMAPSelect(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPSelect(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + clear(); + QString mails = response.EXISTS()[0].mails(); + if (mails.toInt() == 0) { + emit status(tr("Mailbox contained no mails.")); + return; + } + int a = mails.toInt() / 5; + int b = mails.toInt() % 5; + + _downloadSteps = a; + if (b > 0) _downloadSteps++; + _lastStep = b; + _currentProgress = 0; + + emit totalSteps(_downloadSteps); + emit progress(_currentProgress); + emit stopEnabled(true); + + response.imapHandler()->iFetch(QString("1:%1").arg((a == 0) ? b : 5), "ENVELOPE FLAGS UID"); + emit status(tr("Getting mail headers...")); + connect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPFetch(IMAPResponse &))); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>An error occoured during the selection of the mailbox. (Server said: %1)</p>").arg(response.statusResponse().comment()), tr("Ok")); + } +} + +void MailTable::slotIMAPFetch(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPFetch(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + QValueList<IMAPResponseFETCH>::Iterator it; + QValueList<IMAPResponseFETCH> fetch = response.FETCH(); + for (it = fetch.begin(); it != fetch.end(); it++) { + (void) new MailTableItem(this, *it); + } + emit progress(++_currentProgress); + + if (_currentProgress != _downloadSteps) { + if (_stopped) { + _currentProgress = 0; + _downloadSteps = 0; + _lastStep = 0; + _stopped = false; + emit status(tr("Stopped")); + emit resetProgress(); + emit stopEnabled(false); + } else { + response.imapHandler()->iFetch(QString("%1:%2").arg(_currentProgress * 5 + 1).arg((_currentProgress + 1 == _downloadSteps) ? _currentProgress * 5 + _lastStep : _currentProgress * 5 + 5), "ENVELOPE FLAGS UID"); + connect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPFetch(IMAPResponse &))); + } + } else { + _currentProgress = 0; + _downloadSteps = 0; + _lastStep = 0; + emit status(tr("Got all mail headers.")); + emit resetProgress(); + emit stopEnabled(false); + } + } else { + emit status(tr("<font color=#ff0000>Couldn't fetch mail.")); + } +} + +void MailTable::itemClicked(QListViewItem *item) +{ + if (item == NULL) return; + emit mailClicked(((MailTableItem *)item)->fetch(), _handler); +} + + diff --git a/noncore/unsupported/mail2/mailtable.h b/noncore/unsupported/mail2/mailtable.h new file mode 100644 index 0000000..6deb70a --- a/dev/null +++ b/noncore/unsupported/mail2/mailtable.h @@ -0,0 +1,121 @@ +#ifndef MAILTABLE_H +#define MAILTABLE_H + +#include <qdatetime.h> + +#include "listviewplus.h" +#include "imapresponse.h" +#include "folderwidget.h" +#include "imaphandler.h" + +class MailPart +{ +public: + void setMimeType(QString mimeType) { _mimeType = mimeType; } + void setFileName(QString fileName) { _fileName = fileName; } + void setDescription(QString description) { _description = description; } + void setData(QString data) { _data = data; } + + QString mimeType() { return _mimeType; } + QString fileName() { return _fileName; } + QString description() { return _description; } + QString data() { return _data; } + +private: + QString _mimeType, _fileName, _description, _data; + +}; + +class Mail +{ +public: + enum ReadState { New, Unread, Old }; + + void setFrom(QString from) { _from = from; } + void setTo(QString to) { _to = to; } + void setSubject(QString subject) { _subject = subject; } + void setDate(QDate date) { _date = date; } + void setBody(QString body) { _body = body; } + void setReadState(ReadState readState) { _readState = readState; } + void setMailParts(QValueList<MailPart> parts) { _parts = parts; } + void addMailParts(MailPart part) { _parts.append(part); } + + QString from() { return _from; } + QString to() { return _to; } + QString subject() { return _subject; } + QDate date() { return _date; } + QString body() { return _body; } + ReadState readState() { return _readState; } + QValueList<MailPart> mailParts() { return _parts; } + +private: + QString _from, _to, _subject, _body; + QDate _date; + QValueList<MailPart> _parts; + ReadState _readState; + +}; + +class MailTableItem : public QListViewItem +{ +public: + MailTableItem(QListView *parent, IMAPResponseFETCH fetch); + + IMAPResponseFETCH fetch() { return _fetch; } + +protected: + void paintCell(QPainter *painter, const QColorGroup &cg, int col, int width, int align); + +private: + IMAPResponseFETCH _fetch; + bool _draft, _new, _unseen; + +}; + +class MailTable : public ListViewPlus +{ + Q_OBJECT + +public: + MailTable(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + + void addMail(Mail &mail); + void setHeaders(QValueList<IMAPResponseFETCH> response); + +public slots: + void stop() { _stopped = true; } + void setFolder(Folder folder); + +signals: + void totalSteps(int steps); + void progress(int progress); + void resetProgress(); + void mailClicked(IMAPResponseFETCH mail, IMAPHandler *handler); + void status(const QString &text); + void stopEnabled(bool stop); + +protected: + static const int MENU_COPY = 0; + static const int MENU_MARK_READ = 0; + static const int MENU_MARK_UNREAD = 1; + static const int MENU_MARK_MARKED = 2; + static const int MENU_MARK_UNMARKED = 3; + static const int MENU_MARK = 1; + static const int MENU_DELETE = 2; + +protected slots: + void itemClicked(QListViewItem *); + + void slotIMAPSelect(IMAPResponse &response); + void slotIMAPFetch(IMAPResponse &response); + +private: + QWidget *_parent; + IMAPHandler *_handler; + int _downloadSteps, _lastStep, _currentProgress; + bool _stopped; + +}; + +#endif + diff --git a/noncore/unsupported/mail2/main.cpp b/noncore/unsupported/mail2/main.cpp new file mode 100644 index 0000000..ddacf3d --- a/dev/null +++ b/noncore/unsupported/mail2/main.cpp @@ -0,0 +1,14 @@ +#include <qpe/qpeapplication.h> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QPEApplication app(argc, argv); + + MainWindow mw; + app.showMainWidget(&mw); + + return app.exec(); +} + diff --git a/noncore/unsupported/mail2/mainwindow.cpp b/noncore/unsupported/mail2/mainwindow.cpp new file mode 100644 index 0000000..4d15e23 --- a/dev/null +++ b/noncore/unsupported/mail2/mainwindow.cpp @@ -0,0 +1,65 @@ +#include <qprogressbar.h> +#include <qmessagebox.h> +#include <qaction.h> +#include <qlabel.h> + +#include "folderwidget.h" +#include "mainwindow.h" +#include "configdiag.h" +#include "configfile.h" +#include "searchdiag.h" +#include "mailtable.h" +#include "composer.h" +#include "viewmail.h" + +MainWindow::MainWindow(QWidget *parent, const char *name, WFlags fl) + : MainWindowBase(parent, name, fl) +{ + stop->setEnabled(false); + + connect(folderView, SIGNAL(status(const QString &)), statusLabel, SLOT(setText(const QString &))); + connect(folderView, SIGNAL(folderSelected(Folder)), mailView, SLOT(setFolder(Folder))); + + connect(mailView, SIGNAL(mailClicked(IMAPResponseFETCH, IMAPHandler *)), SLOT(mailClicked(IMAPResponseFETCH, IMAPHandler *))); + connect(mailView, SIGNAL(status(const QString &)), statusLabel, SLOT(setText(const QString &))); + connect(mailView, SIGNAL(totalSteps(int)), statusProgress, SLOT(setTotalSteps(int))); + connect(mailView, SIGNAL(progress(int)), statusProgress, SLOT(setProgress(int))); + connect(mailView, SIGNAL(resetProgress()), statusProgress, SLOT(reset())); + connect(mailView, SIGNAL(stopEnabled(bool)), stop, SLOT(setEnabled(bool))); + + connect(stop, SIGNAL(activated()), mailView, SLOT(stop())); + + connect(compose, SIGNAL(activated()), SLOT(slotCompose())); + connect(findmails, SIGNAL(activated()), SLOT(slotSearch())); + connect(configure, SIGNAL(activated()), SLOT(slotConfigure())); +} + +void MainWindow::slotCompose() +{ + Composer *composer = new Composer(); + composer->showMaximized(); + composer->show(); +} + +void MainWindow::slotSearch() +{ + SearchDiag *searchDiag = new SearchDiag(this, 0, true); + searchDiag->showMaximized(); + searchDiag->show(); +} + +void MainWindow::slotConfigure() +{ + ConfigDiag *configDiag = new ConfigDiag(this, 0, true); + configDiag->showMaximized(); + configDiag->show(); + + connect(configDiag, SIGNAL(changed()), folderView, SLOT(update())); +} + +void MainWindow::mailClicked(IMAPResponseFETCH mail, IMAPHandler *handler) +{ + ViewMail *viewMail = new ViewMail(mail, handler); + viewMail->showMaximized(); + viewMail->show(); +} diff --git a/noncore/unsupported/mail2/mainwindow.h b/noncore/unsupported/mail2/mainwindow.h new file mode 100644 index 0000000..1edf10b --- a/dev/null +++ b/noncore/unsupported/mail2/mainwindow.h @@ -0,0 +1,24 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "mainwindowbase.h" + +class IMAPHandler; +class IMAPResponseFETCH; + +class MainWindow : public MainWindowBase +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected slots: + void slotCompose(); + void slotSearch(); + void slotConfigure(); + void mailClicked(IMAPResponseFETCH mail, IMAPHandler *handler); + +}; + +#endif diff --git a/noncore/unsupported/mail2/mainwindowbase.cpp b/noncore/unsupported/mail2/mainwindowbase.cpp new file mode 100644 index 0000000..4054af6 --- a/dev/null +++ b/noncore/unsupported/mail2/mainwindowbase.cpp @@ -0,0 +1,75 @@ +#include <qprogressbar.h> +#include <qtoolbutton.h> +#include <qpopupmenu.h> +#include <qtoolbar.h> +#include <qaction.h> +#include <qheader.h> +#include <qlabel.h> +#include <qvbox.h> + +#include <qpe/resource.h> + +#include "mainwindowbase.h" +#include "folderwidget.h" +#include "mailtable.h" + +MainWindowBase::MainWindowBase(QWidget *parent, const char *name, WFlags fl) + : QMainWindow(parent, name, fl) +{ + setCaption(tr("E-Mail")); + setToolBarsMovable(false); + + toolbar = new QToolBar(this); + addToolBar(toolbar); + toolbar->setHorizontalStretchable(true); + + compose = new QAction(tr("Compose new mail"), QIconSet(Resource::loadPixmap("mail/newmail")), 0, 0, this); + compose->addTo(toolbar); + + folders = new QAction(tr("Show/hide folders"), QIconSet(Resource::loadPixmap("mail/folder")), 0, 0, this, 0, true); + folders->addTo(toolbar); + connect(folders, SIGNAL(toggled(bool)), SLOT(slotFoldersToggled(bool))); + + findmails = new QAction(tr("Search mails"), QIconSet(Resource::loadPixmap("mail/find")), 0, 0, this); + findmails->addTo(toolbar); + + configure = new QAction(tr("Configuration"), QIconSet(Resource::loadPixmap("mail/configure")), 0, 0, this); + configure->addTo(toolbar); + + QLabel *spacer = new QLabel(toolbar); + spacer->setBackgroundMode(QWidget::PaletteButton); + toolbar->setStretchableWidget(spacer); + + stop = new QAction(tr("Abort"), QIconSet(Resource::loadPixmap("mail/abort")), 0, 0, this); + stop->addTo(toolbar); + + QVBox *view = new QVBox(this); + setCentralWidget(view); + + folderView = new FolderWidget(view); + folderView->setMinimumHeight(90); + folderView->setMaximumHeight(90); + folderView->hide(); + + mailView = new MailTable(view); + mailView->setMinimumHeight(50); + + QHBox *status = new QHBox(view); + + statusLabel = new QLabel(status); + QFont tmpFont = statusLabel->font(); + tmpFont.setPixelSize(8); + statusLabel->setFont(tmpFont); + + statusProgress = new QProgressBar(status); + statusProgress->setCenterIndicator(true); + statusProgress->setMaximumHeight(15); + statusProgress->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); +} + +void MainWindowBase::slotFoldersToggled(bool toggled) +{ + if (folderView->isHidden() && toggled) folderView->show(); + if (!folderView->isHidden() && !toggled) folderView->hide(); +} + diff --git a/noncore/unsupported/mail2/mainwindowbase.h b/noncore/unsupported/mail2/mainwindowbase.h new file mode 100644 index 0000000..cf23f4f --- a/dev/null +++ b/noncore/unsupported/mail2/mainwindowbase.h @@ -0,0 +1,35 @@ +#ifndef MAINWINDOWBASE_H +#define MAINWINDOWBASE_H + +#include <qmainwindow.h> + +class ServerConnection; +class QProgressBar; +class FolderWidget; +class MailTable; +class QToolBar; +class QAction; +class QLabel; + +class MainWindowBase : public QMainWindow +{ + Q_OBJECT + +public: + MainWindowBase(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected slots: + void slotFoldersToggled(bool toggled); + +protected: + ServerConnection *serverConnection; + QProgressBar *statusProgress; + FolderWidget *folderView; + MailTable *mailView; + QToolBar *toolbar; + QAction *compose, *folders, *findmails, *configure, *stop; + QLabel *statusLabel; + +}; + +#endif diff --git a/noncore/unsupported/mail2/opendiag.cpp b/noncore/unsupported/mail2/opendiag.cpp new file mode 100644 index 0000000..3dc3fd5 --- a/dev/null +++ b/noncore/unsupported/mail2/opendiag.cpp @@ -0,0 +1,8 @@ +#include "opendiag.h" + +OpenDiag::OpenDiag(QWidget *parent, const char *name, WFlags fl) + : OpenDiagBase(parent, name, fl) +{ + +} + diff --git a/noncore/unsupported/mail2/opendiag.h b/noncore/unsupported/mail2/opendiag.h new file mode 100644 index 0000000..b74490b --- a/dev/null +++ b/noncore/unsupported/mail2/opendiag.h @@ -0,0 +1,16 @@ +#ifndef OPENDIAG_H +#define OPENDIAG_H + +#include "opendiagbase.h" + +class OpenDiag : public OpenDiagBase +{ + Q_OBJECT + +public: + OpenDiag(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +}; + +#endif + diff --git a/noncore/unsupported/mail2/opendiagbase.ui b/noncore/unsupported/mail2/opendiagbase.ui new file mode 100644 index 0000000..8360864 --- a/dev/null +++ b/noncore/unsupported/mail2/opendiagbase.ui @@ -0,0 +1,254 @@ +<!DOCTYPE UI><UI> +<class>OpenDiagBase</class> +<widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>OpenDiagBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>244</width> + <height>269</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Open file...</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="8" column="0" > + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout3</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QProgressBar</class> + <property stdset="1"> + <name>name</name> + <cstring>progress</cstring> + </property> + <property stdset="1"> + <name>centerIndicator</name> + <bool>true</bool> + </property> + </widget> + <widget> + <class>QToolButton</class> + <property stdset="1"> + <name>name</name> + <cstring>stop</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string> Stop </string> + </property> + </widget> + </hbox> + </widget> + <widget row="7" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>statusLabel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>%1</b> kB of <b>%2</b> kB at <b>%3</b> kB/s</string> + </property> + </widget> + <spacer row="6" column="0" > + <property> + <name>name</name> + <cstring>Spacer2</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>icon</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>[Icon]</string> + </property> + <property stdset="1"> + <name>alignment</name> + <set>AlignCenter</set> + </property> + <property> + <name>hAlign</name> + </property> + </widget> + <widget row="1" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>mimeType</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><i>application/v-card</string> + </property> + <property stdset="1"> + <name>alignment</name> + <set>AlignCenter</set> + </property> + <property> + <name>hAlign</name> + </property> + </widget> + <widget row="2" column="0" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>open</cstring> + </property> + <property stdset="1"> + <name>font</name> + <font> + <bold>1</bold> + </font> + </property> + <property stdset="1"> + <name>text</name> + <string>Open using an application</string> + </property> + </widget> + <widget row="3" column="0" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>save</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Save to disk</string> + </property> + </widget> + <widget row="4" column="0" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>show</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Display</string> + </property> + </widget> + <widget row="5" column="0" > + <class>QButtonGroup</class> + <property stdset="1"> + <name>name</name> + <cstring>ButtonGroup1</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>Save to</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget> + <class>QRadioButton</class> + <property stdset="1"> + <name>name</name> + <cstring>saveToRam</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>RAM</string> + </property> + <property stdset="1"> + <name>checked</name> + <bool>true</bool> + </property> + </widget> + <widget> + <class>QRadioButton</class> + <property stdset="1"> + <name>name</name> + <cstring>saveToCf</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>CF</string> + </property> + </widget> + <widget> + <class>QRadioButton</class> + <property stdset="1"> + <name>name</name> + <cstring>saveToSd</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>SD</string> + </property> + </widget> + </hbox> + </widget> + </grid> +</widget> +<tabstops> + <tabstop>open</tabstop> + <tabstop>save</tabstop> + <tabstop>show</tabstop> +</tabstops> +</UI> diff --git a/noncore/unsupported/mail2/opie-mail2.control b/noncore/unsupported/mail2/opie-mail2.control new file mode 100644 index 0000000..5195789 --- a/dev/null +++ b/noncore/unsupported/mail2/opie-mail2.control @@ -0,0 +1,9 @@ +Files: bin/mail $QTDIR/lib/libmail.so* plugins/applets/libbend.so* apps/Applications/mail.desktop pics/mail/*.png +Priority: optional +Section: qpe/applications +Maintainer: Constantin Bergemann <cbergemann@lisa.de> +Architecture: arm +Version: 0.0.9-$SUB_VERSION +Depends: opie-base +Description: An IMAP mail client +License: LGPL diff --git a/noncore/unsupported/mail2/passdiag.cpp b/noncore/unsupported/mail2/passdiag.cpp new file mode 100644 index 0000000..d3daa2c --- a/dev/null +++ b/noncore/unsupported/mail2/passdiag.cpp @@ -0,0 +1,38 @@ +#include <qmessagebox.h> +#include <qpushbutton.h> +#include <qlineedit.h> +#include <qlabel.h> + +#include "passdiag.h" + +PassDiag::PassDiag(QString text, QWidget *parent, const char *name, bool modal, WFlags fl) + : PassDiagBase(parent, name, modal, fl) +{ + infoLabel->setText(text); + + connect(ok, SIGNAL(clicked()), SLOT(accept())); + connect(cancel, SIGNAL(clicked()), SLOT(close())); +} + +void PassDiag::accept() +{ + if (password->text().isEmpty()) { + QMessageBox::information(this, tr("Error"), tr("<p>You have to enter a password or click on cancel.</p>"), tr("Ok")); + return; + } + + QDialog::accept(); +} + +QString PassDiag::getPassword(QWidget *parent, QString text) +{ + PassDiag *diag = new PassDiag(text, parent, 0, true); + diag->show(); + + if (QDialog::Accepted == diag->exec()) { + return diag->password->text(); + } + + return 0; +} + diff --git a/noncore/unsupported/mail2/passdiag.h b/noncore/unsupported/mail2/passdiag.h new file mode 100644 index 0000000..b611dd5 --- a/dev/null +++ b/noncore/unsupported/mail2/passdiag.h @@ -0,0 +1,21 @@ +#ifndef PASSDIAG_H +#define PASSDIAG_H + +#include "passdiagbase.h" + +class PassDiag : public PassDiagBase +{ + Q_OBJECT + +public: + static QString getPassword(QWidget *parent, QString text); + +protected: + PassDiag(QString text, QWidget *parent, const char *name = 0, bool modal = false, WFlags fl = 0); + +protected slots: + void accept(); + +}; + +#endif diff --git a/noncore/unsupported/mail2/passdiagbase.ui b/noncore/unsupported/mail2/passdiagbase.ui new file mode 100644 index 0000000..daf8bad --- a/dev/null +++ b/noncore/unsupported/mail2/passdiagbase.ui @@ -0,0 +1,115 @@ +<!DOCTYPE UI><UI> +<class>PassDiagBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>PassDiagBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>216</width> + <height>120</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Enter your Password</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" rowspan="1" colspan="4" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>infoLabel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Please enter your GPG passphrase:</string> + </property> + </widget> + <widget row="1" column="0" rowspan="1" colspan="4" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>password</cstring> + </property> + <property stdset="1"> + <name>echoMode</name> + <enum>Password</enum> + </property> + </widget> + <widget row="2" column="0" rowspan="1" colspan="4" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>showPasswd</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Show Password</string> + </property> + </widget> + <widget row="4" column="1" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>ok</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Ok</string> + </property> + </widget> + <widget row="4" column="2" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>cancel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Cancel</string> + </property> + </widget> + <spacer row="3" column="2" > + <property> + <name>name</name> + <cstring>Spacer3</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> +</widget> +</UI> diff --git a/noncore/unsupported/mail2/rename.cpp b/noncore/unsupported/mail2/rename.cpp new file mode 100644 index 0000000..8c2fde1 --- a/dev/null +++ b/noncore/unsupported/mail2/rename.cpp @@ -0,0 +1,39 @@ +#include <qlineedit.h> +#include <qlabel.h> + +#include "rename.h" + +Rename::Rename(QWidget *parent, const char *name, bool modal, WFlags fl) + : RenameBase(parent, name, modal, fl) +{ +} + +QString Rename::rename(const QString &on, QWidget *parent) +{ + Rename *rename = new Rename(parent, 0, true); + rename->oldName->setText(on); + rename->newName->setText(on); + rename->newName->setFocus(); + + if (rename->exec() == QDialog::Accepted) { + return rename->newName->text(); + } + + return QString(0); +} + +QString Rename::getText(const QString &caption, const QString &secondLabel, QWidget *parent) +{ + Rename *rename = new Rename(parent, 0, true); + rename->firstLabel->hide(); + rename->oldName->hide(); + rename->setCaption(caption); + rename->secondLabel->setText(secondLabel); + + if (rename->exec() == QDialog::Accepted) { + return rename->newName->text(); + } + + return QString(0); +} + diff --git a/noncore/unsupported/mail2/rename.h b/noncore/unsupported/mail2/rename.h new file mode 100644 index 0000000..757623e --- a/dev/null +++ b/noncore/unsupported/mail2/rename.h @@ -0,0 +1,20 @@ +#ifndef RENAME_H +#define RENAME_H + +#include "renamebase.h" + +class Rename : public RenameBase +{ + Q_OBJECT + +public: + static QString rename(const QString &on, QWidget *parent); + static QString getText(const QString &caption, const QString &secondLabel, QWidget *parent); + +protected: + Rename(QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags fl = 0); + +}; + +#endif + diff --git a/noncore/unsupported/mail2/renamebase.ui b/noncore/unsupported/mail2/renamebase.ui new file mode 100644 index 0000000..20b7ffb --- a/dev/null +++ b/noncore/unsupported/mail2/renamebase.ui @@ -0,0 +1,79 @@ +<!DOCTYPE UI><UI> +<class>RenameBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>RenameBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>179</width> + <height>91</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Renaming</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="1" column="0" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>oldName</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + </widget> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>firstLabel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><div align=center>Renaming</string> + </property> + </widget> + <widget row="2" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>secondLabel</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><div align=center>to</string> + </property> + </widget> + <widget row="3" column="0" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>newName</cstring> + </property> + </widget> + </grid> +</widget> +</UI> diff --git a/noncore/unsupported/mail2/searchdiag.cpp b/noncore/unsupported/mail2/searchdiag.cpp new file mode 100644 index 0000000..33b8afb --- a/dev/null +++ b/noncore/unsupported/mail2/searchdiag.cpp @@ -0,0 +1,128 @@ +#include <qmessagebox.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <qlineedit.h> + +#include <qpe/qpeapplication.h> + +#include "imaphandler.h" +#include "searchdiag.h" +#include "viewmail.h" + +#define INMENU_BODY 0 +#define INMENU_HEADERF 1 +#define INMENU_SUBJECT 2 +#define INMENU_FROM 3 +#define INMENU_TO 4 + +SearchDiag::SearchDiag(QWidget *parent, const char *name, WFlags fl) + : SearchDiagBase(parent, name, fl) +{ + _selected = false; + + in->insertItem(tr("Body"), INMENU_BODY); + in->insertItem(tr("Header Field"), INMENU_HEADERF); + in->insertItem(tr("Subject"), INMENU_SUBJECT); + in->insertItem(tr("From"), INMENU_FROM); + in->insertItem(tr("To"), INMENU_TO); + + connect(folderView, SIGNAL(folderSelected(Folder)), SLOT(folderSelected(Folder))); + connect(in, SIGNAL(activated(int)), SLOT(slotInItemActivated(int))); + connect(mailTable, SIGNAL(mailClicked(IMAPResponseFETCH, IMAPHandler *)), SLOT(slotMailClicked(IMAPResponseFETCH, IMAPHandler *))); +} + +void SearchDiag::accept() +{ + if (searchFor->text().isEmpty()) { + QMessageBox::information(this, tr("Error"), tr("<p>Please enter what to search for.</p>"), tr("Ok")); + return; + } + + if (!_selected) { + QMessageBox::information(this, tr("Error"), tr("<p>Please select a folder.</p>"), tr("Ok")); + return; + } + + if (in->currentItem() == INMENU_HEADERF && other->currentText().isEmpty()) { + QMessageBox::information(this, tr("Error"), tr("<p>Please enter a header field to search in.</p>"), tr("Ok")); + return; + } + + _folder.topFolder().handler()->iSelect(_folder.fullName()); + connect(_folder.topFolder().handler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPSelect(IMAPResponse &))); +} + +void SearchDiag::folderSelected(Folder folder) +{ + _selected = true; + _folder = folder; +} + +void SearchDiag::slotIMAPSelect(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPSelect(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + if (in->currentItem() == INMENU_BODY) { + response.imapHandler()->iSearch("BODY \"" + searchFor->text() + "\""); + } else if (in->currentItem() == INMENU_HEADERF) { + response.imapHandler()->iSearch("HEADER \""+ other->currentText() + "\" \"" + searchFor->text() + "\""); + } else if (in->currentItem() == INMENU_SUBJECT) { + response.imapHandler()->iSearch("SUBJECT \"" + searchFor->text() + "\""); + } else if (in->currentItem() == INMENU_FROM) { + response.imapHandler()->iSearch("FROM \"" + searchFor->text() + "\""); + } else if (in->currentItem() == INMENU_TO) { + response.imapHandler()->iSearch("TO \"" + searchFor->text() + "\""); + } else return; + + connect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPSearch(IMAPResponse &))); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Could not select the folder. Aborting. (Server said: %1)").arg(response.statusResponse().comment()), tr("Ok")); + } +} + +void SearchDiag::slotIMAPSearch(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPSearch(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + IMAPResponseSEARCH results = response.SEARCH()[0]; + if (results.mails().count() == 0) { + QMessageBox::information(this, tr("Results"), tr("<p>No mails match your criteria.</p>"), tr("Ok")); + return; + } + + response.imapHandler()->iFetch(results.mails().join(","), "ENVELOPE FLAGS UID"); + connect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPFetch(IMAPResponse &))); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Search failed. (Server said: %1)").arg(response.statusResponse().comment()), tr("Ok")); + } +} + +void SearchDiag::slotIMAPFetch(IMAPResponse &response) +{ + disconnect(response.imapHandler(), SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPSearch(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + mailTable->setHeaders(response.FETCH()); + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>Couldn't fetch the mail headers. (Server said: %1)").arg(response.statusResponse().comment())); + } +} + +void SearchDiag::slotMailClicked(IMAPResponseFETCH fetch, IMAPHandler *) +{ + ViewMail *viewMail = new ViewMail(fetch, _folder.topFolder().handler()); + viewMail->showMaximized(); + viewMail->show(); +} + +void SearchDiag::slotInItemActivated(int index) +{ + if (index == INMENU_HEADERF) { + other->setEnabled(true); + } else { + other->setEnabled(false); + } +} + diff --git a/noncore/unsupported/mail2/searchdiag.h b/noncore/unsupported/mail2/searchdiag.h new file mode 100644 index 0000000..5db57e3 --- a/dev/null +++ b/noncore/unsupported/mail2/searchdiag.h @@ -0,0 +1,32 @@ +#ifndef SEARCHDIAG_H +#define SEARCHDIAG_H + +#include "searchdiagbase.h" +#include "mailtable.h" + +class IMAPResponse; + +class SearchDiag : public SearchDiagBase +{ + Q_OBJECT + +public: + SearchDiag(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected slots: + void accept(); + void slotInItemActivated(int index); + void folderSelected(Folder folder); + void slotMailClicked(IMAPResponseFETCH response, IMAPHandler *); + + void slotIMAPSelect(IMAPResponse &); + void slotIMAPSearch(IMAPResponse &); + void slotIMAPFetch(IMAPResponse &); + +private: + bool _selected; + Folder _folder; + +}; + +#endif diff --git a/noncore/unsupported/mail2/searchdiagbase.ui b/noncore/unsupported/mail2/searchdiagbase.ui new file mode 100644 index 0000000..644180b --- a/dev/null +++ b/noncore/unsupported/mail2/searchdiagbase.ui @@ -0,0 +1,179 @@ +<!DOCTYPE UI><UI> +<class>SearchDiagBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>SearchDiagBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>260</width> + <height>336</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Mail Search</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget row="0" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel10</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>Search&nbsp;in:</string> + </property> + </widget> + <widget row="1" column="1" > + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>searchFor</cstring> + </property> + </widget> + <widget row="1" column="0" > + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel11</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><b>For:</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout1</cstring> + </property> + <property> + <name>layoutSpacing</name> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>3</number> + </property> + <widget> + <class>QComboBox</class> + <property stdset="1"> + <name>name</name> + <cstring>in</cstring> + </property> + </widget> + <widget> + <class>QComboBox</class> + <property stdset="1"> + <name>name</name> + <cstring>other</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>editable</name> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget row="3" column="0" rowspan="1" colspan="2" > + <class>MailTable</class> + <property stdset="1"> + <name>name</name> + <cstring>mailTable</cstring> + </property> + </widget> + <widget row="2" column="0" rowspan="1" colspan="2" > + <class>FolderWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>folderView</cstring> + </property> + <property stdset="1"> + <name>minimumSize</name> + <size> + <width>0</width> + <height>100</height> + </size> + </property> + <property stdset="1"> + <name>maximumSize</name> + <size> + <width>32767</width> + <height>100</height> + </size> + </property> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>MailTable</class> + <header location="local">mailtable.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> + <customwidget> + <class>FolderWidget</class> + <header location="local">folderwidget.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image> + <name>image0</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> +</images> +<tabstops> + <tabstop>in</tabstop> + <tabstop>other</tabstop> + <tabstop>searchFor</tabstop> +</tabstops> +</UI> diff --git a/noncore/unsupported/mail2/viewmail.cpp b/noncore/unsupported/mail2/viewmail.cpp new file mode 100644 index 0000000..ae1f5f3 --- a/dev/null +++ b/noncore/unsupported/mail2/viewmail.cpp @@ -0,0 +1,172 @@ +#include <qtextbrowser.h> +#include <qmessagebox.h> +#include <qaction.h> + +#include "mailfactory.h" +#include "composer.h" +#include "viewmail.h" + +AttachItem::AttachItem(QListView *parent, AttachItemStore &attachItemStore) + : QListViewItem(parent), _attachItemStore(attachItemStore) +{ + setText(0, _attachItemStore.mimeType()); + setText(1, _attachItemStore.fileName()); + setText(2, _attachItemStore.description()); +} + +AttachItem::AttachItem(QListViewItem *parent, AttachItemStore &attachItemStore) + : QListViewItem(parent), _attachItemStore(attachItemStore) +{ + setText(0, _attachItemStore.mimeType()); + setText(1, _attachItemStore.fileName()); + setText(2, _attachItemStore.description()); +} + +ViewMail::ViewMail(IMAPResponseFETCH &mail, IMAPHandler *handler, QWidget *parent, const char *name, WFlags fl) + : ViewMailBase(parent, name, fl), _mail(mail), _handler(handler) +{ + setCaption(caption().arg(mail.envelope().from()[0].name())); + + _gotBody = false; + _mailHtml = tr( + "<html><body>" + "<div align=center><b>%1</b></div>" + "<b>From:</b> %2<br>" + "<b>To:</b> %3<br>" + "%4" + "%5" + "<b>Date:</b> %6<hr>" + "<font face=fixed>%7</font>") + .arg(deHtml(mail.envelope().subject().isNull() ? tr("(no subject)") + : deHtml(mail.envelope().subject()))) + .arg(deHtml(mail.envelope().from().toString().isNull() ? tr("(no from)") + : mail.envelope().from().toString())) + .arg(deHtml(mail.envelope().to().toString().isNull() ? tr("(no recipient)") + : mail.envelope().to().toString())) + .arg(mail.envelope().cc().toString().isNull() ? QString(0) + : tr("<b>Cc:</b> %1<br>").arg(deHtml(mail.envelope().cc().toString()))) + .arg(mail.envelope().bcc().toString().isNull() ? QString(0) + : tr("<b>Bcc:</b> %1<br>").arg(deHtml(mail.envelope().bcc().toString()))) + .arg(mail.envelope().mailDate().isNull() ? tr("(no date)") + : mail.envelope().mailDate()) + .arg("%1"); + + connect(reply, SIGNAL(activated()), SLOT(slotReply())); + connect(forward, SIGNAL(activated()), SLOT(slotForward())); + + attachments->setEnabled(_gotBody); + browser->setText(QString(_mailHtml).arg(tr("Getting mail body from server. Please wait..."))); + + _handler->iUid("FETCH", QString("%1 (BODY[1])").arg(mail.uid())); + connect(_handler, SIGNAL(gotResponse(IMAPResponse &)), SLOT(slotIMAPUid(IMAPResponse &))); +} + +QString ViewMail::deHtml(const QString &string) +{ + QString string_ = string; + string_.replace(QRegExp("&"), "&"); + string_.replace(QRegExp("<"), "<"); + string_.replace(QRegExp(">"), ">"); + string_.replace(QRegExp("\\n"), "<br>"); + return string_; +} + +void ViewMail::slotReply() +{ + if (!_gotBody) { + QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot reply yet."), tr("Ok")); + return; + } + + QString rtext; + rtext += QString("* %1 wrote on %2:\n") // no i18n on purpose + .arg(_mail.envelope().from()[0].toString()) + .arg(_mail.envelope().mailDate()); + + QString text = _mail.bodyPart(1).data(); + QStringList lines = QStringList::split(QRegExp("\\n"), text); + QStringList::Iterator it; + for (it = lines.begin(); it != lines.end(); it++) { + rtext += "> " + *it + "\n"; + } + rtext += "\n"; + + QString prefix; + if (_mail.envelope().subject().find(QRegExp("^Re: *$")) != -1) prefix = ""; + else prefix = "Re: "; // no i18n on purpose + + SendMail sendMail; + sendMail.setTo(_mail.envelope().from()[0].toString()); + sendMail.setSubject(prefix + _mail.envelope().subject()); + sendMail.setInReplyTo(_mail.envelope().messageId()); + sendMail.setMessage(rtext); + + Composer *composer = new Composer(0, 0, Qt::WType_Modal); + composer->setSendMail(sendMail); + composer->showMaximized(); + composer->show(); +} + +void ViewMail::slotForward() +{ + if (!_gotBody) { + QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot forward yet."), tr("Ok")); + return; + } + + QString ftext; + ftext += QString("\n----- Forwarded message from %1 -----\n\n") + .arg(_mail.envelope().from()[0].toString()); + if (!_mail.envelope().mailDate().isNull()) + ftext += QString("Date: %1\n") + .arg(_mail.envelope().mailDate()); + if (!_mail.envelope().from()[0].toString().isNull()) + ftext += QString("From: %1\n") + .arg(_mail.envelope().from()[0].toString()); + if (!_mail.envelope().to().toString().isNull()) + ftext += QString("To: %1\n") + .arg(_mail.envelope().to().toString()); + if (!_mail.envelope().cc().toString().isNull()) + ftext += QString("Cc: %1\n") + .arg(_mail.envelope().cc().toString()); + if (!_mail.envelope().bcc().toString().isNull()) + ftext += QString("Bcc: %1\n") + .arg(_mail.envelope().bcc().toString()); + if (!_mail.envelope().subject().isNull()) + ftext += QString("Subject: %1\n") + .arg(_mail.envelope().subject()); + + ftext += QString("\n%1\n") + .arg(_mail.bodyPart(1).data()); + + ftext += QString("----- End forwarded message -----\n"); + + SendMail sendMail; + sendMail.setSubject("Fwd: " + _mail.envelope().subject()); + sendMail.setMessage(ftext); + + Composer *composer = new Composer(0, 0, Qt::WType_Modal); + composer->setSendMail(sendMail); + composer->showMaximized(); + composer->show(); +} + +void ViewMail::slotIMAPUid(IMAPResponse &response) +{ + disconnect(_handler, SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPUid(IMAPResponse &))); + + if (response.statusResponse().status() == IMAPResponseEnums::OK) { + QValueList<IMAPResponseBodyPart> bodyParts; + bodyParts.append(response.FETCH()[0].bodyPart(1)); + _mail.setBodyParts(bodyParts); + + browser->setText(QString(_mailHtml).arg(deHtml(response.FETCH()[0].bodyPart(1).data()))); + +// fillList(response.FETCH()[0].bodyStructure()); + + _gotBody = true; + } else { + QMessageBox::warning(this, tr("Error"), tr("<p>I was unable to retrieve the mail from the server. You can try again later or give up.</p>"), tr("Ok")); + } +} + diff --git a/noncore/unsupported/mail2/viewmail.h b/noncore/unsupported/mail2/viewmail.h new file mode 100644 index 0000000..a013e43 --- a/dev/null +++ b/noncore/unsupported/mail2/viewmail.h @@ -0,0 +1,65 @@ +#ifndef VIEWMAIL_H +#define VIEWMAIL_H + +#include <qlistview.h> + +#include "viewmailbase.h" +#include "imapresponse.h" +#include "mailtable.h" + +class AttachItemStore +{ +public: + void setMimeType(QString mimeType) { _mimeType = mimeType; } + QString mimeType() { return _mimeType; } + void setFileName(QString fileName) { _fileName = fileName; } + QString fileName() { return _fileName; } + void setDescription(QString description) { _description = description; } + QString description() { return _description; } + void setPartNum(QString partNum) { _partNum = partNum; } + QString partNum() { return _partNum; } + +private: + QString _mimeType, _fileName, _description, _partNum; + +}; + +class AttachItem : public QListViewItem +{ +public: + AttachItem(QListView *parent, AttachItemStore &attachment); + AttachItem(QListViewItem *parent, AttachItemStore &attachment); + + AttachItemStore attachItemStore() { return _attachItemStore; } + +private: + AttachItemStore _attachItemStore; + +}; + +class ViewMail : public ViewMailBase +{ + Q_OBJECT + +public: + ViewMail(IMAPResponseFETCH &mail, IMAPHandler *handler, QWidget *parent = 0, const char *name = 0, WFlags fl = Qt::WType_Modal); + +protected: +// void fillList(IMAPResponseBODYSTRUCTURE &structure); + QString deHtml(const QString &string); + +protected slots: + void slotReply(); + void slotForward(); + + void slotIMAPUid(IMAPResponse &response); + +private: + IMAPResponseFETCH _mail; + IMAPHandler *_handler; + QString _mailHtml; + bool _gotBody; + +}; + +#endif diff --git a/noncore/unsupported/mail2/viewmailbase.cpp b/noncore/unsupported/mail2/viewmailbase.cpp new file mode 100644 index 0000000..134e5cb --- a/dev/null +++ b/noncore/unsupported/mail2/viewmailbase.cpp @@ -0,0 +1,65 @@ +#include <qtextbrowser.h> +#include <qlistview.h> +#include <qtoolbar.h> +#include <qaction.h> +#include <qlabel.h> +#include <qvbox.h> + +#include <qpe/resource.h> + +#include "viewmailbase.h" +#include "opendiag.h" + +ViewMailBase::ViewMailBase(QWidget *parent, const char *name, WFlags fl) + : QMainWindow(parent, name, fl) +{ + setCaption(tr("E-Mail by %1")); + setToolBarsMovable(false); + + toolbar = new QToolBar(this); + toolbar->setHorizontalStretchable(true); + addToolBar(toolbar); + + reply = new QAction(tr("Reply"), QIconSet(Resource::loadPixmap("mail/reply")), 0, 0, this); + reply->addTo(toolbar); + + forward = new QAction(tr("Forward"), QIconSet(Resource::loadPixmap("mail/forward")), 0, 0, this); + forward->addTo(toolbar); + + attachbutton = new QAction(tr("Attachments"), QIconSet(Resource::loadPixmap("mail/attach")), 0, 0, this, 0, true); + attachbutton->addTo(toolbar); + connect(attachbutton, SIGNAL(toggled(bool)), SLOT(slotChangeAttachview(bool))); + + deleteMail = new QAction(tr("Delete Mail"), QIconSet(Resource::loadPixmap("mail/delete")), 0, 0, this); + deleteMail->addTo(toolbar); + + QLabel *spacer = new QLabel(toolbar); + spacer->setBackgroundMode(QWidget::PaletteButton); + toolbar->setStretchableWidget(spacer); + + QVBox *view = new QVBox(this); + setCentralWidget(view); + + attachments = new QListView(view); + attachments->setMinimumHeight(90); + attachments->setMaximumHeight(90); + attachments->setAllColumnsShowFocus(true); + attachments->addColumn("Mime Type", 100); + attachments->addColumn("Filename", 100); + attachments->addColumn("Description", 100); + attachments->hide(); + + browser = new QTextBrowser(view); + + openDiag = new OpenDiag(view); + openDiag->hide(); + +} + +void ViewMailBase::slotChangeAttachview(bool state) +{ + if (state) attachments->show(); + else attachments->hide(); +} + + diff --git a/noncore/unsupported/mail2/viewmailbase.h b/noncore/unsupported/mail2/viewmailbase.h new file mode 100644 index 0000000..183bb04 --- a/dev/null +++ b/noncore/unsupported/mail2/viewmailbase.h @@ -0,0 +1,32 @@ +#ifndef VIEWMAILBASE_H +#define VIEWMAILBASE_H + +#include <qmainwindow.h> + +class QAction; +class OpenDiag; +class QToolBar; +class QListView; +class QTextBrowser; + +class ViewMailBase : public QMainWindow +{ + Q_OBJECT + +public: + ViewMailBase(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected: + QAction *reply, *forward, *attachbutton, *deleteMail; + QListView *attachments; + QToolBar *toolbar; + QTextBrowser *browser; + OpenDiag *openDiag; + +protected slots: + void slotChangeAttachview(bool state); + +}; + +#endif + |