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 15 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;
}
if(!tmpl.compare("winr")){
keys << AutoTypeAction(TypeKey, XK_Super_R);
return;
}
if(!tmpl.compare("win")){
keys << AutoTypeAction(TypeKey, XK_Super_L);
return;
}
if(!tmpl.compare("tab")){
keys << AutoTypeAction(TypeKey, XK_Tab);
return;
}
if(tmpl.startsWith("delay ") && tmpl.length()>6){
bool ok;
quint16 delay = tmpl.right(tmpl.length()-6).toInt(&ok);
if (ok && delay>0 && delay<=10000)
keys << AutoTypeAction(Delay, delay);
}
}
void AutoTypeX11::stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList){
for(int i=0; i<string.length();i++)
KeySymList << AutoTypeAction(TypeKey, HelperX11::getKeysym(string[i]));
}
// ----------------------------------------------------------------------
// The following code is taken from xvkbd and has been slightly modified.
// ----------------------------------------------------------------------
/*
* xvkbd - Virtual Keyboard for X Window System
* (Version 3.0, 2008-05-05)
*
* Copyright (C) 2000-2008 by Tom Sato <VEF00200@nifty.ne.jp>
* http://homepage3.nifty.com/tsato/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
/*
* Insert a specified keysym to unused position in the keymap table.
* This will be called to add required keysyms on-the-fly.
* if the second parameter is TRUE, the keysym will be added to the
* non-shifted position - this may be required for modifier keys
* (e.g. Mode_switch) and some special keys (e.g. F20).
*/
int AutoTypeX11::AddKeysym(KeySym keysym, bool top)
{
int keycode, pos, max_pos, inx, phase;
if (top) {
max_pos = 0;
} else {
max_pos = keysym_per_keycode - 1;
if (4 <= max_pos) max_pos = 3;
if (2 <= max_pos && altgr_keysym != XK_Mode_switch) max_pos = 1;
}
for (phase = 0; phase < 2; phase++) {
for (keycode = max_keycode; min_keycode <= keycode; keycode--) {
for (pos = max_pos; 0 <= pos; pos--) {
inx = (keycode - min_keycode) * keysym_per_keycode;
if ((phase != 0 || keysym_table[inx] == NoSymbol) && keysym_table[inx] < 0xFF00) {
/* In the first phase, to avoid modifing existing keys, */
/* add the keysym only to the keys which has no keysym in the first position. */
/* If no place fuond in the first phase, add the keysym for any keys except */
/* for modifier keys and other special keys */
if (keysym_table[inx + pos] == NoSymbol) {
keysym_table[inx + pos] = keysym;
XChangeKeyboardMapping(dpy, keycode, keysym_per_keycode, &keysym_table[inx], 1);
XFlush(dpy);
return keycode;
}
}
}
}
}
qWarning("Couldn't add \"%s\" to keymap", XKeysymToString(keysym));
return NoSymbol;
}
/*
* Add the specified key as a new modifier.
* This is used to use Mode_switch (AltGr) as a modifier.
*/
void AutoTypeX11::AddModifier(KeySym keysym)
{
XModifierKeymap *modifiers;
int keycode, i, pos;
keycode = XKeysymToKeycode(dpy, keysym);
if (keycode == NoSymbol) keycode = AddKeysym(keysym, TRUE);
modifiers = XGetModifierMapping(dpy);
for (i = 7; 3 < i; i--) {
if (modifiers->modifiermap[i * modifiers->max_keypermod] == NoSymbol
|| ((keysym_table[(modifiers->modifiermap[i * modifiers->max_keypermod]
- min_keycode) * keysym_per_keycode]) == XK_ISO_Level3_Shift
&& keysym == XK_Mode_switch))
{
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
if (modifiers->modifiermap[i * modifiers->max_keypermod + pos] == NoSymbol) {
modifiers->modifiermap[i * modifiers->max_keypermod + pos] = keycode;
XSetModifierMapping(dpy, modifiers);
return;
}
}
}
}
qWarning("Couldn't add \"%s\" as modifier", XKeysymToString(keysym));
}
/*
* Read keyboard mapping and modifier mapping.
* Keyboard mapping is used to know what keys are in shifted position.
* Modifier mapping is required because we should know Alt and Meta
* key are used as which modifier.
*/
void AutoTypeX11::ReadKeymap()
{
int i;
int keycode, inx, pos;
KeySym keysym;
XModifierKeymap *modifiers;
int last_altgr_mask;
XDisplayKeycodes(dpy, &min_keycode, &max_keycode);
if (keysym_table != NULL) XFree(keysym_table);
keysym_table = XGetKeyboardMapping(dpy,
min_keycode, max_keycode - min_keycode + 1,
&keysym_per_keycode);
for (keycode = min_keycode; keycode <= max_keycode; keycode++) {
/* if the first keysym is alphabet and the second keysym is NoSymbol,
it is equivalent to pair of lowercase and uppercase alphabet */
inx = (keycode - min_keycode) * keysym_per_keycode;
if (keysym_table[inx + 1] == NoSymbol
&& ((XK_A <= keysym_table[inx] && keysym_table[inx] <= XK_Z)
|| (XK_a <= keysym_table[inx] && keysym_table[inx] <= XK_z)))
{
if (XK_A <= keysym_table[inx] && keysym_table[inx] <= XK_Z)
keysym_table[inx] = keysym_table[inx] - XK_A + XK_a;
keysym_table[inx + 1] = keysym_table[inx] - XK_a + XK_A;
}
}
last_altgr_mask = altgr_mask;
alt_mask = 0;
meta_mask = 0;
altgr_mask = 0;
altgr_keysym = NoSymbol;
modifiers = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++) {
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
keycode = modifiers->modifiermap[i * modifiers->max_keypermod + pos];
if (keycode < min_keycode || max_keycode < keycode) continue;
keysym = keysym_table[(keycode - min_keycode) * keysym_per_keycode];
if (keysym == XK_Alt_L || keysym == XK_Alt_R) {
alt_mask = 1 << i;
} else if (keysym == XK_Meta_L || keysym == XK_Meta_R) {
meta_mask = 1 << i;
} else if (keysym == XK_Mode_switch) {
if (altgr_keysym == XK_ISO_Level3_Shift) {
} else {
altgr_mask = 0x0101 << i;
/* I don't know why, but 0x2000 was required for mod3 on my Linux box */
altgr_keysym = keysym;
}
} else if (keysym == XK_ISO_Level3_Shift) {
/* if no Mode_switch, try to use ISO_Level3_Shift instead */
/* however, it may not work as intended - I don't know why */
altgr_mask = 1 << i;
altgr_keysym = keysym;
}
}
}
XFreeModifiermap(modifiers);
}
/*
* Send event to the focused window.
* If input focus is specified explicitly, select the window
* before send event to the window.
*/
void AutoTypeX11::SendEvent(XKeyEvent *event)
{
static bool first = TRUE;
XSync(event->display, FALSE);
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
error_detected = FALSE;
if (focused_window != None) {
/* set input focus if input focus is set explicitly */
XSetInputFocus(event->display, focused_window, RevertToParent, CurrentTime);
XSync(event->display, FALSE);
}
if (!error_detected) {
Window root, child, w;
int root_x, root_y, x, y;
unsigned int mask;
int revert_to;
w = None;
first = FALSE;
w = focused_subwindow;
if (w == None)
XGetInputFocus(event->display, &w, &revert_to);
if (w != None) {
XQueryPointer(event->display, w,
&root, &child, &root_x, &root_y, &x, &y, &mask);
XWarpPointer(event->display, None, w, 0, 0, 0, 0, 1, 1);
XFlush(event->display);
}
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
XFlush(event->display);
if (w != None) {
XWarpPointer(event->display, None, root, 0, 0, 0, 0, root_x, root_y);
XFlush(event->display);
}
} else {
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
XFlush(event->display);
}
if (error_detected) {
/* reset focus because focused window is (probably) no longer exist */
focused_window = None;
focused_subwindow = None;
}
XSetErrorHandler(oldHandler);
}
/*
* Send sequence of KeyPressed/KeyReleased events to the focused
* window to simulate keyboard. If modifiers (shift, control, etc)
* are set ON, many events will be sent.
*/
void AutoTypeX11::SendKeyPressedEvent(KeySym keysym, unsigned int shift)
{
Window cur_focus;
int revert_to;
XKeyEvent event;
int keycode;
int phase, inx;
bool found;
if (focused_subwindow != None)
cur_focus = focused_subwindow;
else
XGetInputFocus(dpy, &cur_focus, &revert_to);
found = FALSE;
keycode = 0;
if (keysym != NoSymbol) {
for (phase = 0; phase < 2; phase++) {
for (keycode = min_keycode; !found && (keycode <= max_keycode); keycode++) {
/* Determine keycode for the keysym: we use this instead
of XKeysymToKeycode() because we must know shift_state, too */
inx = (keycode - min_keycode) * keysym_per_keycode;
if (keysym_table[inx] == keysym) {
shift &= ~altgr_mask;
if (keysym_table[inx + 1] != NoSymbol) shift &= ~ShiftMask;
found = TRUE;
break;
} else if (keysym_table[inx + 1] == keysym) {
shift &= ~altgr_mask;
shift |= ShiftMask;
found = TRUE;
break;
}
}
if (!found && altgr_mask && 3 <= keysym_per_keycode) {
for (keycode = min_keycode; !found && (keycode <= max_keycode); keycode++) {
inx = (keycode - min_keycode) * keysym_per_keycode;
if (keysym_table[inx + 2] == keysym) {
shift &= ~ShiftMask;
shift |= altgr_mask;
found = TRUE;
break;
} else if (4 <= keysym_per_keycode && keysym_table[inx + 3] == keysym) {
shift |= ShiftMask | altgr_mask;
found = TRUE;
break;
}
}
}
if (found) break;
if (0xF000 <= keysym) {
/* for special keys such as function keys,
first try to add it in the non-shifted position of the keymap */
if (AddKeysym(keysym, TRUE) == NoSymbol) AddKeysym(keysym, FALSE);
} else {
AddKeysym(keysym, FALSE);
}
}
}
event.display = dpy;
event.window = cur_focus;
event.root = RootWindow(event.display, DefaultScreen(event.display));
event.subwindow = None;
event.time = CurrentTime;
event.x = 1;
event.y = 1;
event.x_root = 1;
event.y_root = 1;
event.same_screen = TRUE;
Window root, child;
int root_x, root_y, x, y;
unsigned int mask;
XQueryPointer(dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &mask);
event.type = KeyRelease;
event.state = 0;
if (mask & ControlMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Control_L);
SendEvent(&event);
}
if (mask & alt_mask) {
event.keycode = XKeysymToKeycode(dpy, XK_Alt_L);
SendEvent(&event);
}
if (mask & meta_mask) {
event.keycode = XKeysymToKeycode(dpy, XK_Meta_L);
SendEvent(&event);
}
if (mask & altgr_mask) {
event.keycode = XKeysymToKeycode(dpy, altgr_keysym);
SendEvent(&event);
}
if (mask & ShiftMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Shift_L);
SendEvent(&event);
}
if (mask & LockMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Caps_Lock);
SendEvent(&event);
}
event.type = KeyPress;
event.state = 0;
if (shift & ControlMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Control_L);
SendEvent(&event);
event.state |= ControlMask;
}
if (shift & alt_mask) {
event.keycode = XKeysymToKeycode(dpy, XK_Alt_L);
SendEvent(&event);
event.state |= alt_mask;
}
if (shift & meta_mask) {
event.keycode = XKeysymToKeycode(dpy, XK_Meta_L);
SendEvent(&event);
event.state |= meta_mask;
}
if (shift & altgr_mask) {
event.keycode = XKeysymToKeycode(dpy, altgr_keysym);
SendEvent(&event);
event.state |= altgr_mask;
}
if (shift & ShiftMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Shift_L);
SendEvent(&event);
event.state |= ShiftMask;
}
if (keysym != NoSymbol) { /* send event for the key itself */
event.keycode = found ? keycode : XKeysymToKeycode(dpy, keysym);
if (event.keycode == NoSymbol) {
if ((keysym & ~0x7f) == 0 && isprint(keysym))
qWarning("No such key: %c", (char)keysym);
else if (XKeysymToString(keysym) != NULL)
qWarning("No such key: keysym=%s (0x%lX)", XKeysymToString(keysym), (long)keysym);
else
qWarning("No such key: keysym=0x%lX", (long)keysym);
} else {
SendEvent(&event);
event.type = KeyRelease;
SendEvent(&event);
}
}
event.type = KeyRelease;
if (shift & ShiftMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Shift_L);
SendEvent(&event);
event.state &= ~ShiftMask;
}
if (shift & altgr_mask) {
event.keycode = XKeysymToKeycode(dpy, altgr_keysym);
SendEvent(&event);
event.state &= ~altgr_mask;
}
if (shift & meta_mask) {
event.keycode = XKeysymToKeycode(dpy, XK_Meta_L);
SendEvent(&event);
event.state &= ~meta_mask;
}
if (shift & alt_mask) {
event.keycode = XKeysymToKeycode(dpy, XK_Alt_L);
SendEvent(&event);
event.state &= ~alt_mask;
}
if (shift & ControlMask) {
event.keycode = XKeysymToKeycode(dpy, XK_Control_L);
SendEvent(&event);
event.state &= ~ControlMask;
}
}
int AutoTypeX11::MyErrorHandler(Display *my_dpy, XErrorEvent *event)
{
char msg[200];
error_detected = TRUE;
if (event->error_code == BadWindow) {
return 0;
}
XGetErrorText(my_dpy, event->error_code, msg, sizeof(msg) - 1);
qWarning("X error trapped: %s, request-code=%d\n", msg, event->request_code);
return 0;
}

