summaryrefslogtreecommitdiff
path: root/test-client-catchcopy/catchcopy-api-0002
diff options
context:
space:
mode:
Diffstat (limited to 'test-client-catchcopy/catchcopy-api-0002')
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp380
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h114
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp31
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h27
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp725
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h162
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h14
-rwxr-xr-xtest-client-catchcopy/catchcopy-api-0002/documentation.dox31
8 files changed, 1484 insertions, 0 deletions
diff --git a/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp
new file mode 100644
index 0000000..0ac9d04
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp
@@ -0,0 +1,380 @@
+/** \file ClientCatchcopy.cpp
+\brief Define the catchcopy client
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include "ClientCatchcopy.h"
+#include "VariablesCatchcopy.h"
+#include "ExtraSocketCatchcopy.h"
+#include <QDataStream>
+
+ClientCatchcopy::ClientCatchcopy()
+{
+ disconnectedFromSocket();
+ error_string="Unknown error";
+ detectTimeOut.setSingleShot(true);
+ detectTimeOut.setInterval(CATCHCOPY_COMMUNICATION_TIMEOUT); // the max time to without send packet
+ connect(&socket, SIGNAL(connected()), this, SIGNAL(connected()));
+ connect(&socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
+ connect(&socket, SIGNAL(disconnected()), this, SLOT(disconnectedFromSocket()));
+ connect(&socket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)), this, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)));
+ connect(&socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SIGNAL(errorSocket(QLocalSocket::LocalSocketError)));
+ connect(&socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ connect(&detectTimeOut, SIGNAL(timeout()), this, SLOT(checkTimeOut()));
+ connect(&socket, SIGNAL(connected()), this, SLOT(socketIsConnected()));
+}
+
+void ClientCatchcopy::checkTimeOut()
+{
+ if(haveData)
+ {
+ error_string="The server is too long to send the next part of the reply";
+ emit error(error_string);
+ disconnectFromServer();
+ }
+}
+
+const QString ClientCatchcopy::errorString()
+{
+ return error_string;
+}
+
+void ClientCatchcopy::socketIsConnected()
+{
+ orderIdFirstSendProtocol=sendProtocol();
+}
+
+void ClientCatchcopy::connectToServer()
+{
+ socket.connectToServer(ExtraSocketCatchcopy::pathSocket());
+}
+
+void ClientCatchcopy::disconnectFromServer()
+{
+ socket.abort();
+ socket.disconnectFromServer();
+}
+
+const QString ClientCatchcopy::errorStringSocket()
+{
+ return socket.errorString();
+}
+
+/// \brief to send stream of string list
+quint32 ClientCatchcopy::sendRawOrderList(const QStringList & order)
+{
+ if(!socket.isValid())
+ {
+ error_string="Socket is not valid, try send: "+order.join(";");
+ emit error(error_string);
+ return -1;
+ }
+ if(socket.state()!=QLocalSocket::ConnectedState)
+ {
+ error_string="Socket is not connected "+QString::number(socket.state());
+ emit error(error_string);
+ return -1;
+ }
+ do
+ {
+ idNextOrder++;
+ if(idNextOrder>2000000000)
+ idNextOrder=0;
+ } while(notRepliedQuery.contains(idNextOrder));
+ notRepliedQuery << idNextOrder;
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_4);
+ out << int(0);
+ out << idNextOrder;
+ out << order;
+ out.device()->seek(0);
+ out << block.size();
+ if(idNextOrder!=1) // drop if internal protocol send
+ {
+ emit dataSend(idNextOrder,block);
+ emit dataSend(idNextOrder,order);
+ }
+ do //cut string list and send it as block of 32KB
+ {
+ QByteArray blockToSend;
+ int byteWriten;
+ blockToSend=block.left(32*1024);//32KB
+ block.remove(0,blockToSend.size());
+ byteWriten = socket.write(blockToSend);
+ if(!socket.isValid())
+ {
+ error_string="Socket is not valid";
+ emit error(error_string);
+ return -1;
+ }
+ if(socket.errorString()!="Unknown error" && socket.errorString()!="")
+ {
+ error_string=socket.errorString();
+ emit error(error_string);
+ return -1;
+ }
+ if(blockToSend.size()!=byteWriten)
+ {
+ error_string="All the bytes have not be written";
+ emit error(error_string);
+ return -1;
+ }
+ }
+ while(block.size());
+ return idNextOrder;
+}
+
+void ClientCatchcopy::readyRead()
+{
+ while(socket.bytesAvailable()>0)
+ {
+ if(!haveData)
+ {
+ if(socket.bytesAvailable()<(int)sizeof(int))//int of size cuted
+ {
+ /* error_string="Bytes available is not sufficient to do a int";
+ emit error(error_string);
+ disconnectFromServer();*/
+ return;
+ }
+ QDataStream in(&socket);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> dataSize;
+ dataSize-=sizeof(int);
+ if(dataSize>64*1024*1024) // 64MB
+ {
+ error_string="Reply size is >64MB, seam corrupted";
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ if(dataSize<(int)(sizeof(int) //orderId
+ + sizeof(quint32) //returnCode
+ + sizeof(quint32) //string list size
+ ))
+ {
+ error_string="Reply size is too small to have correct code";
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ }
+ if(dataSize<(data.size()+socket.bytesAvailable()))
+ data.append(socket.read(dataSize-data.size()));
+ else
+ data.append(socket.readAll());
+ if(dataSize==data.size())
+ {
+ if(!checkDataIntegrity(data))
+ {
+ data.clear();
+ qWarning() << "Data of the reply is wrong";
+ return;
+ }
+ QStringList returnList;
+ quint32 orderId;
+ quint32 returnCode;
+ QDataStream in(data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> returnCode;
+ in >> returnList;
+ data.clear();
+ if(orderId!=orderIdFirstSendProtocol)
+ {
+ if(!notRepliedQuery.contains(orderId))
+ qWarning() << "Unknown query not replied:" << orderId;
+ else
+ {
+ if(!parseReply(orderId,returnCode,returnList))
+ emit unknowReply(orderId);
+ emit newReply(orderId,returnCode,returnList);
+ }
+ }
+ else
+ {
+ if(!sendProtocolReplied)
+ {
+ sendProtocolReplied=true;
+ if(returnCode!=1000)
+ {
+ error_string="Protocol not supported";
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ }
+ else
+ {
+ error_string=QString("First send protocol send with the query id %1 have been already previously replied").arg(orderIdFirstSendProtocol);
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ }
+ }
+ }
+ if(haveData)
+ detectTimeOut.start();
+ else
+ detectTimeOut.stop();
+}
+
+bool ClientCatchcopy::checkDataIntegrity(QByteArray data)
+{
+ quint32 orderId;
+ qint32 replyCode;
+ qint32 listSize;
+ QDataStream in(data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> replyCode;
+ in >> listSize;
+ if(listSize>65535)
+ {
+ emit error("List size is wrong");
+ qWarning() << "List size is wrong";
+ return false;
+ }
+ int index=0;
+ while(index<listSize)
+ {
+ qint32 stringSize;
+ in >> stringSize;
+ if(stringSize>65535)
+ {
+ emit error("String size is wrong");
+ qWarning() << "String size is wrong";
+ return false;
+ }
+ if(stringSize>(in.device()->size()-in.device()->pos()))
+ {
+ emit error(QString("String size is greater than the data: %1>(%2-%3)").arg(stringSize).arg(in.device()->size()).arg(in.device()->pos()));
+ qWarning() << QString("String size is greater than the data: %1>(%2-%3)").arg(stringSize).arg(in.device()->size()).arg(in.device()->pos());
+ return false;
+ }
+ in.device()->seek(in.device()->pos()+stringSize);
+ index++;
+ }
+ if(in.device()->size()!=in.device()->pos())
+ {
+ emit error("Remaining data after string list parsing");
+ qWarning() << "Remaining data after string list parsing";
+ return false;
+ }
+ return true;
+}
+
+QLocalSocket::LocalSocketState ClientCatchcopy::state()
+{
+ return socket.state();
+}
+
+void ClientCatchcopy::disconnectedFromSocket()
+{
+ haveData = false;
+ orderIdFirstSendProtocol= 0;
+ idNextOrder = 0;
+ sendProtocolReplied = false;
+ notRepliedQuery.clear();
+}
+
+/// \brief to send the protocol version used
+quint32 ClientCatchcopy::sendProtocol()
+{
+ return sendRawOrderList(QStringList() << "protocol" << CATCHCOPY_PROTOCOL_VERSION);
+}
+
+quint32 ClientCatchcopy::askServerName()
+{
+ return sendRawOrderList(QStringList() << "server" << "name?");
+}
+
+quint32 ClientCatchcopy::setClientName(const QString & name)
+{
+ return sendRawOrderList(QStringList() << "client" << name);
+}
+
+quint32 ClientCatchcopy::checkProtocolExtension(const QString & name)
+{
+ return sendRawOrderList(QStringList() << "protocol extension" << name);
+}
+
+quint32 ClientCatchcopy::checkProtocolExtension(const QString & name,const QString & version)
+{
+ return sendRawOrderList(QStringList() << "protocol extension" << name << version);
+}
+
+quint32 ClientCatchcopy::addCopyWithDestination(const QStringList & sources,const QString & destination)
+{
+ return sendRawOrderList(QStringList() << "cp" << sources << destination);
+}
+
+quint32 ClientCatchcopy::addCopyWithoutDestination(const QStringList & sources)
+{
+ return sendRawOrderList(QStringList() << "cp-?" << sources);
+}
+
+quint32 ClientCatchcopy::addMoveWithDestination(const QStringList & sources,const QString & destination)
+{
+ return sendRawOrderList(QStringList() << "mv" << sources << destination);
+}
+
+quint32 ClientCatchcopy::addMoveWithoutDestination(const QStringList & sources)
+{
+ return sendRawOrderList(QStringList() << "mv-?" << sources);
+}
+
+bool ClientCatchcopy::parseReply(quint32 orderId,quint32 returnCode,QStringList returnList)
+{
+ switch(returnCode)
+ {
+ case 1000:
+ emit protocolSupported(orderId);
+ break;
+ case 1001:
+ case 1002:
+ if(returnCode==1001)
+ emit protocolExtensionSupported(orderId,true);
+ else
+ emit protocolExtensionSupported(orderId,false);
+ break;
+ case 1003:
+ emit clientRegistered(orderId);
+ break;
+ case 1004:
+ if(returnList.size()!=1)
+ emit unknowOrder(orderId);
+ else
+ emit serverName(orderId,returnList.last());
+ break;
+ case 1005:
+ case 1006:
+ if(returnCode==1005)
+ emit copyFinished(orderId,false);
+ else
+ emit copyFinished(orderId,true);
+ break;
+ case 1007:
+ emit copyCanceled(orderId);
+ break;
+ case 5000:
+ emit incorrectArgumentListSize(orderId);
+ break;
+ case 5001:
+ emit incorrectArgument(orderId);
+ break;
+ case 5002:
+ emit unknowOrder(orderId); //the server have not understand the order
+ break;
+ case 5003:
+ emit protocolNotSupported(orderId);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
diff --git a/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h
new file mode 100644
index 0000000..278b0cd
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h
@@ -0,0 +1,114 @@
+/** \file ClientCatchcopy.h
+\brief Define the catchcopy client
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef CLIENTCATCHCOPY_H
+#define CLIENTCATCHCOPY_H
+
+#include <QObject>
+#include <QLocalSocket>
+#include <QStringList>
+#include <QString>
+#include <QByteArray>
+#include <QTimer>
+
+/// \brief Define the catchcopy client
+class ClientCatchcopy : public QObject
+{
+ Q_OBJECT
+ public:
+ ClientCatchcopy();
+ /// \brief get the socket stat
+ QLocalSocket::LocalSocketState state();
+ /// \brief error string about the socket
+ const QString errorStringSocket();
+ /// \brief general error string
+ const QString errorString();
+ public slots:
+ void connectToServer();
+ void disconnectFromServer();
+ //to test and internal use
+ /// \brief to send order
+ quint32 sendProtocol();
+ /// \brief ask the server name
+ quint32 askServerName();
+ /// \brief set the client name
+ quint32 setClientName(const QString & name);
+ /// \brief check protocol extension
+ quint32 checkProtocolExtension(const QString & name);
+ /// \brief check protocol extension and version
+ quint32 checkProtocolExtension(const QString & name,const QString & version);
+ /// \brief add copy with destination
+ quint32 addCopyWithDestination(const QStringList & sources,const QString & destination);
+ /// \brief add copy without destination
+ quint32 addCopyWithoutDestination(const QStringList & sources);
+ /// \brief add move with destination
+ quint32 addMoveWithDestination(const QStringList & sources,const QString & destination);
+ /// \brief add move without destination
+ quint32 addMoveWithoutDestination(const QStringList & sources);
+ /// \brief to send stream of string list
+ quint32 sendRawOrderList(const QStringList & order);
+ signals:
+ /// \brief is connected
+ void connected();
+ /// \brief is disconnected
+ void disconnected();
+ /// \brief the socket state have changed
+ void stateChanged(QLocalSocket::LocalSocketState socketState);
+ /// \brief send the error string
+ void error(QString error);
+ /// \brief send socket error
+ void errorSocket(QLocalSocket::LocalSocketError socketError);
+ /// \brief have new reply
+ void newReply(quint32 orderId,quint32 returnCode,QStringList returnList);
+ /// \brief have data send
+ void dataSend(quint32 orderId,QByteArray data);
+ /// \brief have data send by string list
+ void dataSend(quint32 orderId,QStringList data);
+ /// \brief have unknow reply
+ void unknowReply(quint32 orderId);
+ //reply
+ /// \brief protocol is supported
+ void protocolSupported(quint32 orderId);
+ /// \brief incorrect argument list size
+ void incorrectArgumentListSize(quint32 orderId);
+ /// \brief incorrect argument
+ void incorrectArgument(quint32 orderId);
+ /// \brief protocol not supported
+ void protocolNotSupported(quint32 orderId);
+ /// \brief protocol extension supported
+ void protocolExtensionSupported(quint32 orderId,bool isSupported);
+ /// \brief client is registred
+ void clientRegistered(quint32 orderId);
+ /// \brief have the server name
+ void serverName(quint32 orderId,QString name);
+ /// \brief copy finished
+ void copyFinished(quint32 orderId,bool withError);
+ /// \brief copy canceled
+ void copyCanceled(quint32 orderId);
+ /// \brief have unknow order
+ void unknowOrder(quint32 orderId); //the server have not understand the order
+ private:
+ QLocalSocket socket;
+ QString error_string;
+ quint32 idNextOrder;
+ QByteArray data;
+ bool haveData;
+ int dataSize;
+ quint32 orderIdFirstSendProtocol;
+ QTimer detectTimeOut;
+ bool sendProtocolReplied;
+ QList<quint32> notRepliedQuery;
+ bool checkDataIntegrity(QByteArray data);
+ private slots:
+ void readyRead();
+ void disconnectedFromSocket();
+ void socketIsConnected();
+ void checkTimeOut();
+ protected:
+ bool parseReply(quint32 orderId,quint32 returnCode,QStringList returnList);
+};
+
+#endif // CLIENTCATCHCOPY_H
diff --git a/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp
new file mode 100644
index 0000000..7ee05ed
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp
@@ -0,0 +1,31 @@
+/** \file ExtraSocketCatchcopy.cpp
+\brief Define the socket of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include "ExtraSocketCatchcopy.h"
+
+const QString ExtraSocketCatchcopy::pathSocket()
+{
+#ifdef Q_OS_UNIX
+ return "advanced-copier-"+QString::number(getuid());
+#else
+ QString userName;
+ DWORD size=0;
+ if(GetUserNameW(NULL,&size) || (GetLastError()!=ERROR_INSUFFICIENT_BUFFER))
+ {
+ }
+ else
+ {
+ WCHAR * userNameW=new WCHAR[size];
+ if(GetUserNameW(userNameW,&size))
+ {
+ userName.fromWCharArray(userNameW,size*2);
+ userName=QString(QByteArray((char*)userNameW,size*2-2).toHex());
+ }
+ delete userNameW;
+ }
+ return "advanced-copier-"+userName;
+#endif
+}
diff --git a/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h
new file mode 100644
index 0000000..623c668
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h
@@ -0,0 +1,27 @@
+/** \file ExtraSocketCatchcopy.h
+\brief Define the socket of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef EXTRASOCKETCATCHCOPY_H
+#define EXTRASOCKETCATCHCOPY_H
+
+#include <QString>
+
+#ifdef Q_OS_UNIX
+ #include <unistd.h>
+ #include <sys/types.h>
+#else
+ #include <windows.h>
+#endif
+
+/// \brief to have extra socket function
+class ExtraSocketCatchcopy
+{
+public:
+ /// \brief to get the socket path
+ static const QString pathSocket();
+};
+
+#endif // EXTRASOCKETCATCHCOPY_H
diff --git a/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp
new file mode 100644
index 0000000..b17fc0a
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp
@@ -0,0 +1,725 @@
+/** \file ServerCatchcopy.cpp
+\brief Define the server of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include "ServerCatchcopy.h"
+#include "VariablesCatchcopy.h"
+#include "ExtraSocketCatchcopy.h"
+
+ServerCatchcopy::ServerCatchcopy()
+{
+ name="Default avanced copier";
+ autoReply=true;
+ idNextClient=0;
+ error_string="Unknown error";
+ connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+}
+
+ServerCatchcopy::~ServerCatchcopy()
+{
+ close();
+}
+
+bool ServerCatchcopy::isListening()
+{
+ return server.isListening();
+}
+
+void ServerCatchcopy::setName(const QString & name)
+{
+ this->name=name;
+}
+
+QString ServerCatchcopy::getName()
+{
+ return name;
+}
+
+bool ServerCatchcopy::listen()
+{
+ QLocalSocket socketTestConnection;
+ pathSocket=ExtraSocketCatchcopy::pathSocket();
+ socketTestConnection.connectToServer(pathSocket);
+ if(socketTestConnection.waitForConnected(CATCHCOPY_COMMUNICATION_TIMEOUT))
+ {
+ error_string="Other server is listening";
+ emit error(error_string);
+ return false;
+ }
+ else
+ {
+ server.removeServer(pathSocket);
+ if(server.listen(pathSocket))
+ return true;
+ else
+ {
+ error_string=QString("Unable to listen %1: %2").arg(pathSocket).arg(server.errorString());
+ emit error(error_string);
+ return false;
+ }
+ }
+}
+
+void ServerCatchcopy::close()
+{
+ if(server.isListening())
+ {
+ int index=0;
+ while(index<ClientList.size())
+ {
+ ClientList.at(index).socket->disconnectFromServer();
+ index++;
+ }
+ server.close();
+ QLocalServer::removeServer(pathSocket);
+ }
+}
+
+const QString ServerCatchcopy::errorStringServer()
+{
+ return server.errorString();
+}
+
+const QString ServerCatchcopy::errorString()
+{
+ return error_string;
+}
+
+/// \brief New connexion
+void ServerCatchcopy::newConnection()
+{
+ while(server.hasPendingConnections())
+ {
+ QLocalSocket *clientSocket = server.nextPendingConnection();
+ if(clientSocket!=NULL)
+ {
+ do
+ {
+ idNextClient++;
+ if(idNextClient>2000000000)
+ idNextClient=0;
+ } while(clientIdFound(idNextClient));
+ Client newClient;
+ newClient.id = idNextClient;
+ newClient.socket = clientSocket;
+ newClient.haveData = false;
+ newClient.firstProtocolReplied = false;
+ newClient.detectTimeOut = new QTimer(this);
+ newClient.detectTimeOut->setSingleShot(true);
+ newClient.detectTimeOut->setInterval(CATCHCOPY_COMMUNICATION_TIMEOUT);
+ connect(newClient.socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(connectionError(QLocalSocket::LocalSocketError)));
+ connect(newClient.socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ connect(newClient.socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
+ connect(newClient.detectTimeOut,SIGNAL(timeout()), this, SLOT(checkTimeOut()));
+ ClientList << newClient;
+ emit connectedClient(newClient.id);
+ }
+ }
+}
+
+bool ServerCatchcopy::clientIdFound(quint32 id)
+{
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).id==id)
+ return true;
+ index++;
+ }
+ return false;
+}
+
+/// \brief new error at connexion
+void ServerCatchcopy::connectionError(QLocalSocket::LocalSocketError error)
+{
+ QLocalSocket *socket=qobject_cast<QLocalSocket *>(QObject::sender());
+ if(socket==NULL)
+ {
+ qWarning() << "Unlocated client socket!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).socket==socket)
+ {
+ if(error!=QLocalSocket::PeerClosedError)
+ qWarning() << "error detected for the client: " << index << ", type: " << error;
+ ClientList.at(index).socket->disconnectFromServer();
+ return;
+ }
+ index++;
+ }
+}
+
+void ServerCatchcopy::disconnected()
+{
+ QLocalSocket *socket=qobject_cast<QLocalSocket *>(QObject::sender());
+ if(socket==NULL)
+ {
+ qWarning() << "Unlocated client socket!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).socket==socket)
+ {
+ emit disconnectedClient(ClientList.at(index).id);
+ disconnect(ClientList.at(index).socket);
+ disconnect(ClientList.at(index).detectTimeOut);
+ delete ClientList.at(index).detectTimeOut;
+ ClientList.at(index).socket->abort();
+ ClientList.at(index).socket->disconnectFromServer();
+ ClientList.at(index).socket->deleteLater();
+ ClientList.removeAt(index);
+ return;
+ }
+ index++;
+ }
+ qWarning() << "Unlocated client!";
+}
+
+void ServerCatchcopy::disconnectClient(quint32 id)
+{
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).id==id)
+ {
+ ClientList.at(index).socket->disconnectFromServer();
+ return;
+ }
+ index++;
+ }
+ qWarning() << "Unlocated client!";
+}
+
+void ServerCatchcopy::readyRead()
+{
+ QLocalSocket *socket=qobject_cast<QLocalSocket *>(QObject::sender());
+ if(socket==NULL)
+ {
+ qWarning() << "Unlocated client socket!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).socket==socket)
+ {
+ while(socket->bytesAvailable()>0)
+ {
+ if(!ClientList.at(index).haveData)
+ {
+ if(socket->bytesAvailable()<(int)sizeof(int))//ignore because first int is cuted!
+ {
+ /*error_string="Bytes available is not sufficient to do a int";
+ emit error(error_string);
+ disconnectClient(ClientList.at(index).id);*/
+ return;
+ }
+ QDataStream in(socket);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> ClientList[index].dataSize;
+ ClientList[index].dataSize-=sizeof(int);
+ if(ClientList.at(index).dataSize>64*1024*1024) // 64MB
+ {
+ error_string="Reply size is >64MB, seam corrupted";
+ emit error(error_string);
+ disconnectClient(ClientList.at(index).id);
+ return;
+ }
+ if(ClientList.at(index).dataSize<(int)(sizeof(int) //orderId
+ + sizeof(quint32) //returnCode
+ + sizeof(quint32) //string list size
+ ))
+ {
+ error_string="Reply size is too small to have correct code";
+ emit error(error_string);
+ disconnectClient(ClientList.at(index).id);
+ return;
+ }
+ ClientList[index].haveData=true;
+ }
+ if(ClientList.at(index).dataSize<(ClientList.at(index).data.size()+socket->bytesAvailable()))
+ ClientList[index].data.append(socket->read(ClientList.at(index).dataSize-ClientList.at(index).data.size()));
+ else
+ ClientList[index].data.append(socket->readAll());
+ if(ClientList.at(index).dataSize==(quint32)ClientList.at(index).data.size())
+ {
+ if(!checkDataIntegrity(ClientList.at(index).data))
+ {
+ emit error("Data integrity wrong: "+QString(ClientList.at(index).data.toHex()));
+ ClientList[index].data.clear();
+ ClientList[index].haveData=false;
+ qWarning() << "Data integrity wrong";
+ return;
+ }
+ QStringList returnList;
+ quint32 orderId;
+ QDataStream in(ClientList.at(index).data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> returnList;
+ ClientList[index].data.clear();
+ ClientList[index].haveData=false;
+ if(ClientList.at(index).queryNoReplied.contains(orderId))
+ {
+ emit error("Duplicate query id");
+ qWarning() << "Duplicate query id";
+ return;
+ }
+ ClientList[index].queryNoReplied << orderId;
+ if(!ClientList.at(index).firstProtocolReplied && returnList.size()==2 && returnList.first()=="protocol" && autoReply)
+ {
+ ClientList[index].firstProtocolReplied=true;
+ protocolSupported(ClientList.at(index).id,orderId,(returnList.last()==CATCHCOPY_PROTOCOL_VERSION));
+ }
+ else
+ parseInput(ClientList.at(index).id,orderId,returnList);
+ }
+ }
+ if(ClientList.at(index).haveData)
+ ClientList.at(index).detectTimeOut->start();
+ else
+ ClientList.at(index).detectTimeOut->stop();
+ return;
+ }
+ index++;
+ }
+ emit error("Unallocated client!");
+ qWarning() << "Unallocated client!";
+}
+
+bool ServerCatchcopy::checkDataIntegrity(QByteArray data)
+{
+ quint32 orderId;
+ qint32 listSize;
+ QDataStream in(data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> listSize;
+ if(listSize>65535)
+ {
+ emit error("List size is wrong");
+ qWarning() << "List size is wrong";
+ return false;
+ }
+ int index=0;
+ while(index<listSize)
+ {
+ qint32 stringSize;
+ in >> stringSize;
+ if(stringSize>65535)
+ {
+ emit error("String size is wrong");
+ return false;
+ }
+ if(stringSize>(in.device()->size()-in.device()->pos()))
+ {
+ emit error(QString("String size is greater than the data: %1>(%2-%3)").arg(stringSize).arg(in.device()->size()).arg(in.device()->pos()));
+ return false;
+ }
+ in.device()->seek(in.device()->pos()+stringSize);
+ index++;
+ }
+ if(in.device()->size()!=in.device()->pos())
+ {
+ emit error("Remaining data after string list parsing");
+ return false;
+ }
+ return true;
+}
+
+void ServerCatchcopy::parseInput(quint32 client,quint32 orderId,QStringList returnList)
+{
+ switch(parseInputCurrentProtocol(client,orderId,returnList))
+ {
+ case Ok:
+ emit newQuery(client,orderId,returnList);
+ break;
+ case Replied:
+ break;
+ case ExtensionWrong:
+ if(autoReply)
+ protocolExtensionSupported(client,orderId,false);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ case WrongArgument:
+ if(autoReply)
+ incorrectArgument(client,orderId);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ case WrongArgumentListSize:
+ if(autoReply)
+ incorrectArgumentListSize(client,orderId);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ case UnknowOrder:
+ emit error("Unknown query");
+ qWarning() << "Unknown query";
+ if(autoReply)
+ unknowOrder(client,orderId);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ }
+}
+
+ServerCatchcopy::inputReturnType ServerCatchcopy::parseInputCurrentProtocol(quint32 client,quint32 orderId,QStringList returnList)
+{
+ if(returnList.size()==0)
+ return WrongArgumentListSize;
+ //if is supported
+ QString firstArgument=returnList.first();
+ if(firstArgument=="protocol")
+ {
+ if(returnList.size()!=2)
+ return WrongArgumentListSize;
+ emit askProtocolCompatibility(client,orderId,returnList.last());
+ return Ok;
+ }
+ else if(firstArgument=="protocol extension")
+ {
+ if(returnList.size()>3 || returnList.size()<2)
+ return WrongArgumentListSize;
+ if(!autoReply)
+ {
+ if(returnList.size()==2)
+ emit askProtocolExtension(client,orderId,returnList.last());
+ else
+ emit askProtocolExtension(client,orderId,returnList.at(1),returnList.last());
+ }
+ return ExtensionWrong;
+ }
+ else if(firstArgument=="client")
+ {
+ if(returnList.size()!=2)
+ return WrongArgumentListSize;
+ emit clientName(client,returnList.last());
+ if(autoReply)
+ {
+ clientRegistered(client,orderId);
+ return Replied;
+ }
+ else
+ {
+ emit clientName(client,orderId,returnList.last());
+ return Ok;
+ }
+ }
+ else if(firstArgument=="server")
+ {
+ if(returnList.size()!=2)
+ return WrongArgumentListSize;
+ if(returnList.last()!="name?")
+ return WrongArgument;
+ if(autoReply)
+ {
+ serverName(client,orderId,name);
+ return Replied;
+ }
+ else
+ {
+ askServerName(client,orderId);
+ return Ok;
+ }
+ }
+ else if(firstArgument=="cp")
+ {
+ if(returnList.size()<3)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ sourceList.removeLast();
+ emitNewCopy(client,orderId,sourceList,returnList.last());
+ return Ok;
+ }
+ else if(firstArgument=="cp-?")
+ {
+ if(returnList.size()<2)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ emitNewCopy(client,orderId,sourceList);
+ return Ok;
+ }
+ else if(firstArgument=="mv")
+ {
+ if(returnList.size()<3)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ sourceList.removeLast();
+ emitNewMove(client,orderId,sourceList,returnList.last());
+ return Ok;
+ }
+ else if(firstArgument=="mv-?")
+ {
+ if(returnList.size()<2)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ emitNewMove(client,orderId,sourceList);
+ return Ok;
+ }
+ else //if is not supported
+ return UnknowOrder;
+}
+
+void ServerCatchcopy::emitNewCopy(quint32 client,quint32 orderId,QStringList sources)
+{
+ emit newCopy(client,orderId,sources);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newCopy(newAssociation.globalOrderId,sources);
+}
+
+void ServerCatchcopy::emitNewCopy(quint32 client,quint32 orderId,QStringList sources,QString destination)
+{
+ emit newCopy(client,orderId,sources,destination);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newCopy(newAssociation.globalOrderId,sources,destination);
+}
+
+void ServerCatchcopy::emitNewMove(quint32 client,quint32 orderId,QStringList sources)
+{
+ emit newMove(client,orderId,sources);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newMove(newAssociation.globalOrderId,sources);
+}
+
+void ServerCatchcopy::emitNewMove(quint32 client,quint32 orderId,QStringList sources,QString destination)
+{
+ emit newMove(client,orderId,sources,destination);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newMove(newAssociation.globalOrderId,sources,destination);
+}
+
+void ServerCatchcopy::copyFinished(quint32 globalOrderId,bool withError)
+{
+ int index=0;
+ while(index<LinkGlobalToLocalClientList.size())
+ {
+ if(LinkGlobalToLocalClientList.at(index).globalOrderId==globalOrderId)
+ {
+ copyFinished(LinkGlobalToLocalClientList.at(index).idClient,LinkGlobalToLocalClientList.at(index).orderId,withError);
+ LinkGlobalToLocalClientList.removeAt(index);
+ orderList.removeOne(globalOrderId);
+ return;
+ }
+ index++;
+ }
+}
+
+void ServerCatchcopy::copyCanceled(quint32 globalOrderId)
+{
+ int index=0;
+ while(index<LinkGlobalToLocalClientList.size())
+ {
+ if(LinkGlobalToLocalClientList.at(index).globalOrderId==globalOrderId)
+ {
+ copyCanceled(LinkGlobalToLocalClientList.at(index).idClient,LinkGlobalToLocalClientList.at(index).orderId);
+ LinkGlobalToLocalClientList.removeAt(index);
+ orderList.removeOne(globalOrderId);
+ return;
+ }
+ index++;
+ }
+}
+
+void ServerCatchcopy::setAutoReply(bool value)
+{
+ autoReply=value;
+}
+
+bool ServerCatchcopy::getAutoReply()
+{
+ return autoReply;
+}
+
+void ServerCatchcopy::reply(quint32 client,quint32 orderId,quint32 returnCode,QString returnString)
+{
+ reply(client,orderId,returnCode,QStringList() << returnString);
+}
+
+void ServerCatchcopy::reply(quint32 client,quint32 orderId,quint32 returnCode,QStringList returnList)
+{
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).id==client)
+ {
+ if(ClientList.at(index).socket->isValid() && ClientList.at(index).socket->state()==QLocalSocket::ConnectedState)
+ {
+ if(!ClientList.at(index).queryNoReplied.contains(orderId))
+ {
+ qWarning() << "Reply to missing query or previously replied";
+ return;
+ }
+ ClientList[index].queryNoReplied.removeOne(orderId);
+ //cut string list and send it as block of 32KB
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_4);
+ out << int(0);
+ out << orderId;
+ out << returnCode;
+ out << returnList;
+ out.device()->seek(0);
+ out << block.size();
+ emit dataSend(client,orderId,returnCode,block);
+ emit dataSend(client,orderId,returnCode,returnList);
+ do
+ {
+ QByteArray blockToSend;
+ int byteWriten;
+ blockToSend=block.left(32*1024);//32KB
+ block.remove(0,blockToSend.size());
+ byteWriten = ClientList[index].socket->write(blockToSend);
+ if(!ClientList[index].socket->isValid())
+ {
+ error_string="Socket is not valid";
+ emit error(error_string);
+ return;
+ }
+ if(ClientList[index].socket->errorString()!="Unknown error" && ClientList[index].socket->errorString()!="")
+ {
+ error_string="Error with socket: "+ClientList[index].socket->errorString();
+ emit error(error_string);
+ return;
+ }
+ if(blockToSend.size()!=byteWriten)
+ {
+ error_string="All the bytes have not be written";
+ emit error(error_string);
+ return;
+ }
+ }
+ while(block.size());
+ }
+ else
+ {
+ error_string="Socket is not valid or not connected";
+ emit error(error_string);
+ }
+ return;
+ }
+ index++;
+ }
+ qWarning() << "Client id not found:" << client;
+}
+
+void ServerCatchcopy::protocolSupported(quint32 client,quint32 orderId,bool value)
+{
+ if(value)
+ reply(client,orderId,1000,"protocol supported");
+ else
+ reply(client,orderId,5003,"protocol not supported");
+}
+
+void ServerCatchcopy::incorrectArgumentListSize(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,5000,"incorrect argument list size");
+}
+
+void ServerCatchcopy::incorrectArgument(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,5001,"incorrect argument");
+}
+
+void ServerCatchcopy::protocolExtensionSupported(quint32 client,quint32 orderId,bool value)
+{
+ if(value)
+ reply(client,orderId,1001,"protocol extension supported");
+ else
+ reply(client,orderId,1002,"protocol extension not supported");
+}
+
+void ServerCatchcopy::clientRegistered(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,1003,"client registered");
+}
+
+void ServerCatchcopy::serverName(quint32 client,quint32 orderId,QString name)
+{
+ reply(client,orderId,1004,name);
+}
+
+void ServerCatchcopy::copyFinished(quint32 client,quint32 orderId,bool withError)
+{
+ if(!withError)
+ reply(client,orderId,1005,"finished");
+ else
+ reply(client,orderId,1006,"finished with error(s)");
+}
+
+void ServerCatchcopy::copyCanceled(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,1007,"canceled");
+}
+
+void ServerCatchcopy::unknowOrder(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,5002,"unknown order");
+}
+
+void ServerCatchcopy::checkTimeOut()
+{
+ QTimer *timer=qobject_cast<QTimer *>(QObject::sender());
+ if(timer==NULL)
+ {
+ qWarning() << "Unallocated client timer!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).detectTimeOut==timer)
+ {
+ ClientList.at(index).detectTimeOut->stop();
+ if(ClientList.at(index).haveData)
+ {
+ error_string="The client is too long to send the next part of the reply: "+ClientList.at(index).data;
+ ClientList[index].haveData=false;
+ ClientList[index].data.clear();
+ ClientList.at(index).socket->disconnectFromServer();
+ emit error(error_string);
+ }
+ return;
+ }
+ index++;
+ }
+}
+
+quint32 ServerCatchcopy::incrementOrderId()
+{
+ do
+ {
+ nextOrderId++;
+ if(nextOrderId>2000000)
+ nextOrderId=0;
+ } while(orderList.contains(nextOrderId));
+ return nextOrderId;
+}
diff --git a/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h
new file mode 100644
index 0000000..5f7af35
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h
@@ -0,0 +1,162 @@
+/** \file ServerCatchcopy.h
+\brief Define the server of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef SERVERCATCHCOPY_H
+#define SERVERCATCHCOPY_H
+
+#include <QObject>
+#include <QLocalSocket>
+#include <QLocalServer>
+#include <QStringList>
+#include <QString>
+#include <QByteArray>
+#include <QTimer>
+
+/// \brief Define the server of catchcopy
+class ServerCatchcopy : public QObject
+{
+ Q_OBJECT
+ public:
+ ServerCatchcopy();
+ ~ServerCatchcopy();
+ /// \brief return if is listening
+ bool isListening();
+ /// \brief try listen
+ bool listen();
+ /// \brief try close the server
+ void close();
+ /// \brief get the error string on the QLocalServer
+ const QString errorStringServer();
+ /// \brief get the general error string
+ const QString errorString();
+ /// \brief set if automatic reply is used
+ void setAutoReply(bool value);
+ /// \brief get if autoReply is set
+ bool getAutoReply();
+ /// \brief set the name of the server
+ void setName(const QString & name);
+ /// \brief get the name
+ QString getName();
+ private:
+ QString pathSocket;
+ QString name;
+ QString error_string;
+ QLocalServer server;
+ quint32 idNextClient;
+ struct Client
+ {
+ quint32 id;
+ QLocalSocket *socket;
+ QByteArray data;
+ bool haveData;
+ quint32 dataSize;
+ bool firstProtocolReplied;
+ QList<quint32> queryNoReplied;
+ QTimer *detectTimeOut;
+ };
+ QList<Client> ClientList;
+ struct LinkGlobalToLocalClient
+ {
+ quint32 idClient;
+ quint32 orderId;
+ quint32 globalOrderId;
+ };
+ QList<LinkGlobalToLocalClient> LinkGlobalToLocalClientList;
+ enum inputReturnType{Ok,Replied,ExtensionWrong,WrongArgument,WrongArgumentListSize,UnknowOrder};
+ inputReturnType parseInputCurrentProtocol(quint32 client,quint32 orderId,QStringList returnList);
+ bool autoReply;
+ bool clientIdFound(quint32 id);
+ quint32 nextOrderId;
+ QList<quint32> orderList;
+ quint32 incrementOrderId();
+ void emitNewCopy(quint32 client,quint32 orderId,QStringList sources);
+ void emitNewCopy(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ void emitNewMove(quint32 client,quint32 orderId,QStringList sources);
+ void emitNewMove(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ bool checkDataIntegrity(QByteArray data);
+ protected:
+ void parseInput(quint32 client,quint32 orderId,QStringList returnList);
+ private slots:
+ void newConnection();
+ void connectionError(QLocalSocket::LocalSocketError error);
+ void disconnected();
+ void readyRead();
+ void checkTimeOut();
+ public slots:
+ /// \brief disconnect one client
+ void disconnectClient(quint32 id);
+ /// \brief reply to a client with QStringList
+ void reply(quint32 client,quint32 orderId,quint32 returnCode,QStringList returnList);
+ /// \brief reply to a client
+ void reply(quint32 client,quint32 orderId,quint32 returnCode,QString returnString);
+ //reply
+ /// \brief send if the protocol is supported
+ void protocolSupported(quint32 client,quint32 orderId,bool value);
+ /// \brief send incorrect arguement list size
+ void incorrectArgumentListSize(quint32 client,quint32 orderId);
+ /// \brief send incorrect arguement
+ void incorrectArgument(quint32 client,quint32 orderId);
+ /// \brief send if protocol extension is supported
+ void protocolExtensionSupported(quint32 client,quint32 orderId,bool value);
+ /// \brief the client is registred
+ void clientRegistered(quint32 client,quint32 orderId);
+ /// \brief send the server name
+ void serverName(quint32 client,quint32 orderId,QString name);
+ /// \brief send the copy is finished
+ void copyFinished(quint32 client,quint32 orderId,bool withError);
+ /// \brief send the copy is canceled
+ void copyCanceled(quint32 client,quint32 orderId);
+ /// \brief send the copy is finished by global is order
+ void copyFinished(quint32 globalOrderId,bool withError);
+ /// \brief send copy cancel by global is order
+ void copyCanceled(quint32 globalOrderId);
+ /// \brief send the unknow order
+ void unknowOrder(quint32 client,quint32 orderId);
+ signals:
+ /// \brief send connected client
+ void connectedClient(quint32 id);
+ /// \brief send disconnect client
+ void disconnectedClient(quint32 id);
+ /// \brief have new query
+ void newQuery(quint32 client,quint32 orderId,QStringList returnList);
+ /// \brief send new data as string list
+ void dataSend(quint32 client,quint32 orderId,quint32 returnCode,QStringList returnList);
+ /// \brief send new data as raw data
+ void dataSend(quint32 client,quint32 orderId,quint32 returnCode,QByteArray block);
+ /// \brief have new error
+ void error(QString error);
+ //query
+ /// \brief ask the protocol compatility
+ void askProtocolCompatibility(quint32 client,quint32 orderId,QString version);
+ /// \brief ask protocol extension
+ void askProtocolExtension(quint32 client,quint32 orderId,QString extension);
+ /// \brief ask protocol extension with version
+ void askProtocolExtension(quint32 client,quint32 orderId,QString extension,QString version);
+ /// \brief send the client name, with query id
+ void clientName(quint32 client,quint32 orderId,QString name);
+ /// \brief send the client name, without query id
+ void clientName(quint32 client,QString name);
+ /// \brief send the client have ask the server name
+ void askServerName(quint32 client,quint32 orderId);
+ /// \brief copy is send, without destination
+ void newCopy(quint32 client,quint32 orderId,QStringList sources);
+ /// \brief copy is send, with destination
+ void newCopy(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ /// \brief move is send, without destination
+ void newMove(quint32 client,quint32 orderId,QStringList sources);
+ /// \brief move is send, with destination
+ void newMove(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ /// \brief copy is send, by globalOrderId, without destination
+ void newCopy(quint32 globalOrderId,QStringList sources);
+ /// \brief copy is send, by globalOrderId, with destination
+ void newCopy(quint32 globalOrderId,QStringList sources,QString destination);
+ /// \brief move is send, by globalOrderId, without destination
+ void newMove(quint32 globalOrderId,QStringList sources);
+ /// \brief move is send, by globalOrderId, with destination
+ void newMove(quint32 globalOrderId,QStringList sources,QString destination);
+};
+
+#endif // SERVERCATCHCOPY_H
diff --git a/test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h
new file mode 100644
index 0000000..ce73aee
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h
@@ -0,0 +1,14 @@
+/** \file VariablesCatchcopy.h
+\brief Define the variable for catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef VARIABLECATCHCOPY_H
+#define VARIABLECATCHCOPY_H
+
+#define CATCHCOPY_PROTOCOL_VERSION "0002"
+#define CATCHCOPY_COMMUNICATION_TIMEOUT 200
+
+#endif // VARIABLECATCHCOPY_H
+
diff --git a/test-client-catchcopy/catchcopy-api-0002/documentation.dox b/test-client-catchcopy/catchcopy-api-0002/documentation.dox
new file mode 100755
index 0000000..8ee4177
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/documentation.dox
@@ -0,0 +1,31 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- **/
+
+/*
+ This file contains NO source code, just some documentation for doxygen to
+ parse.
+*/
+
+/*!
+ \mainpage Catchcopy API
+
+ \section mainpage_overview Overview
+
+ This code is to interface with the catchcopy protocol, the code is provided by the catchcopy projet: <a href="http://catchcopy.first-world.info/">Catchcopy web site</a>
+
+ \section mainpage_platforms Platforms
+
+ This plugin might be usable in all environments where you find Qt 4.\n
+
+ \section mainpage_downloads Downloads
+
+ You can found link on <a href="http://ultracopier.first-world.info/">Ultracopier (Supercopier/Teracopy)</a> project page, via git, snapshot sources, ...
+
+ \section mainpage_algorithm Protocol
+
+ The protocol in version 0.0.0.2 is used, you can see the documentation on <a href="http://catchcopy.first-world.info/">Catchcopy web site</a>
+
+ \section license GPL Version 3
+ The code source is under GPL3. The image is extacted from Oxygen icon pack of KDE4.
+
+*/
+