author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /noncore/comm | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
31 files changed, 4503 insertions, 0 deletions
diff --git a/noncore/comm/keypebble/.cvsignore b/noncore/comm/keypebble/.cvsignore new file mode 100644 index 0000000..c4782a1 --- a/dev/null +++ b/noncore/comm/keypebble/.cvsignore @@ -0,0 +1,5 @@ +moc_* +*.moc +Makefile +vncoptionsbase.cpp +vncoptionsbase.h diff --git a/noncore/comm/keypebble/LICENSE.GPL b/noncore/comm/keypebble/LICENSE.GPL new file mode 100644 index 0000000..ec5dad8 --- a/dev/null +++ b/noncore/comm/keypebble/LICENSE.GPL @@ -0,0 +1,286 @@ +NOTE! The GPL below is copyrighted by the Free Software Foundation, but +the instance of code that it refers to (the kde programs) are copyrighted +by the authors who actually wrote it. + +--------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/noncore/comm/keypebble/Makefile.in b/noncore/comm/keypebble/Makefile.in new file mode 100644 index 0000000..1dbd5d2 --- a/dev/null +++ b/noncore/comm/keypebble/Makefile.in @@ -0,0 +1,286 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = -I$(QPEDIR)/include +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = keypebble +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = d3des.h \ + krfbbuffer.h \ + krfbcanvas.h \ + krfbconnection.h \ + krfbdecoder.h \ + krfblogin.h \ + krfboptions.h \ + krfbserverinfo.h \ + kvnc.h \ + kvncconnectdlg.h \ + kvncoptionsdlg.h \ + version.h \ + vncauth.h +SOURCES = d3des.c \ + vncauth.c \ + krfbbuffer.cpp \ + krfbcanvas.cpp \ + krfbconnection.cpp \ + krfbdecoder.cpp \ + krfblogin.cpp \ + krfboptions.cpp \ + kvnc.cpp \ + kvncconnectdlg.cpp \ + kvncoptionsdlg.cpp \ + main.cpp +OBJECTS = d3des.o \ + vncauth.o \ + krfbbuffer.o \ + krfbcanvas.o \ + krfbconnection.o \ + krfbdecoder.o \ + krfblogin.o \ + krfboptions.o \ + kvnc.o \ + kvncconnectdlg.o \ + kvncoptionsdlg.o \ + main.o \ + vncoptionsbase.o +INTERFACES = vncoptionsbase.ui +UICDECLS = vncoptionsbase.h +UICIMPLS = vncoptionsbase.cpp +SRCMOC = moc_krfbbuffer.cpp \ + moc_krfbcanvas.cpp \ + moc_krfbconnection.cpp \ + moc_krfbdecoder.cpp \ + moc_krfblogin.cpp \ + moc_kvnc.cpp \ + moc_kvncconnectdlg.cpp \ + moc_kvncoptionsdlg.cpp \ + moc_vncoptionsbase.cpp +OBJMOC = moc_krfbbuffer.o \ + moc_krfbcanvas.o \ + moc_krfbconnection.o \ + moc_krfbdecoder.o \ + moc_krfblogin.o \ + moc_kvnc.o \ + moc_kvncconnectdlg.o \ + moc_kvncoptionsdlg.o \ + moc_vncoptionsbase.o + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake keypebble.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +d3des.o: d3des.c \ + d3des.h + +vncauth.o: vncauth.c \ + vncauth.h \ + d3des.h + +krfbbuffer.o: krfbbuffer.cpp \ + krfbdecoder.h \ + krfbbuffer.h \ + krfbserverinfo.h + +krfbcanvas.o: krfbcanvas.cpp \ + kvncconnectdlg.h \ + krfbconnection.h \ + krfbcanvas.h \ + krfboptions.h \ + krfbbuffer.h \ + $(QPEDIR)/include/qpe/config.h + +krfbconnection.o: krfbconnection.cpp \ + krfbconnection.h \ + krfblogin.h \ + krfboptions.h \ + krfbdecoder.h \ + krfbbuffer.h + +krfbdecoder.o: krfbdecoder.cpp \ + krfbconnection.h \ + krfboptions.h \ + krfbserverinfo.h \ + krfbdecoder.h \ + krfbbuffer.h \ + $(QPEDIR)/include/qpe/qpeapplication.h + +krfblogin.o: krfblogin.cpp \ + vncauth.h \ + krfblogin.h \ + krfbconnection.h + +krfboptions.o: krfboptions.cpp \ + $(QPEDIR)/include/qpe/config.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + krfboptions.h + +kvnc.o: kvnc.cpp \ + $(QPEDIR)/include/qpe/qpemenubar.h \ + $(QPEDIR)/include/qpe/qpetoolbar.h \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + $(QPEDIR)/include/qpe/global.h \ + kvnc.h \ + krfbcanvas.h \ + kvncoptionsdlg.h \ + vncoptionsbase.h \ + krfbconnection.h + +kvncconnectdlg.o: kvncconnectdlg.cpp \ + krfbconnection.h \ + kvncoptionsdlg.h \ + vncoptionsbase.h \ + kvncconnectdlg.h + +kvncoptionsdlg.o: kvncoptionsdlg.cpp \ + krfboptions.h \ + kvncoptionsdlg.h \ + vncoptionsbase.h + +main.o: main.cpp \ + $(QPEDIR)/include/qpe/qpeapplication.h \ + kvnc.h + +vncoptionsbase.h: vncoptionsbase.ui + $(UIC) vncoptionsbase.ui -o $(INTERFACE_DECL_PATH)/vncoptionsbase.h + +vncoptionsbase.cpp: vncoptionsbase.ui + $(UIC) vncoptionsbase.ui -i vncoptionsbase.h -o vncoptionsbase.cpp + +vncoptionsbase.o: vncoptionsbase.cpp \ + vncoptionsbase.h \ + vncoptionsbase.ui + +moc_krfbbuffer.o: moc_krfbbuffer.cpp \ + krfbbuffer.h + +moc_krfbcanvas.o: moc_krfbcanvas.cpp \ + krfbcanvas.h + +moc_krfbconnection.o: moc_krfbconnection.cpp \ + krfbconnection.h + +moc_krfbdecoder.o: moc_krfbdecoder.cpp \ + krfbdecoder.h + +moc_krfblogin.o: moc_krfblogin.cpp \ + krfblogin.h + +moc_kvnc.o: moc_kvnc.cpp \ + kvnc.h + +moc_kvncconnectdlg.o: moc_kvncconnectdlg.cpp \ + kvncconnectdlg.h + +moc_kvncoptionsdlg.o: moc_kvncoptionsdlg.cpp \ + kvncoptionsdlg.h \ + vncoptionsbase.h + +moc_vncoptionsbase.o: moc_vncoptionsbase.cpp \ + vncoptionsbase.h + +moc_krfbbuffer.cpp: krfbbuffer.h + $(MOC) krfbbuffer.h -o moc_krfbbuffer.cpp + +moc_krfbcanvas.cpp: krfbcanvas.h + $(MOC) krfbcanvas.h -o moc_krfbcanvas.cpp + +moc_krfbconnection.cpp: krfbconnection.h + $(MOC) krfbconnection.h -o moc_krfbconnection.cpp + +moc_krfbdecoder.cpp: krfbdecoder.h + $(MOC) krfbdecoder.h -o moc_krfbdecoder.cpp + +moc_krfblogin.cpp: krfblogin.h + $(MOC) krfblogin.h -o moc_krfblogin.cpp + +moc_kvnc.cpp: kvnc.h + $(MOC) kvnc.h -o moc_kvnc.cpp + +moc_kvncconnectdlg.cpp: kvncconnectdlg.h + $(MOC) kvncconnectdlg.h -o moc_kvncconnectdlg.cpp + +moc_kvncoptionsdlg.cpp: kvncoptionsdlg.h + $(MOC) kvncoptionsdlg.h -o moc_kvncoptionsdlg.cpp + +moc_vncoptionsbase.cpp: vncoptionsbase.h + $(MOC) vncoptionsbase.h -o moc_vncoptionsbase.cpp + + diff --git a/noncore/comm/keypebble/README.html b/noncore/comm/keypebble/README.html new file mode 100644 index 0000000..def766b --- a/dev/null +++ b/noncore/comm/keypebble/README.html @@ -0,0 +1,206 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + <head> + <title>Keystone README</title> + </head> + + <body> + <h1>Keystone README</h1> + <div align="justify"> <!-- #BeginEditable "Body" --> + <h3>Contents</h3> + <ul> + <li><a href="#whatisvnc">What is Keystone?</a></li> + <li><a href="#servers">Servers</a></li> + <li><a href="#status">Status</a></li> + <li><a href="#bugs">Bugs</a></li> + <li><a href="#download">Download</a></li> + <li><a href="#faq">FAQs</a></li> + <li><a href="#todo">Todo</a></li> + <li><a href="#credits">Credits</a></li> + <li><a href="#references">References</a></li> + </ul> + <h3><a name="whatiskvnc">What is Keystone?</a></h3> + <p>Keystone is a tool for <a href="http://www.kde.org/">KDE</a> that + allows you to remotely access the desktops of machines using the cross-platform + VNC system. Keystone can access machines running a variety of operating + systems (including most UNIX systems and Windows 95/98/NT/2000) providing + they are running a VNC server. Note that Keystone is only a client + program, you will need to download a server separately in order to + use it.</p> + <p>The protocol used by Keystone (called RFB) was developed, and released + as GPL by ORL (now the UK branch of AT&T research), they also + wrote and maintain GPL servers for several platforms. You can find + both information about the protocol and links to servers for a range + of platforms on their <a href="http://www.uk.research.att.com/vnc/">website</a>.</p> + <p>Keystone started life as a port of Markus Wuebben's kvncviewer program + to KDE 2, but in the course porting the code, I have rewritten and + redesigned most of the system. The new implementation builds on several + new facilities that were not available in KDE 1, such as KPixmapIO + and QSocket. There is so little of the original code left that I have + decided on a name change, and to put the version number back to 0.1.</p> + <p>You can see a few screenshots of <a href="http://www.ipso-facto.demon.co.uk/keystone/screenshots.html">Keystone + in action</a> on my screenshots page. The screenshots may or may not + reflect the look of the current version as I have some look and feel + improvements planned.</p> + <h3><a name="servers">Servers</a></h3> + <p>Most Linux distributions include the standard Xvnc server (usually + run via the <i>vncserver</i> script), you can also download this and + servers for other platforms such as MS Windows from the <a href="http://www.uk.research.att.com/vnc/">VNC + website</a>. If you have a problem with setting up a server then you + should read the <a href="http://www.uk.research.att.com/vnc/faq.html">VNC + FAQ</a>, and if that does not help join the VNC mailing list. Do not + mail me on this topic - I can't help and won't even reply.</p> + <p>I may in future write a server that operates in the same manner as + the Win32 server for KDE. The Win32 server differs from the X11 server + in that it does not virtualise the entire desktop. This has both advantages + and disadvatages, it means that you can make an existing session available + over the network, but only allows you to run a single server. I may + also put a GUI together that makes it easy to configure the ORL server.</p> + <h3><a name="status">Status</a></h3> + <p><font color="#000000">The current version is 0.4, and the following + are now working:</font></p> + <p> + <ul> + <li><b>0.1</b> + <ul> + <li>Non-blocking socket handling</li> + <li>Authentication and logon</li> + <li>KDE 2 user interface</li> + <li>Raw and CopyRect encodings</li> + <li>Full screen mode</li> + <li>Grab keyboard mode</li> + <li>Graphics</li> + <li>Taking screenshots of the remote desktop</li> + <li>Event dispatching</li> + <li>Konqueror helper application support (you can run Keystone + by entering a vnc: URL anywhere in KDE).</li> + <li>Options, login, password and about dialogs</li> + </ul> + </li> + <li><b>0.2</b> + <ul> + <li>XSHM support using KPixmapIO</li> + <li>Now uses KXMLGUI (thanks to Kurt)</li> + <li>Tru64 patch from Tom Leitner</li> + <li>Status reporting improvements</li> + <li>Config handling fixed</li> + <li>Recent connections list implemented</li> + <li>Update frequency respected</li> + </ul> + </li> + <li><b>0.3 [KDE 2.0]</b> + <ul> + <li>Portability fixes for FreeBSD (and maybe others)</li> + </ul> + </li> + <li><b>0.4</b> + <ul> + <li>Icons for the full screen mode now reflect the current state</li> + <li>Added a toolbar (optional of course)</li> + <li>Added support for the clipboard (you can cut and paste between the + local and remote machines)</li> + <li>Added some what's this help to the options dialog</li> + </ul> + </li> + </ul> + <h3><a name="bugs">Bugs</a></h3> + <p>Version 0.4 contains the following known bugs: + <ul> + <li><b>Custom about dialog is not shown</b><br> + I can't see a clean way to fix this without creating a complete custom + help menu. For now I've left the standard about dialog in place. + </li> + <li><b>Crash when you connect to a non-existant server</b><br> + I can reproduce this every time, but I can't figure out what's wrong + other developers have reported similar problems and they seem to be + down to QSocket. The only known fix so far is to use KSocket instead. + I'd prefer to fix the problem at the source, but I'm having no luck and + I suspect QSocket may also be causing some other weird network issues + I've seen, so if I can't track down the bug soon I'll give in and switch + to KSocket like everyone else. + </li> + </ul> + </p> + <h3><a name="download"></a>Download</h3> + <p>Keystone is available in the kdenetwork module of the + <a href="http://www.kde.org/anoncvs.html">KDE CVS</a>, and + is included in the KDE 2.0 release. The current version is 0.4. + Note that Keystone <b>requires KDE 2</b>, you cannot use KDE 1.x.</p> + <h3><a name="faq"></a>FAQs</h3> + <p> + <ul> + <li><b>Why don't the shortcut keys work in full screen mode?</b><br> + When you're in full screen mode Keystone grabs the keyboard to send + every key press to the remote screen. This means that you can send key + combinations that are used by Keystone or KDE to the remote screen. If + you really hate it, then you can add -nograb to the command line + arguments to disable all keyboard grabs. I will add an option to allow + this behaviour to be overridden in a future release. + </li> + <li><b>Why is Keystone so slow?</b><br> + Currently only the simplest of the RFB encodings are supported, this + means that Keystone is only useful on fairly fast networks. This is + a serious bug and is being addressed. + </ul> + </p> + <h3><a name="todo">Todo</a></h3> + These are the things I'm hoping to add to future versions of Keystone. + They're vaguely sorted in order of importance. + <p> + <ul> + <li>RRE encoding.<br> + I've started this, but the implementation has some + bugs so it did not make the cut for Keystone 0.3.</li> + <li>CoRRE and Hextile encodings</li> + <li>Session management</li> + <li>Support for Windows Terminal Server.<br> + There is now a GPL implementation + of the protocol, and the author is happy for me to use the code. If someone + can offer me an account to test it on then this is possible.</li> + <li>Zoom support.<br> + This will be handled using the same protocol extension + as is used in the Palm client, this will allow you to make use of + server side scaling to reduce the amount of network traffic. You + will also be able to do client side zooms, but in this case the + full screen needs to transmitted over the network.</li> + <li>Macros</li> + <li>Monitor mode (thumbnails of several machines)</li> + <li>ZLib extension support</li> + <li>Bookmarks</li> + <li>URL specific settings</li> + <li>Possibly a DnD extension using a mechanism based on mulitpart + MIME attachments.</li> + </ul> + <h3>Credits<a name="credits"></a></h3> + <p>Keystone owes a lot to Markus Wuebben's kvncviewer which some of + the code is derived from. Thanks are also due to Espen Sand the author + of khexedit from which I borrowed some code for the about dialog. + Alison Burch drew the bridge image used in the background of this + page (and in future versions of Keystone too of course). Finally thanks + go to ORL for making the RFB protocol and servers GPL.</p> + <h3><a name="references">References</a><br> + </h3> + <p> + <ul> + <li>The Keystone homepage<br> + <a href="http://www.ipso-facto.demon.co.uk/keystone/">http://www.ipso-facto.demon.co.uk/keystone/</a></li> + <li>The VNC Homepage<br> + <a href="http://www.uk.research.att.com/vnc/">http://www.uk.research.att.com/vnc/</a></li> + <li>The VNC FAQ<br> + <a href="http://www.uk.research.att.com/vnc/faq.html">http://www.uk.research.att.com/vnc/faq.html</a></li> + <li>The KDE Homepage<br> + <a href="http://www.kde.org/">http://www.kde.org/</a> </li> + </ul> + <p></p> + <!-- #EndEditable --> </div> + + + + <hr> + <address><a href="mailto:rich@kde.org">Richard Moore</a></address> +<!-- Created: Tue Dec 5 01:35:56 GMT 2000 --> +<!-- hhmts start --> +Last modified: Tue Dec 5 01:37:17 GMT 2000 +<!-- hhmts end --> + </body> +</html> diff --git a/noncore/comm/keypebble/d3des.c b/noncore/comm/keypebble/d3des.c new file mode 100644 index 0000000..b0f065e --- a/dev/null +++ b/noncore/comm/keypebble/d3des.c @@ -0,0 +1,439 @@ +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. Also the bytebit[] array + * has been reversed so that the most significant bit in each byte of the + * key is ignored, not the least significant. + * + * These changes are Copyright (C) 1998 Olivetti & Oracle Research Laboratory + * + * This software 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. + */ + +/* D3DES (V5.09) - + * + * A portable, public domain, version of the Data Encryption Standard. + * + * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. + * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation + * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis + * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, + * for humouring me on. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. + * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. + */ + +#include "d3des.h" + +static void scrunch(unsigned char *, unsigned long *); +static void unscrun(unsigned long *, unsigned char *); +static void desfunc(unsigned long *, unsigned long *); +static void cookey(unsigned long *); + +static unsigned long KnL[32] = { 0L }; +static unsigned long KnR[32] = { 0L }; +static unsigned long Kn3[32] = { 0L }; +static unsigned char Df_Key[24] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; + +static unsigned short bytebit[8] = { + 01, 02, 04, 010, 020, 040, 0100, 0200 }; + +static unsigned long bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L }; + +/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ + +static unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; + +static unsigned char totrot[16] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; + +static unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; + +void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ +unsigned char *key; +short edf; +{ + register int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + unsigned long kn[32]; + + for ( j = 0; j < 56; j++ ) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; + } + for( i = 0; i < 16; i++ ) { + if( edf == DE1 ) m = (15 - i) << 1; + else m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for( j = 0; j < 28; j++ ) { + l = j + totrot[i]; + if( l < 28 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 28; j < 56; j++ ) { + l = j + totrot[i]; + if( l < 56 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 0; j < 24; j++ ) { + if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; + if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; + } + } + cookey(kn); + return; + } + +static void cookey(raw1) +register unsigned long *raw1; +{ + register unsigned long *cook, *raw0; + unsigned long dough[32]; + register int i; + + cook = dough; + for( i = 0; i < 16; i++, raw1++ ) { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + usekey(dough); + return; + } + +void cpkey(into) +register unsigned long *into; +{ + register unsigned long *from, *endp; + + from = KnL, endp = &KnL[32]; + while( from < endp ) *into++ = *from++; + return; + } + +void usekey(from) +register unsigned long *from; +{ + register unsigned long *to, *endp; + + to = KnL, endp = &KnL[32]; + while( to < endp ) *to++ = *from++; + return; + } + +void des(inblock, outblock) +unsigned char *inblock, *outblock; +{ + unsigned long work[2]; + + scrunch(inblock, work); + desfunc(work, KnL); + unscrun(work, outblock); + return; + } + +static void scrunch(outof, into) +register unsigned char *outof; +register unsigned long *into; +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); + return; + } + +static void unscrun(outof, into) +register unsigned long *outof; +register unsigned char *into; +{ + *into++ = (*outof >> 24) & 0xffL; + *into++ = (*outof >> 16) & 0xffL; + *into++ = (*outof >> 8) & 0xffL; + *into++ = *outof++ & 0xffL; + *into++ = (*outof >> 24) & 0xffL; + *into++ = (*outof >> 16) & 0xffL; + *into++ = (*outof >> 8) & 0xffL; + *into = *outof & 0xffL; + return; + } + +static unsigned long SP1[64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; + +static unsigned long SP2[64] = { + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; + +static unsigned long SP3[64] = { + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; + +static unsigned long SP4[64] = { + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; + +static unsigned long SP5[64] = { + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; + +static unsigned long SP6[64] = { + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; + +static unsigned long SP7[64] = { + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; + +static unsigned long SP8[64] = { + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; + +static void desfunc(block, keys) +register unsigned long *block, *keys; +{ + register unsigned long fval, work, right, leftt; + register int round; + + leftt = block[0]; + right = block[1]; + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; + + for( round = 0; round < 8; round++ ) { + work = (right << 28) | (right >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + leftt ^= fval; + work = (leftt << 28) | (leftt >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + right ^= fval; + } + + right = (right << 31) | (right >> 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >> 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); + *block++ = right; + *block = leftt; + return; + } + +/* Validation sets: + * + * Single-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef + * Plain : 0123 4567 89ab cde7 + * Cipher : c957 4425 6a5e d31d + * + * Double-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cde7 + * Cipher : 7f1d 0a77 826b 8aff + * + * Double-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 + * + * Triple-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cde7 + * Cipher : de0b 7c06 ae5e 0ed5 + * + * Triple-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 + * + * d3des V5.0a rwo 9208.07 18:44 Graven Imagery + **********************************************************************/ diff --git a/noncore/comm/keypebble/d3des.h b/noncore/comm/keypebble/d3des.h new file mode 100644 index 0000000..5da6013 --- a/dev/null +++ b/noncore/comm/keypebble/d3des.h @@ -0,0 +1,50 @@ +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. + * + * These changes are Copyright (C) 1998 Olivetti & Oracle Research Laboratory + * + * This software 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. + */ + +/* d3des.h - + * + * Headers and defines for d3des.c + * Graven Imagery, 1992. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge + * (GEnie : OUTER; CIS : [71755,204]) + */ + +#define EN0 0 /* MODE == encrypt */ +#define DE1 1 /* MODE == decrypt */ + +extern void deskey(unsigned char *, short); +/* hexkey[8] MODE + * Sets the internal key register according to the hexadecimal + * key contained in the 8 bytes of hexkey, according to the DES, + * for encryption or decryption according to MODE. + */ + +extern void usekey(unsigned long *); +/* cookedkey[32] + * Loads the internal key register with the data in cookedkey. + */ + +extern void cpkey(unsigned long *); +/* cookedkey[32] + * Copies the contents of the internal key register into the storage + * located at &cookedkey[0]. + */ + +extern void des(unsigned char *, unsigned char *); +/* from[8] to[8] + * Encrypts/Decrypts (according to the key currently loaded in the + * internal key register) one block of eight bytes at address 'from' + * into the block at address 'to'. They can be the same. + */ + +/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery + ********************************************************************/ diff --git a/noncore/comm/keypebble/keypebble.pro b/noncore/comm/keypebble/keypebble.pro new file mode 100644 index 0000000..6b11801 --- a/dev/null +++ b/noncore/comm/keypebble/keypebble.pro @@ -0,0 +1,38 @@ +TEMPLATE = app + +CONFIG += qt warn_on release +DESTDIR = ../bin + +HEADERS = d3des.h \ + krfbbuffer.h \ + krfbcanvas.h \ + krfbconnection.h \ + krfbdecoder.h \ + krfblogin.h \ + krfboptions.h \ + krfbserverinfo.h \ + kvnc.h \ + kvncconnectdlg.h \ + kvncoptionsdlg.h \ + version.h \ + vncauth.h + +SOURCES = d3des.c \ + vncauth.c \ + krfbbuffer.cpp \ + krfbcanvas.cpp \ + krfbconnection.cpp \ + krfbdecoder.cpp \ + krfblogin.cpp \ + krfboptions.cpp \ + kvnc.cpp \ + kvncconnectdlg.cpp \ + kvncoptionsdlg.cpp \ + main.cpp +INTERFACES = vncoptionsbase.ui +TARGET = keypebble + +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe + diff --git a/noncore/comm/keypebble/krfbbuffer.cpp b/noncore/comm/keypebble/krfbbuffer.cpp new file mode 100644 index 0000000..4885261 --- a/dev/null +++ b/noncore/comm/keypebble/krfbbuffer.cpp @@ -0,0 +1,163 @@ +#include <assert.h> +#include <qpixmap.h> +#include <qbrush.h> +#include <qimage.h> +#include <qpainter.h> +#include <qapplication.h> +#include "krfbdecoder.h" +#include "krfbbuffer.h" +#include "krfbserverinfo.h" + +// +// Endian stuff +// +#ifndef KDE_USE_FINAL +const int endianTest = 1; +#endif + +#define Swap16IfLE(s) \ + (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define Swap32IfLE(l) \ + (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +KRFBBuffer::KRFBBuffer( KRFBDecoder *decoder, + QObject *parent, const char *name ) + : QObject( parent, name ) +{ + assert( decoder ); + this->decoder = decoder; + pix = new QPixmap(); +} + +KRFBBuffer::~KRFBBuffer() +{ + delete pix; +} + +void KRFBBuffer::resize( int w, int h ) +{ + qWarning( "Resizing buffer" ); + + pix->resize( w, h ); + + QPalette pal = qApp->palette(); + pix->fill( pal.active().base() ); + + emit sizeChanged( w, h ); +} + +void KRFBBuffer::soundBell() +{ + emit bell(); +} + +void KRFBBuffer::mouseEvent( QMouseEvent *e ) +{ + decoder->sendMouseEvent( e ); +} + +void KRFBBuffer::keyPressEvent( QKeyEvent *e ) +{ + qWarning( "Buffer got a key" ); + + decoder->sendKeyPressEvent( e ); +} + +void KRFBBuffer::keyReleaseEvent( QKeyEvent *e ) +{ + decoder->sendKeyReleaseEvent( e ); +} + +void KRFBBuffer::copyRect( int srcX, int srcY, + int destX, int destY, int w, int h ) +{ +// qWarning( "Got copy rect" ); + bitBlt( pix, destX, destY, pix, srcX, srcY, w, h, CopyROP ); + + emit updated( destX, destY, w, h ); +} + +void KRFBBuffer::drawRawRectChunk( void *data, + int x, int y, int w, int h ) +{ + QImage img( w, h, 32 ); + + int redMax = Swap16IfLE( decoder->format->redMax ); + int greenMax = Swap16IfLE( decoder->format->greenMax ); + int blueMax = Swap16IfLE( decoder->format->blueMax ); + + QPainter p( pix ); + + if ( decoder->format->bpp == 8 ) { + uchar *d = (unsigned char *) data; + + uint r,g,b; + + for ( int j = 0; j < h; j++ ) { + for ( int i = 0; i < w ; i++ ) { + r = d[ j * w + i ]; + r = r >> decoder->format->redShift; + r = r & redMax; + + g = d[ j * w + i ]; + g = g >> decoder->format->greenShift; + g = g & greenMax; + + b = d[ j * w + i ]; + b = b >> decoder->format->blueShift; + b = b & blueMax; + + r = ( r * 255 ) / redMax; + g = ( g * 255 ) / greenMax; + b = ( b * 255 ) / blueMax; + + uint *p = ( uint * ) img.scanLine( j ) + i; + *p = qRgb( r,g,b ); + } + } + } + else if ( decoder->format->bpp == 32 ) { + ulong *d = (ulong *) data; + + ulong r,g,b; + + for ( int j = 0; j < h; j++ ) { + for ( int i = 0; i < w ; i++ ) { + ulong pixel = d[ j * w + i ]; + pixel = Swap32IfLE( pixel ); + + r = pixel; + r = r >> decoder->format->redShift; + r = r & redMax; + + g = pixel; + g = g >> decoder->format->greenShift; + g = g & greenMax; + + b = pixel; + b = b >> decoder->format->blueShift; + b = b & blueMax; + + r = ( r * 255 ) / redMax; + g = ( g * 255 ) / greenMax; + b = ( b * 255 ) / blueMax; + + uint *p = ( uint * ) img.scanLine( j ) + i; + *p = qRgb( r,g,b ); + } + } + } + else { + p.setBrush( QBrush( Qt::black ) ); + p.drawRect( x, y, w, h ); + } + + p.drawImage( x, y, img ); + + emit updated( x, y, w, h ); +} + diff --git a/noncore/comm/keypebble/krfbbuffer.h b/noncore/comm/keypebble/krfbbuffer.h new file mode 100644 index 0000000..1116d00 --- a/dev/null +++ b/noncore/comm/keypebble/krfbbuffer.h @@ -0,0 +1,62 @@ +// -*- c++ -*- + +#ifndef KRFBBUFFER_H +#define KRFBBUFFER_H + +#include <qobject.h> + +class QPixmap; +class KRFBDecoder; +class QMouseEvent; +class QKeyEvent; + +/** + * A wrapper around QPixmap that knows how to implement the RFB + * drawing primitives. If possible it makes use of the MIT XSHM + * extension to optimise the drawing operations. + */ +class KRFBBuffer : public QObject +{ + Q_OBJECT + +public: + KRFBBuffer( KRFBDecoder *decoder, QObject *parent, const char *name=0 ); + ~KRFBBuffer(); + + QPixmap *pixmap() const { return pix; }; + + /** + * Draw a chunk of a raw encoded rectangle. + */ + void drawRawRectChunk( void *data, int x, int y, int w, int h ); + + void copyRect( int srcX, int srcY, + int destX, int destY, int w, int h ); + + void fillRect( int ,int , int , int , unsigned long ) {}; + + void resize( int w, int h ); + + void mouseEvent( QMouseEvent *e ); + + void keyPressEvent( QKeyEvent *e ); + void keyReleaseEvent( QKeyEvent *e ); + + void soundBell(); + +signals: + /** + * Emitted when the size of the buffer changes. + */ + void sizeChanged( int w, int h ); + + void updated( int x, int y, int w, int h ); + + void bell(); + +private: + KRFBDecoder *decoder; + QPixmap *pix; +}; + +#endif // KRFBBUFFER_H diff --git a/noncore/comm/keypebble/krfbcanvas.cpp b/noncore/comm/keypebble/krfbcanvas.cpp new file mode 100644 index 0000000..f74ab7b --- a/dev/null +++ b/noncore/comm/keypebble/krfbcanvas.cpp @@ -0,0 +1,169 @@ +#include "kvncconnectdlg.h" +#include "krfbconnection.h" +#include "krfbcanvas.h" +#include "krfboptions.h" +#include "krfbbuffer.h" + +#include <qpe/config.h> + +#include <qapplication.h> +#include <qclipboard.h> +#include <qaction.h> +#include <qpixmap.h> +#include <qapplication.h> +#include <qmainwindow.h> +#include <qiconset.h> + +KRFBCanvas::KRFBCanvas( QWidget *parent, const char *name ) + : QScrollView( parent, name ) +{ + connection_ = new KRFBConnection(); + connect( connection_, SIGNAL( passwordRequired( KRFBConnection * ) ), + this, SLOT( passwordRequired( KRFBConnection * ) ) ); + connect( connection_, SIGNAL( loggedIn() ), + this, SLOT( loggedIn() ) ); + + loggedIn_ = false; + + viewport()->setFocusPolicy( QWidget::StrongFocus ); + viewport()->setFocus(); +} + +KRFBCanvas::~KRFBCanvas() +{ +} + +void KRFBCanvas::openConnection() +{ + KVNCConnectDlg dlg( connection_, this, "connect dialog" ); + if ( dlg.exec() ) { + QCString host = dlg.hostname().latin1(); + password = dlg.password(); + connection_->connectTo( host, dlg.display() ); + } +} + +void KRFBCanvas::openURL( const QUrl &url ) +{ + if ( loggedIn_ ) { + qWarning( "openURL invoked when logged in\n" ); + return; + } + + QCString host = url.host().latin1(); + int display = url.port(); + if ( url.hasPassword() ) + connection_->setPassword( url.password().latin1() ); + + connection_->connectTo( host, display ); +} + +void KRFBCanvas::closeConnection() +{ + loggedIn_ = false; + connection_->disconnect(); + + viewport()->setMouseTracking( false ); + viewport()->setBackgroundMode( PaletteDark ); + setBackgroundMode( PaletteDark ); + update(); +} + +void KRFBCanvas::passwordRequired( KRFBConnection *con ) +{ + con->setPassword( password.latin1() ); +} + +void KRFBCanvas::bell() +{ + if ( connection_->options()->deIconify ) { + topLevelWidget()->raise(); + topLevelWidget()->show(); + } +} + +void KRFBCanvas::loggedIn() +{ + qWarning( "Ok, we're logged in" ); + + // + // Get ready for action + // + loggedIn_ = true; + viewport()->setMouseTracking( true ); + viewport()->setBackgroundMode( NoBackground ); + setBackgroundMode( NoBackground ); + + // Start using the buffer + connect( connection_->buffer(), SIGNAL( sizeChanged( int, int ) ), + this, SLOT( resizeContents(int,int) ) ); + connect( connection_->buffer(), SIGNAL( updated( int, int, int, int ) ), + this, SLOT( viewportUpdate(int,int,int,int) ) ); + connect( connection_->buffer(), SIGNAL( bell() ), + this, SLOT( bell() ) ); + connect( qApp->clipboard(), SIGNAL( dataChanged() ), + this, SLOT( clipboardChanged() ) ); +} + +void KRFBCanvas::viewportPaintEvent( QPaintEvent *e ) +{ + QRect r = e->rect(); + + if ( loggedIn_ ) { + bitBlt( viewport(), r.x(), r.y(), + connection_->buffer()->pixmap(), + r.x() + contentsX(), r.y() + contentsY(), + r.width(), r.height() ); + } + else { + QScrollView::viewportPaintEvent( e ); + } +} + +void KRFBCanvas::viewportUpdate( int x, int y, int w, int h ) +{ + updateContents( x, y, w, h ); +} + +void KRFBCanvas::contentsMousePressEvent( QMouseEvent *e ) +{ + if ( loggedIn_ ) + connection_->buffer()->mouseEvent( e ); +} + +void KRFBCanvas::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + if ( loggedIn_ ) + connection_->buffer()->mouseEvent( e ); +} + +void KRFBCanvas::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if ( loggedIn_ ) + connection_->buffer()->mouseEvent( e ); +} + +void KRFBCanvas::keyPressEvent( QKeyEvent *e ) +{ + if ( loggedIn_ ) + connection_->buffer()->keyPressEvent( e ); +} + +void KRFBCanvas::keyReleaseEvent( QKeyEvent *e ) +{ + if ( loggedIn_ ) + connection_->buffer()->keyReleaseEvent( e ); +} + +void KRFBCanvas::refresh() +{ + if ( loggedIn_ ) + connection_->refresh(); +} + +void KRFBCanvas::clipboardChanged() +{ + if ( loggedIn_ ) { + connection_->sendCutText( qApp->clipboard()->text() ); + } +} diff --git a/noncore/comm/keypebble/krfbcanvas.h b/noncore/comm/keypebble/krfbcanvas.h new file mode 100644 index 0000000..7864f1c --- a/dev/null +++ b/noncore/comm/keypebble/krfbcanvas.h @@ -0,0 +1,54 @@ +// -*- c++ -*- + +#ifndef KRFBCANVAS_H +#define KRFBCANVAS_H + +#include <qscrollview.h> +#include <qurl.h> + +class KRFBConnection; + +/** + * Displays data from an KRFBDecoder, and sends events to the + * KRFBConnection. + */ +class KRFBCanvas : public QScrollView +{ + Q_OBJECT +public: + KRFBCanvas( QWidget *parent, const char *name=0 ); + ~KRFBCanvas(); + + void setConnection( KRFBConnection * ); + KRFBConnection *connection() { return connection_; }; + +public slots: + void openConnection(); + void openURL( const QUrl & ); + void closeConnection(); + void passwordRequired( KRFBConnection * ); + + void refresh(); + void bell(); + +protected: + virtual void keyPressEvent( QKeyEvent * ); + virtual void keyReleaseEvent( QKeyEvent * ); + virtual void contentsMousePressEvent( QMouseEvent * ); + virtual void contentsMouseReleaseEvent( QMouseEvent * ); + virtual void contentsMouseMoveEvent( QMouseEvent * ); + + virtual void viewportPaintEvent( QPaintEvent *e ); + +protected slots: + void loggedIn(); + void viewportUpdate( int x, int y, int w, int h ); + void clipboardChanged(); + +private: + KRFBConnection *connection_; + QString password; + bool loggedIn_; +}; + +#endif // KRFBCANVAS_H diff --git a/noncore/comm/keypebble/krfbconnection.cpp b/noncore/comm/keypebble/krfbconnection.cpp new file mode 100644 index 0000000..c413186 --- a/dev/null +++ b/noncore/comm/keypebble/krfbconnection.cpp @@ -0,0 +1,242 @@ +#include <assert.h> +#include <qsocket.h> +#include <qtimer.h> +#include <string.h> + +#include "krfbconnection.h" +#include "krfblogin.h" +#include "krfboptions.h" +#include "krfbdecoder.h" +#include "krfbbuffer.h" + +KRFBConnection::KRFBConnection( QObject *parent ) + : QObject( parent, "KRFBConnection" ) +{ + portBase_ = 5900; + currentState_ = Disconnected; + sock = 0; + minData_ = 0; + options_ = new KRFBOptions(); + updater = 0; + decoder_ = 0; + buffer_ = 0; +} + +KRFBConnection::~KRFBConnection() +{ + if ( ( currentState_ != Disconnected ) && ( currentState_ != Disconnecting ) && sock ) { + disconnectDone(); + } + delete options_; +} + +void KRFBConnection::connectTo( const QCString &host, int display ) +{ + if ( currentState_ != Disconnected ); + disconnect(); + + this->host_= host; + this->display_ = display; + + sock = new QSocket( this, "rfbSocket" ); + CHECK_PTR( sock ); + + // Connect to something to notice connection or error + connect( sock, SIGNAL( error( int ) ), SLOT( gotSocketError( int ) ) ); + connect( sock, SIGNAL( connected() ), SLOT( gotSocketConnection() ) ); + + qWarning( "Connecting..." ); + + currentState_ = Connecting; + sock->connectToHost( host_, portBase_ + display_ ); +} + +void KRFBConnection::disconnect() +{ + qWarning( "Disconnecting from server" ); + + if ( ( currentState_ != Disconnected ) + && ( currentState_ != Disconnecting ) + && sock ) { + currentState_ = Disconnecting; + + connect( sock, SIGNAL( delayedCloseFinished() ), SLOT( disconnectDone() ) ); + sock->close(); + + if ( sock->state() != QSocket::Closing ) + disconnectDone(); + } +} + +void KRFBConnection::disconnectDone() +{ + qWarning( "KRFBConnection disconnected" ); + currentState_ = Disconnected; + delete sock; + sock = 0; + minData_ = 0; + delete updater; + delete decoder_; + delete buffer_; + emit disconnected(); +} + +void KRFBConnection::gotSocketConnection() +{ + currentState_ = LoggingIn; + + qWarning( "Connected, logging in..." ); + + static QString statusMsg = tr( "Connected" ); + emit statusChanged( statusMsg ); + + // Do some login stuff + login = new KRFBLogin( this ); +} + +void KRFBConnection::gotRFBConnection() +{ + qWarning( "Logged into server" ); + + currentState_ = Connected; + emit connected(); + + // Create the decoder and start doing stuff + decoder_ = new KRFBDecoder( this ); + CHECK_PTR( decoder_ ); + + buffer_ = new KRFBBuffer( decoder_, this, "RFB Buffer" ); + CHECK_PTR( buffer_ ); + decoder_->setBuffer( buffer_ ); + + connect( decoder_, SIGNAL( status( const QString & ) ), + this, SIGNAL( statusChanged( const QString & ) ) ); + emit loggedIn(); + + decoder_->start(); + + updater = new QTimer; + connect( updater, SIGNAL( timeout() ), SLOT( updateTimer() ) ); + updater->start( options_->updateRate ); +} + +void KRFBConnection::gotSocketError( int errno ) +{ + currentState_ = Error; + + // Do some error handling stuff + qWarning( "KRFBConnection: Socket error %d", errno ); + + static QString refused = tr( "Connection Refused" ); + static QString host = tr( "Host not found" ); + static QString read = tr( "Read Error: QSocket reported an error reading\n" + "data, the remote host has probably dropped the\n" + "connection." ); + static QString confused = tr( "QSocket reported an invalid error code" ); + + QString msg; + switch ( errno ) { + case QSocket::ErrConnectionRefused: + msg = refused; + break; + case QSocket::ErrHostNotFound: + msg = host; + break; + case QSocket::ErrSocketRead: + msg = read; + break; + default: + msg = confused; + }; + + QObject::disconnect( sock, SIGNAL( readyRead() ), this, SLOT( gotMoreData() ) ); + delete sock; + sock = 0; + currentState_ = Disconnected; + + emit error( msg ); +} + +void KRFBConnection::gotMoreData() +{ + assert( minData_ > 0 ); + + if ( sock->size() >= minData_ ) { + minData_ = 0; + QObject::disconnect( sock, SIGNAL( readyRead() ), this, SLOT( gotMoreData() ) ); + emit gotEnoughData(); + } +} + +void KRFBConnection::waitForData( unsigned int sz ) +{ + assert( minData_ == 0 ); + assert( sz > 0 ); + assert( currentState_ != Error ); + + if ( sock->size() >= sz ) { + // qWarning( "No need to wait for data" ); + emit gotEnoughData(); + } + else { + // qWarning( "Waiting for %u bytes", sz ); + + minData_ = sz; + connect( sock, SIGNAL( readyRead() ), SLOT( gotMoreData() ) ); + } +} + +int KRFBConnection::read( void *buf, int sz ) +{ + return sock->readBlock( (char *) buf, sz ); +} + +int KRFBConnection::write( void *buf, int sz ) +{ + return sock->writeBlock( (const char *) buf, sz ); +} + +KRFBConnection::State KRFBConnection::state() const +{ + return currentState_; +} + +void KRFBConnection::setPortBase( int base ) +{ + portBase_ = base; +} + +int KRFBConnection::portBase() const +{ + return portBase_; +} + +void KRFBConnection::setPassword( const QCString &pass ) +{ + this->pass_ = pass; +} + +void KRFBConnection::updateTimer() +{ + decoder_->sendUpdateRequest( true ); +} + +void KRFBConnection::refresh() +{ + decoder_->sendUpdateRequest( false ); +} + +void KRFBConnection::sendCutText( const QString &text ) +{ + decoder_->sendCutEvent( text ); +} + +const QUrl &KRFBConnection::url() +{ + url_.setProtocol( "vnc" ); + url_.setPort( display() ); + url_.setHost( host() ); + url_.setPath( "/" ); + + return url_; +} diff --git a/noncore/comm/keypebble/krfbconnection.h b/noncore/comm/keypebble/krfbconnection.h new file mode 100644 index 0000000..fe477c1 --- a/dev/null +++ b/noncore/comm/keypebble/krfbconnection.h @@ -0,0 +1,152 @@ +// -*- c++ -*- + +#ifndef KRFBCONNECTION_H +#define KRFBCONNECTION_H + +#include <qobject.h> +#include <qstring.h> +#include <qcstring.h> +#include <qurl.h> + +class KRFBLogin; +class KRBUpdateHandler; +class KRFBOptions; +class QSocket; +class KRFBDecoder; +class KRFBBuffer; +class QTimer; + +/** + * Encapsulates the RFB socket. + * + */ +class KRFBConnection : public QObject +{ + Q_OBJECT + +public: + friend class KRFBLogin; + friend class KRFBDecoder; + + //* The state of the connection. + enum State { + Connecting, + LoggingIn, + Connected, + Disconnecting, + Disconnected, + Error + }; + + KRFBConnection( QObject *parent = 0 ); + ~KRFBConnection(); + + //* Get the state of a connection. + State state() const; + + //* Get the options for this connection + KRFBOptions *options() const { return options_; }; + + KRFBBuffer *buffer() const { return buffer_; }; + + KRFBDecoder *decoder() const { return decoder_; }; + + //* Set the base from which the port for a given display will be calculated. + void setPortBase( int base ); + + //* Get the base from which the port for a given display is calculated. + int portBase() const; + + //* Set the password which will be used to login + void setPassword( const QCString &pass ); + + //* Open a connection + void connectTo( const QCString &host, int display ); + + //* Close the connection + void disconnect(); + + //* Get the host + const QCString host() const { return host_; }; + + //* Get the display + int display() const { return display_; }; + + //* Get the current host/display as a URL + const QUrl &url(); + + //* Reload the display + void refresh(); + + //* Send text to the remote clipboard + void sendCutText( const QString & ); + +protected slots: + //* When the shit hits the fan + void gotSocketError( int ); + + //* When we have an open socket + void gotSocketConnection(); + + //* When we have logged in + void gotRFBConnection(); + + //* When some more data arrived + void gotMoreData(); + + void updateTimer(); + + void disconnectDone(); + +signals: + //* Emitted when the status of the connection changes. + void statusChanged( const QString & ); + + /** + * Emitted when we *really* need a password. If the password + * was specified before you tried to connect then you won't + * see this. + */ + void passwordRequired( KRFBConnection * ); + + //* When we have a working RFB connection + void connected(); + + void loggedIn(); + + void disconnected(); + + //* What happened? + void error( const QString &msg ); + + //* Emitted in response to a waitForData() call. + void gotEnoughData(); + +private: + // + // The following are called by our friends. + // + + void waitForData( unsigned int ); + + int read( void *buf, int sz ); + int write( void *buf, int sz ); + +private: + QCString host_; + int portBase_; + int display_; + QCString pass_; + QSocket *sock; + State currentState_; + unsigned int minData_; + QTimer *updater; + KRFBLogin *login; + KRFBDecoder *decoder_; + KRFBOptions *options_; + KRFBBuffer *buffer_; + QUrl url_; +}; + +#endif // KRFBCONNECTION_H + diff --git a/noncore/comm/keypebble/krfbdecoder.cpp b/noncore/comm/keypebble/krfbdecoder.cpp new file mode 100644 index 0000000..174dd7b --- a/dev/null +++ b/noncore/comm/keypebble/krfbdecoder.cpp @@ -0,0 +1,839 @@ +#include "krfbconnection.h" +#include "krfboptions.h" +#include "krfbserverinfo.h" +#include "krfbdecoder.h" +#include "krfbbuffer.h" + +#include <qpe/qpeapplication.h> + +#include <qpixmap.h> +#include <qsocket.h> +#include <qevent.h> +#include <qstring.h> +#include <qclipboard.h> + +#include <assert.h> + +// +// Endian stuff +// +#ifndef KDE_USE_FINAL +const int endianTest = 1; +#endif + +#define Swap16IfLE(s) \ + (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define Swap32IfLE(l) \ + (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +// +// The lengths of the messages we need to wait for +// +const int ServerInitLength = 24; +const int UpdateHeaderLength = 4; +const int RectHeaderLength = 12; +const int RectChunkSize = 4; +const int CopyRectPosLength = 4; +const int ServerCutLenLength = 7; + +// +// Client -> Server Message Identifiers +// +static CARD8 SetPixelFormatId = 0; +//static CARD8 FixColourMapEntriesId = 1; // Not used +static CARD8 SetEncodingsId = 2; +static CARD8 UpdateRequestId = 3; +static CARD8 KeyEventId = 4; +static CARD8 PointerEventId = 5; +static CARD8 ClientCutTextId = 6; + +// +// Server -> Client Message Identifiers +// +static CARD8 UpdateId = 0; +static CARD8 BellId = 2; +static CARD8 ServerCutId = 3; + +// +// Encoding identifiers +// +static CARD32 RawEncoding = Swap32IfLE( 0 ); +static CARD32 CopyRectEncoding = Swap32IfLE(1 ); +static CARD32 RreEncoding = Swap32IfLE( 2 ); +static CARD32 CorreEncoding = Swap32IfLE( 4 ); +static CARD32 HexTileEncoding = Swap32IfLE( 5 ); + +static struct { + int keysym; + int keycode; +} keyMap[] = { + { 0xff08, Qt::Key_Backspace }, + { 0xff09, Qt::Key_Tab }, + { 0xff0d, Qt::Key_Return }, + { 0xff1b, Qt::Key_Escape }, + { 0xff63, Qt::Key_Insert }, + { 0xffff, Qt::Key_Delete }, + { 0xff50, Qt::Key_Home }, + { 0xff57, Qt::Key_End }, + { 0xff55, Qt::Key_Prior }, + { 0xff56, Qt::Key_Next }, + { 0xff51, Qt::Key_Left }, + { 0xff52, Qt::Key_Up }, + { 0xff53, Qt::Key_Right }, + { 0xff54, Qt::Key_Down }, + { 0xffbe, Qt::Key_F1 }, + { 0xffbf, Qt::Key_F2 }, + { 0xffc0, Qt::Key_F3 }, + { 0xffc1, Qt::Key_F4 }, + { 0xffc2, Qt::Key_F5 }, + { 0xffc3, Qt::Key_F6 }, + { 0xffc4, Qt::Key_F7 }, + { 0xffc5, Qt::Key_F8 }, + { 0xffc6, Qt::Key_F9 }, + { 0xffc7, Qt::Key_F10 }, + { 0xffc8, Qt::Key_F11 }, + { 0xffc9, Qt::Key_F12 }, + { 0xffe1, Qt::Key_Shift }, + { 0xffe2, Qt::Key_Shift }, + { 0xffe3, Qt::Key_Control }, + { 0xffe4, Qt::Key_Control }, + { 0xffe7, Qt::Key_Meta }, + { 0xffe8, Qt::Key_Meta }, + { 0xffe9, Qt::Key_Alt }, + { 0xffea, Qt::Key_Alt }, + { 0, 0 } +}; + + +KRFBDecoder::KRFBDecoder( KRFBConnection *con ) + : QObject( con, "RFB Decoder" ) +{ + assert( con ); + assert( con->state() == KRFBConnection::Connected ); + + this->con = con; + this->buf = 0; + this->info = 0; + this->format = 0; + this->buttonMask = 0; + currentState = Idle; +} + +KRFBDecoder::~KRFBDecoder() +{ + if ( info ) + delete info; + if ( format ) + delete format; +} + +void KRFBDecoder::start() +{ + sendClientInit(); +} + +void KRFBDecoder::sendClientInit() +{ + con->write( &( con->options()->shared ), 1 ); + + // Wait for server init + qWarning( "Waiting for server init" ); + + static QString statusMsg = tr( "Waiting for server initialisation..." ); + emit status( statusMsg ); + + currentState = AwaitingServerInit; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerInit() ) ); + con->waitForData( ServerInitLength ); +} + +void KRFBDecoder::gotServerInit() +{ + qWarning( "Got server init" ); + disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerInit() ) ); + + if ( info ) + delete info; + info = new KRFBServerInfo; + CHECK_PTR( info ); + + con->read( &(info->width), 2 ); + info->width = Swap16IfLE( info->width ); + con->read( &info->height, 2 ); + info->height = Swap16IfLE( info->height ); + + con->read( &(info->bpp), 1 ); + con->read( &(info->depth), 1 ); + con->read( &(info->bigEndian), 1 ); + con->read( &(info->trueColor), 1 ); + + con->read( &(info->redMax), 2 ); + info->redMax = Swap16IfLE( info->redMax ); + con->read( &(info->greenMax), 2 ); + info->greenMax = Swap16IfLE( info->greenMax ); + con->read( &(info->blueMax), 2 ); + info->blueMax = Swap16IfLE( info->blueMax ); + + con->read( &(info->redShift), 1 ); + con->read( &(info->greenShift), 1 ); + con->read( &(info->blueShift), 1 ); + + con->read( info->padding, 3 ); + + con->read( &(info->nameLength), 4 ); + info->nameLength = Swap32IfLE( info->nameLength ); + + qWarning( "Width = %d, Height = %d", info->width, info->height ); + qWarning( "Bpp = %d, Depth = %d, Big = %d, True = %d", + info->bpp, info->depth, info->bigEndian, info->trueColor ); + qWarning( "RedMax = %d, GreenMax = %d, BlueMax = %d", + info->redMax, info->greenMax, info->blueMax ); + qWarning( "RedShift = %d, GreenShift = %d, BlueShift = %d", + info->redShift, info->greenShift,info-> blueShift ); + + buf->resize( info->width, info->height ); + + // Wait for desktop name + qWarning( "Waiting for desktop name" ); + + static QString statusMsg = tr( "Waiting for desktop name..." ); + emit status( statusMsg ); + + currentState = AwaitingDesktopName; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotDesktopName() ) ); + con->waitForData( info->nameLength ); +} + +void KRFBDecoder::gotDesktopName() +{ + assert( info ); + assert( currentState == AwaitingDesktopName ); + + qWarning( "Got desktop name" ); + + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotDesktopName() ) ); + + char *buf = new char[ info->nameLength + 1 ]; + CHECK_PTR( buf ); + + con->read( buf, info->nameLength ); + buf[ info->nameLength ] = '\0'; + info->name = buf; + + qWarning( "Desktop: %s", info->name.latin1() ); + + delete buf; + + // Get the format we'll really use and tell the server + decidePixelFormat(); + sendPixelFormat(); + sendAllowedEncodings(); + currentState = Idle; + + QString msg; + msg = tr( "Connected to %1" ); + msg = msg.arg( info->name ); + emit status( msg ); + + sendUpdateRequest( false ); +} + +void KRFBDecoder::decidePixelFormat() +{ + assert( info ); + + if ( format ) + delete format; + format = new KRFBPixelFormat; + CHECK_PTR( format ); + + // What depth do we want? + // + // We'll use the minimum of the remote and local depths, UNLESS an + // eight bit session has been specifically requested by the user. + int screenDepth = QPixmap::defaultDepth(); + int bestDepth = ( screenDepth > info->depth ) ? info->depth : screenDepth; + int chosenDepth; + + if ( con->options()->colors256 ) + chosenDepth = 8; + else + chosenDepth = bestDepth; + + qWarning( "Screen depth=%d, server depth=%d, best depth=%d, " \ + "eight bit %d, chosenDepth=%d", + screenDepth, + info->depth, + bestDepth, + con->options()->colors256, chosenDepth ); + + format->depth = chosenDepth; + + // If we're using the servers native depth + if ( chosenDepth == info->depth ) { + // Use the servers native format + format->bpp = info->bpp; + // format->bigEndian = info->bigEndian; + format->bigEndian = true; + format->trueColor = info->trueColor; + format->redMax = info->redMax; + format->greenMax = info->greenMax; + format->blueMax = info->blueMax; + format->redShift = info->redShift; + format->greenShift = info->greenShift; + format->blueShift = info->blueShift; + } + else { + if ( chosenDepth == 8 ) { + format->bpp = 8; + format->bigEndian = true; + format->trueColor = true; + format->redMax = 7; + format->greenMax = 7; + format->blueMax = 3; + format->redShift = 0; + format->greenShift = 3; + format->blueShift = 6; + } + } + + format->redMax = Swap16IfLE( format->redMax ); + format->greenMax = Swap16IfLE( format->greenMax ); + format->blueMax = Swap16IfLE( format->blueMax ); +} + +void KRFBDecoder::sendPixelFormat() +{ + static char padding[3]; + con->write( &SetPixelFormatId, 1 ); + con->write( padding, 3 ); + + con->write( &(format->bpp), 1 ); + con->write( &(format->depth), 1 ); + con->write( &(format->bigEndian), 1 ); + con->write( &(format->trueColor), 1 ); + + con->write( &(format->redMax), 2 ); + con->write( &(format->greenMax), 2 ); + con->write( &(format->blueMax), 2 ); + + con->write( &(format->redShift), 1 ); + con->write( &(format->greenShift), 1 ); + con->write( &(format->blueShift), 1 ); + con->write( format->padding, 3 ); // Padding +} + +void KRFBDecoder::sendAllowedEncodings() +{ + static CARD8 padding[1]; + con->write( &SetEncodingsId, 1 ); + con->write( padding, 1 ); + + static CARD16 noEncodings = con->options()->encodings(); + noEncodings = Swap16IfLE( noEncodings ); + con->write( &noEncodings, 2 ); + + if ( con->options()->corre ) + con->write( &CorreEncoding, 4 ); + if ( con->options()->hexTile ) + con->write( &HexTileEncoding, 4 ); + if ( con->options()->rre ) + con->write( &RreEncoding, 4 ); + if ( con->options()->copyrect ) + con->write( &CopyRectEncoding, 4 ); + // We always support this + con->write( &RawEncoding, 4 ); +} + +void KRFBDecoder::sendUpdateRequest( bool incremental ) +{ + if ( currentState != Idle ) + return; + + con->write( &UpdateRequestId, 1 ); + con->write( &incremental, 1 ); + + static CARD16 x = 0, y = 0; + static CARD16 w = Swap16IfLE( info->width ); + static CARD16 h = Swap16IfLE( info->height ); + + con->write( &x, 2 ); + con->write( &y, 2 ); + con->write( &w, 2 ); + con->write( &h, 2 ); + + // Now wait for the update + currentState = AwaitingUpdate; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); + con->waitForData( UpdateHeaderLength ); +} + +void KRFBDecoder::gotUpdateHeader() +{ + assert( currentState == AwaitingUpdate ); + + // qWarning( "Got update header" ); + + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotUpdateHeader() ) ); + + CARD8 msgType; + con->read( &msgType, 1 ); + + if ( msgType != UpdateId ) { + // We might have a bell or server cut + if ( msgType == ServerCutId ) { + oldState = currentState; + gotServerCut(); + } + else if ( msgType == BellId ) { + oldState = currentState; + gotBell(); + } + else { + int msg = msgType; + QString protocolError = tr( "Protocol Error: Message Id %1 was " + "found when expecting an update " + "message." ).arg( msg ); + currentState = Error; + emit error( protocolError ); + } + return; + } + + CARD8 padding; + con->read( &padding, 1 ); + + con->read( &noRects, 2 ); + noRects = Swap16IfLE( noRects ); + + // qWarning( "Expecting %d rects", noRects ); + + // Now wait for the data + currentState = AwaitingRectHeader; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); + con->waitForData( RectHeaderLength ); +} + +void KRFBDecoder::gotRectHeader() +{ + assert( currentState == AwaitingRectHeader ); + + // qWarning( "Got rect header" ); + + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotRectHeader() ) ); + + con->read( &x, 2 ); + x = Swap16IfLE( x ); + con->read( &y, 2 ); + y = Swap16IfLE( y ); + + con->read( &w, 2 ); + w = Swap16IfLE( w ); + con->read( &h, 2 ); + h = Swap16IfLE( h ); + + con->read( &encoding, 4 ); + + // CARD32 encodingLocal = Swap32IfLE( encoding ); + // qWarning( "Rect: x=%d, y= %d, w=%d, h=%d, encoding=%ld", + // x, y, w, h, encodingLocal ); + + // + // Each encoding needs to be handled differently. Some require + // waiting for more data, but others like a copyrect do not. + // Our constants have already been byte swapped, so we use + // the remote value as is. + // + if ( encoding == RawEncoding ) { + // qWarning( "Raw encoding" ); + handleRawRect(); + } + else if ( encoding == CopyRectEncoding ) { +// qWarning( "CopyRect encoding" ); + handleCopyRect(); + } + else if ( encoding == RreEncoding ) { + qWarning( "RRE encoding" ); + handleRRERect(); + } + else if ( encoding == CorreEncoding ) { + qWarning( "CoRRE encoding" ); + handleCoRRERect(); + } + else if ( encoding == HexTileEncoding ) { + qWarning( "HexTile encoding" ); + handleHexTileRect(); + } + else { + int msg = Swap32IfLE( encoding ); + QString protocolError = tr( "Protocol Error: An unknown encoding was " + "used by the server %1" ).arg( msg ); + currentState = Error; + qWarning( "Unknown encoding, %d", msg ); + emit error( protocolError ); + return; + } +} + +// +// Raw Encoding +// + +void KRFBDecoder::handleRawRect() +{ + // We need something a bit cleverer here to handle large + // rectanges nicely. The chunking should be based on the + // overall size (but has to be in complete lines). + + // qWarning( "Handling a raw rect chunk" ); + + // CARD32 lineCount = w * format->bpp / 8; + + if ( h > RectChunkSize ) { + // if ( con->sock->size() / lineCount ) { + // getRawRectChunk( con->sock->size() / lineCount ); + // } + // else { + getRawRectChunk( RectChunkSize ); + // } + } + else { + getRawRectChunk( h ); + } +} + +void KRFBDecoder::getRawRectChunk( int lines ) +{ + this->lines = lines; + CARD32 count = lines * w * format->bpp / 8; + + // Wait for server init + // qWarning( "Waiting for raw rect chunk, %ld", count ); + + currentState = AwaitingRawRectChunk; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRawRectChunk() ) ); + con->waitForData( count ); +} + +void KRFBDecoder::gotRawRectChunk() +{ + assert( currentState == AwaitingRawRectChunk ); + + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotRawRectChunk() ) ); + + // qWarning( "Got raw rect chunk" ); + + // + // Read the rect data and copy it to the buffer. + // + + // TODO: Replace this! + int count = lines * w * format->bpp / 8; + char *hack = new char[ count ]; + con->read( hack, count ); + buf->drawRawRectChunk( hack, x, y, w, lines ); + delete hack; + // /TODO: + + h = h - lines; + y = y + lines; + + if ( h > 0 ) { + handleRawRect(); + } + else { + noRects--; + + // qWarning( "There are %d rects left", noRects ); + + if ( noRects ) { + currentState = AwaitingRectHeader; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); + con->waitForData( RectHeaderLength ); + } + else + currentState = Idle; + } +} + +// +// Copy Rectangle Encoding +// + +void KRFBDecoder::handleCopyRect() +{ + currentState = AwaitingCopyRectPos; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotCopyRectPos() ) ); + con->waitForData( CopyRectPosLength ); +} + +void KRFBDecoder::gotCopyRectPos() +{ + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotCopyRectPos() ) ); + + CARD16 srcX; + CARD16 srcY; + + con->read( &srcX, 2 ); + con->read( &srcY, 2 ); + + srcX = Swap16IfLE( srcX ); + srcY = Swap16IfLE( srcY ); + + buf->copyRect( srcX, srcY, x, y, w, h ); + + noRects--; + + // qWarning( "There are %d rects left", noRects ); + + if ( noRects ) { + currentState = AwaitingRectHeader; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); + con->waitForData( RectHeaderLength ); + } + else + currentState = Idle; +} + +void KRFBDecoder::handleRRERect() +{ + qWarning( "RRE not implemented" ); +} + +void KRFBDecoder::handleCoRRERect() +{ + qWarning( "CoRRE not implemented" ); +} + +void KRFBDecoder::handleHexTileRect() +{ + qWarning( "HexTile not implemented" ); +} + +void KRFBDecoder::sendMouseEvent( QMouseEvent *e ) +{ + // Deal with the buttons + if ( e->type() != QEvent::MouseMove ) { + buttonMask = 0; + if ( e->type() == QEvent::MouseButtonPress ) { + if ( e->button() & LeftButton ) + buttonMask |= 0x01; + if ( e->button() & MidButton ) + buttonMask |= 0x04; + if ( e->button() & RightButton ) + buttonMask |= 0x02; + } + else if ( e->type() == QEvent::MouseButtonRelease ) { + if ( e->button() & LeftButton ) + buttonMask &= 0x06; + if ( e->button() & MidButton ) + buttonMask |= 0x03; + if ( e->button() & RightButton ) + buttonMask |= 0x05; + } + } + + CARD16 x = Swap16IfLE( e->x() ); + CARD16 y = Swap16IfLE( e->y() ); + + con->write( &PointerEventId, 1 ); + con->write( &buttonMask, 1 ); + con->write( &x, 2 ); + con->write( &y, 2 ); +} + + +void KRFBDecoder::sendCutEvent( const QString &unicode ) +{ + // + // Warning: There is a bug in the RFB protocol because there is no way to find + // out the codepage in use on the remote machine. This could be fixed by requiring + // the remote server to use utf8 etc. but for now we have to assume they're the + // same. I've reported this problem to the ORL guys, but they apparantly have no + // immediate plans to fix the issue. :-( (rich) + // + + CARD8 padding[3]; + QCString text = unicode.local8Bit(); + CARD32 length = text.length(); + length = Swap32IfLE( length ); + + con->write( &ClientCutTextId, 1 ); + con->write( &padding, 3 ); + con->write( &length, 4 ); + con->write( text.data(), length ); +} + +void KRFBDecoder::gotServerCut() +{ + qWarning( "Got server cut" ); + + currentState = AwaitingServerCutLength; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutLength() ) ); + con->waitForData( ServerCutLenLength ); +} + +void KRFBDecoder::gotServerCutLength() +{ + assert( currentState = AwaitingServerCutLength ); + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotServerCutLength() ) ); + + CARD8 padding[3]; + con->read( padding, 3 ); + + con->read( &serverCutTextLen, 4 ); + serverCutTextLen = Swap32IfLE( serverCutTextLen ); + + currentState = AwaitingServerCutText; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutText() ) ); + con->waitForData( serverCutTextLen ); +} + +void KRFBDecoder::gotServerCutText() +{ + assert( currentState = AwaitingServerCutText ); + + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotServerCutText() ) ); + + // + // Warning: There is a bug in the RFB protocol because there is no way to find + // out the codepage in use on the remote machine. This could be fixed by requiring + // the remote server to use utf8 etc. but for now we have to assume they're the + // same. I've reported this problem to the ORL guys, but they apparantly have no + // immediate plans to fix the issue. :-( (rich) + // + + char *cutbuf = new char[ serverCutTextLen + 1 ]; + CHECK_PTR( cutbuf ); + + con->read( cutbuf, serverCutTextLen ); + cutbuf[ serverCutTextLen ] = '\0'; + + qWarning( "Server cut: %s", cutbuf ); + + QString cutText( cutbuf ); // DANGER!! + qApp->clipboard()->setText( cutText ); + + delete cutbuf; + + // Now wait for the update (again) + if ( oldState == AwaitingUpdate ) { + currentState = AwaitingUpdate; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); + con->waitForData( UpdateHeaderLength ); + } + else if ( oldState == Idle ) { + currentState = Idle; + } + else { + qWarning( "Async handled in weird state" ); + currentState = oldState; + }; +} + +void KRFBDecoder::gotBell() +{ + qWarning( "Got server bell" ); + buf->soundBell(); + + // Now wait for the update (again) + if ( oldState == AwaitingUpdate ) { + currentState = AwaitingUpdate; + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); + con->waitForData( UpdateHeaderLength ); + } + else if ( oldState == Idle ) { + currentState = Idle; + } + else { + qWarning( "Async handled in weird state" ); + currentState = oldState; + }; +} + +void KRFBDecoder::sendKeyPressEvent( QKeyEvent *event ) +{ + int key; + key = toKeySym( event ); + if ( key ) { + key = Swap32IfLE( key ); + + CARD8 mask = true; + + CARD16 padding = 0; + con->write( &KeyEventId, 1 ); + con->write( &mask, 1 ); + con->write( &padding, 2 ); + con->write( &key, 4 ); + } +} + +void KRFBDecoder::sendKeyReleaseEvent( QKeyEvent *event ) +{ + int key; + key = toKeySym( event ); + if ( key ) { + key = Swap32IfLE( key ); + + CARD8 mask = false; + + CARD16 padding = 0; + con->write( &KeyEventId, 1 ); + con->write( &mask, 1 ); + con->write( &padding, 2 ); + con->write( &key, 4 ); + } +} + +int KRFBDecoder::toKeySym( QKeyEvent *k ) +{ + int ke = 0; + + ke = k->ascii(); + // Markus: Crappy hack. I dont know why lower case letters are + // not defined in qkeydefs.h. The key() for e.g. 'l' == 'L'. + // This sucks. :-( + + if ( (ke == 'a') || (ke == 'b') || (ke == 'c') || (ke == 'd') + || (ke == 'e') || (ke == 'f') || (ke == 'g') || (ke == 'h') + || (ke == 'i') || (ke == 'j') || (ke == 'k') || (ke == 'l') + || (ke == 'm') || (ke == 'n') || (ke == 'o') || (ke == 'p') + || (ke == 'q') || (ke == 'r') || (ke == 's') || (ke == 't') + || (ke == 'u') || (ke == 'v') ||( ke == 'w') || (ke == 'x') + || (ke == 'y') || (ke == 'z') ) { + ke = k->key(); + ke = ke + 0x20; + return ke; + } + + // qkeydefs = xkeydefs! :-) + if ( ( k->key() >= 0x0a0 ) && k->key() <= 0x0ff ) + return k->key(); + + if ( ( k->key() >= 0x20 ) && ( k->key() <= 0x7e ) ) + return k->key(); + + // qkeydefs != xkeydefs! :-( + // This is gonna suck :-( + + int i = 0; + while ( keyMap[i].keycode ) { + if ( k->key() == keyMap[i].keycode ) + return keyMap[i].keysym; + i++; + } + + return 0; +} + diff --git a/noncore/comm/keypebble/krfbdecoder.h b/noncore/comm/keypebble/krfbdecoder.h new file mode 100644 index 0000000..4ba0185 --- a/dev/null +++ b/noncore/comm/keypebble/krfbdecoder.h @@ -0,0 +1,134 @@ +// -*- c++ -*- + +#ifndef KRFBDECODER_H +#define KRFBDECODER_H + +#include <qobject.h> + +class KRFBConnection; +class KRFBServerInfo; +class KRFBPixelFormat; +class KRFBBuffer; + + +typedef unsigned char CARD8; +typedef unsigned short CARD16; +typedef unsigned long CARD32; + +/** + * Negotiates the pixel format to be used then decodes the resulting + * data stream. + * + * @author Richard Moore, rich@kde.org + */ +class KRFBDecoder : public QObject +{ + Q_OBJECT + +public: + friend class KRFBBuffer; + + enum State { + AwaitingServerInit, + AwaitingDesktopName, + AwaitingUpdate, + AwaitingRectHeader, + AwaitingRawRectChunk, + AwaitingCopyRectPos, + AwaitingServerCutLength, + AwaitingServerCutText, + Idle, + Error + }; + + /** + * Create a KRFBDecoder that reads data from a logged in KRFBConnection + * and sends its output to a KRFBBuffer. + */ + KRFBDecoder( KRFBConnection *con ); + ~KRFBDecoder(); + + void setBuffer( KRFBBuffer *buf ) { this->buf = buf; }; + void start(); + + int toKeySym( QKeyEvent *k ); + + // + // Client -> Server messages + // + void sendUpdateRequest( bool incremental ); + void sendMouseEvent( QMouseEvent *e ); + void sendKeyPressEvent( QKeyEvent *e ); + void sendKeyReleaseEvent( QKeyEvent *e ); + void sendCutEvent( const QString &text ); + +protected: + // + // Initial format negotiation + // + void decidePixelFormat(); + void sendPixelFormat(); + void sendClientInit(); + void sendAllowedEncodings(); + + // + // Rectange processing + // + void handleRawRect(); + void handleCopyRect(); + void handleRRERect(); + void handleCoRRERect(); + void handleHexTileRect(); + + void getRawRectChunk( int lines ); + +protected slots: + void gotServerInit(); + void gotDesktopName(); + void gotUpdateHeader(); + void gotRectHeader(); + void gotRawRectChunk(); + void gotCopyRectPos(); + void gotServerCut(); + void gotServerCutLength(); + void gotServerCutText(); + void gotBell(); + +signals: + void error( const QString & ); + void status( const QString & ); + +private: + State currentState; + + // Used to store the state we were in before a cut or bell msg + State oldState; + + // The number of rects we're expecting + CARD16 noRects; + + // + // Info about the current rect. + // + CARD16 x, y, w, h; + int lines; + CARD32 encoding; + + CARD32 serverCutTextLen; + + /** Where we draw the data (and the source of our events). */ + KRFBBuffer *buf; + /** The connection to the server. */ + KRFBConnection *con; + + /** Info about the RFB server. */ + KRFBServerInfo *info; + /** The pixel format we want. */ + KRFBPixelFormat *format; + + CARD8 buttonMask; +}; + +#endif // KRFBDECODER_H + + diff --git a/noncore/comm/keypebble/krfblogin.cpp b/noncore/comm/keypebble/krfblogin.cpp new file mode 100644 index 0000000..073ba0e --- a/dev/null +++ b/noncore/comm/keypebble/krfblogin.cpp @@ -0,0 +1,255 @@ +#include <assert.h> + + +extern "C" { +#include "vncauth.h" +} + +#include "krfblogin.h" +#include "krfbconnection.h" +#include <qtimer.h> + +// The length of the various messages (used to decide how many bytes to +// wait for). +const int ServerVersionLength = 12; +const int ClientVersionLength = 12; +const int AuthSchemeLength = 4; +const int FailureReasonSizeLength = 4; +const int ChallengeLength = 16; +const int AuthResultLength = 4; + +// Authentication results +enum AuthResult { + AuthOk, + AuthFailed, + AuthTooMany +}; + +typedef unsigned char CARD8; +typedef unsigned short CARD16; +typedef unsigned long CARD32; + +const int endianTest = 1; + +// Endian stuff +#define Swap16IfLE(s) \ + (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define Swap32IfLE(l) \ + (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +KRFBLogin::KRFBLogin( KRFBConnection *con ) + : QObject( con, "RFB login manager" ) +{ + assert( con ); + this->con = con; + currentState = AwaitingServerVersion; + + connect( this, SIGNAL( error( const QString & ) ), + con, SIGNAL( error( const QString & ) ) ); + + connect( this, SIGNAL( passwordRequired( KRFBConnection * ) ), + con, SIGNAL( passwordRequired( KRFBConnection * ) ) ); + + qWarning( "Waiting for server version..." ); + + static QString statusMsg = tr( "Waiting for server version..." ); + emit status( statusMsg ); + + // Kick off the state machine + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerVersion() ) ); + con->waitForData( ServerVersionLength ); +} + +KRFBLogin::~KRFBLogin() +{ + +} + +KRFBLogin::State KRFBLogin::state() const +{ + return currentState; +} + +void KRFBLogin::gotServerVersion() +{ + qWarning( "Got server version" ); + + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotServerVersion() ) ); + + // Read the server's version message + char serverVersion[ ServerVersionLength + 1 ]; + con->read( serverVersion, ServerVersionLength ); + serverVersion[ ServerVersionLength ] = '\0'; + + QCString rfbString( serverVersion, ServerVersionLength + 1 ); + versionString = rfbString; + + QRegExp regexp( "RFB [0-9][0-9][0-9]\\.[0-9][0-9][0-9]\n" ); + + if ( rfbString.find( regexp ) == -1 ) { + static QString msg = tr( "Error: Invalid server version, %1" ).arg( rfbString ); + + qWarning( msg ); + emit error( msg ); + currentState = Error; + return; + } + + // Calculate the actual version number + serverMajor = (serverVersion[4] - '0') * 100 + + (serverVersion[5] - '0') * 10 + + (serverVersion[6] - '0'); + serverMinor = (serverVersion[8] - '0') * 100 + + (serverVersion[9] - '0') * 10 + + (serverVersion[10] - '0'); + + qWarning("Server Version: %03d.%03d", serverMajor, serverMinor ); + + if ( serverMajor != 3 ) { + QString msg = tr( "Error: Unsupported server version, %1" ) + .arg( rfbString ); + + qWarning( msg ); + emit error( msg ); + currentState = Error; + return; + } + + if ( serverMinor != 3 ) { + qWarning( "Minor version mismatch: %d", serverMinor ); + } + + // Setup for the next state + sendClientVersion(); + + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotAuthScheme() ) ); + con->waitForData( AuthSchemeLength ); +} + +void KRFBLogin::gotAuthScheme() +{ + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotAuthScheme() ) ); + + // Got data + CARD32 scheme; + con->read( &scheme, AuthSchemeLength ); + scheme = Swap32IfLE( scheme ); + + static QString statusMsgOk = tr( "Logged in" ); + + switch ( scheme ) { + case 0: + qWarning( "Failed" ); + // Handle failure + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotFailureReasonSize() ) ); + con->waitForData( FailureReasonSizeLength ); + break; + case 1: + // Handle no auth + emit status( statusMsgOk ); + con->gotRFBConnection(); + break; + case 2: + // Handle VNC auth + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotChallenge() ) ); + con->waitForData( ChallengeLength ); + break; + default: + qWarning( "Unknown authentication scheme, 0x%08lx", scheme ); + currentState = Error; + break; + }; +} + +void KRFBLogin::gotChallenge() +{ + disconnect( con, SIGNAL( gotEnoughData() ), + this, SLOT( gotChallenge() ) ); + + QTimer::singleShot( 0, this, SLOT(getPassword()) ); +} + +void KRFBLogin::getPassword() +{ + // Got data + CARD8 challenge[ ChallengeLength ]; + con->read( challenge, ChallengeLength ); + + // Last chance to enter a password + if ( con->pass_.isNull() ) { + qWarning( "krfblogin needs a password" ); + emit passwordRequired( con ); + } + + if ( con->pass_.isNull() ) { + QString msg = tr( "Error: This server requires a password, but none " + "has been specified.\n" ); + + emit error( msg ); + return; + } + + vncEncryptBytes( (unsigned char *) challenge, con->pass_.data() ); + con->write( challenge, ChallengeLength ); + + connect( con, SIGNAL( gotEnoughData() ), SLOT( gotAuthResult() ) ); + con->waitForData( AuthResultLength ); +} + +void KRFBLogin::gotFailureReasonSize() +{ + disconnect( con, SIGNAL( gotEnoughData() ), this, + SLOT( gotFailureReasonSize() ) ); +} + +void KRFBLogin::gotAuthResult() +{ + // Got data + disconnect( con, SIGNAL( gotEnoughData() ), this, + SLOT( gotAuthResult() ) ); + + long result; + con->read( &result, AuthResultLength ); + result = Swap32IfLE( result ); + + qWarning( "Authentication Result is 0x%08lx", result ); + + static QString failed = tr( "Error: The password you specified was incorrect." ); + static QString tooMany = tr( "Error: Too many invalid login attempts have been made\n" + "to this account, please try later." ); + + static QString statusMsgOk = tr( "Logged in" ); + static QString statusMsgFailed = tr( "Login Failed" ); + static QString statusMsgTooMany = tr( "Too many failures" ); + + switch( result ) { + case AuthOk: + emit status( statusMsgOk ); + con->gotRFBConnection(); + break; + case AuthFailed: + qWarning( "Dammit" ); + emit status( statusMsgFailed ); + emit error( failed ); + break; + case AuthTooMany: + emit status( statusMsgTooMany ); + emit error( tooMany ); + break; + default: + qWarning( "Invalid authentication result, %lx", result ); + break; + } +} + +void KRFBLogin::sendClientVersion() +{ + qWarning( "Sending client version" ); + con->write( (void*)"RFB 003.003\n", ClientVersionLength ); +} diff --git a/noncore/comm/keypebble/krfblogin.h b/noncore/comm/keypebble/krfblogin.h new file mode 100644 index 0000000..5208210 --- a/dev/null +++ b/noncore/comm/keypebble/krfblogin.h @@ -0,0 +1,62 @@ +// -*- c++ -*- + +#ifndef KRFBLOGIN_H +#define KRFBLOGIN_H + +#include <qobject.h> + +class KRFBConnection; + +/** + * Handles logging into the RFB server. + * + * @version $Id$ + * @author Richard Moore, rich@kde.org + */ +class KRFBLogin : QObject +{ + Q_OBJECT + +public: + enum State { + AwaitingServerVersion, + AwaitingAuthScheme, + AwaitingChallenge, + WaitingForResponse, + Authenticated, + Ready, + Failed, + Error + }; + + KRFBLogin( KRFBConnection *con ); + ~KRFBLogin(); + + KRFBLogin::State state() const; + +protected: + void sendClientVersion(); + +protected slots: + void getPassword(); + void gotServerVersion(); + void gotAuthScheme(); + void gotChallenge(); + void gotAuthResult(); + void gotFailureReasonSize(); + +signals: + void passwordRequired( KRFBConnection * ); + void error( const QString & ); + void status( const QString & ); + +private: + KRFBConnection *con; + State currentState; + QCString versionString; + int serverMajor; + int serverMinor; +}; + +#endif // KRFBLOGIN_H + diff --git a/noncore/comm/keypebble/krfboptions.cpp b/noncore/comm/keypebble/krfboptions.cpp new file mode 100644 index 0000000..9daf3f0 --- a/dev/null +++ b/noncore/comm/keypebble/krfboptions.cpp @@ -0,0 +1,52 @@ +#include <qpe/config.h> +#include <qpe/qpeapplication.h> +#include "krfboptions.h" + +KRFBOptions::KRFBOptions() +{ + Config config( "keypebble" ); + readSettings( &config ); +} + +KRFBOptions::~KRFBOptions() +{ + Config config( "keypebble" ); + writeSettings( &config ); +} + +void KRFBOptions::readSettings( Config *config ) +{ + hexTile = config->readBoolEntry( "HexTile" ); + corre = config->readBoolEntry( "CORRE" ); + rre = config->readBoolEntry( "RRE" ); + copyrect = config->readBoolEntry( "CopyRect", true ); + colors256 = config->readBoolEntry( "Colors256" ); + shared = config->readBoolEntry( "Shared" ); + readOnly = config->readBoolEntry( "ReadOnly" ); + updateRate = config->readNumEntry( "UpdateRate", 50 ); +} + +void KRFBOptions::writeSettings( Config *config ) +{ + config->writeEntry( "HexTile", hexTile ); + config->writeEntry( "CORRE", corre ); + config->writeEntry( "RRE", rre ); + config->writeEntry( "CopyRect", copyrect ); + config->writeEntry( "Colors256", colors256 ); + config->writeEntry( "Shared", shared ); + config->writeEntry( "ReadOnly", readOnly ); + config->writeEntry( "UpdateRate", updateRate ); +} + +int KRFBOptions::encodings() +{ + // Initially one because we always support raw encoding + int count = 1; + + count += hexTile ? 1 : 0; + count += corre ? 1 : 0; + count += rre ? 1 : 0; + count += copyrect ? 1 : 0; + + return count; +} diff --git a/noncore/comm/keypebble/krfboptions.h b/noncore/comm/keypebble/krfboptions.h new file mode 100644 index 0000000..41cea35 --- a/dev/null +++ b/noncore/comm/keypebble/krfboptions.h @@ -0,0 +1,31 @@ +// -*- c++ -*- + +#ifndef KRFBOPTIONS_H +#define KRFBOPTIONS_H + +class Config; + +class KRFBOptions +{ +public: + KRFBOptions(); + ~KRFBOptions(); + + int encodings(); + void readSettings( Config *config ); + void writeSettings( Config *config ); + + bool hexTile; + bool corre; + bool rre; + bool copyrect; + + bool colors256; + bool shared; + bool readOnly; + bool deIconify; + + int updateRate; +}; + +#endif // KRFBOPTIONS_H diff --git a/noncore/comm/keypebble/krfbserverinfo.h b/noncore/comm/keypebble/krfbserverinfo.h new file mode 100644 index 0000000..7449da9 --- a/dev/null +++ b/noncore/comm/keypebble/krfbserverinfo.h @@ -0,0 +1,42 @@ +// -*- c++ -*- + +#ifndef KRFBSERVERINFO_H +#define KRFBSERVERINFO_H + +#include <qstring.h> + +typedef unsigned char CARD8; +typedef unsigned short CARD16; +typedef unsigned long CARD32; + +class KRFBPixelFormat +{ +public: + CARD8 bpp; + CARD8 depth; + CARD8 bigEndian; + CARD8 trueColor; + CARD16 redMax; + CARD16 greenMax; + CARD16 blueMax; + CARD8 redShift; + CARD8 greenShift; + CARD8 blueShift; + CARD8 padding[3]; // 3 bytes padding +}; + +/** + * Information sent by the server in its init message. + */ +class KRFBServerInfo : public KRFBPixelFormat +{ +public: + CARD16 width; + CARD16 height; + CARD32 nameLength; + QString name; +}; + +#endif // KRFBSERVERINFO_H + + diff --git a/noncore/comm/keypebble/kvnc.cpp b/noncore/comm/keypebble/kvnc.cpp new file mode 100644 index 0000000..bb18999 --- a/dev/null +++ b/noncore/comm/keypebble/kvnc.cpp @@ -0,0 +1,191 @@ +#include <qiconset.h> +#include <qdialog.h> +#include <qpixmap.h> +#include <qdom.h> +#include <qaction.h> +#include <qpe/qpemenubar.h> +#include <qstatusbar.h> +#include <qpopupmenu.h> +#include <qpushbutton.h> +#include <qpe/qpetoolbar.h> +#include <qtimer.h> +#include <qmessagebox.h> +#include <qpe/qpeapplication.h> +#include <qpe/global.h> +#include <assert.h> + +#include "kvnc.h" +#include "krfbcanvas.h" +#include "kvncoptionsdlg.h" +#include "krfbconnection.h" + + +/* XPM */ +static char * menu_xpm[] = { +"12 12 5 1", +" c None", +". c #000000", +"+ c #FFFDAD", +"@ c #FFFF00", +"# c #E5E100", +" ", +" ", +" ......... ", +" .+++++++. ", +" .+@@@@#. ", +" .+@@@#. ", +" .+@@#. ", +" .+@#. ", +" .+#. ", +" .+. ", +" .. ", +" "}; + +const int StatusTextId = 0; + +KVNC::KVNC( const char *name ) : QMainWindow( 0, name ) +{ + setCaption( tr("VNC Viewer") ); + fullscreen = false; + + canvas = new KRFBCanvas( this, "canvas" ); + setCentralWidget( canvas ); + + connect( canvas->connection(), SIGNAL(statusChanged(const QString &)), + this, SLOT(statusMessage(const QString &)) ); + connect( canvas->connection(), SIGNAL(error(const QString &)), + this, SLOT(error(const QString &)) ); + connect( canvas->connection(), SIGNAL(connected()), this, SLOT(connected()) ); + connect( canvas->connection(), SIGNAL(loggedIn()), this, SLOT(loggedIn()) ); + connect( canvas->connection(), SIGNAL(disconnected()), this, SLOT(disconnected()) ); + + setupActions(); + + cornerButton = new QPushButton( this ); + cornerButton->setPixmap( QPixmap( (const char**)menu_xpm ) ); + connect( cornerButton, SIGNAL(pressed()), this, SLOT(showMenu()) ); + canvas->setCornerWidget( cornerButton ); + + QTimer::singleShot( 0, canvas, SLOT(openConnection()) ); +} + +KVNC::~KVNC() +{ + +} + +void KVNC::openURL( const QUrl &url ) +{ + canvas->openURL( url ); +} + +void KVNC::setupActions() +{ + cornerMenu = new QPopupMenu( this ); + + fullScreenAction = new QAction( tr("Full Screen"), QString::null, 0, 0 ); + connect( fullScreenAction, SIGNAL(activated()), + this, SLOT( toggleFullScreen() ) ); + fullScreenAction->addTo( cornerMenu ); + fullScreenAction->setEnabled( false ); + + optionsAction = new QAction( tr("Settings"), QString::null, 0, 0 ); + connect( optionsAction, SIGNAL(activated()), this, SLOT( showOptions() ) ); + optionsAction->addTo( cornerMenu ); + + connectAction = new QAction( tr("Connect..."), QString::null, 0, 0 ); + connect( connectAction, SIGNAL(activated()), + canvas, SLOT( openConnection() ) ); + connectAction->addTo( cornerMenu ); + + disconnectAction = new QAction( tr("Disconnect"), QString::null, 0, 0 ); + connect( disconnectAction, SIGNAL(activated()), + this, SLOT( closeConnection() ) ); + disconnectAction->addTo( cornerMenu ); + disconnectAction->setEnabled( false ); +} + +void KVNC::toggleFullScreen() +{ + if ( fullscreen ) { + canvas->releaseKeyboard(); + canvas->reparent( this, 0, QPoint(0,0), false ); + canvas->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + setCentralWidget( canvas ); + canvas->show(); + fullScreenAction->setText( tr("Full Screen") ); + } else { + canvas->setFrameStyle( QFrame::NoFrame ); + canvas->reparent( 0,WStyle_Tool | WStyle_Customize | WStyle_StaysOnTop, + QPoint(0,0),false); + canvas->resize(qApp->desktop()->width(), qApp->desktop()->height()); + canvas->raise(); + canvas->setFocus(); + canvas->grabKeyboard(); + canvas->show(); + + fullScreenAction->setText( tr("Stop Full Screen") ); + } + + fullscreen = !fullscreen; +} + +void KVNC::closeConnection() +{ + if ( fullscreen ) + toggleFullScreen(); + canvas->closeConnection(); +} + +void KVNC::showMenu() +{ + QPoint pt = mapToGlobal(cornerButton->pos()); + QSize s = cornerMenu->sizeHint(); + pt.ry() -= s.height(); + pt.rx() -= s.width(); + cornerMenu->popup( pt ); +} + +void KVNC::connected() +{ + static QString msg = tr( "Connected to remote host" ); + statusMessage( msg ); + connectAction->setEnabled( false ); + disconnectAction->setEnabled( true ); + fullScreenAction->setEnabled( true ); +} + +void KVNC::loggedIn() +{ + static QString msg = tr( "Logged in to remote host" ); + statusMessage( msg ); +} + +void KVNC::disconnected() +{ + static QString msg = tr( "Connection closed" ); + statusMessage( msg ); + connectAction->setEnabled( true ); + disconnectAction->setEnabled( false ); + fullScreenAction->setEnabled( false ); +} + +void KVNC::statusMessage( const QString &m ) +{ + Global::statusMessage( m ); +} + +void KVNC::error( const QString &msg ) +{ + statusMessage( msg ); + QMessageBox::warning( this, tr("VNC Viewer"), msg ); +} + +void KVNC::showOptions() +{ + KVNCOptionsDlg *wdg = new KVNCOptionsDlg( canvas->connection()->options(), this ); + wdg->showMaximized(); + wdg->exec(); + delete wdg; +} + diff --git a/noncore/comm/keypebble/kvnc.h b/noncore/comm/keypebble/kvnc.h new file mode 100644 index 0000000..92666c5 --- a/dev/null +++ b/noncore/comm/keypebble/kvnc.h @@ -0,0 +1,56 @@ +// -*- c++ -*- + +#ifndef KVNC_H +#define KVNC_H + +#include <qmainwindow.h> +#include <qurl.h> + +class QAction; +class KRFBCanvas; +class QPushButton; +class QToolBar; + +/** + * Top level window for Keystone. + * + * @author Richard Moore, rich@kde.org + * @version $Id$ + */ +class KVNC : public QMainWindow +{ + Q_OBJECT +public: + KVNC( const char *name = 0 ); + ~KVNC(); + +public slots: + void toggleFullScreen(); + void openURL( const QUrl & ); + void closeConnection(); + void showOptions(); + +protected: + void setupActions(); + +protected slots: + void showMenu(); + + void connected(); + void loggedIn(); + void disconnected(); + void statusMessage( const QString & ); + void error( const QString & ); + +private: + bool fullscreen; + KRFBCanvas *canvas; + QPopupMenu *cornerMenu; + QPushButton *cornerButton; + QAction *fullScreenAction; + QAction *optionsAction; + QAction *disconnectAction; + QAction *connectAction; +}; + +#endif // KVNC_H diff --git a/noncore/comm/keypebble/kvncconnectdlg.cpp b/noncore/comm/keypebble/kvncconnectdlg.cpp new file mode 100644 index 0000000..467cebf --- a/dev/null +++ b/noncore/comm/keypebble/kvncconnectdlg.cpp @@ -0,0 +1,79 @@ +#include <qstring.h> +#include <qlayout.h> +#include <qframe.h> +#include <qspinbox.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qfont.h> + +#include <assert.h> + +#include "krfbconnection.h" +#include "kvncoptionsdlg.h" +#include "kvncconnectdlg.h" + + +KVNCConnectDlg::KVNCConnectDlg( KRFBConnection *con, + QWidget *parent, const char *name ) + : QDialog( parent, name, true ) +{ + setCaption( tr("Connect to VNC server") ); + assert( con ); + this->con = con; + + QGridLayout *inner = new QGridLayout( this, 3, 2, 6 ); + + QLabel *label = new QLabel( tr("Host Name:"), + this , "hostLabel"); + hostNameCombo = new QComboBox( true, this ); + hostNameCombo->setInsertionPolicy( QComboBox::AtTop ); + hostNameCombo->setMaxCount( 10 ); + hostNameCombo->insertItem( "localhost" ); + hostNameCombo->setFocus(); + + inner->addWidget( label, 0, 0 ); + inner->addWidget( hostNameCombo, 0, 1 ); + + label = new QLabel( tr("Display Number:"), this, "displayNumber" ); + displayNumberEdit = new QSpinBox( this ); + + inner->addWidget( label, 1, 0 ); + inner->addWidget( displayNumberEdit, 1, 1 ); + + // if ( viewer->display() != -1 ) { + // displayNumberEdit->setValue( viewer->display() ); + displayNumberEdit->setValue( 1 ); + // } + + label = new QLabel( tr("Password:"), this ); + inner->addWidget( label, 2, 0 ); + + passwordEdit = new QLineEdit( this ); + passwordEdit->setEchoMode( QLineEdit::Password ); + inner->addWidget( passwordEdit, 2, 1 ); + + inner->setColStretch( 0, 0 ); + inner->setColStretch( 1, 15 ); +} + + +void KVNCConnectDlg::accept() +{ + int dis; + // viewer->setHost(hostNameCombo->currentText()); + QString temp = displayNumberEdit->text(); + if(temp.isEmpty()) + dis = -1; + else + dis = temp.toUInt(); + // viewer->setDisplay(dis); + QDialog::accept(); +} + +void KVNCConnectDlg::options() +{ + KVNCOptionsDlg *wdg = new KVNCOptionsDlg( con->options(), this ); + wdg->exec(); + delete wdg; +} + diff --git a/noncore/comm/keypebble/kvncconnectdlg.h b/noncore/comm/keypebble/kvncconnectdlg.h new file mode 100644 index 0000000..cf34aab --- a/dev/null +++ b/noncore/comm/keypebble/kvncconnectdlg.h @@ -0,0 +1,39 @@ +// -*- c++ -*- + +#ifndef KVNCCONNECTDLG_H +#define KVNCCONNECTDLG_H + +#include <qdialog.h> +#include <qspinbox.h> +#include <qcombobox.h> +#include <qlineedit.h> +#include <qurl.h> + +class KRFBConnection; + +class KVNCConnectDlg : public QDialog +{ + Q_OBJECT + +public: + KVNCConnectDlg( KRFBConnection *con, + QWidget *parent = 0, const char *name = 0 ); + + QString hostname() { return hostNameCombo->currentText(); }; + int display() { return displayNumberEdit->value(); }; + QString password() const { return passwordEdit->text(); } + +protected: + void accept(); + +protected slots: + void options(); + +private: + QComboBox *hostNameCombo; + QSpinBox *displayNumberEdit; + QLineEdit *passwordEdit; + KRFBConnection *con; +}; + +#endif // KVNCCONNECTDLG_H diff --git a/noncore/comm/keypebble/kvncoptionsdlg.cpp b/noncore/comm/keypebble/kvncoptionsdlg.cpp new file mode 100644 index 0000000..b9f57d1 --- a/dev/null +++ b/noncore/comm/keypebble/kvncoptionsdlg.cpp @@ -0,0 +1,53 @@ +#include <qframe.h> +#include <qvbox.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qwhatsthis.h> +#include <qapplication.h> +#include "krfboptions.h" + +#include "kvncoptionsdlg.h" + +KVNCOptionsDlg::KVNCOptionsDlg( KRFBOptions *options, + QWidget *parent, char *name, bool modal ) + : VncOptionsBase( parent, name, modal ) +{ + this->options = options; + + hex->setChecked( options->hexTile ); + corre->setChecked( options->corre ); + rre->setChecked( options->rre ); + copyRect->setChecked( options->copyrect ); + + // TODO + hex->setEnabled( false ); + corre->setEnabled( false ); + rre->setEnabled( false ); + // /TODO + + deIconify->setChecked( options->deIconify ); + bit->setChecked( options->colors256 ); + shared->setChecked( options->shared ); + timeBox->setValue( options->updateRate ); +} + +KVNCOptionsDlg::~KVNCOptionsDlg() +{ +} + +void KVNCOptionsDlg::accept() +{ + options->hexTile = hex->isChecked(); + options->corre = corre->isChecked(); + options->rre = rre->isChecked(); + options->copyrect = copyRect->isChecked(); + options->deIconify = deIconify->isChecked(); + options->colors256 = bit->isChecked(); + options->shared = shared->isChecked(); + options->updateRate = timeBox->value(); + + QDialog::accept(); +} + diff --git a/noncore/comm/keypebble/kvncoptionsdlg.h b/noncore/comm/keypebble/kvncoptionsdlg.h new file mode 100644 index 0000000..a166490 --- a/dev/null +++ b/noncore/comm/keypebble/kvncoptionsdlg.h @@ -0,0 +1,30 @@ +// -*- c++ -*- + +#ifndef KVNCOPTIONSDIALOG_H +#define KVNCOPTIONSDIALOG_H + +#include "vncoptionsbase.h" + +class KRFBOptions; + +class KVNCOptionsDlg : public VncOptionsBase +{ +Q_OBJECT + +public: + KVNCOptionsDlg( KRFBOptions *options, + QWidget *parent = 0, char *name = 0, bool modal = true ); + ~KVNCOptionsDlg(); + +protected: + void accept(); + +private: + KRFBOptions *options; +}; + +#endif // KVNCOPTIONSDIALOG_H + + + + diff --git a/noncore/comm/keypebble/main.cpp b/noncore/comm/keypebble/main.cpp new file mode 100644 index 0000000..a32a368 --- a/dev/null +++ b/noncore/comm/keypebble/main.cpp @@ -0,0 +1,18 @@ + + +#include <qurl.h> +#include <qpe/qpeapplication.h> +#include "kvnc.h" + +int main( int argc, char **argv ) +{ + QPEApplication app( argc, argv ); + KVNC *view = new KVNC( "Keypebble" ); + app.showMainWidget( view ); + + if ( argc > 1 ) + view->openURL( QUrl(argv[1]) ); + + return app.exec(); +} + diff --git a/noncore/comm/keypebble/qpe-keypebble.control b/noncore/comm/keypebble/qpe-keypebble.control new file mode 100644 index 0000000..75c1b9f --- a/dev/null +++ b/noncore/comm/keypebble/qpe-keypebble.control @@ -0,0 +1,10 @@ +Files: bin/keypebble apps/Applications/keypebble.desktop pics/vnc.png +Priority: optional +Section: qpe/applications +Maintainer: Martin Jones <mjones@trolltech.com> +Architecture: arm +Arch: iPAQ +Version: $QPE_VERSION-2 +Depends: qpe-base ($QPE_VERSION) +Description: VNC Viewer + Virtual Network Computing (VNC) viewer diff --git a/noncore/comm/keypebble/vncauth.c b/noncore/comm/keypebble/vncauth.c new file mode 100644 index 0000000..dc276bf --- a/dev/null +++ b/noncore/comm/keypebble/vncauth.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncauth.c - Functions for VNC password management and authentication. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> +#include "vncauth.h" +#include "d3des.h" + + +/* + * We use a fixed key to store passwords, since we assume that our local + * file system is secure but nonetheless don't want to store passwords + * as plaintext. + */ + +unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7}; + + +/* + * Encrypt a password and store it in a file. Returns 0 if successful, + * 1 if the file could not be written. + */ + +int +vncEncryptAndStorePasswd(char *passwd, char *fname) +{ + FILE *fp; + int i; + unsigned char encryptedPasswd[8]; + + if ((fp = fopen(fname,"w")) == NULL) return 1; + + chmod(fname, S_IRUSR|S_IWUSR); + + /* pad password with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + encryptedPasswd[i] = passwd[i]; + } else { + encryptedPasswd[i] = 0; + } + } + + /* Do encryption in-place - this way we overwrite our copy of the plaintext + password */ + + deskey(fixedkey, EN0); + des(encryptedPasswd, encryptedPasswd); + + for (i = 0; i < 8; i++) { + putc(encryptedPasswd[i], fp); + } + + fclose(fp); + return 0; +} + + +/* + * Decrypt a password from a file. Returns a pointer to a newly allocated + * string containing the password or a null pointer if the password could + * not be retrieved for some reason. + */ + +char * +vncDecryptPasswdFromFile(char *fname) +{ + FILE *fp; + int i, ch; + unsigned char *passwd = (unsigned char *)malloc(9); + + if ((fp = fopen(fname,"r")) == NULL) return NULL; + + for (i = 0; i < 8; i++) { + ch = getc(fp); + if (ch == EOF) { + fclose(fp); + return NULL; + } + passwd[i] = ch; + } + + deskey(fixedkey, DE1); + des(passwd, passwd); + + passwd[8] = 0; + + return (char *)passwd; +} + + +/* + * Generate CHALLENGESIZE random bytes for use in challenge-response + * authentication. + */ + +void +vncRandomBytes(unsigned char *bytes) +{ + int i; + unsigned int seed = (unsigned int) time(0); + + srandom(seed); + for (i = 0; i < CHALLENGESIZE; i++) { + bytes[i] = (unsigned char)(random() & 255); + } +} + + +/* + * Encrypt CHALLENGESIZE bytes in memory using a password. + */ + +void +vncEncryptBytes(unsigned char *bytes, char *passwd) +{ + unsigned char key[8]; + int i; + + /* key is simply password padded with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + key[i] = passwd[i]; + } else { + key[i] = 0; + } + } + + deskey(key, EN0); + + for (i = 0; i < CHALLENGESIZE; i += 8) { + des(bytes+i, bytes+i); + } +} diff --git a/noncore/comm/keypebble/vncauth.h b/noncore/comm/keypebble/vncauth.h new file mode 100644 index 0000000..38b289e --- a/dev/null +++ b/noncore/comm/keypebble/vncauth.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncauth.h - describes the functions provided by the vncauth library. + */ + +#define MAXPWLEN 8 +#define CHALLENGESIZE 16 + +extern int vncEncryptAndStorePasswd(char *passwd, char *fname); +extern char *vncDecryptPasswdFromFile(char *fname); +extern void vncRandomBytes(unsigned char *bytes); +extern void vncEncryptBytes(unsigned char *bytes, char *passwd); diff --git a/noncore/comm/keypebble/vncoptionsbase.ui b/noncore/comm/keypebble/vncoptionsbase.ui new file mode 100644 index 0000000..d049a79 --- a/dev/null +++ b/noncore/comm/keypebble/vncoptionsbase.ui @@ -0,0 +1,270 @@ +<!DOCTYPE UI><UI> +<class>VncOptionsBase</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>VncOptionsBase</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>234</width> + <height>221</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>VNC Viewer Options</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QTabWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>TabWidget3</cstring> + </property> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Data Encoding</string> + </attribute> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Check for screen updates every:</string> + </property> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout2</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>QSpinBox</class> + <property stdset="1"> + <name>name</name> + <cstring>timeBox</cstring> + </property> + <property stdset="1"> + <name>maxValue</name> + <number>500</number> + </property> + <property stdset="1"> + <name>minValue</name> + <number>1</number> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel2</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Milliseconds</string> + </property> + </widget> + </hbox> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>bit</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Request 8-bit session</string> + </property> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>deIconify</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Raise on bell</string> + </property> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>shared</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Request shared session</string> + </property> + </widget> + <spacer> + <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> + </vbox> + </widget> + <widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>tab</cstring> + </property> + <attribute> + <name>title</name> + <string>Connection</string> + </attribute> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>hex</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>text</name> + <string>Hextile encoding</string> + </property> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>corre</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>text</name> + <string>CoRRE encoding</string> + </property> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>rre</cstring> + </property> + <property stdset="1"> + <name>enabled</name> + <bool>false</bool> + </property> + <property stdset="1"> + <name>text</name> + <string>RRE encoding</string> + </property> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>copyRect</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Copy rectangle encoding</string> + </property> + </widget> + <spacer> + <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> + </vbox> + </widget> + </widget> + </vbox> +</widget> +</UI> |