New structure of auto-type classes

Use xvkbd code for sending auto-type keys
Fixed bug that prevented auto-typing non-latin1 chars
Added Italian translation
Fixed some new gcc warnings

git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@238 b624d157-de02-0410-bad0-e51aec6abb33
master
sniperbeamer 16 years ago
parent bb80c9616a
commit 888d0982d4
  1. 2
      keepassx.pro
  2. 7
      src/Application_X11.cpp
  3. 16
      src/Database.h
  4. 96
      src/Kdb3Database.cpp
  5. 16
      src/Kdb3Database.h
  6. 2
      src/crypto/twofish.cpp
  7. 5
      src/dialogs/AutoTypeDlg.cpp
  8. 5
      src/dialogs/SelectIconDlg.cpp
  9. 6
      src/dialogs/SettingsDlg.cpp
  10. 2
      src/dialogs/TargetWindowDlg.cpp
  11. 2
      src/export/Export.cpp
  12. 2
      src/import/Import_KWalletXml.cpp
  13. 2
      src/import/Import_KeePassX_Xml.cpp
  14. 5
      src/import/Import_PwManager.cpp
  15. 44
      src/lib/AutoType.h
  16. 267
      src/lib/AutoTypeGlobalX11.cpp
  17. 46
      src/lib/AutoTypeGlobalX11.h
  18. 866
      src/lib/AutoTypeX11.cpp
  19. 71
      src/lib/AutoTypeX11.h
  20. 665
      src/lib/AutoType_X11.cpp
  21. 34
      src/lib/EntryView.cpp
  22. 4
      src/lib/GroupView.cpp
  23. 38
      src/lib/HelperX11.cpp
  24. 3
      src/lib/HelperX11.h
  25. 2
      src/lib/ShortcutWidget.cpp
  26. 2
      src/lib/tools.h
  27. 12
      src/main.cpp
  28. 6
      src/mainwindow.cpp
  29. 10
      src/src.pro
  30. 2929
      src/translations/keepassx-it_IT.ts
  31. 5
      todo

@ -25,4 +25,4 @@ SUBDIRS += src
message("Install Prefix:" $$PREFIX)
#message("KDE Prefix:" $$KDEDIR)
message("*** Makefile successfully generated.")
message("*** Start make now.")
message("*** Start make now.")

