1 /* 2 * sxesession.h - Sxe Session 3 * Copyright (C) 2007 Joonas Govenius 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 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 library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 */ 20 21 #ifndef SXDESESSION_H 22 #define SXDESESSION_H 23 24 #define SXENS "http://jabber.org/protocol/sxe" 25 /* ^^^^ make sure corresponds to NS used for parsing in iris/src/xmpp/xmpp-im/types.cpp ^^^^ */ 26 27 #include <QObject> 28 #include <QList> 29 #include <QPointer> 30 #include <QDomNode> 31 32 #include "im.h" 33 #include "psiaccount.h" 34 #include "sxerecord.h" 35 36 namespace XMPP { 37 class Client; 38 class Jid; 39 class Message; 40 } 41 42 using namespace XMPP; 43 44 class SxeManager; 45 46 /*! \brief Class for storing the record and the XML document for an established SXE session.*/ 47 class SxeSession : public QObject { 48 Q_OBJECT 49 50 // Make SxeManager a friend class so it can emit peerJoined/Left session. 51 friend class SxeManager; 52 53 private: 54 struct IncomingEdit { 55 QString id; 56 QDomElement xml; 57 }; 58 59 public: 60 /*! \brief Constructor. 61 * Creates a new session for the specified jid and session identifier. 62 */ 63 SxeSession(SxeManager *manager, const Jid &target, const QString &session, const Jid &ownJid, bool groupChat, bool serverSupport, const QList<QString> &features); 64 /*! \brief Destructor. 65 * Emits sessionEnded() 66 */ 67 ~SxeSession(); 68 69 /*! \brief Initializes the shared document. Only used if starting a new session; not when joining one. */ 70 void initializeDocument(const QDomDocument &doc); 71 /*! \brief Processes the incoming SXE element and remembers its identifying information.*/ 72 void processIncomingSxeElement(const QDomElement &, const QString &id); 73 /*! \brief Returns a const reference to the target document.*/ 74 const QDomDocument& document() const; 75 /*! \brief Returns true if the target is a groupchat.*/ 76 bool groupChat() const; 77 /*! \brief Returns true if the target is a groupchat.*/ 78 bool serverSupport() const; 79 /*! \brief Returns the target contact's JID.*/ 80 const Jid target() const; 81 /*! \brief Returns the session identifier.*/ 82 const QString session() const; 83 /*! \brief Returns the JID used by the user in the session.*/ 84 const Jid ownJid() const; 85 /*! \brief Returns the session identifier.*/ 86 const QList<QString> features() const; 87 88 /*! \brief Starts queueing new edits to the document. 89 * Queueing should be started just before sending <document-begin/>. 90 */ 91 QList<const SxeEdit*> startQueueing(); 92 /*! \brief Stop queueing new edits to the document and process the queued ones. 93 * Queueing should be stopped after sending <document-end/>. 94 */ 95 void stopQueueing(); 96 97 /*! \brief Initializes the document with the prolog of \a doc if provided. 98 * Should be used when <document-begin/> is received when joining. 99 */ 100 void startImporting(const QDomDocument &doc = QDomDocument()); 101 /*! \brief Enters the normal editing mode. 102 * Should be used when <document-end/> is received when joining. 103 */ 104 void stopImporting(); 105 106 /*! \brief Add the given ID to the list of used IDs for <sxe/> elements.*/ 107 void addUsedSxeId(QString id); 108 /*! \brief Return the list of used IDs for <sxe/> elements.*/ 109 QList<QString> usedSxeIds(); 110 111 void setUUIDPrefix(const QString uuidPrefix = QString()); 112 /*! \brief Returns a random UUID without enclosing { }. */ 113 static QString generateUUID(); 114 /*! \brief Returns the prolog of the document as a string. */ 115 static QString parseProlog(const QDomDocument &doc); 116 117 public slots: 118 /*! \brief Ends the session.*/ 119 void endSession(); 120 /*! \brief Inserts or moves the given node so that it is before the reference element. 121 * If the reference element is the null element the element is inserted as the first child of the parent. 122 * Returns \a node if the node was already in the document. Otherwise returns the created node. 123 */ 124 const QDomNode insertNodeBefore(const QDomNode &node, const QDomNode &parent, const QDomNode &referenceNode = QDomNode()); 125 /*! \brief Inserts or moves the given node so that it is after the reference element. 126 * If the reference element is the null element the element is inserted as the last child of the parent. 127 * Returns \a node if the node was already in the document. Otherwise returns the created node. 128 */ 129 const QDomNode insertNodeAfter(const QDomNode &node, const QDomNode &parent, const QDomNode &referenceNode = QDomNode()); 130 /*! \brief Removes the given element.*/ 131 void removeNode(const QDomNode &node); 132 /*! \brief Sets the value of \a attribute of \a node to \a value. */ 133 void setAttribute(const QDomNode &node, const QString &attribute, const QString &value, int from = -1, int n = 0); 134 /*! \brief Sets the value of \a node to \a value. */ 135 void setNodeValue(const QDomNode &node, const QString &value, int from = -1, int n = 0); 136 137 /*! \brief Sends all queued edits.*/ 138 void flush(); 139 140 signals: 141 /*! \brief used to pass the new <sxe/> elements to sxemanager.*/ 142 void newSxeElement(const QDomElement &element, const Jid &, bool groupChat); 143 144 /*! \brief Emitted after each processed SXE element.*/ 145 void documentUpdated(bool remote); 146 /*! \brief Emitted just before \a node is inserted.*/ 147 void nodeToBeAdded(const QDomNode &node, bool remote); 148 /*! \brief Emitted after \a node is inserted.*/ 149 void nodeAdded(const QDomNode &node, bool remote); 150 /*! \brief Emitted just before \a node is moved in the document tree due to processing of an SXE element.*/ 151 void nodeToBeMoved(const QDomNode &node, bool remote); 152 /*! \brief Emitted after \a node has been moved in the document tree due to processing of an SXE element.*/ 153 void nodeMoved(const QDomNode &node, bool remote); 154 /*! \brief Emitted just before \a node is removed from the document tree due to processing of an SXE element.*/ 155 void nodeToBeRemoved(const QDomNode &node, bool remote); 156 /*! \brief Emitted after \a node has been removed from the document tree due to processing of an SXE element.*/ 157 void nodeRemoved(const QDomNode &node, bool remote); 158 /*! \brief Emitted when the name of \a node has been changed. */ 159 // void nameChanged(const QDomNode &node, bool remote); 160 /*! \brief Emitted just before the chdata of \a node is changed. */ 161 void chdataToBeChanged(const QDomNode &node, bool remote); 162 /*! \brief Emitted when the chdata of \a node has been changed. */ 163 void chdataChanged(const QDomNode &node, bool remote); 164 165 /*! \brief Signals that a peer joined the session.*/ 166 void peerJoinedSession(const Jid &); 167 /*! \brief Signals that a peer left the session.*/ 168 void peerLeftSession(const Jid &); 169 /*! \brief Signals that the session ended and the session is to be deleted.*/ 170 void sessionEnded(SxeSession*); 171 172 private slots: 173 /*! \brief Adds \a node to the document tree and emits the appropriate public signals. */ 174 void handleNodeToBeAdded(const QDomNode &node, bool remote); 175 /*! \brief Moves \a node in the document tree and emits the appropriate public signals. */ 176 void handleNodeToBeMoved(const QDomNode &node, bool remote); 177 /*! \brief Remove the record entry from the lookup tables and emit the appropriate public signals. */ 178 void handleNodeToBeRemoved(const QDomNode &node, bool remote); 179 /*! \brief Add a node node to the lookup table. */ 180 // void addToLookup(const QDomNode &node, bool, const QString &rid); 181 182 private: 183 /*! \brief Inserts or moves a node according to it's record (parent and primary-weight). */ 184 void reposition(const QDomNode &node, bool remote); 185 /*! \brief Remove the record associated with \a node from the lookup tables. */ 186 void removeRecord(const QDomNode &node); 187 /*! \brief Remove the item with smaller secondary weight. 188 Returns true iff \a meta1 was removed. */ 189 bool removeSmaller(SxeRecord* meta1, SxeRecord* meta2); 190 /*! \brief Processes an incoming sxe element.*/ 191 bool processSxe(const QDomElement &sxe, const QString &id); 192 /*! \brief Queues an outgoing edit to be sent when flushed.*/ 193 void queueOutgoingEdit(SxeEdit* edit); 194 /*! \brief Creates the record of node with rid \a id. Returns a pointer to it. */ 195 SxeRecord* createRecord(const QString &id); 196 /*! \brief Returns a pointer to the record of node with rid \a id. */ 197 SxeRecord* record(const QString &id); 198 /*! \brief Returns a pointer to the record of \a node. */ 199 SxeRecord* record(const QDomNode &node) const; 200 /*! \brief Generates SxeNewEdits for \a node and its children. 201 * Returns the created node. */ 202 QDomNode generateNewNode(const QDomNode node, const QString &parent, double primaryWeight); 203 /*! \brief Generates SxeRemoveEdits for \a node and its children. */ 204 void generateRemoves(const QDomNode &node); 205 /*! \brief Recursive helper method for arranging edits for the snapshot. */ 206 void arrangeEdits(QHash<QString, QString> &ridByParent, QList<const SxeEdit*> &output, const QString &iterator); 207 /*! \brief Insert node with the given primaryWeight. 208 * Returns node if the node was already in the document. Otherwise returns the created node. */ 209 const QDomNode insertNode(const QDomNode &node, const QString &parentId, double primaryWeight); 210 /*! \brief Returns a random UUID without enclosing { } and checks that it's not used as a rid. 211 Necessary because you often generate the same UUID on two different processes on the same computer (non-windows). */ 212 QString generateUUIDForSession(); 213 214 /*! \brief The string identifying the session.*/ 215 QString session_; 216 /*! \brief The target JID.*/ 217 Jid target_; 218 /*! \brief The target JID.*/ 219 Jid ownJid_; 220 /*! \brief The target XML document.*/ 221 QDomDocument document_; 222 223 /*! \brief Hash used for rid -> SxeRecord* lookups.*/ 224 QHash< 225 QString, 226 SxeRecord* 227 > recordByNodeId_; 228 /*! \brief List of queued incoming sxe elements.*/ 229 QList<IncomingEdit> queuedIncomingEdits_; 230 /*! \brief List of queued outgoing sxe elements.*/ 231 QList<QDomNode> queuedOutgoingEdits_; 232 /*! \brief QDomDocument representing the the contents when queueing_ was set true.*/ 233 QList<SxeEdit*> snapshot_; 234 /*! \brief True if the target is a groupchat.*/ 235 bool groupChat_; 236 /*! \brief True if the session was not established with a server supporting SXE.*/ 237 bool serverSupport_; 238 /*! \brief If true, new sxe elements are queued rather than processed.*/ 239 bool queueing_; 240 /*! \brief True while initial contents of the document are being imported.*/ 241 bool importing_; 242 /*! \brief A list of supported features for the session.*/ 243 QList<QString> features_; 244 /*! \brief Identifiers for the <sxe/> elements that have been processed already.*/ 245 QList<QString> usedSxeIds_; 246 /*! \brief A unique id is generated as "uuidPrefix.counter".*/ 247 QString uuidPrefix_; 248 int uuidMaxPostfix_; 249 /*! \brief The main DOM document.*/ 250 QDomDocument doc_; 251 }; 252 253 #endif 254