bool Import_PwManager::importDatabase(QWidget* GuiParent, IDatabase* db){	
	database=db;
	QFile* file=openFile(GuiParent,identifier(),QStringList()<<tr("PwManager Files (*.pwm)")<<tr("All Files (*)"));
	if(!file)return false;
	QString password=getPassword(GuiParent);
	if(password.isEmpty()){delete file; return false;}
	char* buffer=NULL;
	int offset=0;
	int len=0;
	if((len=file->size())){
		buffer=new char[len];
	}
	else {
		QMessageBox::critical(GuiParent,tr("Import Failed"),tr("File is empty."));
		delete file;
		return false;
	}
	file->read(buffer,len);
	file->close();
	delete file;
	if(QString::fromAscii(buffer,17)!="PWM_PASSWORD_FILE")
	{QMessageBox::critical(GuiParent,tr("Import Failed"),tr("File is no valid PwManager file.")); return false;}
	offset+=17;
	if(buffer[offset]!=0x05)
	{QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Unsupported file version.")); return false;}
	offset++;
	if(buffer[offset]!=0x01)
	{QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Unsupported hash algorithm.")); return false;}
	offset++;
	if(buffer[offset]!=0x01)
	{QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Unsupported hash algorithm.")); return false;}
	offset++;
	if(buffer[offset]!=0x01)
	{QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Unsupported encryption algorithm.")); return false;}
	offset++;
	if(buffer[offset]==0x00)Compression=0;
	if(buffer[offset]==0x01)Compression=1;
	if(buffer[offset]==0x02)Compression=2;
	///@TODO Compression
	if(buffer[offset])
	{QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Compressed files are not supported yet.")); return false;}
	offset++;
	if(buffer[offset]==0x00)KeyFlag=true;
	else KeyFlag=false;
	offset++;
	//Reserved Bytes (64)
	offset+=64;
	memcpy(KeyHash,buffer+offset,20);
	offset+=20;
	memcpy(DataHash,buffer+offset,20);
	offset+=20;
	
	Blowfish blowfish;
	int pwlen=password.length();
	byte* Key=new byte[pwlen];
	byte* xml=new byte[len-offset+1];
	xml[len-offset]=0;
	memcpy(Key,password.toAscii(),pwlen);
	QCryptographicHash sha(QCryptographicHash::Sha1);
	sha.addData((const char*)Key,pwlen);
	QByteArray key_hash = sha.result();
	if(memcmp(key_hash.constData(),KeyHash,20)){
		delete[] Key;
		delete [] buffer;
		QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Wrong password."));
		return false;
	}
	blowfish.bf_setkey(Key,password.length());
	blowfish.bf_decrypt(xml,(byte*)buffer+offset,len-offset);
	delete [] Key;
	delete [] buffer;
	sha.reset();
	sha.addData((const char*)xml,strlen((char*)xml)-1);
	QByteArray content_hash = sha.result();
	if(memcmp(content_hash.constData(),DataHash,20)){
		delete [] xml;
		QMessageBox::critical(GuiParent,tr("Import Failed"),tr("File is damaged (hash test failed)."));
		return false;
	}
	
	if(!parseXmlContent((char*)xml)){
		delete [] xml;
		QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details).")); return false;
	}
	return true;
}
static int handle_xml_cmd(int sock, char *data, int len)
{
	int   out_fields[RESP_FIELD_MAX + 1];
	void *out_params[RESP_FIELD_MAX + 1];
	int   in_fields[CMD_FIELD_MAX + 1];
	void *in_params[CMD_FIELD_MAX];

	int ret;
	char *resp_buf = NULL;
	struct node_info info = {
		.cmd = -1,
		.timeout = DEF_TIMEOUT,
		.debug = 0
	};

	INFO("recv cmd: %s", data);

	memset(in_fields, 0, sizeof(in_fields));
	memset(in_params, 0, sizeof(in_params));
	memset(out_fields, 0, sizeof(out_fields));
	memset(out_params, 0, sizeof(out_params));

	if (parseXmlContent(data, len, in_fields, in_params, &info)) {
		ERROR("xml parsing error.");
		return -1;
	}

	if (!info.debug) {
		/* DEBUG("alarm %d", info.timeout); */
		alarm(info.timeout);
	}
	ret = executeCmd(info.cmd, in_fields, in_params, out_fields, out_params);
	freeParams(in_fields, in_params);

	if (ret)
		ERROR("cmd %s failed: %s", cmd_name[info.cmd], strerror(ret));

	ret = createXmlResult(info.cmd, ret, out_fields, out_params, &resp_buf);
	freeParams(out_fields, out_params);

	if (!info.debug)
		alarm(0);

	if (ret || !resp_buf) {
		ERROR("create result string error.");
		return -1;
	}

	ret = send_resp(sock, resp_buf, strlen(resp_buf));
	free(resp_buf);

	return ret;
}

static void handle_request(int sock)
{
	int command, ret = 0;
	char *buffer = malloc(MAX_CMD_BUF + 1);

	if (!buffer) {
		ERROR("malloc error : %s", strerror(errno));
		return;
	}

	while (ret == 0) {

		ret = receive_cmd(sock, buffer, MAX_CMD_BUF, &command);
		//DEBUG("received cmd %d len %d", command, ret);

		if (ret == 0) {
			ERROR("Socket closed");
			break;
		}

		if (ret > 0 && command != CMD_XML) {
			ERROR("Not supported command %d", command);
			ret = INVALID_DATA;
		}

		if (ret < 0) {
			sprintf(buffer, resp_xml, status_str[-ret]);
			send_resp(sock, buffer, strlen(buffer));
			break;
		}

		ret = handle_xml_cmd(sock, buffer, ret /* len */);
		if (ret < 0) {
			ERROR("xml command %d error %d", command, ret);
			break;
		}
	}
	free(buffer);
}