@ -28,9 +28,12 @@ KeepassApplication::KeepassApplication(int& argc, char** argv) : QApplication(ar
}
bool KeepassApplication::x11EventFilter(XEvent* event){
if (event->type==KeyPress && AutoType::shortcut.key!=0u && event->xkey.keycode==XKeysymToKeycode(event->xkey.display,HelperX11::getKeysym(AutoType::shortcut.key)) && (event->xkey.state&remove_invalid)==HelperX11::getShortcutModifierMask(AutoType::shortcut) && focusWidget()==NULL ){
if (event->type==KeyPress && autoType->getShortcut().key!=0u &&
event->xkey.keycode==XKeysymToKeycode(event->xkey.display,HelperX11::getKeysym(autoType->getShortcut().key)) &&
(event->xkey.state&remove_invalid)==HelperX11::getShortcutModifierMask(autoType->getShortcut()) && focusWidget()==NULL )
{
EventOccurred = true;
AutoType::performGlobal();
autoType->performGlobal();
return true;
}
else{

@ -23,7 +23,7 @@
extern const QDateTime Date_Never;
typedef enum CryptAlgorithm{
enum CryptAlgorithm{
Rijndael_Cipher=0,
Twofish_Cipher=1
};
@ -371,7 +371,7 @@ public:
*/
virtual QPixmap& icon(int index)=0;
//! \return the number of icons provided by the database. This number can vary at runtime if the database supports custom icons.
virtual int numIcons()=0;
virtual int numIcons()=0;
/*! Deletes all old invalid handles of the database.
Make sure that there are no pointers to those handles which are still in use before calling this function.*/
@ -395,16 +395,8 @@ public:
\param Fields A pointer to a six element bool array. It defines which fields are included into the search. The order is: title, username, url, password, comment, attachment description. The pointer can also be NULL, than the default pattern is used instead.
\return the search results as a list of pointers to the entry handles.*/
virtual QList<IEntryHandle*> search(IGroupHandle* Group,const QString& SearchString, bool CaseSensitve, bool RegExp,bool Recursive,bool* Fields)=0;
//! Moves an entry to the recycle bin.
virtual void moveToTrash(IEntryHandle* entry)=0;
//! \returns all entries of the recycle bin.
virtual QList<IEntryHandle*> trashEntries()=0;
//! Empty the recycle bin.
virtual void emptyTrash()=0;
//virtual IDatabase* groupToNewDb(IGroupHandle* group)=0;
};
class IKdbSettings{

@ -247,10 +247,16 @@ void Kdb3Database::parseCustomIconsMetaStreamV3(const QByteArray& dta){
}
void Kdb3Database::parseGroupTreeStateMetaStream(const QByteArray& dta){
if(dta.size()<4){qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error."); return;}
if(dta.size()<4){
qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error.");
return;
}
quint32 Num;
memcpyFromLEnd32(&Num,dta.data());
if(Num*5!=dta.size()-4){qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error."); return;}
if(Num*5!=dta.size()-4){
qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error.");
return;
}
TreeStateMetaStream.clear();
for(int i=0;i<Num;i++){
quint32 GroupID;
@ -1002,14 +1008,17 @@ QList<IGroupHandle*> Kdb3Database::groups(){
quint32 Kdb3Database::getNewGroupId(){
quint32 id;
bool used;
while(1){
do{
used=false;
randomize(&id,4);
if(!id)continue; //group IDs must not be 0
for(int j=0;j<Groups.size();j++){
if(Groups[j].Id==id)used=true;}
if(used==false)break;
}
if(Groups[j].Id==id){
used=true;
break;
}
}
} while(used);
return id;
}
@ -1027,6 +1036,10 @@ IGroupHandle* Kdb3Database::addGroup(const CGroup* group,IGroupHandle* ParentHan
else{
Groups.back().Parent=&RootGroup;
Groups.back().Index=RootGroup.Children.size();
if (group->Title!="Backup" && RootGroup.Children.size() && RootGroup.Children.last()->Title=="Backup"){
RootGroup.Children.last()->Index = Groups.back().Index;
Groups.back().Index--;
}
Groups.back().Parent->Children.append(&Groups.back());
}
return &GroupHandles.back();
@ -1256,7 +1269,7 @@ bool Kdb3Database::save(){
}
if(!File->isOpen()){
if(!File->open(QIODevice::ReadWrite)){
error= tr("Could not open file for writing.");
error = tr("Could not open file for writing.");
return false;
}
}
@ -1376,14 +1389,16 @@ bool Kdb3Database::save(){
delete [] buffer;
return false;
}
if(!File->resize(EncryptedPartSize+DB_HEADER_SIZE)){
int size = EncryptedPartSize+DB_HEADER_SIZE;
if(!File->resize(size)){
delete [] buffer;
error=decodeFileError(File->error());
return false;
}
File->seek(0);
if(File->write(buffer,EncryptedPartSize+DB_HEADER_SIZE)!=EncryptedPartSize+DB_HEADER_SIZE){
if(File->write(buffer,size)!=size){
delete [] buffer;
error=decodeFileError(File->error());
return false;
@ -1824,34 +1839,6 @@ bool Kdb3Database::changeFile(const QString& filename){
return true;
}
void Kdb3Database::moveToTrash(IEntryHandle* entry){
TrashEntry trash=*((TrashEntry*)dynamic_cast<EntryHandle*>(entry)->Entry);
IGroupHandle* CurGroup=entry->group();
while(CurGroup){
trash.GroupPath << CurGroup->title();
CurGroup=CurGroup->parent();
}
deleteEntry(entry);
trash.Group=NULL;
TrashEntries.append(trash);
TrashHandles.append(EntryHandle(this));
TrashHandles.back().Entry=&TrashEntries.back();
TrashEntries.back().Handle=&TrashHandles.back();
}
void Kdb3Database::emptyTrash(){
TrashEntries.clear();
TrashHandles.clear();
}
QList<IEntryHandle*> Kdb3Database::trashEntries(){
QList<IEntryHandle*> handles;
for(int i=0; i<TrashHandles.size();i++)
if(TrashHandles[i].isValid())
handles << &TrashHandles[i];
return handles;
}
void Kdb3Database::generateMasterKey(){
randomize(TransfRandomSeed,32);
RawMasterKey.unlock();
@ -1861,6 +1848,34 @@ void Kdb3Database::generateMasterKey(){
MasterKey.lock();
}
/*void Kdb3Database::copyTree(Kdb3Database* db, GroupHandle* orgGroup, IGroupHandle* parent) {
IGroupHandle* newParent = db->addGroup(orgGroup->Group, parent);
QList<IEntryHandle*> entryList = entries(orgGroup);
for (int i=0; i<entryList.size(); i++) {
EntryHandle* entry = static_cast<EntryHandle*>(entryList[i]);
db->addEntry(entry->Entry, newParent);
}
QList<IGroupHandle*> children = orgGroup->children();
for (int i=0; i<children.size(); i++) {
GroupHandle* child = static_cast<GroupHandle*>(children[i]);
copyTree(db, child, newParent);
}
}
IDatabase* Kdb3Database::groupToNewDb(IGroupHandle* group){
Kdb3Database* db = new Kdb3Database();
db->create();
copyTree(db, static_cast<GroupHandle*>(group), NULL);
db->changeFile("/ramtmp/test.kdb");
if (!db->save())
qWarning("%s", CSTR(db->error));
return db;
}*/
void KeyTransform::transform(quint8* src, quint8* dst, quint8* KeySeed, int rounds){
KeyTransform* ktLeft = new KeyTransform(&src[0], &dst[0], KeySeed, rounds);
@ -1896,9 +1911,8 @@ int KeyTransformBenchmark::benchmark(int pMSecs){
KeyTransformBenchmark* ktbRight = new KeyTransformBenchmark(pMSecs);
ktbLeft->start();
ktbRight->start();
while (ktbLeft->isRunning() || ktbRight->isRunning()){
QThread::msleep(100);
}
ktbLeft->wait();
ktbRight->wait();
int num = ktbLeft->rounds + ktbRight->rounds;
delete ktbLeft;
delete ktbRight;

@ -133,11 +133,6 @@ public:
QList<StdEntry*> Entries;
};
class TrashEntry: public StdEntry{
public:
QStringList GroupPath;
};
Kdb3Database();
virtual ~Kdb3Database(){};
virtual bool load(QString identifier);
@ -150,7 +145,7 @@ public:
virtual bool isKeyError();
virtual void cleanUpHandles();
virtual QPixmap& icon(int index);
virtual int numIcons();
virtual int numIcons();
virtual void addIcon(const QPixmap& icon);
virtual void removeIcon(int index);
virtual void replaceIcon(int index,const QPixmap& icon);
@ -178,9 +173,6 @@ public:
virtual IEntryHandle* addEntry(const CEntry* NewEntry, IGroupHandle* group);
virtual void moveEntry(IEntryHandle* entry, IGroupHandle* group);
virtual void deleteLastEntry();
virtual void moveToTrash(IEntryHandle* entry);
virtual QList<IEntryHandle*> trashEntries();
virtual void emptyTrash();
virtual QList<IGroupHandle*> groups();
@ -192,8 +184,7 @@ public:
virtual bool isParent(IGroupHandle* parent, IGroupHandle* child);
virtual void generateMasterKey();
//virtual IDatabase* groupToNewDb(IGroupHandle* group);
private:
QDateTime dateFromPackedStruct5(const unsigned char* pBytes);
@ -220,6 +211,7 @@ private:
void getEntriesRecursive(IGroupHandle* Group, QList<IEntryHandle*>& EntryList);
void rebuildIndices(QList<StdGroup*>& list);
void restoreGroupTreeState();
//void copyTree(Kdb3Database* db, GroupHandle* orgGroup, IGroupHandle* parent);
StdEntry* getEntry(const KpxUuid& uuid);
StdEntry* getEntry(EntryHandle* handle);
@ -231,10 +223,8 @@ private:
QList<EntryHandle> EntryHandles;
QList<GroupHandle> GroupHandles;
QList<EntryHandle> TrashHandles;
QList<StdEntry> Entries;
QList<StdGroup> Groups;
QList<TrashEntry> TrashEntries;
StdGroup RootGroup;
QList<QPixmap>CustomIcons;
QFile* File;

@ -365,7 +365,7 @@
* This default definition of SWAP works, but on many platforms there is a
* more efficient implementation.
*/
#define BSWAP(x) (ROL32((x),8)&0x00ff00ff | ROR32((x),8) & 0xff00ff00)
#define BSWAP(x) ( (ROL32((x),8) & 0x00ff00ff) | (ROR32((x),8) & 0xff00ff00) )
/*

@ -92,7 +92,7 @@ void AutoTypeDlg::resizeEvent(QResizeEvent* event){
bool AutoTypeDlg::event(QEvent* event){
if (!EventOccurred){
int t = event->type();
if ( t>=QEvent::MouseButtonPress&&t<=QEvent::KeyRelease || t>=QEvent::HoverEnter&&t<=QEvent::HoverMove )
if ( (t>=QEvent::MouseButtonPress && t<=QEvent::KeyRelease) || (t>=QEvent::HoverEnter && t<=QEvent::HoverMove) )
EventOccurred = true;
}
return QWidget::event(event);
@ -100,6 +100,5 @@ bool AutoTypeDlg::event(QEvent* event){
void AutoTypeDlg::itemSelected(QTreeWidgetItem* item){
close();
QString err;
AutoType::perform(itemToEntry[item].dbHandle, err, pWasLocked, itemToEntry[item].nr, pWasLocked);
autoType->perform(itemToEntry[item].dbHandle, pWasLocked, itemToEntry[item].nr, pWasLocked);
}

@ -60,8 +60,9 @@ void CSelectIconDlg::OnAddIcon(){
QPixmap icon;
if(!icon.load(filenames[i])){
errors+=tr("%1: File could not be loaded.").arg(filenames[i].section("/",-1)).append("\n");
continue;}
dynamic_cast<ICustomIcons*>(db)->addIcon(icon.scaled(16,16,Qt::KeepAspectRatio,Qt::SmoothTransformation));
continue;
}
dynamic_cast<ICustomIcons*>(db)->addIcon(icon.scaled(16,16,Qt::KeepAspectRatio,Qt::SmoothTransformation));
}
if(errors.size())
QMessageBox::warning(this,tr("Error"),tr("An error occured while loading the icon(s):").append("\n").append(errors));

@ -72,7 +72,7 @@ CSettingsDlg::CSettingsDlg(QWidget* parent):QDialog(parent,Qt::Dialog)
#endif
#ifdef GLOBAL_AUTOTYPE
pShortcut = AutoType::shortcut;
pShortcut = autoType->getShortcut();
connect(this,SIGNAL(rejected()),SLOT(resetGlobalShortcut()));
#endif
@ -417,7 +417,7 @@ void CSettingsDlg::OnSelectLanguage(int index){
#ifdef GLOBAL_AUTOTYPE
void CSettingsDlg::resetGlobalShortcut(){
AutoType::unregisterGlobalShortcut();
AutoType::registerGlobalShortcut(pShortcut);
autoType->unregisterGlobalShortcut();
autoType->registerGlobalShortcut(pShortcut);
}
#endif

@ -22,7 +22,7 @@
TargetWindowDlg::TargetWindowDlg(QWidget* parent) : QDialog(parent){
setupUi(this);
QStringList windowTitles = AutoType::getAllWindowTitles();
QStringList windowTitles = autoType->getAllWindowTitles();
windowTitles.sort();
for (QStringList::const_iterator i = windowTitles.constBegin(); i != windowTitles.constEnd(); ++i)
comboWindow->addItem(*i);

@ -23,7 +23,7 @@
#include "dialogs/SimplePasswordDlg.h"
QFile* ExporterBase::openFile(QWidget* parent, QString id, QStringList Filters){
QString filename=KpxFileDialogs::saveFile(parent,id,tr("Import File..."),Filters);
QString filename=KpxFileDialogs::saveFile(parent,id,tr("Export File..."),Filters);
if(filename.isEmpty())return NULL;
QFile* file=new QFile(filename);
if(!file->open(QIODevice::ReadWrite|QIODevice::Truncate)){

@ -34,7 +34,7 @@ bool Import_KWalletXml::importDatabase(QWidget* GuiParent, IDatabase* db){
int col,line;
if(!doc.setContent(QString::fromUtf8((char*)buffer,len),false,&xmlerr,&line,&col)){
qWarning("Import_PwManager::parseXmlContent():\n");
qWarning(((xmlerr+" (Line:%1 Column:%2)").arg(line).arg(col)+QString('\n')).toAscii());
qWarning("%s (Line:%d Column:%d)\n",CSTR(xmlerr), line, col);
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details)."));
delete [] buffer;
return false;}

@ -45,7 +45,7 @@ bool Import_KeePassX_Xml::importDatabase(QWidget* Parent, IDatabase* database){
QStringList GroupNames;
for(int i=0;i<TopLevelGroupNodes.count();i++){
if(TopLevelGroupNodes.at(i).toElement().tagName()!="group"){
qWarning("Import_KeePassX_Xml: Error: Unknow tag '%s'",TopLevelGroupNodes.at(i).toElement().tagName().toUtf8().constData());
qWarning("Import_KeePassX_Xml: Error: Unknow tag '%s'",CSTR(TopLevelGroupNodes.at(i).toElement().tagName()));
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Parsing error: File is no valid KeePassX XML file."));
return false;
}

@ -116,8 +116,9 @@ bool Import_PwManager::parseXmlContent(char* content){
int col,line;
if(!db.setContent(QString::fromUtf8(content,strlen(content)-1),false,&err,&line,&col)){
qWarning("Import_PwManager::parseXmlContent():\n");
qWarning(((err+" (Line:%1 Column:%2)").arg(line).arg(col)+QString('\n')).toAscii());
return false;}
qWarning("%s (Line:%d Column:%d)\n", CSTR(err), line, col);
return false;
}
QDomElement root=db.documentElement();
if(root.tagName()!="P")return false;
//Achtung! Kommentare und Kategorien haben das selbe Tag "c"

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi, Felix Geyer *
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
@ -16,34 +16,42 @@
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
***************************************************************************/
#ifndef _AUTOTYPE_H_
#define _AUTOTYPE_H_
class KeepassMainWindow;
void initAutoType(KeepassMainWindow* mainWin);
class AutoType{
public:
virtual void perform(IEntryHandle* entry, bool hideWindow=true, int nr=0, bool wasLocked=false) = 0;
};
#ifdef GLOBAL_AUTOTYPE
struct Shortcut{
bool ctrl, shift, alt, altgr, win;
quint32 key;
};
#endif
#ifdef AUTOTYPE
class KeepassMainWindow;
class AutoType{
class AutoTypeGlobal : public AutoType{
public:
static KeepassMainWindow* MainWin;
static void perform(IEntryHandle* entry, QString& err,bool hideWindow=true,int nr=0,bool wasLocked=false);
#ifdef GLOBAL_AUTOTYPE
static Shortcut shortcut;
static void performGlobal();
static bool registerGlobalShortcut(const Shortcut& s);
static void unregisterGlobalShortcut();
static void init();
static QStringList getAllWindowTitles();
#endif // GLOBAL_AUTOTYPE
virtual void performGlobal() = 0;
inline const Shortcut& getShortcut() { return shortcut; };
virtual bool registerGlobalShortcut(const Shortcut& s) = 0;
virtual void unregisterGlobalShortcut() = 0;
virtual QStringList getAllWindowTitles() = 0;
protected:
Shortcut shortcut;
};
#endif // AUTOTYPE
#endif
#ifdef GLOBAL_AUTOTYPE
extern AutoTypeGlobal* autoType;
#else
extern AutoType* autoType;
#endif
#endif

@ -0,0 +1,267 @@
/***************************************************************************
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "AutoTypeGlobalX11.h"
#include "mainwindow.h"
#include "lib/HelperX11.h"
#include "dialogs/AutoTypeDlg.h"
#include <QX11Info>
AutoTypeGlobal* autoType = NULL;
void initAutoType(KeepassMainWindow* mainWin) {
autoType = new AutoTypeGlobalX11(mainWin);
}
AutoTypeGlobalX11::AutoTypeGlobalX11(KeepassMainWindow* mainWin) : AutoTypeX11(mainWin) {
wm_state = XInternAtom(dpy, "WM_STATE", true);
windowRoot = XRootWindow(dpy, mainWin->x11Info().screen());
focusedWindow = NULL;
//windowBlacklist << "kicker" << "KDE Desktop";
classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
classBlacklist << "kdesktop" << "kicker"; // KDE 3
classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
}
void AutoTypeGlobalX11::perform(IEntryHandle* entry, bool hideWindow, int nr, bool wasLocked){
if (focusedWindow && (!hideWindow || wasLocked)) { // detect if global auto-type
XSetInputFocus(dpy, focusedWindow, RevertToPointerRoot, CurrentTime);
focusedWindow = NULL;
}
AutoTypeX11::perform(entry, hideWindow, nr, wasLocked);
}
void AutoTypeGlobalX11::windowTitles(Window window, QStringList& titleList){
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char* data;
XGetWindowProperty(dpy, window, wm_state, 0, 0, false, AnyPropertyType, &type, &format, &nitems, &after, &data);
if (type){
XTextProperty textProp;
if (XGetWMName(dpy, window, &textProp) != 0) {
char** list = NULL;
int count;
if (Xutf8TextPropertyToTextList(dpy, &textProp, &list, &count)>=0 && list){
QString title = QString::fromUtf8(list[0]);
QString className;
XClassHint* wmClass = XAllocClassHint();
if (XGetClassHint(dpy, window, wmClass)!=0 && wmClass->res_name!=NULL)
className = QString::fromLocal8Bit(wmClass->res_name);
XFree(wmClass);
if (window!=windowRoot && window!=mainWin->winId() &&
(QApplication::activeWindow()==NULL || window!=QApplication::activeWindow()->winId()) &&
// !windowBlacklist.contains(title) &&
(className.isNull() || !classBlacklist.contains(className))
){
titleList.append(title);
}
XFreeStringList(list);
}
}
}
Window root;
Window parent;
Window* children = NULL;
unsigned int num_children;
int tree = XQueryTree(dpy, window, &root, &parent, &children, &num_children);
if (tree && children){
for (int i=0; i<num_children; i++)
windowTitles(children[i], titleList);
}
else
XFree(children);
}
QStringList AutoTypeGlobalX11::getAllWindowTitles(){
QStringList titleList;
if (wm_state) // don't do anything if WM_STATE doesn't exist
windowTitles(windowRoot, titleList);
return titleList;
}
void AutoTypeGlobalX11::performGlobal(){
bool wasLocked = mainWin->isLocked();
if (wasLocked)
mainWin->OnUnLockWorkspace();
if (!mainWin->isOpened())
return;
Window w;
int revert_to_return;
XGetInputFocus(dpy, &w, &revert_to_return);
char** list = NULL;
int tree;
do {
XTextProperty textProp;
if (XGetWMName(dpy, w, &textProp) != 0) {
int count;
if (Xutf8TextPropertyToTextList(dpy, &textProp, &list, &count)<0) return;
if (list) break;
}
Window root = 0;
Window parent = 0;
Window* children = NULL;
unsigned int num_children;
tree = XQueryTree(dpy, w, &root, &parent, &children, &num_children);
w = parent;
if (children) XFree(children);
} while (tree && w);
if (!list) return;
QString title = QString::fromUtf8(list[0]).toLower();
XFreeStringList(list);
QList<IEntryHandle*> validEntries;
QList<int> entryNumbers;
QList<IEntryHandle*> entries = mainWin->db->entries();
QRegExp lineMatch("Auto-Type-Window(?:-(\\d+)|):([^\\n]+)", Qt::CaseInsensitive, QRegExp::RegExp2);
QDateTime now = QDateTime::currentDateTime();
for (int i=0; i<entries.size(); i++){
if ( (entries[i]->expire()!=Date_Never && entries[i]->expire()<now) ||
(getRootGroupName(entries[i]).compare("backup",Qt::CaseInsensitive)==0)
){
continue;
}
bool hasWindowEntry=false;
QString comment = entries[i]->comment();
int offset = 0;
while ( (offset=lineMatch.indexIn(comment, offset))!=-1 ){
QStringList captured = lineMatch.capturedTexts();
offset += captured[0].length();
int nr;
QString entryWindow;
bool valid;
if (captured.size()==2){
nr = 0;
entryWindow = captured[1].trimmed().toLower();
}
else{
nr = captured[1].toInt();
entryWindow = captured[2].trimmed().toLower();
}
if (entryWindow.length()==0) continue;
hasWindowEntry = true;
bool wildStart = (entryWindow[0]=='*');
bool wildEnd = (entryWindow[entryWindow.size()-1]=='*');
if (wildStart&&wildEnd){
entryWindow.remove(0,1);
if (entryWindow.length()!=0){
entryWindow.remove(entryWindow.size()-1,1);
valid = title.contains(entryWindow);
}
else
valid = true;
}
else if (wildStart){
entryWindow.remove(0,1);
valid = title.endsWith(entryWindow);
}
else if (wildEnd){
entryWindow.remove(entryWindow.size()-1,1);
valid = title.startsWith(entryWindow);
}
else {
valid = (title==entryWindow);
}
if (valid){
validEntries << entries[i];
entryNumbers << nr;
break;
}
}
if (!hasWindowEntry && config->entryTitlesMatch()){
QString entryTitle = entries[i]->title().toLower();
if (!entryTitle.isEmpty() && title.contains(entryTitle)){
validEntries << entries[i];
entryNumbers << 0;
}
}
}
if (validEntries.size()==1){
focusedWindow = NULL;
perform(validEntries[0],wasLocked,entryNumbers[0],wasLocked);
}
else if (validEntries.size()>1){
focusedWindow = w;
AutoTypeDlg* dlg = new AutoTypeDlg(validEntries, entryNumbers, wasLocked);
dlg->show();
}
}
bool AutoTypeGlobalX11::registerGlobalShortcut(const Shortcut& s){
if (s.key==shortcut.key && s.ctrl==shortcut.ctrl && s.shift==shortcut.shift && s.alt==shortcut.alt && s.altgr==shortcut.altgr && s.win==shortcut.win)
return true;
int code=XKeysymToKeycode(dpy, HelperX11::getKeysym(s.key));
int mod=HelperX11::getShortcutModifierMask(s);
HelperX11::startCatchErrors();
XGrabKey(dpy, code, mod, windowRoot, true, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, mod | Mod2Mask, windowRoot, true, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, mod | LockMask, windowRoot, true, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, mod | Mod2Mask | LockMask, windowRoot, true, GrabModeAsync, GrabModeAsync);
HelperX11::stopCatchErrors();
if (HelperX11::errorOccurred()){
XUngrabKey(dpy, code, mod, windowRoot);
XUngrabKey(dpy, code, mod | Mod2Mask, windowRoot);
XUngrabKey(dpy, code, mod | LockMask, windowRoot);
XUngrabKey(dpy, code, mod | Mod2Mask | LockMask, windowRoot);
return false;
}
else {
unregisterGlobalShortcut();
shortcut = s;
return true;
}
}
void AutoTypeGlobalX11::unregisterGlobalShortcut(){
if (shortcut.key==0) return;
int code=XKeysymToKeycode(dpy, HelperX11::getKeysym(shortcut.key));
int mod=HelperX11::getShortcutModifierMask(shortcut);
XUngrabKey(dpy, code, mod, windowRoot);
XUngrabKey(dpy, code, mod | Mod2Mask, windowRoot);
XUngrabKey(dpy, code, mod | LockMask, windowRoot);
XUngrabKey(dpy, code, mod | Mod2Mask | LockMask, windowRoot);
shortcut.key = 0;
}
QString AutoTypeGlobalX11::getRootGroupName(IEntryHandle* entry){
IGroupHandle* group = entry->group();
int level = group->level();
for (int i=0; i<level; i++)
group = group->parent();
return group->title();
}

@ -0,0 +1,46 @@
/***************************************************************************
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef _AUTOTYPEGLOBALX11_H_
#define _AUTOTYPEGLOBALX11_H_
#include "AutoTypeX11.h"
class AutoTypeGlobalX11 : public AutoTypeX11, public AutoTypeGlobal {
public:
AutoTypeGlobalX11(KeepassMainWindow* mainWin);
void perform(IEntryHandle* entry, bool hideWindow=true, int nr=0, bool wasLocked=false);
void performGlobal();
bool registerGlobalShortcut(const Shortcut& s);
void unregisterGlobalShortcut();
QStringList getAllWindowTitles();
private:
void windowTitles(Window window, QStringList& titleList);
QString getRootGroupName(IEntryHandle* entry);
Window windowRoot;
//QSet<QString> windowBlacklist;
QSet<QString> classBlacklist;
Atom wm_state;
Window focusedWindow;
};
#endif // _AUTOTYPEGLOBALX11_H_

@ -0,0 +1,866 @@
/***************************************************************************
* Copyright (C) 2005-2008 by Tarek Saidi, Felix Geyer *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "AutoTypeX11.h"
#include "mainwindow.h"
#include "lib/HelperX11.h"
#include <QX11Info>
#ifndef GLOBAL_AUTOTYPE
AutoType* autoType = NULL;
void initAutoType(KeepassMainWindow* mainWin) {
autoType = new AutoTypeX11(mainWin);
}
#endif
AutoTypeAction::AutoTypeAction(AutoTypeActionType t, quint16 d) : type(t), data(d){
}
bool AutoTypeX11::error_detected = false;
AutoTypeX11::AutoTypeX11(KeepassMainWindow* mainWin) {
this->mainWin = mainWin;
dpy = mainWin->x11Info().display();
keysym_table = NULL;
alt_mask = 0;
meta_mask = 0;
altgr_mask = 0;
altgr_keysym = NoSymbol;
focused_window = None;
focused_subwindow = None;
ReadKeymap();
if (!altgr_mask)
AddModifier(XK_Mode_switch);
}
void AutoTypeX11::perform(IEntryHandle* entry, bool hideWindow, int nr, bool wasLocked){
QString indexStr;
if (nr==0)
indexStr = "Auto-Type:";
else
indexStr = QString("Auto-Type-%1:").arg(nr);
QString str;
QString comment=entry->comment();
int c=comment.count(indexStr, Qt::CaseInsensitive);
if(c>1) {
qWarning("More than one 'Auto-Type:' key sequence found.\nAllowed is only one per entry.");
return;
}
else if (c==1) {
int start = comment.indexOf(indexStr,0,Qt::CaseInsensitive) + indexStr.length();
int end = comment.indexOf("\n", start);
if (end == -1)
end = comment.length();
str=comment.mid(start,end-start).trimmed();
if (str.isEmpty())
return;
}
else {
bool usernameEmpty = entry->username().trimmed().isEmpty();
SecString password=entry->password();
password.unlock();
bool passwordEmpty = password.string().trimmed().isEmpty();
if (usernameEmpty && passwordEmpty)
return;
else if (usernameEmpty)
str="{PASSWORD}{ENTER}";
else if (passwordEmpty)
str="{USERNAME}{ENTER}";
else
str="{USERNAME}{TAB}{PASSWORD}{ENTER}";
}
QList<AutoTypeAction> Keys;
for(int i=0;i<str.size();i++){
if(str[i]=='{'){
QString tmpl;
i++;
while(str[i]!='}' && i<str.size()){
tmpl += str[i];
i++;
}
if(i>=str.size()){
qWarning("Syntax Error in Auto-Type sequence near character %d\nFound '{' without closing '}'", i+10);
return;
}
templateToKeysyms(tmpl.toLower(),Keys,entry);
continue;
}
else{
Keys << AutoTypeAction(TypeKey, str[i].unicode());
}
}
if (hideWindow)
mainWin->hide();
QApplication::processEvents();
sleepTime(config->autoTypePreGap());
QString type;
for(int i=0;i<Keys.size();i++){
if (Keys[i].type==TypeKey){
SendKeyPressedEvent(Keys[i].data, 0);
sleepKeyStrokeDelay();
}
else if (Keys[i].type==Delay){
QApplication::processEvents();
sleepTime(Keys[i].data);
}
}
if (config->lockOnMinimize()){
if (hideWindow || wasLocked){
if ( !(config->showSysTrayIcon() && config->minimizeTray()) )
mainWin->showMinimized();
else
mainWin->OnUnLockWorkspace();
}
}
else{
if (hideWindow && !(config->showSysTrayIcon() && config->minimizeTray()) )
mainWin->showMinimized();
if (wasLocked)
mainWin->OnUnLockWorkspace();
}
}
void AutoTypeX11::sleepTime(int msec){
if (msec==0) return;
timespec timeOut, remains;
timeOut.tv_sec = msec/1000;
timeOut.tv_nsec = (msec%1000)*1000000;
nanosleep(&timeOut, &remains);
}
void AutoTypeX11::templateToKeysyms(const QString& tmpl, QList<AutoTypeAction>& keys,IEntryHandle* entry){
//tmpl must be lower case!!!
if(!tmpl.compare("title")){
stringToKeysyms(entry->title(),keys);
return;
}
if(!tmpl.compare("username")){
stringToKeysyms(entry->username(),keys);
return;
}
if(!tmpl.compare("url")){
stringToKeysyms(entry->url(),keys);
return;
}
if(!tmpl.compare("password")){
SecString password=entry->password();
password.unlock();
stringToKeysyms(password,keys);
return;
}
if(!tmpl.compare("space")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(' '));
return;
}
if(!tmpl.compare("backspace") || !tmpl.compare("bs") || !tmpl.compare("bksp")){
keys << AutoTypeAction(TypeKey, XK_BackSpace);
return;
}
if(!tmpl.compare("break")){
keys << AutoTypeAction(TypeKey, XK_Break);
return;
}
if(!tmpl.compare("capslock")){
keys << AutoTypeAction(TypeKey, XK_Caps_Lock);
return;
}
if(!tmpl.compare("del") || !tmpl.compare("delete")){
keys << AutoTypeAction(TypeKey, XK_Delete);
return;
}
if(!tmpl.compare("end")){
keys << AutoTypeAction(TypeKey, XK_End);
return;
}
if(!tmpl.compare("enter")){
keys << AutoTypeAction(TypeKey, XK_Return);
return;
}
if(!tmpl.compare("esc")){
keys << AutoTypeAction(TypeKey, XK_Escape);
return;
}
if(!tmpl.compare("help")){
keys << AutoTypeAction(TypeKey, XK_Help);
return;
}
if(!tmpl.compare("home")){
keys << AutoTypeAction(TypeKey, XK_Home);
return;
}
if(!tmpl.compare("insert") || !tmpl.compare("ins")){
keys << AutoTypeAction(TypeKey, XK_Insert);
return;
}
if(!tmpl.compare("numlock")){
keys << AutoTypeAction(TypeKey, XK_Num_Lock);
return;
}
if(!tmpl.compare("scroll")){
keys << AutoTypeAction(TypeKey, XK_Scroll_Lock);
return;
}
if(!tmpl.compare("pgdn")){
keys << AutoTypeAction(TypeKey, XK_Page_Down);
return;
}
if(!tmpl.compare("pgup")){
keys << AutoTypeAction(TypeKey, XK_Page_Up);
return;
}
if(!tmpl.compare("prtsc")){
keys << AutoTypeAction(TypeKey, XK_3270_PrintScreen);
return;
}
if(!tmpl.compare("up")){
keys << AutoTypeAction(TypeKey, XK_Up);
return;
}
if(!tmpl.compare("down")){
keys << AutoTypeAction(TypeKey, XK_Down);
return;
}
if(!tmpl.compare("left")){
keys << AutoTypeAction(TypeKey, XK_Left);
return;
}
if(!tmpl.compare("right")){
keys << AutoTypeAction(TypeKey, XK_Right);
return;
}
if(!tmpl.compare("f1")){
keys << AutoTypeAction(TypeKey, XK_F1);
return;
}
if(!tmpl.compare("f2")){
keys << AutoTypeAction(TypeKey, XK_F2);
return;
}
if(!tmpl.compare("f3")){
keys << AutoTypeAction(TypeKey, XK_F3);
return;
}
if(!tmpl.compare("f4")){
keys << AutoTypeAction(TypeKey, XK_F4);
return;
}
if(!tmpl.compare("f5")){
keys << AutoTypeAction(TypeKey, XK_F5);
return;
}
if(!tmpl.compare("f6")){
keys << AutoTypeAction(TypeKey, XK_F6);
return;
}
if(!tmpl.compare("f7")){
keys << AutoTypeAction(TypeKey, XK_F7);
return;
}
if(!tmpl.compare("f8")){
keys << AutoTypeAction(TypeKey, XK_F8);
return;
}
if(!tmpl.compare("f9")){
keys << AutoTypeAction(TypeKey, XK_F9);
return;
}
if(!tmpl.compare("f10")){
keys << AutoTypeAction(TypeKey, XK_F10);
return;
}
if(!tmpl.compare("f11")){
keys << AutoTypeAction(TypeKey, XK_F11);
return;
}
if(!tmpl.compare("f12")){
keys << AutoTypeAction(TypeKey, XK_F12);
return;
}
if(!tmpl.compare("f13")){
keys << AutoTypeAction(TypeKey, XK_F13);
return;
}
if(!tmpl.compare("f14")){
keys << AutoTypeAction(TypeKey, XK_F14);
return;
}
if(!tmpl.compare("f15")){
keys << AutoTypeAction(TypeKey, XK_F15);
return;
}
if(!tmpl.compare("f16")){
keys << AutoTypeAction(TypeKey, XK_F16);
return;
}
if(!tmpl.compare("add") || !tmpl.compare("plus")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('+'));
return;
}
if(!tmpl.compare("subtract")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('-'));
return;
}
if(!tmpl.compare("multiply")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('+'));
return;
}
if(!tmpl.compare("divide")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('/'));
return;
}
if(!tmpl.compare("at")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('@'));
return;
}
if(!tmpl.compare("percent")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('%'));
return;
}
if(!tmpl.compare("caret")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('^'));
return;
}
if(!tmpl.compare("tilde")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('~'));
return;
}
if(!tmpl.compare("leftbrace")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('{'));
return;
}
if(!tmpl.compare("rightbrace")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('}'));
return;
}
if(!tmpl.compare("leftparen")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym('('));
return;
}
if(!tmpl.compare("rightparen")){
keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(')'));
return;
}
if(!tmpl.compare("winl")){
keys << AutoTypeAction(TypeKey, XK_Super_L);
return;