@ -0,0 +1,71 @@
/***************************************************************************
* 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 _AUTOTYPEX11_H_
#define _AUTOTYPEX11_H_
#include "AutoType.h"
#include <X11/Xutil.h>
enum AutoTypeActionType{
TypeKey, Delay
};
struct AutoTypeAction{
AutoTypeAction(AutoTypeActionType t, quint16 d);
AutoTypeActionType type;
quint16 data;
};
class AutoTypeX11 : public AutoType {
public:
AutoTypeX11(KeepassMainWindow* mainWin);
void perform(IEntryHandle* entry, bool hideWindow=true, int nr=0, bool wasLocked=false);
protected:
void sleepTime(int msec);
inline void sleepKeyStrokeDelay(){ sleep(config->autoTypeKeyStrokeDelay()); };
void templateToKeysyms(const QString& Template, QList<AutoTypeAction>& KeySymList,IEntryHandle* entry);
void stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList);
int AddKeysym(KeySym keysym, bool top);
void AddModifier(KeySym keysym);
void ReadKeymap();
void SendKeyPressedEvent(KeySym keysym, unsigned int shift);
void SendEvent(XKeyEvent *event);
static int MyErrorHandler(Display *my_dpy, XErrorEvent *event);
KeepassMainWindow* mainWin;
Display* dpy;
KeySym *keysym_table;
int min_keycode, max_keycode;
int keysym_per_keycode;
static bool error_detected;
int alt_mask;
int meta_mask;
int altgr_mask;
KeySym altgr_keysym;
Window focused_window;
Window focused_subwindow;
};
#endif // _AUTOTYPEX11_H_

@ -1,665 +0,0 @@
/***************************************************************************
* Copyright (C) 2005-2006 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 <QX11Info>
#include <X11/Xutil.h>
#include "mainwindow.h"
#include "HelperX11.h"
#include "AutoType.h"
#ifdef GLOBAL_AUTOTYPE
#include "dialogs/AutoTypeDlg.h"
#endif
enum AutoTypeActionType{
TypeKey, Delay
};
struct AutoTypeAction{
AutoTypeAction(AutoTypeActionType t, quint16 d);
AutoTypeActionType type;
quint16 data;
};
class AutoTypePrivate{
public:
static void sleep(int msec);
inline static void sleepKeyStrokeDelay(){ sleep(config->autoTypeKeyStrokeDelay()); };
static void templateToKeysyms(const QString& Template, QList<AutoTypeAction>& KeySymList,IEntryHandle* entry);
static void stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList);
static QString getRootGroupName(IEntryHandle* entry);
};
// AutoType
KeepassMainWindow* AutoType::MainWin=NULL;
#ifdef GLOBAL_AUTOTYPE
Shortcut AutoType::shortcut;
#endif
void AutoType::perform(IEntryHandle* entry, QString& err,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){
err=QCoreApplication::translate("AutoType","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
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()){
err=QCoreApplication::translate("AutoType","Syntax Error in Auto-Type sequence near character %1\n\
Found '{' without closing '}'").arg(i+10);
return;
}
AutoTypePrivate::templateToKeysyms(tmpl.toLower(),Keys,entry);
continue;
}
else{
Keys << AutoTypeAction(TypeKey, HelperX11::getKeysym(str[i]));
}
}
if (hideWindow)
MainWin->hide();
AutoTypePrivate::sleep(config->autoTypePreGap());
Display* pDisplay = QX11Info::display();
bool capsEnabled = HelperX11::keyboardModifiers(pDisplay)&LockMask;
if (capsEnabled){
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),true,0);
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),false,0);
AutoTypePrivate::sleepKeyStrokeDelay();
}
char keys_return[32];
XQueryKeymap(pDisplay, keys_return);
for (int i=0; i<32; i++)
for (int j=0; j<8; j++)
if ( keys_return[i] & (1<<j) ){
XTestFakeKeyEvent(pDisplay,i*8+j,false,2);
AutoTypePrivate::sleepKeyStrokeDelay();
}
for(int i=0;i<Keys.size();i++){
if (Keys[i].type==TypeKey){
int keycode=XKeysymToKeycode(pDisplay,Keys[i].data);
if (keycode==0){
err = QCoreApplication::translate("AutoType","Auto-Type string contains invalid characters");
break;
}
int mods=HelperX11::getModifiers(pDisplay,Keys[i].data,keycode);
HelperX11::pressModifiers(pDisplay,mods);
AutoTypePrivate::sleepKeyStrokeDelay();
XTestFakeKeyEvent(pDisplay,keycode,True,0);
AutoTypePrivate::sleepKeyStrokeDelay();
XTestFakeKeyEvent(pDisplay,keycode,False,1);
AutoTypePrivate::sleepKeyStrokeDelay();
HelperX11::releaseModifiers(pDisplay,mods);
AutoTypePrivate::sleepKeyStrokeDelay();
}
else if (Keys[i].type==Delay){
QApplication::processEvents();
AutoTypePrivate::sleep(Keys[i].data);
}
}
if (capsEnabled){
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),true,0);
XTestFakeKeyEvent(pDisplay,XKeysymToKeycode(pDisplay,XK_Caps_Lock),false,0);
}
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();
}
}
#ifdef GLOBAL_AUTOTYPE
Window windowRoot;
//QSet<QString> windowBlacklist;
QSet<QString> classBlacklist;
Atom wm_state;
void windowTitles(Window window, QStringList& titleList){
Display* d = QX11Info::display();
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char* data;
XGetWindowProperty(d, window, wm_state, 0, 0, false, AnyPropertyType, &type, &format, &nitems, &after, &data);
if (type){
XTextProperty textProp;
if (XGetWMName(d, window, &textProp) != 0) {
char** list = NULL;
int count;
if (Xutf8TextPropertyToTextList(d, &textProp, &list, &count)>=0 && list){
QString title = QString::fromUtf8(list[0]);
QString className;
XClassHint* wmClass = XAllocClassHint();
if (XGetClassHint(d, window, wmClass)!=0 && wmClass->res_name!=NULL)
className = QString::fromLocal8Bit(wmClass->res_name);
XFree(wmClass);
if (window!=windowRoot && window!=AutoType::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(d, window, &root, &parent, &children, &num_children);
if (tree && children){
for (int i=0; i<num_children; i++)
windowTitles(children[i], titleList);
}
else
XFree(children);
}
void AutoType::init(){
Display* d = QX11Info::display();
wm_state = XInternAtom(d, "WM_STATE", true);
windowRoot = XRootWindow(d, MainWin->x11Info().screen());
//windowBlacklist << "kicker" << "KDE Desktop";
classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
classBlacklist << "kdesktop" << "kicker"; // KDE 3
classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
}
QStringList AutoType::getAllWindowTitles(){
QStringList titleList;
if (wm_state) // don't do anything if WM_STATE doesn't exist
windowTitles(windowRoot, titleList);
return titleList;
}
void AutoType::performGlobal(){
bool wasLocked = MainWin->isLocked();
if (wasLocked)
MainWin->OnUnLockWorkspace();
if (!MainWin->isOpened())
return;
Display* d = QX11Info::display();
Window w;
int revert_to_return;
XGetInputFocus(d, &w, &revert_to_return);
char** list = NULL;
int tree;
do {
XTextProperty textProp;
if (XGetWMName(d, w, &textProp) != 0) {
int count;
if (Xutf8TextPropertyToTextList(d, &textProp, &list, &count)<0) return;
if (list) break;
}
Window root = 0;
Window parent = 0;
Window* children = NULL;
unsigned int num_children;
tree = XQueryTree(d, 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) ||
(AutoTypePrivate::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){
QString err;
perform(validEntries[0],err,wasLocked,entryNumbers[0],wasLocked);
}
else if (validEntries.size()>1){
AutoTypeDlg* dlg = new AutoTypeDlg(validEntries, entryNumbers, wasLocked);
dlg->show();
}
}
bool AutoType::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;
Display* display = QX11Info::display();
Window root = XRootWindow(display, MainWin->x11Info().screen());
int code=XKeysymToKeycode(display, HelperX11::getKeysym(s.key));
int mod=HelperX11::getShortcutModifierMask(s);
HelperX11::startCatchErrors();
XGrabKey(display, code, mod, root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(display, code, mod | Mod2Mask, root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(display, code, mod | LockMask, root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(display, code, mod | Mod2Mask | LockMask, root, True, GrabModeAsync, GrabModeAsync);
HelperX11::stopCatchErrors();
if (HelperX11::errorOccurred()){
XUngrabKey(display, code, mod, root);
XUngrabKey(display, code, mod | Mod2Mask, root);
XUngrabKey(display, code, mod | LockMask, root);
XUngrabKey(display, code, mod | Mod2Mask | LockMask, root);
return false;
}
else {
unregisterGlobalShortcut();
shortcut = s;
return true;
}
}
void AutoType::unregisterGlobalShortcut(){
if (shortcut.key==0) return;
Display* display = QX11Info::display();
Window root = XDefaultRootWindow(display);
int code=XKeysymToKeycode(display, HelperX11::getKeysym(shortcut.key));
int mod=HelperX11::getShortcutModifierMask(shortcut);
XUngrabKey(display, code, mod, root);
XUngrabKey(display, code, mod | Mod2Mask, root);
XUngrabKey(display, code, mod | LockMask, root);
XUngrabKey(display, code, mod | Mod2Mask | LockMask, root);
shortcut.key = 0;
}
#endif // GLOBAL_AUTOTYPE
AutoTypeAction::AutoTypeAction(AutoTypeActionType t, quint16 d) : type(t), data(d){
}
// AutoTypePrivate
void AutoTypePrivate::sleep(int msec){
if (msec==0) return;
timespec timeOut, remains;
timeOut.tv_sec = msec/1000;
timeOut.tv_nsec = (msec%1000)*1000000;
nanosleep(&timeOut, &remains);
}
void AutoTypePrivate::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;}
if(!tmpl.compare("winr")){
keys << AutoTypeAction(TypeKey, XK_Super_R);
return;}
if(!tmpl.compare("win")){
keys << AutoTypeAction(TypeKey, XK_Super_L);
return;}
if(!tmpl.compare("tab")){
keys << AutoTypeAction(TypeKey, XK_Tab);
return;}
if(tmpl.startsWith("delay ") && tmpl.length()>6){
bool ok;
quint16 delay = tmpl.right(tmpl.length()-6).toInt(&ok);
if (ok && delay>0 && delay<=10000)
keys << AutoTypeAction(Delay, delay);
}
}
void AutoTypePrivate::stringToKeysyms(const QString& string,QList<AutoTypeAction>& KeySymList){
for(int i=0; i<string.length();i++)
KeySymList << AutoTypeAction(TypeKey, HelperX11::getKeysym(string[i]));
}
QString AutoTypePrivate::getRootGroupName(IEntryHandle* entry){
IGroupHandle* group = entry->group();
int level = group->level();
for (int i=0; i<level; i++)
group = group->parent();
return group->title();
}

@ -536,9 +536,12 @@ void KeepassEntryView::OnColumnMoved(int LogIndex,int OldVisIndex,int NewVisInde
int KeepassEntryView::logicalColIndex(int LstIndex){
int c=-1;
for(int i=0;i<NUM_COLUMNS;i++){
if(Columns.at(i))c++;
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)c--;
if(i==LstIndex)return c;
if(Columns.at(i))
c++;
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)
c--;
if(i==LstIndex)
return c;
}
Q_ASSERT(false);
return -1;
@ -578,15 +581,18 @@ void KeepassEntryView::resizeColumns(){
int KeepassEntryView::columnListIndex(int LogicalIndex){
int c=-1; int i;
for(i=0;i<NUM_COLUMNS;i++){
if(Columns.at(i))c++;
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)c--;
if(c==LogicalIndex)break;
if(Columns.at(i))
c++;
if(i==10 && Columns.at(10) && ViewMode!=ShowSearchResults)
c--;
if(c==LogicalIndex)
break;
}
return i;
}
void KeepassEntryView::OnColumnResized(int lindex,int Old, int New){
void KeepassEntryView::OnColumnResized(int lindex, int Old, int New){
if(!AutoResizeColumns)return;
for(int i=0;i<header()->count();i++){
ColumnSizes[columnListIndex(i)]=header()->sectionSize(i);
@ -611,15 +617,20 @@ void KeepassEntryView::mouseMoveEvent(QMouseEvent *event){
EntryViewItem* DragStartItem=(EntryViewItem*)itemAt(DragStartPos);
if(!DragStartItem){
while(selectedItems().size()){
setItemSelected(selectedItems().first(),false);}
setItemSelected(selectedItems().first(),false);
}
return;
}
if(selectedItems().isEmpty()){
setItemSelected(DragStartItem,true);}
setItemSelected(DragStartItem,true);
}
else{
bool AlreadySelected=false;
for(int i=0;i<selectedItems().size();i++){
if(selectedItems()[i]==DragStartItem){AlreadySelected=true; break;}
if(selectedItems()[i]==DragStartItem){
AlreadySelected=true;
break;
}
}
if(!AlreadySelected){
while(selectedItems().size()){
@ -656,8 +667,7 @@ void KeepassEntryView::removeDragItems(){
#ifdef AUTOTYPE
void KeepassEntryView::OnAutoType(){
if (selectedItems().size() == 0) return;
QString error;
AutoType::perform(((EntryViewItem*)selectedItems().first())->EntryHandle,error);
autoType->perform(((EntryViewItem*)selectedItems().first())->EntryHandle);
}
#endif

@ -60,7 +60,7 @@ void KeepassGroupView::createItems(){
void KeepassGroupView::updateIcons(){
for(int i=0;i<Items.size();i++){
Items[i]->setIcon(0,db->icon(Items[i]->GroupHandle->image()));
}
}
}
void KeepassGroupView::showSearchResults(){
@ -86,7 +86,7 @@ void KeepassGroupView::addChildren(GroupViewItem* item){
void KeepassGroupView::OnDeleteGroup(){
if(config->askBeforeDelete()){
if(QMessageBox::question(this,tr("Delete?"),
tr("Are you sure you want to delete this group, all it's child groups and all their entries?"),
tr("Are you sure you want to delete this group, all its child groups and all their entries?"),
QMessageBox::Yes | QMessageBox::No,QMessageBox::No) == QMessageBox::No)
return;
}

@ -21,40 +21,6 @@
#include "HelperX11.h"
#include <QX11Info>
int HelperX11::getModifiers(Display *d,KeySym keysym, int keycode){
int SymsPerKey;
KeySym* Syms=XGetKeyboardMapping(d,keycode,1,&SymsPerKey);
int c=-1;
for(int i=0;i<4;i++)
if(Syms[i]==keysym){
c=i; break;
}
Q_ASSERT(c!=-1);
XFree(Syms);
return c;
}
void HelperX11::pressModifiers(Display* d,int mods,bool press){
switch(mods){
case 0: //no modifier
break;
case 1: //Shift
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_Shift_L),press,2);
break;
case 2: //AltGr
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_ISO_Level3_Shift),press,2);
break;
case 3: //Shift+AltGr
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_Shift_L),press,2);
XTestFakeKeyEvent(d,XKeysymToKeycode(d,XK_ISO_Level3_Shift),press,2);
break;
}
}
void HelperX11::releaseModifiers(Display* d,int mods){
pressModifiers(d,mods,False);
}
#ifdef GLOBAL_AUTOTYPE
int HelperX11::getShortcutModifierMask(const Shortcut& s){
int mod=0;
@ -889,8 +855,8 @@ quint16 HelperX11::getKeysym(const QChar& c){
int MapSize = sizeof(KeysymMap) / sizeof(quint16) / 2;
for (int i=0; i<MapSize; i++){
if(unicode==KeysymMap[i][0])
return KeysymMap[i][1];
if (unicode==KeysymMap[i][1])
return KeysymMap[i][0];
}
return 0;

@ -33,9 +33,6 @@
class HelperX11{
public:
static int getModifiers(Display *d,KeySym keysym, int keycode);
static void pressModifiers(Display*,int mods,bool Press=true);
static void releaseModifiers(Display*,int mods);
static quint16 getKeysym(const QChar& c);
#ifdef GLOBAL_AUTOTYPE
static int getShortcutModifierMask(const Shortcut& s);

@ -90,7 +90,7 @@ void ShortcutWidget::displayShortcut(quint32 key, bool release, bool ctrl, bool
pShortcut.alt = alt;
pShortcut.altgr = altgr;
pShortcut.win = win;
failed = AutoType::registerGlobalShortcut(pShortcut);
failed = autoType->registerGlobalShortcut(pShortcut);
if (!failed)
setBackgroundColor(QColor(255, 150, 150));
else

@ -23,7 +23,7 @@
class IEntryHandle;
typedef enum tKeyType {PASSWORD=0,KEYFILE=1,BOTH=2};
enum tKeyType {PASSWORD=0,KEYFILE=1,BOTH=2};
struct Translation {
QString nameCode;
QString nameLong;

@ -52,7 +52,7 @@ int main(int argc, char **argv)
initAppPaths(argc,argv);
CmdLineArgs args;
if(!args.preparse(argc,argv)){ // searches only for the -cfg parameter
qCritical(CSTR( args.error().append("\n") ));
qCritical("%s", CSTR( args.error().append("\n") ));
args.printHelp();
return 1;
}
@ -88,7 +88,7 @@ int main(int argc, char **argv)
if(!plugin.load()){
PluginLoadError=plugin.errorString();
qWarning("Could not load desktop integration plugin:");
qWarning(CSTR(PluginLoadError));
qWarning("%s", CSTR(PluginLoadError));
}
else{
QObject *plugininstance=plugin.instance();
@ -128,7 +128,7 @@ int main(int argc, char **argv)
#endif
}
if ( !args.parse(QApplication::arguments()) ){
qCritical(CSTR( args.error().append("\n") ));
qCritical("%s", CSTR( args.error().append("\n") ));
args.printHelp();
return 1;
}
@ -151,9 +151,7 @@ int main(int argc, char **argv)
QApplication::setQuitOnLastWindowClosed(false);
KeepassMainWindow *mainWin = new KeepassMainWindow(args.file(), args.startMinimized(), args.startLocked());
#ifdef GLOBAL_AUTOTYPE
AutoType::init();
#endif
int r=app->exec();
delete mainWin;
delete eventListener;
@ -255,7 +253,7 @@ QString findPlugin(const QString& filename){
bool EventListener::eventFilter(QObject*, 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;
}

@ -61,10 +61,10 @@ KeepassMainWindow::KeepassMainWindow(const QString& ArgFile,bool ArgMin,bool Arg
setUnifiedTitleAndToolBarOnMac(true);
#endif
#ifdef AUTOTYPE
AutoType::MainWin=this;
initAutoType(this);
#endif
#ifdef GLOBAL_AUTOTYPE
AutoType::registerGlobalShortcut(config->globalShortcut());
autoType->registerGlobalShortcut(config->globalShortcut());
#endif
setWindowModified(false);
setGeometry(config->mainWindowGeometry(geometry()));
@ -1016,7 +1016,7 @@ void KeepassMainWindow::closeEvent(QCloseEvent* e){
}
#ifdef GLOBAL_AUTOTYPE
AutoType::unregisterGlobalShortcut();
autoType->unregisterGlobalShortcut();
#endif
config->setMainWindowGeometry(geometry());

@ -45,12 +45,12 @@ unix : !macx : !isEqual(QMAKE_WIN32,1){
INSTALLS += share
contains(DEFINES,AUTOTYPE){
LIBS += -lXtst
SOURCES += lib/HelperX11.cpp lib/AutoType_X11.cpp
HEADERS += lib/HelperX11.h
SOURCES += lib/HelperX11.cpp lib/AutoTypeX11.cpp
HEADERS += lib/HelperX11.h lib/AutoTypeX11.h
}
contains(DEFINES,GLOBAL_AUTOTYPE){
SOURCES += Application_X11.cpp
HEADERS += Application_X11.h
SOURCES += Application_X11.cpp lib/AutoTypeGlobalX11.cpp
HEADERS += Application_X11.h lib/AutoTypeGlobalX11.h
}
SOURCES += main_unix.cpp
}
@ -93,7 +93,7 @@ macx {
#-------------------------------------------------------------------------------
isEqual(QMAKE_WIN32,1){
CONFIG += windows
isEmpty(PREFIX): PREFIX = "C:/Program files/KeePassX"
isEmpty(PREFIX): PREFIX = "C:/Program\ files/KeePassX"
TARGET = ../bin/KeePassX
target.path = $${PREFIX}
data.files += ../share/keepassx/*

File diff suppressed because it is too large Load Diff

@ -1,5 +0,0 @@
Mass modify entries
Backup group (exclude from search)
Improve password generator
Manually select language
kde4 plugin: clear klipper history