Initial commit
[keepassx] / src / import / Import_KeePassX_Xml.cpp
1 /***************************************************************************
2  *   Copyright (C) 2007 by Tarek Saidi                                     *
3  *   tarek.saidi@arcor.de                                                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; version 2 of the License.               *
8
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20  
21
22 #include "Import_KeePassX_Xml.h"
23
24 bool Import_KeePassX_Xml::importDatabase(QWidget* Parent, IDatabase* database){
25         db=database;
26         GuiParent=Parent;
27         QFile* file=openFile(GuiParent,identifier(),QStringList()<<tr("KeePass XML Files (*.xml)")<<tr("All Files (*)"));
28         if(!file)return false;
29         QDomDocument doc;
30         QString ErrMsg;
31         int ErrLine;
32         int ErrCol;
33         if(!doc.setContent(file,false,&ErrMsg,&ErrLine,&ErrCol)){
34                 QMessageBox::critical(GuiParent,tr("Import Failed"),tr("XML parsing error on line %1 column %2:\n%3").arg(ErrLine).arg(ErrCol).arg(ErrMsg));            
35                 delete file;
36                 return false;
37         }       
38         delete file;
39         QDomElement root=doc.documentElement();
40         if(root.tagName()!="database"){
41                 QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Parsing error: File is no valid KeePassX XML file."));          
42                 return false;           
43         }
44         QDomNodeList TopLevelGroupNodes=root.childNodes();
45         QStringList GroupNames;
46         for(int i=0;i<TopLevelGroupNodes.count();i++){
47                 if(TopLevelGroupNodes.at(i).toElement().tagName()!="group"){
48                         qWarning("Import_KeePassX_Xml: Error: Unknow tag '%s'",CSTR(TopLevelGroupNodes.at(i).toElement().tagName()));
49                         QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Parsing error: File is no valid KeePassX XML file."));          
50                         return false;
51                 }
52                 if(!parseGroup(TopLevelGroupNodes.at(i).toElement(),NULL)){
53                         QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Parsing error: File is no valid KeePassX XML file."));
54                         return false;}          
55         }
56         
57         return true;
58         
59 }
60
61 bool Import_KeePassX_Xml::parseGroup(const QDomElement& GroupElement,IGroupHandle* ParentGroup){
62         CGroup Group;
63         QDomNodeList ChildNodes=GroupElement.childNodes();
64         for(int i=0;i<ChildNodes.size();i++){
65                 if(!ChildNodes.item(i).isElement()){
66                         qWarning("Import_KeePassX_Xml: Error: Invalid node.");
67                         return false;
68                 }
69                 if(ChildNodes.item(i).toElement().tagName()=="icon")
70                         Group.Image=ChildNodes.item(i).toElement().text().toInt();
71                 else if(ChildNodes.item(i).toElement().tagName()=="title")
72                         Group.Title=ChildNodes.item(i).toElement().text();
73         }
74         
75         IGroupHandle* GroupHandle=db->addGroup(&Group,ParentGroup);
76         
77         for(int i=0;i<ChildNodes.size();i++){
78                 if(ChildNodes.item(i).toElement().tagName()=="entry"){
79                         if(!parseEntry(ChildNodes.item(i).toElement(), GroupHandle))return false;
80                 }else if(ChildNodes.item(i).toElement().tagName()=="group"){
81                         if(!parseGroup(ChildNodes.item(i).toElement(),GroupHandle))return false;
82                 }               
83         }
84         
85         return true;
86
87 }
88
89
90 bool Import_KeePassX_Xml::parseEntry(const QDomElement& EntryElement,IGroupHandle* Group){
91         if(EntryElement.isNull()){
92                 qWarning("Import_KeePassX_Xml: Error: Entry element is null.");
93                 return false;
94         }
95         IEntryHandle* entry=db->newEntry(Group);
96         QDomNodeList ChildNodes=EntryElement.childNodes();
97         for(int i=0;i<ChildNodes.size();i++){
98                 if(!ChildNodes.item(i).isElement()){
99                         qWarning("Import_KeePassX_Xml: Error: Invalid node.");
100                         return false;
101                 }
102                 if(ChildNodes.item(i).toElement().tagName()=="title")
103                         entry->setTitle(ChildNodes.item(i).toElement().text());
104                 else if(ChildNodes.item(i).toElement().tagName()=="username")
105                         entry->setUsername(ChildNodes.item(i).toElement().text());
106                 else if(ChildNodes.item(i).toElement().tagName()=="password"){
107                         SecString pw;
108                         QString cpw=ChildNodes.item(i).toElement().text();
109                         pw.setString(cpw,true);
110                         entry->setPassword(pw);                 
111                 }
112                 else if(ChildNodes.item(i).toElement().tagName()=="url")
113                         entry->setUrl(ChildNodes.item(i).toElement().text());
114                 else if(ChildNodes.item(i).toElement().tagName()=="icon")
115                         entry->setImage(ChildNodes.item(i).toElement().text().toInt());
116                 else if(ChildNodes.item(i).toElement().tagName()=="creation")
117                         entry->setCreation(KpxDateTime::fromString(ChildNodes.item(i).toElement().text(),Qt::ISODate));                 
118                 else if(ChildNodes.item(i).toElement().tagName()=="lastaccess")
119                         entry->setLastAccess(KpxDateTime::fromString(ChildNodes.item(i).toElement().text(),Qt::ISODate));       
120                 else if(ChildNodes.item(i).toElement().tagName()=="lastmod")
121                         entry->setLastMod(KpxDateTime::fromString(ChildNodes.item(i).toElement().text(),Qt::ISODate));  
122                 else if(ChildNodes.item(i).toElement().tagName()=="expire")
123                         entry->setExpire(KpxDateTime::fromString(ChildNodes.item(i).toElement().text(),Qt::ISODate));
124                 else if(ChildNodes.item(i).toElement().tagName()=="bindesc")
125                         entry->setBinaryDesc(ChildNodes.item(i).toElement().text());
126                 else if(ChildNodes.item(i).toElement().tagName()=="bin")
127                         entry->setBinary(QByteArray::fromBase64(ChildNodes.item(i).toElement().text().toAscii()));
128                 else if(ChildNodes.item(i).toElement().tagName()=="comment"){
129                         QDomNodeList Lines=ChildNodes.item(i).childNodes();
130                         QString comment;
131                         for(int i=0;i<Lines.size();i++){
132                                 if(Lines.item(i).isText())
133                                         comment+=Lines.item(i).toText().data();
134                                 else if(Lines.item(i).toElement().tagName()=="br")
135                                         comment+="\n";
136                                 else{
137                                         qWarning("Import_KeePassX_Xml: Error: Comment element contains invalid nodes.");
138                                         return false;
139                                 }                               
140                         }
141                         entry->setComment(comment);
142                 }
143         }
144         return true;    
145 }