diff --git a/README.txt b/README.txt index 1b95ef7c5..2dff121e9 100644 --- a/README.txt +++ b/README.txt @@ -1,42 +1,38 @@ To use this branch: - chekcout the last version of openpgp SDK: - # svn co svn://openpgp.nominet.org.uk/openpgpsdk/tags/openpgpsdk-0.9 openpgpsdk - # cd openpgpsdk - # ./configure --without-idea - # make + - get source code for libssh-0.5.2, unzip it, and create build directory (if needed) - For the moment, the compilation is not workign on ubuntu + # wget http://www.libssh.org/files/0.5/libssh-0.5.2.tar.gz + # tar zxvf libssh-0.5.2.tar.gz + # cd libssh-0.5.2 + # mkdir build + # cd build + # cmake -DWITH_STATIC_LIB=ON .. + # make + # cd ../.. + + - build the google proto files -Work to do -========== -Put a 'x' when done. 1,2,3 means started/ongoing/almost finished. + # cd rsctrl/src + # make -Compilation - 00 [1] make sure the library compiles on linux - 01 [ ] make sure the library compiles on windows + Don't bother about python related errors. -Project - 02 [1] determine what's missing in OpenPGP-SDK - 03 [3] make a separate layer in RS to handle PGP. AuthPGP is too close to libretroshare. - 04 [1] write the new AuthGPG class - 05 [ ] consider removing thread behaviour of AuthGPG - 06 [ ] remove callback system and services from AuthGPG, since it's not useful anymore - 07 [ ] make all RS use GPGIdType isntead of std::string. + - go to retroshare-nogui, and compile it -Notes -===== - Questions to answer: - - do we rely on updates from openPGP-sdk ? Probably not. This code seems frozen. - - do we need an abstract layer for PGP handling in RS ? - - what new functionalities do we need in RS ? - * pgp keyring sharing/import/export - * identity import/export + # cd ../../retroshare-nogui + # qmake + # make - Code struture - - replace current AuthGPG (virtual class) by a class named GPGHandler, - that is responsible for signing, checking signatures, encrypting etc. - - add a specific 8-bytes type for GPG Ids. Could be a uint64_t, or a - uchar[8] + - to use the SSH RS server: + + # ssh-keygen -t rsa -f rs_ssh_host_rsa_key # this makes a RSA + # ./retroshare-nogui -G # generates a login+passwd hash for the RSA key used. + # ./retroshare-nogui -S 7022 -U[SSLid] -P [Passwd hash] + - to connect from a remote place to the server by SSH: + + # ssh -T -p 7022 [user]@[host] + + and use the command line interface to control your RS instance. diff --git a/libbitdht/src/bitdht/bdmanager.cc b/libbitdht/src/bitdht/bdmanager.cc index 0803899ea..4659486f6 100644 --- a/libbitdht/src/bitdht/bdmanager.cc +++ b/libbitdht/src/bitdht/bdmanager.cc @@ -87,6 +87,8 @@ bdNodeManager::bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string b mFns->bdPrintNodeId(std::cerr, id); std::cerr << std::endl; #endif + + mLocalNetEnhancements = true; } int bdNodeManager::stopDht() @@ -400,34 +402,39 @@ void bdNodeManager::iteration() std::cerr << std::endl; #endif - /* run a random search for ourselves, from own App DHT peer */ - QueryRandomLocalNet(); + /* This stuff is only important for "LocalNet based Features */ + if (mLocalNetEnhancements) + { + /* run a random search for ourselves, from own App DHT peer */ + QueryRandomLocalNet(); + #define SEARCH_MAX_SIZE 10 - if (mBdNetworkSize < SEARCH_MAX_SIZE) - { -#ifdef DEBUG_MGR - std::cerr << "Local Netsize: " << mBdNetworkSize << " to small...searching"; - std::cerr << std::endl; -#endif - - /* if the network size is very small */ - SearchForLocalNet(); - mSearchingDone = false; - } - else - { - if (!mSearchingDone) + if (mBdNetworkSize < SEARCH_MAX_SIZE) { - mSearchingDone = true; - mSearchTS = now; #ifdef DEBUG_MGR - std::cerr << "Completed LocalNet Search in : " << mSearchTS-mStartTS; + std::cerr << "Local Netsize: " << mBdNetworkSize << " to small...searching"; std::cerr << std::endl; #endif + + /* if the network size is very small */ + SearchForLocalNet(); + mSearchingDone = false; + } + else + { + if (!mSearchingDone) + { + mSearchingDone = true; + mSearchTS = now; +#ifdef DEBUG_MGR + std::cerr << "Completed LocalNet Search in : " << mSearchTS-mStartTS; + std::cerr << std::endl; +#endif + } } } - + #ifdef DEBUG_MGR std::cerr << "bdNodeManager::iteration(): REFRESH "; std::cerr << std::endl; diff --git a/libbitdht/src/bitdht/bdmanager.h b/libbitdht/src/bitdht/bdmanager.h index 635a5eb3f..a43a88342 100644 --- a/libbitdht/src/bitdht/bdmanager.h +++ b/libbitdht/src/bitdht/bdmanager.h @@ -187,6 +187,8 @@ void SearchForLocalNet(); bdBloom mBloomFilter; + bool mLocalNetEnhancements; + /* future node functions */ //addPeerPing(foundId); //clearPing(it->first); diff --git a/libbitdht/src/example/Makefile b/libbitdht/src/example/Makefile index 2585c28b6..447407bb9 100644 --- a/libbitdht/src/example/Makefile +++ b/libbitdht/src/example/Makefile @@ -6,11 +6,11 @@ LIBS = -L../lib -lbitdht -lpthread -EXEC : bdexample +EXEC : bssdht -EGOBJ = bdhandler.o bdexample.o +EGOBJ = bdhandler.o bssdht.o bootstrap_fn.o -bdexample: $(EGOBJ) - $(CXX) $(CXXFLAGS) -o bdexample $(EGOBJ) $(LIBS) +bssdht: $(EGOBJ) + $(CXX) $(CXXFLAGS) -o bssdht $(EGOBJ) $(LIBS) diff --git a/libbitdht/src/example/bdexample.cc b/libbitdht/src/example/bdexample.cc deleted file mode 100644 index 0c965eabd..000000000 --- a/libbitdht/src/example/bdexample.cc +++ /dev/null @@ -1,42 +0,0 @@ - - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bdhandler.h" - -int main(int argc, char **argv) -{ - - /* startup dht : with a random id! */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - uint16_t port = 6775; - std::string appId = "exId"; - std::string bootstrapfile = "bdboot.txt"; - - BitDhtHandler dht(&ownId, port, appId, bootstrapfile); - - /* run your program */ - while(1) - { - bdNodeId searchId; - bdStdRandomNodeId(&searchId); - - dht.FindNode(&searchId); - - sleep(180); - - dht.DropNode(&searchId); - } - - return 1; -} - - - - - - - - diff --git a/libbitdht/src/example/bdhandler.cc b/libbitdht/src/example/bdhandler.cc index 21a3b626f..0b8766a5a 100644 --- a/libbitdht/src/example/bdhandler.cc +++ b/libbitdht/src/example/bdhandler.cc @@ -29,8 +29,24 @@ #include #include +#include + #include "bdhandler.h" + +/**** + * This example bitdht app is designed to perform a single shot DHT search. + * Ww want to minimise the dht work, and number of UDP packets sent. + * + * This means we need to add: + * - don't search for App network. (libbitdht option) + * - don't bother filling up Space. (libbitdht option) + * - Programmatically add bootstrap peers. (libbitdht option) + * + */ + + + /* This is a conversion callback class */ @@ -111,6 +127,11 @@ BitDhtHandler::BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, mUdpBitDht->start(); /* starts up the bitdht thread */ + /* setup best mode for quick search */ + uint32_t dhtFlags = BITDHT_MODE_TRAFFIC_MED | BITDHT_MODE_RELAYSERVERS_IGNORED; + mUdpBitDht->setDhtMode(dhtFlags); + mUdpBitDht->setAttachMode(false); + /* switch on the dht too */ mUdpBitDht->startDht(); } @@ -163,8 +184,19 @@ bool BitDhtHandler::FindNode(bdNodeId *peerId) bdStdPrintNodeId(std::cerr, peerId); std::cerr << ")" << std::endl; + + BssResult res; + res.id.id = *peerId; + res.mode = BSS_SINGLE_SHOT; + res.status = 0; + + { + bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ + mSearchNodes[*peerId] = res; + } + /* add in peer */ - mUdpBitDht->addFindNode(peerId, BITDHT_QFLAGS_DO_IDLE); + mUdpBitDht->addFindNode(peerId, BITDHT_QFLAGS_DISGUISE); return true ; } @@ -179,10 +211,50 @@ bool BitDhtHandler::DropNode(bdNodeId *peerId) /* remove in peer */ mUdpBitDht->removeFindNode(peerId); + bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ + + /* find the node from our list */ + std::map::iterator it; + it = mSearchNodes.find(*peerId); + if (it != mSearchNodes.end()) + { + std::cerr << "BitDhtHandler::DropNode() Found NodeId, removing"; + std::cerr << std::endl; + + mSearchNodes.erase(it); + } return true ; } +bool BitDhtHandler::SearchResult(bdId *id, uint32_t &status) +{ + bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ + + /* find the node from our list */ + std::map::iterator it; + it = mSearchNodes.find(id->id); + if (it != mSearchNodes.end()) + { + if (it->second.status != 0) + { + std::cerr << "BitDhtHandler::SearchResults() Found Results"; + std::cerr << std::endl; + status = it->second.status; + *id = it->second.id; + return true; + } + + std::cerr << "BitDhtHandler::SearchResults() No Results Yet"; + std::cerr << std::endl; + return false; + } + + std::cerr << "BitDhtHandler::SearchResults() ERROR: No Search Entry"; + std::cerr << std::endl; + return false; +} + /********************** Callback Functions **************************/ @@ -204,6 +276,20 @@ int BitDhtHandler::PeerCallback(const bdId *id, uint32_t status) bdStdPrintId(std::cerr, id); std::cerr << std::endl; + bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ + + /* find the node from our list */ + std::map::iterator it; + it = mSearchNodes.find(id->id); + if (it == mSearchNodes.end()) + { + std::cerr << "BitDhtHandler::PeerCallback() Unknown NodeId !!! "; + std::cerr << std::endl; + + return 1; + } + it->second.status = status; + bool connect = false; switch(status) { @@ -212,6 +298,7 @@ int BitDhtHandler::PeerCallback(const bdId *id, uint32_t status) std::cerr << "BitDhtHandler::PeerCallback() QUERY FAILURE ... do nothin "; std::cerr << std::endl; + break; case BITDHT_MGR_QUERY_PEER_OFFLINE: @@ -225,19 +312,19 @@ int BitDhtHandler::PeerCallback(const bdId *id, uint32_t status) case BITDHT_MGR_QUERY_PEER_UNREACHABLE: /* do nothing */ - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER UNREACHABLE ... flag? / do nothin "; + std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER UNREACHABLE ... saving address "; std::cerr << std::endl; - + it->second.id = *id; break; case BITDHT_MGR_QUERY_PEER_ONLINE: /* do something */ - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER ONLINE ... try udp connection"; + std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER ONLINE ... saving address"; std::cerr << std::endl; - connect = true; + it->second.id = *id; break; } return 1; diff --git a/libbitdht/src/example/bdhandler.h b/libbitdht/src/example/bdhandler.h index e2ad55dc8..c0c942db6 100644 --- a/libbitdht/src/example/bdhandler.h +++ b/libbitdht/src/example/bdhandler.h @@ -37,6 +37,18 @@ /*** This class can be overloaded to use the XXXXCallback() Functions *****/ class BitDhtIntCallback; + +class BssResult +{ + public: + bdId id; + uint32_t mode; // single shot + uint32_t status; // SEARCHING, FAILURE, FOUND, MULTIPLE HITS. +}; + +#define BSS_SINGLE_SHOT 0x0001 + + class BitDhtHandler { @@ -58,12 +70,17 @@ virtual int NodeCallback(const bdId *id, uint32_t peerflags); virtual int PeerCallback(const bdId *id, uint32_t status); virtual int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); +bool SearchResult(bdId *id, uint32_t &status); + private: /* real DHT classes */ UdpStack *mStack; UdpBitDht *mUdpBitDht; + bdMutex resultsMtx; /* for all class data (below) */ + + std::map mSearchNodes; }; diff --git a/libbitdht/src/example/bootstrap_fn.cc b/libbitdht/src/example/bootstrap_fn.cc new file mode 100644 index 000000000..e58d9a10a --- /dev/null +++ b/libbitdht/src/example/bootstrap_fn.cc @@ -0,0 +1,60 @@ + + +#include "bitdht/bdiface.h" +#include "bitdht/bdstddht.h" +#include "bdhandler.h" + +#include "bootstrap_fn.h" + +bool bdSingleShotFindPeer(const std::string bootstrapfile, const std::string peerId, std::string &peer_ip, uint16_t &peer_port) +{ + /* startup dht : with a random id! */ + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + + uint16_t port = 6775; + std::string appId = "bsId"; + BitDhtHandler dht(&ownId, port, appId, bootstrapfile); + + /* install search node */ + bdNodeId searchId; + bdStdRandomNodeId(&searchId); + + std::cerr << "bssdht: searching for Id: "; + bdStdPrintNodeId(std::cerr, &searchId); + std::cerr << std::endl; + + dht.FindNode(&searchId); + + /* run your program */ + bdId resultId; + uint32_t status; + + resultId.id = searchId; + + while(false == dht.SearchResult(&resultId, status)) + { + sleep(10); + } + + std::cerr << "bdSingleShotFindPeer(): Found Result:" << std::endl; + + std::cerr << "\tId: "; + bdStdPrintId(std::cerr, &resultId); + std::cerr << std::endl; + + std::cerr << "\tstatus: " << status; + std::cerr << std::endl; + + dht.shutdown(); + + return true; +} + + + + + + + + diff --git a/libbitdht/src/example/bootstrap_fn.h b/libbitdht/src/example/bootstrap_fn.h new file mode 100644 index 000000000..19ff6d714 --- /dev/null +++ b/libbitdht/src/example/bootstrap_fn.h @@ -0,0 +1,17 @@ + +#include +#include + + +/* NOTE. At the moment only the bootstrapfile is actually used. + * peerId is ignored (a random peerId is searched for). ip & port are not filled in either. + * + * This is mainly to finish testing. + * + * Once the best form of the return functions is decided (ipv4 structure, or strings). + * this can be finished off. + * + */ + +bool bdSingleShotFindPeer(const std::string bootstrapfile, const std::string peerId, std::string &ip, uint16_t &port); + diff --git a/libbitdht/src/example/bssdht.cc b/libbitdht/src/example/bssdht.cc new file mode 100644 index 000000000..9d5f0e4e7 --- /dev/null +++ b/libbitdht/src/example/bssdht.cc @@ -0,0 +1,31 @@ + +#include "bootstrap_fn.h" +#include +#include + +int main(int argc, char **argv) +{ + + std::string bootstrapfile = "bdboot.txt"; + std::string peerId; + std::string ip; + uint16_t port; + + std::cerr << "bssdht: starting up"; + std::cerr << std::endl; + + bdSingleShotFindPeer(bootstrapfile, peerId, ip, port); + + std::cerr << "bssdht: finished"; + std::cerr << std::endl; + + return 1; +} + + + + + + + + diff --git a/libretroshare/src/dbase/fimonitor.cc b/libretroshare/src/dbase/fimonitor.cc index 49437a23f..6cb29aa9c 100644 --- a/libretroshare/src/dbase/fimonitor.cc +++ b/libretroshare/src/dbase/fimonitor.cc @@ -23,6 +23,7 @@ #ifdef WINDOWS_SYS #include "util/rsstring.h" +#include "util/rswin.h" #endif #include "dbase/fimonitor.h" diff --git a/libretroshare/src/ft/ftfileprovider.cc b/libretroshare/src/ft/ftfileprovider.cc index 5d5232ae5..c17d291c6 100644 --- a/libretroshare/src/ft/ftfileprovider.cc +++ b/libretroshare/src/ft/ftfileprovider.cc @@ -1,3 +1,7 @@ +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif // WINDOWS_SYS + #include "ftfileprovider.h" #include "ftchunkmap.h" @@ -5,10 +9,6 @@ #include #include -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif // WINDOWS_SYS - /******** * #define DEBUG_FT_FILE_PROVIDER 1 * #define DEBUG_TRANSFERS 1 // TO GET TIMESTAMPS of DATA READING diff --git a/libretroshare/src/gxs/gxscoreserver.cc b/libretroshare/src/gxs/gxscoreserver.cc index c4068164c..024e7d9df 100644 --- a/libretroshare/src/gxs/gxscoreserver.cc +++ b/libretroshare/src/gxs/gxscoreserver.cc @@ -1,10 +1,30 @@ + /* - * gxscoreserver.cpp + * libretroshare/src/gxs: gxscoreserver.cc + * + * General Data service, interface for RetroShare. + * + * Copyright 2011-2011 by Evi-Parker Christopher + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". * - * Created on: 24 Jul 2012 - * Author: crispy */ + #include "gxscoreserver.h" GxsCoreServer::GxsCoreServer() @@ -28,10 +48,12 @@ void GxsCoreServer::run() { std::set::iterator sit; - double timeDelta = 0.2; + double timeDelta = 0.02; while(isRunning()) { + for(sit = mGxsServices.begin(); sit != mGxsServices.end(); sit++) + (*sit)->tick(); #ifndef WINDOWS_SYS usleep((int) (timeDelta * 1000000)); @@ -39,9 +61,6 @@ void GxsCoreServer::run() Sleep((int) (timeDelta * 1000)); #endif - for(sit = mGxsServices.begin(); sit != mGxsServices.end(); sit++) - (*sit)->tick(); - } } diff --git a/libretroshare/src/gxs/gxscoreserver.h b/libretroshare/src/gxs/gxscoreserver.h index b0534e38d..664a93f8a 100644 --- a/libretroshare/src/gxs/gxscoreserver.h +++ b/libretroshare/src/gxs/gxscoreserver.h @@ -1,17 +1,37 @@ -/* - * gxscoreserver.h - * - * Created on: 24 Jul 2012 - * Author: crispy - */ - #ifndef GXSCORESERVER_H_ #define GXSCORESERVER_H_ +/* + * libretroshare/src/gxs: gxscoreserver.h + * + * General Data service, interface for RetroShare. + * + * Copyright 2011-2011 by Evi-Parker Christopher + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + #include "util/rsthreads.h" #include "gxs/rsgxs.h" -class GxsCoreServer : RsThread { +class GxsCoreServer : public RsThread +{ public: GxsCoreServer(); ~GxsCoreServer(); diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc new file mode 100644 index 000000000..f0e4b9be7 --- /dev/null +++ b/libretroshare/src/gxs/gxssecurity.cc @@ -0,0 +1,400 @@ + +/* + * libretroshare/src/gxs: gxssecurity.cc + * + * + * Copyright 2008-2010 by Robert Fernie + * 2011-2012 Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "gxssecurity.h" +#include "pqi/authgpg.h" +#include "retroshare/rspeers.h" + +#define GXS_SECURITY_DEBUG + +GxsSecurity::GxsSecurity() +{ +} + +GxsSecurity::~GxsSecurity() +{ +} + +RSA *GxsSecurity::extractPublicKey(RsTlvSecurityKey& key) +{ + const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; + long keylen = key.keyData.bin_len; + + /* extract admin key */ + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); + + return rsakey; +} + +bool GxsSecurity::getSignature(char* data, uint32_t data_len, RsTlvSecurityKey* privKey, RsTlvKeySignature& sign) +{ + RSA* rsa_pub = extractPrivateKey(*privKey); + EVP_PKEY *key_pub = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(key_pub, rsa_pub); + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + bool ok = EVP_SignInit(mdctx, EVP_sha1()) == 1; + ok &= EVP_SignUpdate(mdctx, data, data_len) == 1; + + unsigned int siglen = EVP_PKEY_size(key_pub); + unsigned char sigbuf[siglen]; + ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_pub) == 1; + + // clean up + EVP_MD_CTX_destroy(mdctx); + EVP_PKEY_free(key_pub); + + sign.signData.setBinData(sigbuf, siglen); + sign.keyId = privKey->keyId; + + return ok; +} + +bool GxsSecurity::validateNxsMsg(RsNxsMsg& msg, RsTlvKeySignature& sign, RsTlvSecurityKey& key) +{ + #ifdef GXS_SECURITY_DEBUG + std::cerr << "GxsSecurity::validateNxsMsg()"; + std::cerr << std::endl; + std::cerr << "RsNxsMsg :"; + std::cerr << std::endl; + msg.print(std::cerr, 10); + std::cerr << std::endl; + #endif + + RsGxsMsgMetaData& msgMeta = *(msg.metaData); + + // /********************* check signature *******************/ + + /* check signature timeperiod */ + if ((msgMeta.mPublishTs < key.startTS) || + (msgMeta.mPublishTs > key.endTS)) + { + #ifdef GXS_SECURITY_DEBUG + std::cerr << " GxsSecurity::validateNxsMsg() TS out of range"; + std::cerr << std::endl; + #endif + return false; + } + + /* decode key */ + const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; + long keylen = key.keyData.bin_len; + unsigned int siglen = sign.signData.bin_len; + unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data; + + #ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity::validateNxsMsg() Decode Key"; + std::cerr << " keylen: " << keylen << " siglen: " << siglen; + std::cerr << std::endl; + #endif + + /* extract admin key */ + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); + + if (!rsakey) + { + #ifdef GXS_SECURITY_DEBUG + std::cerr << "GxsSecurity::validateNxsMsg()"; + std::cerr << " Invalid RSA Key"; + std::cerr << std::endl; + + key.print(std::cerr, 10); + #endif + } + + + RsTlvKeySignatureSet signSet = msgMeta.signSet; + msgMeta.signSet.TlvClear(); + + uint32_t metaDataLen = msgMeta.serial_size(); + uint32_t allMsgDataLen = metaDataLen + msg.msg.bin_len; + char* metaData = new char[metaDataLen]; + char* allMsgData = new char[allMsgDataLen]; // msgData + metaData + + msgMeta.serialise(metaData, &metaDataLen); + + // copy msg data and meta in allmsgData buffer + memcpy(allMsgData, msg.msg.bin_data, msg.msg.bin_len); + memcpy(allMsgData+(msg.msg.bin_len), metaData, metaDataLen); + + + EVP_PKEY *signKey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(signKey, rsakey); + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_VerifyInit(mdctx, EVP_sha1()); + EVP_VerifyUpdate(mdctx, allMsgData, allMsgDataLen); + int signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); + + /* clean up */ + EVP_PKEY_free(signKey); + EVP_MD_CTX_destroy(mdctx); + + + if (signOk == 1) + { + #ifdef GXS_SECURITY_DEBUG + std::cerr << "GxsSecurity::validateNxsMsg() Signature OK"; + std::cerr << std::endl; + #endif + return true; + } + + #ifdef GXS_SECURITY_DEBUG + std::cerr << "GxsSecurity::validateNxsMsg() Signature invalid"; + std::cerr << std::endl; + #endif + + return false; +} + + + +std::string GxsSecurity::getBinDataSign(void *data, int len) +{ + unsigned char *tmp = (unsigned char *) data; + + // copy first CERTSIGNLEN bytes... + if (len > CERTSIGNLEN) + { + len = CERTSIGNLEN; + } + + std::string id; + for(uint32_t i = 0; i < CERTSIGNLEN; i++) + { + rs_sprintf_append(id, "%02x", (uint16_t) (((uint8_t *) (tmp))[i])); + } + + return id; +} + + + +bool GxsSecurity::encrypt(void *& out, int & outlen, const void *in, int inlen, EVP_PKEY *privateKey) +{ + + +#ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity::encrypt() " << std::endl; +#endif + + RSA *rsa_publish_pub = NULL; + EVP_PKEY *public_key = NULL; + + RSA* rsa_publish = EVP_PKEY_get1_RSA(privateKey); + rsa_publish_pub = RSAPublicKey_dup(rsa_publish); + + + if(rsa_publish_pub != NULL){ + public_key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(public_key, rsa_publish_pub); + }else{ +#ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity(): Could not generate publish key " << grpId + << std::endl; +#endif + return false; + } + + EVP_CIPHER_CTX ctx; + int eklen, net_ekl; + unsigned char *ek; + unsigned char iv[EVP_MAX_IV_LENGTH]; + EVP_CIPHER_CTX_init(&ctx); + int out_currOffset = 0; + int out_offset = 0; + + int max_evp_key_size = EVP_PKEY_size(public_key); + ek = (unsigned char*)malloc(max_evp_key_size); + const EVP_CIPHER *cipher = EVP_aes_128_cbc(); + int cipher_block_size = EVP_CIPHER_block_size(cipher); + int size_net_ekl = sizeof(net_ekl); + + int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; + + // intialize context and send store encrypted cipher in ek + if(!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) return false; + + // now assign memory to out accounting for data, and cipher block size, key length, and key length val + out = new unsigned char[inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH]; + + net_ekl = htonl(eklen); + memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); + out_offset += size_net_ekl; + + memcpy((unsigned char*)out + out_offset, ek, eklen); + out_offset += eklen; + + memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); + out_offset += EVP_MAX_IV_LENGTH; + + // now encrypt actual data + if(!EVP_SealUpdate(&ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) return false; + + // move along to partial block space + out_offset += out_currOffset; + + // add padding + if(!EVP_SealFinal(&ctx, (unsigned char*) out + out_offset, &out_currOffset)) return false; + + // move to end + out_offset += out_currOffset; + + // make sure offset has not gone passed valid memory bounds + if(out_offset > max_outlen) return false; + + // free encrypted key data + free(ek); + + outlen = out_offset; + return true; + + delete[] ek; + +#ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity::encrypt() finished with outlen : " << outlen << std::endl; +#endif + + return true; +} + + +bool GxsSecurity::decrypt(void *& out, int & outlen, const void *in, int inlen, EVP_PKEY *privateKey) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "GxsSecurity::decrypt() " << std::endl; +#endif + + EVP_CIPHER_CTX ctx; + int eklen = 0, net_ekl = 0; + unsigned char *ek = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + ek = (unsigned char*)malloc(EVP_PKEY_size(privateKey)); + EVP_CIPHER_CTX_init(&ctx); + + int in_offset = 0, out_currOffset = 0; + int size_net_ekl = sizeof(net_ekl); + + memcpy(&net_ekl, (unsigned char*)in, size_net_ekl); + eklen = ntohl(net_ekl); + in_offset += size_net_ekl; + + memcpy(ek, (unsigned char*)in + in_offset, eklen); + in_offset += eklen; + + memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); + in_offset += EVP_MAX_IV_LENGTH; + + const EVP_CIPHER* cipher = EVP_aes_128_cbc(); + + if(!EVP_OpenInit(&ctx, cipher, ek, eklen, iv, privateKey)) return false; + + out = new unsigned char[inlen - in_offset]; + + if(!EVP_OpenUpdate(&ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) return false; + + in_offset += out_currOffset; + outlen += out_currOffset; + + if(!EVP_OpenFinal(&ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) return false; + + outlen += out_currOffset; + + free(ek); + + return true; +} + +std::string GxsSecurity::getRsaKeySign(RSA *pubkey) +{ + int len = BN_num_bytes(pubkey -> n); + unsigned char tmp[len]; + BN_bn2bin(pubkey -> n, tmp); + + // copy first CERTSIGNLEN bytes... + if (len > CERTSIGNLEN) + { + len = CERTSIGNLEN; + } + + std::string id; + for(uint32_t i = 0; i < CERTSIGNLEN; i++) + { + rs_sprintf_append(id, "%02x", (uint16_t) (((uint8_t *) (tmp))[i])); + } + + return id; +} + + +bool GxsSecurity::validateNxsGrp(RsNxsGrp *newGrp, RsTlvKeySignature& sign, RsTlvSecurityKey& key) +{ + return false; +} + +void GxsSecurity::setRSAPublicKey(RsTlvSecurityKey & key, RSA *rsa_pub) +{ + unsigned char data[10240]; /* more than enough space */ + unsigned char *ptr = data; + int reqspace = i2d_RSAPublicKey(rsa_pub, &ptr); + + key.keyData.setBinData(data, reqspace); + + std::string keyId = getRsaKeySign(rsa_pub); + key.keyId = keyId; +} + + + +void GxsSecurity::setRSAPrivateKey(RsTlvSecurityKey & key, RSA *rsa_priv) +{ + unsigned char data[10240]; /* more than enough space */ + unsigned char *ptr = data; + int reqspace = i2d_RSAPrivateKey(rsa_priv, &ptr); + + key.keyData.setBinData(data, reqspace); + + std::string keyId = getRsaKeySign(rsa_priv); + key.keyId = keyId; +} + +RSA *GxsSecurity::extractPrivateKey(RsTlvSecurityKey & key) +{ + const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; + long keylen = key.keyData.bin_len; + + /* extract admin key */ + RSA *rsakey = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); + + return rsakey; +} + + diff --git a/libretroshare/src/gxs/gxssecurity.h b/libretroshare/src/gxs/gxssecurity.h new file mode 100644 index 000000000..889006017 --- /dev/null +++ b/libretroshare/src/gxs/gxssecurity.h @@ -0,0 +1,145 @@ +#ifndef GXSSECURITY_H +#define GXSSECURITY_H + +/* + * libretroshare/src/gxs: gxssecurity.h + * + * Security functions for Gxs + * + * Copyright 2008-2010 by Robert Fernie + * 2011-2012 Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rstlvkeys.h" +#include "serialiser/rsnxsitems.h" + +#include +#include + + +/*! + * This contains functionality for performing security + * operations needed to validate data received in RsGenExchange + * Also has routine for creating security objects around msgs and groups + */ +class GxsSecurity { + +public: + + GxsSecurity(); + ~GxsSecurity(); + + /*! + * extracts the public key from an RsTlvSecurityKey + * @param key RsTlvSecurityKey to extract public RSA key from + * @return pointer to the public RSA key if successful, null otherwise + */ + static RSA *extractPublicKey(RsTlvSecurityKey &key); + + /*! + * extracts the public key from an RsTlvSecurityKey + * @param key RsTlvSecurityKey to extract private RSA key from + * @return pointer to the private RSA key if successful, null otherwise + */ + static RSA *extractPrivateKey(RsTlvSecurityKey &key); + + /*! + * stores the rsa public key in a RsTlvSecurityKey + * @param key RsTlvSecurityKey to store the public rsa key in + * @param rsa_pub + */ + static void setRSAPublicKey(RsTlvSecurityKey &key, RSA *rsa_pub); + + /*! + * stores the rsa private key in a RsTlvSecurityKey + * @param key stores the rsa private key in a RsTlvSecurityKey + * @param rsa_priv the rsa private key to store + */ + static void setRSAPrivateKey(RsTlvSecurityKey &key, RSA *rsa_priv); + + /*! + * extracts signature from RSA key + * @param pubkey + * @return signature of RSA key in hex format + */ + static std::string getRsaKeySign(RSA *pubkey); + + /*! + * extracts the first CERTSIGNLEN bytes of signature and stores it in a string + * in hex format + * @param data signature + * @param len the length of the signature data + * @return returns the first CERTSIGNLEN of the signature as a string + */ + static std::string getBinDataSign(void *data, int len); + + /*! + * Encrypts data using envelope encryption (taken from open ssl's evp_sealinit ) + * only full publish key holders can encrypt data for given group + *@param out + *@param outlen + *@param in + *@param inlen + */ + static bool encrypt(void *&out, int &outlen, const void *in, int inlen, EVP_PKEY *privateKey); + + + /** + * Decrypts data using evelope decryption (taken from open ssl's evp_sealinit ) + * only full publish key holders can decrypt data for a group + * @param out where decrypted data is written to + * @param outlen + * @param in + * @param inlen + * @return false if encryption failed + */ + static bool decrypt(void *&out, int &outlen, const void *in, int inlen, EVP_PKEY *privateKey); + + /*! + * uses grp signature to check if group has been + * tampered with + * @param newGrp the Nxs group to be validated + * @param sign the signature to validdate against + * @param key the public key to use to check signature + * @return true if group valid false otherwise + */ + static bool validateNxsGrp(RsNxsGrp *newGrp, RsTlvKeySignature& sign, RsTlvSecurityKey& key); + + /*! + * Validate a msg's signature using the given public key + * @param msg the Nxs message to be validated + * @param sign the signature to validdate against + * @param key the public key to use to check signature + * @return false if verfication of signature is not passed + */ + static bool validateNxsMsg(RsNxsMsg& msg, RsTlvKeySignature& sign, RsTlvSecurityKey& key); + + + /*! + * @param data data to be signed + * @param data_len length of data to be signed + * @param privKey private key to used to make signature + * @param sign the signature is stored here + * @return false if signature creation failed, true is signature created + */ + static bool getSignature(char* data, uint32_t data_len, RsTlvSecurityKey* privKey, RsTlvKeySignature& sign); +}; + +#endif // GXSSECURITY_H diff --git a/libretroshare/src/gxs/gxstokenqueue.cc b/libretroshare/src/gxs/gxstokenqueue.cc new file mode 100644 index 000000000..95284dfd4 --- /dev/null +++ b/libretroshare/src/gxs/gxstokenqueue.cc @@ -0,0 +1,95 @@ +/* + * libretroshare/src/gxs gxstokenqueue.cc + * + * Gxs Support for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "gxs/gxstokenqueue.h" + +bool GxsTokenQueue::queueRequest(uint32_t token, uint32_t req_type) +{ + RsStackMutex stack(mQueueMtx); /********** STACK LOCKED MTX ******/ + mQueue.push_back(GxsTokenQueueItem(token, req_type)); + return true; +} + + +void GxsTokenQueue::checkRequests() +{ + { + RsStackMutex stack(mQueueMtx); /********** STACK LOCKED MTX ******/ + if (mQueue.empty()) + { + return; + } + } + + // Must check all, and move to a different list - for reentrant / good mutex behaviour. + std::list toload; + std::list::iterator it; + + bool stuffToLoad = false; + { + RsStackMutex stack(mQueueMtx); /********** STACK LOCKED MTX ******/ + for(it = mQueue.begin(); it != mQueue.end();) + { + uint32_t token = it->mToken; + uint32_t status = mGenExchange->getTokenService()->requestStatus(token); + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + toload.push_back(*it); + it = mQueue.erase(it); + stuffToLoad = true; + } + else if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + // maybe we should do alternative callback? + std::cerr << "GxsTokenQueue::checkRequests() ERROR Request Failed: " << token; + std::cerr << std::endl; + + it = mQueue.erase(it); + } + else + { + it++; + } + } + } + + if (stuffToLoad) + { + for(it = toload.begin(); it != toload.end(); it++) + { + handleResponse(it->mToken, it->mReqType); + } + } +} + + // This must be overloaded to complete the functionality. +void GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type) +{ + std::cerr << "GxsTokenQueue::handleResponse(" << token << "," << req_type << ") ERROR: NOT HANDLED"; + std::cerr << std::endl; +} + + diff --git a/libretroshare/src/gxs/gxstokenqueue.h b/libretroshare/src/gxs/gxstokenqueue.h new file mode 100644 index 000000000..5787c1f28 --- /dev/null +++ b/libretroshare/src/gxs/gxstokenqueue.h @@ -0,0 +1,73 @@ +#ifndef R_GXS_TOKEN_QUEUE_H +#define R_GXS_TOKEN_QUEUE_H +/* + * libretroshare/src/gxs gxstokenqueue.h + * + * Gxs Support for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "gxs/rsgenexchange.h" +#include "util/rsthreads.h" + + +/* + * + * A little helper class, to manage callbacks from requests + * + */ + +class GxsTokenQueueItem +{ + public: + GxsTokenQueueItem(const uint32_t token, const uint32_t req_type) + :mToken(token),mReqType(req_type) { return; } + + GxsTokenQueueItem(): mToken(0), mReqType(0) { return; } + + uint32_t mToken; + uint32_t mReqType; +}; + + +class GxsTokenQueue +{ + public: + + GxsTokenQueue(RsGenExchange *gxs) + :mGenExchange(gxs), mQueueMtx("GxsTokenQueueMtx") { return; } +bool queueRequest(uint32_t token, uint32_t req_type); + +void checkRequests(); // must be called by + + protected: + + // This must be overloaded to complete the functionality. +virtual void handleResponse(uint32_t token, uint32_t req_type); + + private: + RsGenExchange *mGenExchange; + RsMutex mQueueMtx; + std::list mQueue; +}; + + +#endif //R_GXS_TOKEN_QUEUE_H diff --git a/libretroshare/src/gxs/rsdataservice.cc b/libretroshare/src/gxs/rsdataservice.cc index 932da998f..075894e5b 100644 --- a/libretroshare/src/gxs/rsdataservice.cc +++ b/libretroshare/src/gxs/rsdataservice.cc @@ -1,3 +1,30 @@ + +/* + * libretroshare/src/gxs: rsdataservice.cc + * + * Data Access, interface for RetroShare. + * + * Copyright 2011-2011 by Evi-Parker Christopher + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + #include #include "rsdataservice.h" @@ -13,16 +40,21 @@ #define KEY_NXS_IDENTITY std::string("identity") #define KEY_GRP_ID std::string("grpId") #define KEY_ORIG_GRP_ID std::string("origGrpId") -#define KEY_IDENTITY_SIGN std::string("idSign") +#define KEY_SIGN_SET std::string("signSet") #define KEY_TIME_STAMP std::string("timeStamp") #define KEY_NXS_FLAGS std::string("flags") #define KEY_NXS_META std::string("meta") +#define KEY_NXS_SERV_STRING std::string("serv_str") // grp table columns -#define KEY_ADMIN_SIGN std::string("adminSign") #define KEY_KEY_SET std::string("keySet") #define KEY_GRP_NAME std::string("grpName") +#define KEY_GRP_SIGN_FLAGS std::string("signFlags") +#define KEY_GRP_CIRCLE_ID std::string("circleId") +#define KEY_GRP_CIRCLE_TYPE std::string("circleType") +#define KEY_GRP_INTERNAL_CIRCLE std::string("internalCircle") +#define KEY_GRP_ORIGINATOR std::string("originator") // grp local #define KEY_GRP_SUBCR_FLAG std::string("subscribeFlag") @@ -33,7 +65,6 @@ // msg table columns -#define KEY_PUBLISH_SIGN std::string("publishSign") #define KEY_MSG_ID std::string("msgId") #define KEY_ORIG_MSG_ID std::string("origMsgId") #define KEY_MSG_PARENT_ID std::string("parentId") @@ -61,47 +92,62 @@ // grp col numbers -#define COL_ADMIN_SIGN 5 -#define COL_KEY_SET 6 -#define COL_GRP_SUBCR_FLAG 7 -#define COL_GRP_POP 8 -#define COL_MSG_COUNT 9 -#define COL_GRP_STATUS 10 -#define COL_GRP_NAME 11 -#define COL_GRP_LAST_POST 12 -#define COL_ORIG_GRP_ID 13 +#define COL_KEY_SET 5 +#define COL_GRP_SUBCR_FLAG 6 +#define COL_GRP_POP 7 +#define COL_MSG_COUNT 8 +#define COL_GRP_STATUS 9 +#define COL_GRP_NAME 10 +#define COL_GRP_LAST_POST 11 +#define COL_ORIG_GRP_ID 12 +#define COL_GRP_SERV_STRING 13 +#define COL_GRP_SIGN_FLAGS 14 +#define COL_GRP_CIRCLE_ID 15 +#define COL_GRP_CIRCL_TYPE 16 +#define COL_GRP_INTERN_CIRCLE 17 +#define COL_GRP_ORIGINATOR 18 + // msg col numbers -#define COL_PUBLISH_SIGN 5 -#define COL_MSG_ID 6 -#define COL_ORIG_MSG_ID 7 -#define COL_MSG_STATUS 8 -#define COL_CHILD_TS 9 -#define COL_PARENT_ID 10 -#define COL_THREAD_ID 11 -#define COL_MSG_NAME 12 +#define COL_MSG_ID 5 +#define COL_ORIG_MSG_ID 6 +#define COL_MSG_STATUS 7 +#define COL_CHILD_TS 8 +#define COL_PARENT_ID 9 +#define COL_THREAD_ID 10 +#define COL_MSG_NAME 11 +#define COL_MSG_SERV_STRING 12 // generic meta shared col numbers #define COL_GRP_ID 0 #define COL_TIME_STAMP 1 #define COL_NXS_FLAGS 2 -#define COL_IDENTITY_SIGN 3 +#define COL_SIGN_SET 3 #define COL_IDENTITY 4 #define RS_DATA_SERVICE_DEBUG +const std::string RsGeneralDataService::GRP_META_SERV_STRING = KEY_NXS_SERV_STRING; +const std::string RsGeneralDataService::GRP_META_STATUS = KEY_GRP_STATUS; +const std::string RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG = KEY_GRP_SUBCR_FLAG; + +const std::string RsGeneralDataService::MSG_META_SERV_STRING = KEY_NXS_SERV_STRING; +const std::string RsGeneralDataService::MSG_META_STATUS = KEY_MSG_STATUS; + + RsDataService::RsDataService(const std::string &serviceDir, const std::string &dbName, uint16_t serviceType, RsGxsSearchModule *mod) - : RsGeneralDataService(), mServiceDir(serviceDir), mDbName(mServiceDir + "/" + dbName), mServType(serviceType){ + : RsGeneralDataService(), mServiceDir(serviceDir), mDbName(mServiceDir + "/" + dbName), mServType(serviceType), + mDbMutex("RsDataService"){ initialise(); // for retrieving msg meta msgMetaColumns.push_back(KEY_GRP_ID); msgMetaColumns.push_back(KEY_TIME_STAMP); msgMetaColumns.push_back(KEY_NXS_FLAGS); - msgMetaColumns.push_back(KEY_IDENTITY_SIGN); msgMetaColumns.push_back(KEY_NXS_IDENTITY); msgMetaColumns.push_back(KEY_PUBLISH_SIGN); + msgMetaColumns.push_back(KEY_SIGN_SET); msgMetaColumns.push_back(KEY_NXS_IDENTITY); msgMetaColumns.push_back(KEY_MSG_ID); msgMetaColumns.push_back(KEY_ORIG_MSG_ID); msgMetaColumns.push_back(KEY_MSG_STATUS); msgMetaColumns.push_back(KEY_CHILD_TS); msgMetaColumns.push_back(KEY_MSG_PARENT_ID); msgMetaColumns.push_back(KEY_MSG_THREAD_ID); - msgMetaColumns.push_back(KEY_MSG_NAME); + msgMetaColumns.push_back(KEY_MSG_NAME); msgMetaColumns.push_back(KEY_NXS_SERV_STRING); // for retrieving actual data msgColumns.push_back(KEY_GRP_ID); msgColumns.push_back(KEY_NXS_FILE); msgColumns.push_back(KEY_NXS_FILE_OFFSET); @@ -109,10 +155,12 @@ RsDataService::RsDataService(const std::string &serviceDir, const std::string &d // for retrieving grp meta data grpMetaColumns.push_back(KEY_GRP_ID); grpMetaColumns.push_back(KEY_TIME_STAMP); grpMetaColumns.push_back(KEY_NXS_FLAGS); - grpMetaColumns.push_back(KEY_IDENTITY_SIGN); grpMetaColumns.push_back(KEY_NXS_IDENTITY); grpMetaColumns.push_back(KEY_ADMIN_SIGN); + grpMetaColumns.push_back(KEY_SIGN_SET); grpMetaColumns.push_back(KEY_NXS_IDENTITY); grpMetaColumns.push_back(KEY_KEY_SET); grpMetaColumns.push_back(KEY_GRP_SUBCR_FLAG); grpMetaColumns.push_back(KEY_GRP_POP); grpMetaColumns.push_back(KEY_MSG_COUNT); grpMetaColumns.push_back(KEY_GRP_STATUS); grpMetaColumns.push_back(KEY_GRP_NAME); - grpMetaColumns.push_back(KEY_GRP_LAST_POST); grpMetaColumns.push_back(KEY_ORIG_GRP_ID); + grpMetaColumns.push_back(KEY_GRP_LAST_POST); grpMetaColumns.push_back(KEY_ORIG_GRP_ID); grpMetaColumns.push_back(KEY_NXS_SERV_STRING); + grpMetaColumns.push_back(KEY_GRP_SIGN_FLAGS); grpMetaColumns.push_back(KEY_GRP_CIRCLE_ID); grpMetaColumns.push_back(KEY_GRP_CIRCLE_TYPE); + grpMetaColumns.push_back(KEY_GRP_INTERNAL_CIRCLE); grpMetaColumns.push_back(KEY_GRP_ORIGINATOR); // for retrieving actual grp data grpColumns.push_back(KEY_GRP_ID); grpColumns.push_back(KEY_NXS_FILE); grpColumns.push_back(KEY_NXS_FILE_OFFSET); @@ -126,6 +174,8 @@ RsDataService::~RsDataService(){ void RsDataService::initialise(){ + RsStackMutex stack(mDbMutex); + // initialise database mDb = new RetroDb(mDbName, RetroDb::OPEN_READWRITE_CREATE); @@ -136,9 +186,8 @@ void RsDataService::initialise(){ KEY_NXS_FLAGS + " INT," + KEY_ORIG_MSG_ID + " TEXT," + KEY_TIME_STAMP + " INT," + - KEY_PUBLISH_SIGN + " BLOB," + KEY_NXS_IDENTITY + " TEXT," + - KEY_IDENTITY_SIGN + " BLOB," + + KEY_SIGN_SET + " BLOB," + KEY_NXS_FILE + " TEXT,"+ KEY_NXS_FILE_OFFSET + " INT," + KEY_MSG_STATUS + " INT," + @@ -147,13 +196,13 @@ void RsDataService::initialise(){ KEY_MSG_THREAD_ID + " TEXT," + KEY_MSG_PARENT_ID + " TEXT,"+ KEY_MSG_NAME + " TEXT," + + KEY_NXS_SERV_STRING + " TEXT," + KEY_NXS_FILE_LEN + " INT);"); // create table for grp data mDb->execSQL("CREATE TABLE " + GRP_TABLE_NAME + "(" + KEY_GRP_ID + " TEXT," + KEY_TIME_STAMP + " INT," + - KEY_ADMIN_SIGN + " BLOB," + " BLOB," + KEY_NXS_FILE + " TEXT," + KEY_NXS_FILE_OFFSET + " INT," + KEY_KEY_SET + " BLOB," + @@ -167,8 +216,14 @@ void RsDataService::initialise(){ KEY_GRP_STATUS + " INT," + KEY_NXS_IDENTITY + " TEXT," + KEY_ORIG_GRP_ID + " TEXT," + + KEY_NXS_SERV_STRING + " TEXT," + KEY_NXS_FLAGS + " INT," + - KEY_IDENTITY_SIGN + " BLOB);"); + KEY_GRP_SIGN_FLAGS + " INT," + + KEY_GRP_CIRCLE_ID + " TEXT," + + KEY_GRP_CIRCLE_TYPE + " INT," + + KEY_GRP_INTERNAL_CIRCLE + " TEXT," + + KEY_GRP_ORIGINATOR + " TEXT," + + KEY_SIGN_SET + " BLOB);"); } @@ -193,22 +248,13 @@ RsGxsGrpMetaData* RsDataService::getGrpMeta(RetroCursor &c) c.getString(COL_IDENTITY, grpMeta->mAuthorId); c.getString(COL_GRP_NAME, grpMeta->mGroupName); c.getString(COL_ORIG_GRP_ID, grpMeta->mOrigGrpId); + c.getString(COL_GRP_SERV_STRING, grpMeta->mServiceString); + grpMeta->mSignFlags = c.getInt32(COL_GRP_SIGN_FLAGS); grpMeta->mPublishTs = c.getInt32(COL_TIME_STAMP); grpMeta->mGroupFlags = c.getInt32(COL_NXS_FLAGS); - // identity if any - if(!grpMeta->mAuthorId.empty() && ok){ - offset = 0; - data = (char*)c.getData(COL_IDENTITY_SIGN, data_len); - if(data) - grpMeta->idSign.GetTlv(data, data_len, &offset); - } - offset = 0; - data = (char*)c.getData(COL_ADMIN_SIGN, data_len); - if(data) - grpMeta->adminSign.GetTlv(data, data_len, &offset); offset = 0; data = NULL; data_len = 0; @@ -224,6 +270,11 @@ RsGxsGrpMetaData* RsDataService::getGrpMeta(RetroCursor &c) grpMeta->mLastPost = c.getInt32(COL_GRP_LAST_POST); grpMeta->mGroupStatus = c.getInt32(COL_GRP_STATUS); + c.getString(COL_GRP_CIRCLE_ID, grpMeta->mCircleId); + grpMeta->mCircleType = c.getInt32(COL_GRP_CIRCL_TYPE); + c.getString(COL_GRP_INTERN_CIRCLE, grpMeta->mInternalCircle); + c.getString(COL_GRP_ORIGINATOR, grpMeta->mOriginator); + if(ok) return grpMeta; @@ -307,26 +358,18 @@ RsGxsMsgMetaData* RsDataService::getMsgMeta(RetroCursor &c) c.getString(COL_ORIG_MSG_ID, msgMeta->mOrigMsgId); c.getString(COL_IDENTITY, msgMeta->mAuthorId); c.getString(COL_MSG_NAME, msgMeta->mMsgName); + c.getString(COL_MSG_SERV_STRING, msgMeta->mServiceString); + + offset = 0; + data = (char*)c.getData(COL_SIGN_SET, data_len); + msgMeta->signSet.GetTlv(data, data_len, &offset); - if(!msgMeta->mAuthorId.empty()){ - offset = 0; - data = (char*)c.getData(COL_IDENTITY_SIGN, data_len); - msgMeta->idSign.GetTlv(data, data_len, &offset); - } msgMeta->mMsgFlags = c.getInt32(COL_NXS_FLAGS); msgMeta->mPublishTs = c.getInt32(COL_TIME_STAMP); offset = 0; data_len = 0; - if(ok){ - - data = (char*)c.getData(COL_PUBLISH_SIGN, data_len); - if(data) - msgMeta->pubSign.GetTlv(data, data_len, &offset); - - } - // thread and parent id c.getString(COL_THREAD_ID, msgMeta->mThreadId); c.getString(COL_PARENT_ID, msgMeta->mParentId); @@ -376,7 +419,7 @@ RsNxsMsg* RsDataService::getMessage(RetroCursor &c) if(ok){ - char msg_data[data_len]; + char* msg_data = new char[data_len]; std::ifstream istrm(msgFile.c_str(), std::ios::binary); istrm.seekg(offset, std::ios::beg); istrm.read(msg_data, data_len); @@ -384,6 +427,7 @@ RsNxsMsg* RsDataService::getMessage(RetroCursor &c) istrm.close(); offset = 0; ok &= msg->msg.GetTlv(msg_data, data_len, &offset); + delete[] msg_data; } if(ok) @@ -396,6 +440,9 @@ RsNxsMsg* RsDataService::getMessage(RetroCursor &c) int RsDataService::storeMessage(std::map &msg) { + + RsStackMutex stack(mDbMutex); + std::map::iterator mit = msg.begin(); // start a transaction @@ -419,20 +466,16 @@ int RsDataService::storeMessage(std::map &msg) cv.put(KEY_NXS_FILE_LEN, (int32_t)msgPtr->msg.TlvSize()); cv.put(KEY_MSG_ID, msgMetaPtr->mMsgId); cv.put(KEY_GRP_ID, msgMetaPtr->mGroupId); - char pubSignData[msgMetaPtr->pubSign.TlvSize()]; + cv.put(KEY_NXS_SERV_STRING, msgMetaPtr->mServiceString); + + + char signSetData[msgMetaPtr->signSet.TlvSize()]; offset = 0; - msgMetaPtr->pubSign.SetTlv(pubSignData, msgMetaPtr->pubSign.TlvSize(), &offset); - cv.put(KEY_PUBLISH_SIGN, msgMetaPtr->pubSign.TlvSize(), pubSignData); + msgMetaPtr->signSet.SetTlv(signSetData, msgMetaPtr->signSet.TlvSize(), &offset); + cv.put(KEY_SIGN_SET, msgMetaPtr->signSet.TlvSize(), signSetData); + cv.put(KEY_NXS_IDENTITY, msgMetaPtr->mAuthorId); - if(! (msgMetaPtr->mAuthorId.empty()) ){ - char idSignData[msgMetaPtr->idSign.TlvSize()]; - offset = 0; - msgMetaPtr->idSign.SetTlv(idSignData, msgMetaPtr->idSign.TlvSize(), &offset); - cv.put(KEY_IDENTITY_SIGN, msgMetaPtr->idSign.TlvSize(), idSignData); - cv.put(KEY_NXS_IDENTITY, msgMetaPtr->mAuthorId); - } - cv.put(KEY_NXS_FLAGS, (int32_t) msgMetaPtr->mMsgFlags); cv.put(KEY_TIME_STAMP, (int32_t) msgMetaPtr->mPublishTs); @@ -451,27 +494,44 @@ int RsDataService::storeMessage(std::map &msg) cv.put(KEY_CHILD_TS, (int32_t)msgMetaPtr->mChildTs); offset = 0; - char msgData[msgPtr->msg.TlvSize()]; + char* msgData = new char[msgPtr->msg.TlvSize()]; msgPtr->msg.SetTlv(msgData, msgPtr->msg.TlvSize(), &offset); ostrm.write(msgData, msgPtr->msg.TlvSize()); ostrm.close(); + delete[] msgData; mDb->sqlInsert(MSG_TABLE_NAME, "", cv); } // finish transaction - return mDb->execSQL("COMMIT;"); + bool ret = mDb->execSQL("COMMIT;"); + + for(mit = msg.begin(); mit != msg.end(); mit++) + { + //TODO: API encourages aliasing, remove this abomination + if(mit->second != mit->first->metaData) + delete mit->second; + + delete mit->first; + ; + } + + return ret; } int RsDataService::storeGroup(std::map &grp) { + + RsStackMutex stack(mDbMutex); + std::map::iterator sit = grp.begin(); // begin transaction mDb->execSQL("BEGIN;"); - for(; sit != grp.end(); sit++){ + for(; sit != grp.end(); sit++) + { RsNxsGrp* grpPtr = sit->first; RsGxsGrpMetaData* grpMetaPtr = sit->second; @@ -494,25 +554,19 @@ int RsDataService::storeGroup(std::map &grp) cv.put(KEY_GRP_ID, grpPtr->grpId); cv.put(KEY_GRP_NAME, grpMetaPtr->mGroupName); cv.put(KEY_ORIG_GRP_ID, grpMetaPtr->mOrigGrpId); + cv.put(KEY_NXS_SERV_STRING, grpMetaPtr->mServiceString); cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); cv.put(KEY_TIME_STAMP, (int32_t)grpMetaPtr->mPublishTs); + cv.put(KEY_GRP_SIGN_FLAGS, (int32_t)grpMetaPtr->mSignFlags); + cv.put(KEY_GRP_CIRCLE_ID, grpMetaPtr->mCircleId); + cv.put(KEY_GRP_CIRCLE_TYPE, (int32_t)grpMetaPtr->mCircleType); + cv.put(KEY_GRP_INTERNAL_CIRCLE, grpMetaPtr->mInternalCircle); + cv.put(KEY_GRP_ORIGINATOR, grpMetaPtr->mOriginator); if(! (grpMetaPtr->mAuthorId.empty()) ){ cv.put(KEY_NXS_IDENTITY, grpMetaPtr->mAuthorId); - - char idSignData[grpMetaPtr->idSign.TlvSize()]; - offset = 0; - grpMetaPtr->idSign.SetTlv(idSignData, grpMetaPtr->idSign.TlvSize(), &offset); - cv.put(KEY_IDENTITY_SIGN, grpMetaPtr->idSign.TlvSize(), idSignData); - std::string wat(idSignData, grpMetaPtr->idSign.TlvSize()); - std::cerr << wat << std::endl; } - char adminSignData[grpMetaPtr->adminSign.TlvSize()]; - offset = 0; - grpMetaPtr->adminSign.SetTlv(adminSignData, grpMetaPtr->adminSign.TlvSize(), &offset); - cv.put(KEY_ADMIN_SIGN, grpMetaPtr->adminSign.TlvSize(), adminSignData); - offset = 0; char keySetData[grpMetaPtr->keys.TlvSize()]; grpMetaPtr->keys.SetTlv(keySetData, grpMetaPtr->keys.TlvSize(), &offset); @@ -539,61 +593,91 @@ int RsDataService::storeGroup(std::map &grp) mDb->sqlInsert(GRP_TABLE_NAME, "", cv); } // finish transaction - return mDb->execSQL("COMMIT;"); + bool ret = mDb->execSQL("COMMIT;"); + + for(sit = grp.begin(); sit != grp.end(); sit++) + { + //TODO: API encourages aliasing, remove this abomination + if(sit->second != sit->first->metaData) + delete sit->second; + delete sit->first; + + } + + return ret; } int RsDataService::retrieveNxsGrps(std::map &grp, bool withMeta, bool cache){ - if(grp.empty()){ + if(grp.empty()){ - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpColumns, "", ""); + RsStackMutex stack(mDbMutex); + RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpColumns, "", ""); - if(c) - { - std::vector grps; + if(c) + { + std::vector grps; - retrieveGroups(c, grps, withMeta); - std::vector::iterator vit = grps.begin(); + retrieveGroups(c, grps); + std::vector::iterator vit = grps.begin(); - for(; vit != grps.end(); vit++) - { - grp[(*vit)->grpId] = *vit; - } + for(; vit != grps.end(); vit++) + { + grp[(*vit)->grpId] = *vit; + } - delete c; - } + delete c; + } - }else{ + }else{ - std::map::iterator mit = grp.begin(); + RsStackMutex stack(mDbMutex); + std::map::iterator mit = grp.begin(); - for(; mit != grp.end(); mit++) - { - const std::string& grpId = mit->first; - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpColumns, "grpId='" + grpId + "'", ""); + for(; mit != grp.end(); mit++) + { + const std::string& grpId = mit->first; + RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpColumns, "grpId='" + grpId + "'", ""); - if(c) - { - std::vector grps; - retrieveGroups(c, grps); + if(c) + { + std::vector grps; + retrieveGroups(c, grps); - if(!grps.empty()) - { - RsNxsGrp* ng = grps.front(); - grp[ng->grpId] = ng; - }else{ - grp.erase(grpId); - } + if(!grps.empty()) + { + RsNxsGrp* ng = grps.front(); + grp[ng->grpId] = ng; + }else{ + grp.erase(grpId); + } - delete c; - } - } - } + delete c; + } + } + } - return 1; + if(withMeta) + { + std::map metaMap; + std::map::iterator mit = grp.begin(); + for(; mit != grp.end(); mit++) + metaMap.insert(std::make_pair(mit->first, (RsGxsGrpMetaData*)(NULL))); + + retrieveGxsGrpMetaData(metaMap); + + mit = grp.begin(); + for(; mit != grp.end(); mit++) + { + RsNxsGrp* grpPtr = grp[mit->first]; + grpPtr->metaData = metaMap[mit->first]; + } + } + + return 1; } -void RsDataService::retrieveGroups(RetroCursor* c, std::vector& grps, bool withMeta){ +void RsDataService::retrieveGroups(RetroCursor* c, std::vector& grps){ if(c){ bool valid = c->moveToFirst(); @@ -604,12 +688,6 @@ void RsDataService::retrieveGroups(RetroCursor* c, std::vector& grps, // only add the latest grp info if(g) { - RsGxsGrpMetaData* meta; - - if(withMeta) - meta = getGrpMeta(*c); - - if(meta) g->metaData = meta; grps.push_back(g); } valid = c->moveToNext(); @@ -617,11 +695,13 @@ void RsDataService::retrieveGroups(RetroCursor* c, std::vector& grps, } } -int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, bool cache) +int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, bool cache, bool withMeta) { GxsMsgReq::const_iterator mit = reqIds.begin(); + GxsMsgReq metaReqIds;// collects metaReqIds if needed + for(; mit != reqIds.end(); mit++) { @@ -632,6 +712,9 @@ int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, b std::vector msgSet; if(msgIdV.empty()){ + + RsStackMutex stack(mDbMutex); + RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, msgColumns, KEY_GRP_ID+ "='" + grpId + "'", ""); if(c) @@ -645,6 +728,9 @@ int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, b for(; sit!=msgIdV.end();sit++){ const std::string& msgId = *sit; + + RsStackMutex stack(mDbMutex); + RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, msgColumns, KEY_GRP_ID+ "='" + grpId + "' AND " + KEY_MSG_ID + "='" + msgId + "'", ""); @@ -657,7 +743,75 @@ int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, b msg[grpId] = msgSet; msgSet.clear(); + + if(withMeta) + { + std::vector msgIds; + + std::vector::iterator lit = msgSet.begin(), + lit_end = msgSet.end(); + + for(; lit != lit_end; lit++) + msgIds.push_back( (*lit)->msgId ); + + metaReqIds[grpId] = msgIds; + } } + + // tres expensive !? + if(withMeta) + { + + GxsMsgMetaResult metaResult; + + // request with meta ids so there is no chance of + // a mem leak being left over + retrieveGxsMsgMetaData(metaReqIds, metaResult); + + GxsMsgResult::iterator mit2 = msg.begin(), mit2_end = msg.end(); + + for(; mit2 != mit2_end; mit2++) + { + const RsGxsGroupId& grpId = mit2->first; + std::vector& msgV = msg[grpId]; + std::vector::iterator lit = msgV.begin(), + lit_end = msgV.end(); + + // as retrieval only attempts to retrieve what was found this elimiates chance + // of a memory fault as all are assigned + for(; lit != lit_end; lit++) + { + std::vector& msgMetaV = metaResult[grpId]; + std::vector::iterator meta_lit = msgMetaV.begin(); + RsNxsMsg* msgPtr = *lit; + for(; meta_lit != msgMetaV.end(); ) + { + RsGxsMsgMetaData* meta = *meta_lit; + if(meta->mMsgId == msgPtr->msgId) + { + msgPtr->metaData = meta; + meta_lit = msgMetaV.erase(meta_lit); + }else{ + meta_lit++; + } + } + } + + std::vector& msgMetaV = metaResult[grpId]; + std::vector::iterator meta_lit; + + // clean up just in case, should not go in here + for(meta_lit = msgMetaV.begin(); meta_lit != + msgMetaV.end(); ) + { + RsGxsMsgMetaData* meta = *meta_lit; + delete meta; + meta_lit = msgMetaV.erase(meta_lit); + } + } + } + + return 1; } void RsDataService::retrieveMessages(RetroCursor *c, std::vector &msgs) @@ -668,8 +822,6 @@ void RsDataService::retrieveMessages(RetroCursor *c, std::vector &ms if(m){ msgs.push_back(m);; - }else{ - delete m; } valid = c->moveToNext(); @@ -677,60 +829,122 @@ void RsDataService::retrieveMessages(RetroCursor *c, std::vector &ms return; } -int RsDataService::retrieveGxsMsgMetaData(const std::vector &grpIds, GxsMsgMetaResult &msgMeta) +int RsDataService::retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult &msgMeta) { - std::vector::const_iterator vit = grpIds.begin(); - for(; vit != grpIds.end(); vit++) + RsStackMutex stack(mDbMutex); + + GxsMsgReq::const_iterator mit = reqIds.begin(); + + for(; mit != reqIds.end(); mit++) { - const std::string& grpId = *vit; - std::vector meta; + const std::string& grpId = mit->first; - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, msgMetaColumns, "", KEY_GRP_ID+ "='" + grpId + "'"); + // if vector empty then request all messages + const std::vector& msgIdV = mit->second; + std::vector metaSet; - if(c) - { - bool valid = c->moveToFirst(); - while(valid){ - RsGxsMsgMetaData* m = getMsgMeta(*c); + if(msgIdV.empty()){ + RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, msgMetaColumns, KEY_GRP_ID+ "='" + grpId + "'", ""); - if(m){ - meta.push_back(m); - }else{ - delete m; - } - valid = c->moveToNext(); + retrieveMsgMeta(c, metaSet); + + }else{ + + // request each grp + std::vector::const_iterator sit = msgIdV.begin(); + + for(; sit!=msgIdV.end();sit++){ + const std::string& msgId = *sit; + RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, msgMetaColumns, KEY_GRP_ID+ "='" + grpId + + "' AND " + KEY_MSG_ID + "='" + msgId + "'", ""); + + retrieveMsgMeta(c, metaSet); } - - msgMeta[grpId] = meta; } - delete c; + msgMeta[grpId] = metaSet; } + return 1; } -int RsDataService::retrieveGxsGrpMetaData(std::map& grp) +void RsDataService::retrieveMsgMeta(RetroCursor *c, std::vector &msgMeta) { - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpMetaColumns, "", ""); if(c) { bool valid = c->moveToFirst(); + while(valid){ + RsGxsMsgMetaData* m = getMsgMeta(*c); - while(valid) - { - RsGxsGrpMetaData* g = getGrpMeta(*c); + if(m != NULL) + msgMeta.push_back(m); - if(g) - { - grp[g->mGroupId] = g; - } valid = c->moveToNext(); } + delete c; } - delete c; +} + +int RsDataService::retrieveGxsGrpMetaData(std::map& grp) +{ + + RsStackMutex stack(mDbMutex); + + if(grp.empty()){ + + RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpMetaColumns, "", ""); + + if(c) + { + bool valid = c->moveToFirst(); + + while(valid) + { + RsGxsGrpMetaData* g = getGrpMeta(*c); + + if(g) + { + grp[g->mGroupId] = g; + } + valid = c->moveToNext(); + } + delete c; + } + + }else + { + + std::map::iterator mit = grp.begin(); + + for(; mit != grp.end(); mit++) + { + const RsGxsGroupId& grpId = mit->first; + RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, grpMetaColumns, "grpId='" + grpId + "'", ""); + + if(c) + { + bool valid = c->moveToFirst(); + + while(valid) + { + RsGxsGrpMetaData* g = getGrpMeta(*c); + + if(g) + { + grp[g->mGroupId] = g; + } + valid = c->moveToNext(); + } + delete c; + } + + } + + } + return 1; } @@ -748,6 +962,7 @@ int RsDataService::resetDataStore() std::map::iterator mit = grps.begin(); + // remove all grp msgs files from service dir for(; mit != grps.end(); mit++){ std::string file = mServiceDir + "/" + mit->first; @@ -755,8 +970,11 @@ int RsDataService::resetDataStore() remove(file.c_str()); // remove group file remove(msgFile.c_str()); // and remove messages file } + { + RsStackMutex stack(mDbMutex); + mDb->closeDb(); + } - mDb->closeDb(); remove(mDbName.c_str()); // remove db file // recreate database @@ -771,18 +989,22 @@ int RsDataService::removeGroups(const std::vector &grpIds) return 0; } -int RsDataService::updateGroupMetaData(GrpLocMetaData *meta) +int RsDataService::updateGroupMetaData(GrpLocMetaData &meta) { - return 0; + RsGxsGroupId& grpId = meta.grpId; + return mDb->sqlUpdate(GRP_TABLE_NAME, KEY_GRP_ID+ "='" + grpId + "'", meta.val) ? 1 : 0; } -int RsDataService::updateMessageMetaData(MsgLocMetaData *metaData) +int RsDataService::updateMessageMetaData(MsgLocMetaData &metaData) { - return 0; + RsGxsGroupId& grpId = metaData.msgId.first; + RsGxsMessageId& msgId = metaData.msgId.second; + return mDb->sqlUpdate(MSG_TABLE_NAME, KEY_GRP_ID+ "='" + grpId + + "' AND " + KEY_MSG_ID + "='" + msgId + "'", metaData.val) ? 1 : 0; } -int RsDataService::removeMsgs(const std::string grpId, const std::vector &msgIds) +int RsDataService::removeMsgs(const GxsMsgReq& msgIds) { return 0; } diff --git a/libretroshare/src/gxs/rsdataservice.h b/libretroshare/src/gxs/rsdataservice.h index 13bc26bf3..7a8a8fb25 100644 --- a/libretroshare/src/gxs/rsdataservice.h +++ b/libretroshare/src/gxs/rsdataservice.h @@ -1,6 +1,31 @@ #ifndef RSDATASERVICE_H #define RSDATASERVICE_H +/* + * libretroshare/src/gxs: rsdataservice.h + * + * General Data service, interface for RetroShare. + * + * Copyright 2011-2012 by Evi-Parker Christopher + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + #include "gxs/rsgds.h" #include "util/retrodb.h" @@ -10,7 +35,7 @@ class RsDataService : public RsGeneralDataService public: RsDataService(const std::string& serviceDir, const std::string& dbName, uint16_t serviceType, RsGxsSearchModule* mod = NULL); - virtual ~RsDataService() ; + virtual ~RsDataService(); /*! * Retrieves all msgs @@ -19,7 +44,7 @@ public: * @param cache whether to store results of this retrieval in memory for faster later retrieval * @return error code */ - int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool cache); + int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool cache, bool withMeta = false); /*! * Retrieves groups, if empty, retrieves all grps, if map is not empty @@ -36,7 +61,7 @@ public: * @param cache whether to store retrieval in mem for faster later retrieval * @return error code */ - int retrieveGxsGrpMetaData(std::map& grp); + int retrieveGxsGrpMetaData(std::map& grp); /*! * Retrieves meta data of all groups stored (most current versions only) @@ -45,7 +70,7 @@ public: * @param cache whether to store retrieval in mem for faster later retrieval * @return error code */ - int retrieveGxsMsgMetaData(const std::vector& grpIds, GxsMsgMetaResult& msgMeta); + int retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult& msgMeta); /*! * remove msgs in data store @@ -53,14 +78,14 @@ public: * @param msgIds ids of messages to be removed * @return error code */ - int removeMsgs(const std::string grpId, const std::vector& msgIds); + int removeMsgs(const GxsMsgReq& msgIds); /*! * remove groups in data store listed in grpIds param * @param grpIds ids of groups to be removed * @return error code */ - int removeGroups(const std::vector& grpIds); + int removeGroups(const std::vector& grpIds); /*! * @return the cache size set for this RsGeneralDataService in bytes @@ -90,13 +115,13 @@ public: * @param metaData The meta data item to update * @return error code */ - int updateMessageMetaData(MsgLocMetaData* metaData); + int updateMessageMetaData(MsgLocMetaData& metaData); /*! * @param metaData The meta data item to update * @return error code */ - int updateGroupMetaData(GrpLocMetaData* meta); + int updateGroupMetaData(GrpLocMetaData& meta); /*! @@ -117,11 +142,18 @@ private: void retrieveMessages(RetroCursor* c, std::vector& msgs); /*! - * Retrieves all the msg results from a cursor - * @param c cursor to result set - * @param msgs messages retrieved from cursor are stored here - */ - void retrieveGroups(RetroCursor* c, std::vector& grps, bool withMeta = false); + * Retrieves all the grp results from a cursor + * @param c cursor to result set + * @param grps groups retrieved from cursor are stored here + */ + void retrieveGroups(RetroCursor* c, std::vector& grps); + + /*! + * Retrieves all the msg meta results from a cursor + * @param c cursor to result set + * @param metaSet message metadata retrieved from cursor are stored here + */ + void retrieveMsgMeta(RetroCursor* c, std::vector& msgMeta); /*! * extracts a msg meta item from a cursor at its @@ -158,6 +190,8 @@ private: RetroDb* mDb; + RsMutex mDbMutex; + std::list msgColumns; std::list msgMetaColumns; diff --git a/libretroshare/src/gxs/rsgds.h b/libretroshare/src/gxs/rsgds.h index 4a178f575..bfcee886c 100644 --- a/libretroshare/src/gxs/rsgds.h +++ b/libretroshare/src/gxs/rsgds.h @@ -36,6 +36,7 @@ #include "serialiser/rsnxsitems.h" #include "gxs/rsgxsdata.h" #include "rsgxs.h" +#include "util/contentvalue.h" class RsGxsSearchModule { @@ -53,6 +54,11 @@ public: */ class MsgLocMetaData { +public: + MsgLocMetaData(const MsgLocMetaData& meta){ msgId = meta.msgId; val = meta.val;} + MsgLocMetaData() {} + RsGxsGrpMsgIdPair msgId; + ContentValue val; }; /*! @@ -61,11 +67,17 @@ class MsgLocMetaData { */ class GrpLocMetaData { +public: + GrpLocMetaData(const GrpLocMetaData& meta){ grpId = meta.grpId; val = meta.val;} + GrpLocMetaData(){} + RsGxsGroupId grpId; + ContentValue val; + }; -//typedef std::map > GxsMsgReq; // - -//typedef std::map > GxsMsgMetaResult; // +typedef std::map > NxsMsgDataResult; +typedef std::map > NxsMsgRelatedDataResult; +typedef std::map > GxsMsgResult; // /*! * The main role of GDS is the preparation and handing out of messages requested from @@ -91,6 +103,15 @@ class GrpLocMetaData { class RsGeneralDataService { +public: + + static const std::string MSG_META_SERV_STRING; + static const std::string MSG_META_STATUS; + + static const std::string GRP_META_SUBSCRIBE_FLAG; + static const std::string GRP_META_STATUS; + static const std::string GRP_META_SERV_STRING; + public: RsGeneralDataService(){} @@ -103,12 +124,12 @@ public: * @param cache whether to store results of this retrieval in memory for faster later retrieval * @return error code */ - virtual int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool cache) = 0; + virtual int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool cache, bool withMeta=false) = 0; /*! * Retrieves all groups stored * @param grp retrieved groups - * @param withMeta this initialises the meta handles nxs grps + * @param withMeta if true the meta handle of nxs grps is intitialised * @param cache whether to store retrieval in mem for faster later retrieval * @return error code */ @@ -130,7 +151,7 @@ public: * @param cache whether to store retrieval in mem for faster later retrieval * @return error code */ - virtual int retrieveGxsMsgMetaData(const std::vector& grpIds, GxsMsgMetaResult& msgMeta) = 0; + virtual int retrieveGxsMsgMetaData(const GxsMsgReq& msgIds, GxsMsgMetaResult& msgMeta) = 0; /*! * remove msgs in data store listed in msgIds param @@ -161,25 +182,25 @@ public: * @param msg map of message and decoded meta data information * @return error code */ - virtual int storeMessage(std::map& msg) = 0; + virtual int storeMessage(std::map& msgs) = 0; /*! * Stores a list of groups in data store * @param grp map of group and decoded meta data * @return error code */ - virtual int storeGroup(std::map& grp) = 0; + virtual int storeGroup(std::map& grsp) = 0; /*! * @param metaData */ - virtual int updateMessageMetaData(MsgLocMetaData* metaData) = 0; + virtual int updateMessageMetaData(MsgLocMetaData& metaData) = 0; /*! * @param metaData */ - virtual int updateGroupMetaData(GrpLocMetaData* meta) = 0; + virtual int updateGroupMetaData(GrpLocMetaData& meta) = 0; /*! diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 0337ce5a9..3430c2fd3 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -1,8 +1,60 @@ -#include "rsgenexchange.h" -RsGenExchange::RsGenExchange(RsGeneralDataService *gds, - RsNetworkExchangeService *ns, RsSerialType *serviceSerialiser, uint16_t servType) -: mGenMtx("GenExchange"), mDataStore(gds), mNetService(ns), mSerialiser(serviceSerialiser), mServType(servType) +/* + * libretroshare/src/gxs: rsgenexchange.cc + * + * RetroShare Gxs exchange interface. + * + * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include + +#include "pqi/pqihash.h" +#include "rsgenexchange.h" +#include "gxssecurity.h" +#include "util/contentvalue.h" +#include "rsgxsflags.h" +#include "rsgixs.h" + + +#define PUB_GRP_MASK 0x000f +#define RESTR_GRP_MASK 0x00f0 +#define PRIV_GRP_MASK 0x0f00 +#define GRP_OPTIONS_MASK 0xf000 + +#define PUB_GRP_OFFSET 0 +#define RESTR_GRP_OFFSET 8 +#define PRIV_GRP_OFFSET 9 +#define GRP_OPTIONS_OFFSET 7 + +#define GXS_MASK "GXS_MASK_HACK" + +#define GEN_EXCH_DEBUG 1 + +RsGenExchange::RsGenExchange(RsGeneralDataService *gds, RsNetworkExchangeService *ns, + RsSerialType *serviceSerialiser, uint16_t servType, RsGixs* gixs, uint32_t authenPolicy) +: mGenMtx("GenExchange"), mDataStore(gds), mNetService(ns), mSerialiser(serviceSerialiser), + mServType(servType), mGixs(gixs), mAuthenPolicy(authenPolicy) { mDataAccess = new RsGxsDataAccess(gds); @@ -22,6 +74,22 @@ RsGenExchange::~RsGenExchange() } +void RsGenExchange::run() +{ + + double timeDelta = 0.1; // slow tick + + while(isRunning()) + { + tick(); + +#ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); +#else + Sleep((int) (timeDelta * 1000)); +#endif + } +} void RsGenExchange::tick() { @@ -31,8 +99,593 @@ void RsGenExchange::tick() publishMsgs(); + processGrpMetaChanges(); + + processMsgMetaChanges(); + + processRecvdData(); + + if(!mNotifications.empty()) + { + notifyChanges(mNotifications); + mNotifications.clear(); + } + + // implemented service tick function + service_tick(); } +bool RsGenExchange::acknowledgeTokenMsg(const uint32_t& token, + RsGxsGrpMsgIdPair& msgId) +{ + RsStackMutex stack(mGenMtx); + + std::map::iterator mit = + mMsgNotify.find(token); + + if(mit == mMsgNotify.end()) + { + return false; + } + + + msgId = mit->second; + + // no dump token as client has ackowledged its completion + mDataAccess->disposeOfPublicToken(token); + + return true; +} + + + +bool RsGenExchange::acknowledgeTokenGrp(const uint32_t& token, + RsGxsGroupId& grpId) +{ + RsStackMutex stack(mGenMtx); + + std::map::iterator mit = + mGrpNotify.find(token); + + if(mit == mGrpNotify.end()) + return false; + + grpId = mit->second; + + // no dump token as client has ackowledged its completion + mDataAccess->disposeOfPublicToken(token); + + return true; +} + +void RsGenExchange::generateGroupKeys(RsTlvSecurityKeySet& keySet, bool genPublishKeys) +{ + /* create Keys */ + + // admin keys + RSA *rsa_admin = RSA_generate_key(2048, 65537, NULL, NULL); + RSA *rsa_admin_pub = RSAPublicKey_dup(rsa_admin); + + /* set admin keys */ + RsTlvSecurityKey adminKey, privAdminKey; + + GxsSecurity::setRSAPublicKey(adminKey, rsa_admin_pub); + GxsSecurity::setRSAPrivateKey(privAdminKey, rsa_admin); + + adminKey.startTS = time(NULL); + adminKey.endTS = 0; /* no end */ + + privAdminKey.startTS = adminKey.startTS; + privAdminKey.endTS = 0; /* no end */ + + // for now all public + adminKey.keyFlags = RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_PUBLIC_ONLY; + privAdminKey.keyFlags = RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL; + + keySet.keys[adminKey.keyId] = adminKey; + keySet.keys[privAdminKey.keyId] = privAdminKey; + + // clean up + RSA_free(rsa_admin); + RSA_free(rsa_admin_pub); + + if(genPublishKeys) + { + // publish keys + RSA *rsa_publish = RSA_generate_key(2048, 65537, NULL, NULL); + RSA *rsa_publish_pub = RSAPublicKey_dup(rsa_publish); + + /* set publish keys */ + RsTlvSecurityKey pubKey, privPubKey; + + GxsSecurity::setRSAPublicKey(pubKey, rsa_publish_pub); + GxsSecurity::setRSAPrivateKey(privPubKey, rsa_publish); + + pubKey.startTS = adminKey.startTS; + pubKey.endTS = pubKey.startTS + 60 * 60 * 24 * 365 * 5; /* approx 5 years */ + + privPubKey.startTS = adminKey.startTS; + privPubKey.endTS = 0; /* no end */ + + // for now all public + pubKey.keyFlags = RSTLV_KEY_DISTRIB_PUBLIC | RSTLV_KEY_TYPE_PUBLIC_ONLY; + privPubKey.keyFlags = RSTLV_KEY_DISTRIB_PRIVATE | RSTLV_KEY_TYPE_FULL; + + keySet.keys[pubKey.keyId] = pubKey; + keySet.keys[privPubKey.keyId] = privPubKey; + + RSA_free(rsa_publish); + RSA_free(rsa_publish_pub); + } + +} + +bool RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& keySet) +{ + std::cerr << "RsGenExchange::createGroup()"; + std::cerr << std::endl; + + RsGxsGrpMetaData* meta = grp->metaData; + + /* add public admin and publish keys to grp */ + + // find private admin key + RsTlvSecurityKey privAdminKey; + std::map::iterator mit = keySet.keys.begin(); + + bool privKeyFound = false; + for(; mit != keySet.keys.end(); mit++) + { + RsTlvSecurityKey& key = mit->second; + + // add public admin key + if(key.keyFlags & (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_PUBLIC_ONLY)) + meta->keys.keys.insert(std::make_pair(key.keyId, key)); + + // add public publish key + if(key.keyFlags & (RSTLV_KEY_DISTRIB_PUBLIC | RSTLV_KEY_TYPE_PUBLIC_ONLY)) + meta->keys.keys.insert(std::make_pair(key.keyId, key)); + + if(key.keyFlags & (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) + { + privAdminKey = key; + privKeyFound = true; + } + } + + if(!privKeyFound) + { + std::cerr << "RsGenExchange::createGroup() Missing private ADMIN Key"; + std::cerr << std::endl; + + return false; + } + + // group is self signing + // for the creation of group signature + // only public admin and publish keys are present in meta + uint32_t metaDataLen = meta->serial_size(); + uint32_t allGrpDataLen = metaDataLen + grp->grp.bin_len; + char* metaData = new char[metaDataLen]; + char* allGrpData = new char[allGrpDataLen]; // msgData + metaData + + meta->serialise(metaData, metaDataLen); + + // copy msg data and meta in allMsgData buffer + memcpy(allGrpData, grp->grp.bin_data, grp->grp.bin_len); + memcpy(allGrpData+(grp->grp.bin_len), metaData, metaDataLen); + + RsTlvKeySignature adminSign; + bool ok = GxsSecurity::getSignature(allGrpData, allGrpDataLen, &privAdminKey, adminSign); + + // add admin sign to grpMeta + meta->signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_ADMIN] = adminSign; + + // set meta to be transported as meta without private + // key components + grp->meta.setBinData(metaData, metaDataLen); + + // but meta that is stored locally + // has all keys + // nxs net transports only bin data + meta->keys = keySet; + + // clean up + delete[] allGrpData; + delete[] metaData; + + if (!ok) + { + std::cerr << "RsGenExchange::createGroup() ERROR !okay (getSignature error)"; + std::cerr << std::endl; + } + + return ok; +} + +bool RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& msgData, + const RsGxsMsgMetaData& msgMeta, RsGxsGrpMetaData& grpMeta) +{ + bool isParent = false; + bool needPublishSign = false, needIdentitySign = false; + bool ok = true; + uint32_t grpFlag = grpMeta.mGroupFlags; + + // publish signature is determined by whether group is public or not + // for private group signature is not needed as it needs decrypting with + // the private publish key anyways + + // restricted is a special case which heeds whether publish sign needs to be checked or not + // one may or may not want + + if(msgMeta.mParentId.empty()) + { + isParent = true; + } + else + { + isParent = false; + } + + + if(isParent) + { + needIdentitySign = false; + needPublishSign = false; + + if(grpFlag & GXS_SERV::FLAG_PRIVACY_PUBLIC) + { + needPublishSign = false; + + if(checkMsgAuthenFlag(PUBLIC_GRP_BITS, GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN)) + needIdentitySign = true; + + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) + { + needPublishSign = true; + + if(checkMsgAuthenFlag(RESTRICTED_GRP_BITS, GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN)) + needIdentitySign = true; + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) + { + needPublishSign = false; + + if(checkMsgAuthenFlag(PRIVATE_GRP_BITS, GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN)) + needIdentitySign = true; + } + + }else + { + if(grpFlag & GXS_SERV::FLAG_PRIVACY_PUBLIC) + { + needPublishSign = false; + + if(checkMsgAuthenFlag(PUBLIC_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN)) + needIdentitySign = true; + + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) + { + if(checkMsgAuthenFlag(RESTRICTED_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN)) + needPublishSign = true; + + if(checkMsgAuthenFlag(RESTRICTED_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN)) + needIdentitySign = true; + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) + { + needPublishSign = false; + + if(checkMsgAuthenFlag(PRIVATE_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN)) + needIdentitySign = true; + } + } + + if(needPublishSign) + { + + // public and shared is publish key + RsTlvSecurityKeySet& keys = grpMeta.keys; + RsTlvSecurityKey* pubKey; + + std::map::iterator mit = + keys.keys.begin(), mit_end = keys.keys.end(); + bool pub_key_found = false; + for(; mit != mit_end; mit++) + { + + pub_key_found = mit->second.keyFlags == (RSTLV_KEY_DISTRIB_PRIVATE | RSTLV_KEY_TYPE_FULL); + if(pub_key_found) + break; + } + + // private publish key + pubKey = &(mit->second); + + RsTlvKeySignature pubSign = signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH]; + + ok &= GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, pubKey, pubSign); + + //place signature in msg meta + signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH] = pubSign; + } + + + if(needIdentitySign) + { + if(mGixs) + { + bool haveKey = mGixs->havePrivateKey(msgMeta.mAuthorId); + + if(haveKey) + { + mGixs->requestPrivateKey(msgMeta.mAuthorId); + + RsTlvSecurityKey authorKey; + + double timeDelta = 0.002; // fast polling + time_t now = time(NULL); + + // poll immediately but, don't spend more than a second polling + while( (mGixs->getPrivateKey(msgMeta.mAuthorId, authorKey) == -1) && + ((now + 1) >> time(NULL)) + ) + { + #ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); + #else + Sleep((int) (timeDelta * 1000)); + #endif + } + + + RsTlvKeySignature sign; + ok &= GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, + &authorKey, sign); + signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY] = sign; + + }else + { + ok = false; + } + } + else + { +#ifdef GEN_EXHANGE_DEBUG + std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; +#endif + ok = false; + } + } + + return ok; + + +} + +bool RsGenExchange::createMessage(RsNxsMsg* msg) +{ + const RsGxsGroupId& id = msg->grpId; + + std::map metaMap; + + metaMap.insert(std::make_pair(id, (RsGxsGrpMetaData*)(NULL))); + mDataStore->retrieveGxsGrpMetaData(metaMap); + bool ok = true; + RsGxsMsgMetaData &meta = *(msg->metaData); + + if(!metaMap[id]) + { + return false; + } + else + { + // get publish key + RsGxsGrpMetaData* grpMeta = metaMap[id]; + + uint32_t metaDataLen = meta.serial_size(); + uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len; + char* metaData = new char[metaDataLen]; + char* allMsgData = new char[allMsgDataLen]; // msgData + metaData + + meta.serialise(metaData, &metaDataLen); + + // copy msg data and meta in allmsgData buffer + memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len); + memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen); + + RsTlvBinaryData msgData(0); + + msgData.setBinData(allMsgData, allMsgDataLen); + + // create signatures + ok &= createMsgSignatures(meta.signSet, msgData, meta, *grpMeta); + + // get hash of msg data to create msg id + pqihash hash; + hash.addData(allMsgData, allMsgDataLen); + hash.Complete(msg->msgId); + + // assign msg id to msg meta + msg->metaData->mMsgId = msg->msgId; + + delete[] metaData; + delete[] allMsgData; + + delete grpMeta; + } + + return ok; +} + +bool RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecurityKeySet& grpKeySet) +{ + bool isParent = false; + bool checkPublishSign, checkIdentitySign; + bool valid = true; + + // publish signature is determined by whether group is public or not + // for private group signature is not needed as it needs decrypting with + // the private publish key anyways + + // restricted is a special case which heeds whether publish sign needs to be checked or not + // one may or may not want + + if(msg->metaData->mParentId.empty()) + { + isParent = true; + } + else + { + isParent = false; + } + + + if(isParent) + { + checkIdentitySign = false; + checkPublishSign = false; + + if(grpFlag & GXS_SERV::FLAG_PRIVACY_PUBLIC) + { + checkPublishSign = false; + + if(checkMsgAuthenFlag(PUBLIC_GRP_BITS, GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN)) + checkIdentitySign = true; + + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) + { + checkPublishSign = true; + + if(checkMsgAuthenFlag(RESTRICTED_GRP_BITS, GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN)) + checkIdentitySign = true; + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) + { + checkPublishSign = false; + + if(checkMsgAuthenFlag(PRIVATE_GRP_BITS, GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN)) + checkIdentitySign = true; + } + + }else + { + if(grpFlag & GXS_SERV::FLAG_PRIVACY_PUBLIC) + { + checkPublishSign = false; + + if(checkMsgAuthenFlag(PUBLIC_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN)) + checkIdentitySign = true; + + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) + { + if(checkMsgAuthenFlag(RESTRICTED_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN)) + checkPublishSign = true; + + if(checkMsgAuthenFlag(RESTRICTED_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN)) + checkIdentitySign = true; + } + else if(grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) + { + checkPublishSign = false; + + if(checkMsgAuthenFlag(PRIVATE_GRP_BITS, GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN)) + checkIdentitySign = true; + } + } + + RsGxsMsgMetaData& metaData = *(msg->metaData); + + if(checkPublishSign) + { + RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH]; + + if(grpKeySet.keys.find(sign.keyId) != grpKeySet.keys.end()) + { + RsTlvSecurityKey publishKey = grpKeySet.keys[sign.keyId]; + valid &= GxsSecurity::validateNxsMsg(*msg, sign, publishKey); + } + else + { + valid = false; + } + + } + + + + if(checkIdentitySign) + { + if(mGixs) + { + bool haveKey = mGixs->haveKey(metaData.mAuthorId); + + if(haveKey) + { + std::list peers; + mGixs->requestKey(metaData.mAuthorId, peers); + + RsTlvSecurityKey authorKey; + + double timeDelta = 0.002; // fast polling + time_t now = time(NULL); + // poll immediately but, don't spend more than a second polling + while( (mGixs->getKey(metaData.mAuthorId, authorKey) == -1) && + ((now + 1) >> time(NULL)) + ) + { + #ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); + #else + Sleep((int) (timeDelta * 1000)); + #endif + } + + RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH]; + valid &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey); + }else + { + valid = false; + } + } + else + { +#ifdef GEN_EXHANGE_DEBUG + std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; +#endif + valid = false; + } + + } + + return valid; +} + +bool RsGenExchange::checkMsgAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const +{ + switch(pos) + { + case PUBLIC_GRP_BITS: + return mAuthenPolicy & flag; + break; + case RESTRICTED_GRP_BITS: + return flag & (mAuthenPolicy >> RESTR_GRP_OFFSET); + break; + case PRIVATE_GRP_BITS: + return flag & (mAuthenPolicy >> PRIV_GRP_OFFSET); + break; + case GRP_OPTION_BITS: + return flag & (mAuthenPolicy >> GRP_OPTIONS_OFFSET); + break; + default: + std::cerr << "pos option not recognised"; + return false; + } +} bool RsGenExchange::getGroupList(const uint32_t &token, std::list &groupIds) { @@ -46,6 +699,11 @@ bool RsGenExchange::getMsgList(const uint32_t &token, return mDataAccess->getMsgList(token, msgIds); } +bool RsGenExchange::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) +{ + return mDataAccess->getMsgRelatedList(token, msgIds); +} + bool RsGenExchange::getGroupMeta(const uint32_t &token, std::list &groupInfo) { std::list metaL; @@ -61,10 +719,6 @@ bool RsGenExchange::getGroupMeta(const uint32_t &token, std::list::iterator cit = metaL.begin(); - for(; cit != metaL.end(); cit++) - delete *cit; - return ok; } @@ -81,20 +735,56 @@ bool RsGenExchange::getMsgMeta(const uint32_t &token, for(; mit != result.end(); mit++) { std::vector& metaV = mit->second; - //msgInfo[mit->first] = metaV; + + msgInfo[mit->first] = std::vector(); + std::vector& msgInfoV = msgInfo[mit->first]; std::vector::iterator vit = metaV.begin(); - + RsMsgMetaData meta; for(; vit != metaV.end(); vit++) { + RsGxsMsgMetaData& m = *(*vit); + meta = m; + msgInfoV.push_back(meta); delete *vit; } + metaV.clear(); } return ok; } -bool RsGenExchange::getGroupData(const uint32_t &token, std::vector grpItem) +bool RsGenExchange::getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMap &msgMeta) +{ + MsgRelatedMetaResult result; + bool ok = mDataAccess->getMsgRelatedSummary(token, result); + + MsgRelatedMetaResult::iterator mit = result.begin(); + + for(; mit != result.end(); mit++) + { + std::vector& metaV = mit->second; + + msgMeta[mit->first] = std::vector(); + std::vector& msgInfoV = msgMeta[mit->first]; + + std::vector::iterator vit = metaV.begin(); + RsMsgMetaData meta; + for(; vit != metaV.end(); vit++) + { + RsGxsMsgMetaData& m = *(*vit); + meta = m; + msgInfoV.push_back(meta); + delete *vit; + } + metaV.clear(); + } + + return ok; +} + + +bool RsGenExchange::getGroupData(const uint32_t &token, std::vector& grpItem) { std::list nxsGrps; @@ -102,15 +792,28 @@ bool RsGenExchange::getGroupData(const uint32_t &token, std::vector::iterator lit = nxsGrps.begin(); - if(ok) + std::cerr << "RsGenExchange::getGroupData() RsNxsGrp::len: " << nxsGrps.size(); + std::cerr << std::endl; + + if(ok) { for(; lit != nxsGrps.end(); lit++) { RsTlvBinaryData& data = (*lit)->grp; RsItem* item = mSerialiser->deserialise(data.bin_data, &data.bin_len); - RsGxsGrpItem* gItem = dynamic_cast(item); - grpItem.push_back(gItem); - delete *lit; + + if(item != NULL) + { + RsGxsGrpItem* gItem = dynamic_cast(item); + gItem->meta = *((*lit)->metaData); + grpItem.push_back(gItem); + delete *lit; + } + else + { + std::cerr << "RsGenExchange::getGroupData() ERROR deserialising item"; + std::cerr << std::endl; + } } } return ok; @@ -119,42 +822,115 @@ bool RsGenExchange::getGroupData(const uint32_t &token, std::vectorgetMsgData(token, msgResult); - NxsMsgDataResult::iterator mit = msgResult.begin(); - if(ok) - { - for(; mit != msgResult.end(); mit++) - { - std::vector gxsMsgItems; - const RsGxsGroupId& grpId = mit->first; - std::vector& nxsMsgsV = mit->second; - std::vector::iterator vit - = nxsMsgsV.begin(); - for(; vit != nxsMsgsV.end(); vit++) - { - RsNxsMsg*& msg = *vit; + RsStackMutex stack(mGenMtx); + NxsMsgDataResult msgResult; + bool ok = mDataAccess->getMsgData(token, msgResult); + NxsMsgDataResult::iterator mit = msgResult.begin(); - RsItem* item = mSerialiser->deserialise(msg->msg.bin_data, - &msg->msg.bin_len); - RsGxsMsgItem* mItem = dynamic_cast(item); - gxsMsgItems.push_back(mItem); - delete msg; - } - msgItems[grpId] = gxsMsgItems; - } - } + if(ok) + { + for(; mit != msgResult.end(); mit++) + { + std::vector gxsMsgItems; + const RsGxsGroupId& grpId = mit->first; + std::vector& nxsMsgsV = mit->second; + std::vector::iterator vit + = nxsMsgsV.begin(); + for(; vit != nxsMsgsV.end(); vit++) + { + RsNxsMsg*& msg = *vit; + + RsItem* item = mSerialiser->deserialise(msg->msg.bin_data, + &msg->msg.bin_len); + RsGxsMsgItem* mItem = dynamic_cast(item); + mItem->meta = *((*vit)->metaData); // get meta info from nxs msg + gxsMsgItems.push_back(mItem); + delete msg; + } + msgItems[grpId] = gxsMsgItems; + } + } + return ok; +} + +bool RsGenExchange::getMsgRelatedData(const uint32_t &token, GxsMsgRelatedDataMap &msgItems) +{ + + RsStackMutex stack(mGenMtx); + NxsMsgRelatedDataResult msgResult; + bool ok = mDataAccess->getMsgRelatedData(token, msgResult); + NxsMsgRelatedDataResult::iterator mit = msgResult.begin(); + + if(ok) + { + for(; mit != msgResult.end(); mit++) + { + std::vector gxsMsgItems; + const RsGxsGrpMsgIdPair& msgId = mit->first; + std::vector& nxsMsgsV = mit->second; + std::vector::iterator vit + = nxsMsgsV.begin(); + for(; vit != nxsMsgsV.end(); vit++) + { + RsNxsMsg*& msg = *vit; + + RsItem* item = mSerialiser->deserialise(msg->msg.bin_data, + &msg->msg.bin_len); + RsGxsMsgItem* mItem = dynamic_cast(item); + + if(mItem != NULL) + { + mItem->meta = *((*vit)->metaData); // get meta info from nxs msg + gxsMsgItems.push_back(mItem); + } + delete msg; + } + msgItems[msgId] = gxsMsgItems; + } + } return ok; } -RsTokenServiceV2* RsGenExchange::getTokenService() + + +RsTokenService* RsGenExchange::getTokenService() { return mDataAccess; } +bool RsGenExchange::setAuthenPolicyFlag(const uint8_t &msgFlag, uint32_t& authenFlag, const PrivacyBitPos &pos) +{ + uint32_t temp = 0; + temp = msgFlag; + + switch(pos) + { + case PUBLIC_GRP_BITS: + authenFlag &= ~PUB_GRP_MASK; + authenFlag |= temp; + break; + case RESTRICTED_GRP_BITS: + authenFlag &= ~RESTR_GRP_MASK; + authenFlag |= (temp << RESTR_GRP_OFFSET); + break; + case PRIVATE_GRP_BITS: + authenFlag &= ~PRIV_GRP_MASK; + authenFlag |= (temp << PRIV_GRP_OFFSET); + break; + case GRP_OPTION_BITS: + authenFlag &= ~GRP_OPTIONS_MASK; + authenFlag |= (temp << GRP_OPTIONS_OFFSET); + break; + default: + std::cerr << "pos option not recognised"; + return false; + } + return true; +} + void RsGenExchange::notifyNewGroups(std::vector &groups) { std::vector::iterator vit = groups.begin(); @@ -165,7 +941,7 @@ void RsGenExchange::notifyNewGroups(std::vector &groups) } -void RsGenExchange::notifyNewMessages(std::vector messages) +void RsGenExchange::notifyNewMessages(std::vector& messages) { std::vector::iterator vit = messages.begin(); @@ -176,116 +952,723 @@ void RsGenExchange::notifyNewMessages(std::vector messages) } -bool RsGenExchange::publishGroup(RsGxsGrpItem *grpItem) +void RsGenExchange::publishGroup(uint32_t& token, RsGxsGrpItem *grpItem) { - RsStackMutex stack(mGenMtx); + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + mGrpsToPublish.insert(std::make_pair(token, grpItem)); - mGrpsToPublish.push_back(grpItem); +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::publishGroup() token: " << token; + std::cerr << std::endl; +#endif - return true; } -bool RsGenExchange::publishMsg(RsGxsMsgItem *msgItem) +void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + mMsgsToPublish.insert(std::make_pair(token, msgItem)); + +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::publishMsg() token: " << token; + std::cerr << std::endl; +#endif + +} + +void RsGenExchange::setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& flag, const uint32_t& mask) +{ + /* TODO APPLY MASK TO FLAGS */ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + GrpLocMetaData g; + g.grpId = grpId; + g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, (int32_t)flag); + g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location + mGrpLocMetaMap.insert(std::make_pair(token, g)); +} + +void RsGenExchange::setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask) +{ + /* TODO APPLY MASK TO FLAGS */ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + GrpLocMetaData g; + g.grpId = grpId; + g.val.put(RsGeneralDataService::GRP_META_STATUS, (int32_t)status); + g.val.put(RsGeneralDataService::GRP_META_STATUS+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location + mGrpLocMetaMap.insert(std::make_pair(token, g)); +} + + +void RsGenExchange::setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + GrpLocMetaData g; + g.grpId = grpId; + g.val.put(RsGeneralDataService::GRP_META_SERV_STRING, servString); + mGrpLocMetaMap.insert(std::make_pair(token, g)); +} + +void RsGenExchange::setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask) +{ + /* TODO APPLY MASK TO FLAGS */ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + MsgLocMetaData m; + m.val.put(RsGeneralDataService::MSG_META_STATUS, (int32_t)status); + m.val.put(RsGeneralDataService::MSG_META_STATUS+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location + m.msgId = msgId; + mMsgLocMetaMap.insert(std::make_pair(token, m)); +} + +void RsGenExchange::setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ) +{ + RsStackMutex stack(mGenMtx); + token = mDataAccess->generatePublicToken(); + + MsgLocMetaData m; + m.val.put(RsGeneralDataService::MSG_META_SERV_STRING, servString); + m.msgId = msgId; + mMsgLocMetaMap.insert(std::make_pair(token, m)); +} + +void RsGenExchange::processMsgMetaChanges() { - RsStackMutex stack(mGenMtx); + RsStackMutex stack(mGenMtx); - mMsgsToPublish.push_back(msgItem); - return true; + std::map::iterator mit = mMsgLocMetaMap.begin(), + mit_end = mMsgLocMetaMap.end(); + + for(; mit != mit_end; mit++) + { + MsgLocMetaData& m = mit->second; + + int32_t value, mask; + bool ok = true; + + // for meta flag changes get flag to apply mask + if(m.val.getAsInt32(RsGeneralDataService::MSG_META_STATUS, value)) + { + ok = false; + if(m.val.getAsInt32(RsGeneralDataService::MSG_META_STATUS+GXS_MASK, mask)) + { + GxsMsgReq req; + std::vector msgIdV; + msgIdV.push_back(m.msgId.second); + req.insert(std::make_pair(m.msgId.first, msgIdV)); + GxsMsgMetaResult result; + mDataStore->retrieveGxsMsgMetaData(req, result); + GxsMsgMetaResult::iterator mit = result.find(m.msgId.first); + + if(mit != result.end()) + { + std::vector& msgMetaV = mit->second; + + if(!msgMetaV.empty()) + { + RsGxsMsgMetaData* meta = *(msgMetaV.begin()); + value = (meta->mMsgStatus & ~mask) | (mask & value); + m.val.put(RsGeneralDataService::MSG_META_STATUS, value); + delete meta; + ok = true; + } + } + m.val.removeKeyValue(RsGeneralDataService::MSG_META_STATUS+GXS_MASK); + } + } + + + ok &= mDataStore->updateMessageMetaData(m) == 1; + uint32_t token = mit->first; + + if(ok) + { + mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); + }else + { + mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); + } + mMsgNotify.insert(std::make_pair(token, m.msgId)); + } + + mMsgLocMetaMap.clear(); } +void RsGenExchange::processGrpMetaChanges() +{ + RsStackMutex stack(mGenMtx); + + std::map::iterator mit = mGrpLocMetaMap.begin(), + mit_end = mGrpLocMetaMap.end(); + + for(; mit != mit_end; mit++) + { + GrpLocMetaData& g = mit->second; + uint32_t token = mit->first; + + // process mask + bool ok = processGrpMask(g.grpId, g.val); + + ok &= mDataStore->updateGroupMetaData(g) == 1; + + if(ok) + { + mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); + }else + { + mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); + } + mGrpNotify.insert(std::make_pair(token, g.grpId)); + } + + mGrpLocMetaMap.clear(); +} + +bool RsGenExchange::processGrpMask(const RsGxsGroupId& grpId, ContentValue &grpCv) +{ + // first find out which mask is involved + int32_t value, mask, currValue; + std::string key; + RsGxsGrpMetaData* grpMeta = NULL; + bool ok = false; + + + std::map grpMetaMap; + std::map::iterator mit; + grpMetaMap.insert(std::make_pair(grpId, (RsGxsGrpMetaData*)(NULL))); + + mDataStore->retrieveGxsGrpMetaData(grpMetaMap); + + if((mit = grpMetaMap.find(grpId)) != grpMetaMap.end()) + { + grpMeta = mit->second; + ok = true; + } + + if(grpCv.getAsInt32(RsGeneralDataService::GRP_META_STATUS, value)) + { + key = RsGeneralDataService::GRP_META_STATUS; + currValue = grpMeta->mGroupStatus; + } + else if(grpCv.getAsInt32(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, value)) + { + key = RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG; + currValue = grpMeta->mSubscribeFlags; + }else + { + if(grpMeta) + delete grpMeta; + return true; + } + + ok &= grpCv.getAsInt32(key+GXS_MASK, mask); + + // remove mask entry so it doesn't affect + grpCv.removeKeyValue(key+GXS_MASK); + + // apply mask to current value + value = (currValue & ~mask) | (value & mask); + + grpCv.put(key, value); + + if(grpMeta) + delete grpMeta; + + return ok; +} void RsGenExchange::publishMsgs() { RsStackMutex stack(mGenMtx); - std::vector::iterator vit = mMsgsToPublish.begin(); + std::map::iterator mit = mMsgsToPublish.begin(); - for(; vit != mMsgsToPublish.end(); ) + for(; mit != mMsgsToPublish.end(); mit++) { - RsNxsMsg* msg = new RsNxsMsg(mServType); - RsGxsMsgItem* msgItem = *vit; - uint32_t size = mSerialiser->size(msgItem); - char mData[size]; - bool ok = mSerialiser->serialise(msgItem, mData, &size); + RsNxsMsg* msg = new RsNxsMsg(mServType); + RsGxsMsgItem* msgItem = mit->second; - if(ok) - { - msg->metaData = new RsGxsMsgMetaData(); - ok = mDataAccess->addMsgData(msg); + msg->grpId = msgItem->meta.mGroupId; - if(ok) - { - RsGxsMsgChange* mc = new RsGxsMsgChange(); - mNotifications.push_back(mc); - } - } + uint32_t size = mSerialiser->size(msgItem); + char* mData = new char[size]; + bool serialOk = false; + bool createOk = false; + serialOk = mSerialiser->serialise(msgItem, mData, &size); + + if(serialOk) + { + msg->msg.setBinData(mData, size); + + // now create meta + msg->metaData = new RsGxsMsgMetaData(); + *(msg->metaData) = msgItem->meta; + + // assign time stamp + msg->metaData->mPublishTs = time(NULL); + + // now intialise msg (sign it) + createOk = createMessage(msg); + RsGxsMessageId msgId; + RsGxsGroupId grpId = msgItem->meta.mGroupId; + + bool msgDoesnExist = false; + + if(createOk) + { + + GxsMsgReq req; + std::vector msgV; + msgV.push_back(msg->msgId); + GxsMsgMetaResult res; + req.insert(std::make_pair(msg->grpId, msgV)); + mDataStore->retrieveGxsMsgMetaData(req, res); + msgDoesnExist = res[grpId].empty(); - if(!ok) - { #ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishMsgs() failed to publish msg " << std::endl; + if (!msgDoesnExist) + { + std::cerr << "RsGenExchange::publishMsgs() msg exists already :( " << std::endl; + } #endif - delete msg; - continue; + } - } + if(createOk && msgDoesnExist) + { + // empty orig msg id means this is the original + // msg + // TODO: a non empty msgid means one should at least + // have the msg on disk, after which this msg is signed + // based on the security settings + // public grp (sign by grp public pub key, private/id: signed by + // id + if(msg->metaData->mOrigMsgId.empty()) + { + msg->metaData->mOrigMsgId = msg->metaData->mMsgId; + } - delete msgItem; + // now serialise meta data + size = msg->metaData->serial_size(); + char metaDataBuff[size]; + msg->metaData->serialise(metaDataBuff, &size); + msg->meta.setBinData(metaDataBuff, size); + + msg->metaData->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; + msgId = msg->msgId; + grpId = msg->grpId; + mDataAccess->addMsgData(msg); + + + // add to published to allow acknowledgement + mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(grpId, msgId))); + mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); + } + else + { + // delete msg if created wasn't ok + delete msg; + mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); + +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::publishMsgs() failed to publish msg " << std::endl; +#endif + } + } + else + { +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::publishMsgs() failed to serialise msg " << std::endl; +#endif + } + + delete[] mData; + delete msgItem; } + + // clear msg list as we're done publishing them and entries + // are invalid + mMsgsToPublish.clear(); } +void RsGenExchange::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) +{ +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::service_CreateGroup(): Does nothing" + << std::endl; +#endif + return; +} + + +#define GEN_EXCH_GRP_CHUNK 3 + void RsGenExchange::publishGrps() { - RsStackMutex stack(mGenMtx); + RsStackMutex stack(mGenMtx); - std::vector::iterator vit = mGrpsToPublish.begin(); + std::map::iterator mit = mGrpsToPublish.begin(); + std::vector toRemove; + int i = 0; + for(; mit != mGrpsToPublish.end(); mit++) + { - for(; vit != mGrpsToPublish.end();) - { + if(i > GEN_EXCH_GRP_CHUNK-1) break; - RsNxsGrp* grp = new RsNxsGrp(mServType); - RsGxsGrpItem* grpItem = *vit; - uint32_t size = mSerialiser->size(grpItem); + toRemove.push_back(mit->first); + i++; - char gData[size]; - bool ok = mSerialiser->serialise(grpItem, gData, &size); + RsNxsGrp* grp = new RsNxsGrp(mServType); + RsGxsGrpItem* grpItem = mit->second; - if(ok) - { - grp->metaData = new RsGxsGrpMetaData(); - ok = mDataAccess->addGroupData(grp); - RsGxsGroupChange* gc = new RsGxsGroupChange(); - mNotifications.push_back(gc); - } + RsTlvSecurityKeySet keySet; + generateGroupKeys(keySet, + !(grpItem->meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_PUBLIC)); - if(!ok) - { + // find private admin key + RsTlvSecurityKey privAdminKey; + std::map::iterator mit_keys = keySet.keys.begin(); + + bool privKeyFound = false; + for(; mit_keys != keySet.keys.end(); mit_keys++) + { + RsTlvSecurityKey& key = mit_keys->second; + + if(key.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) + { + privAdminKey = key; + privKeyFound = true; + } + } + + bool ok = true; + + if(privKeyFound) + { + // get group id from private admin key id + grpItem->meta.mGroupId = grp->grpId = privAdminKey.keyId; + } + else + { + ok = false; + } + + + service_CreateGroup(grpItem, keySet); + + uint32_t size = mSerialiser->size(grpItem); + char gData[size]; + ok = mSerialiser->serialise(grpItem, gData, &size); + + if (!ok) + { + std::cerr << "RsGenExchange::publishGrps() !ok ERROR After First Serialise" << std::endl; + } + + grp->grp.setBinData(gData, size); + + if(ok) + { + grp->metaData = new RsGxsGrpMetaData(); + grpItem->meta.mPublishTs = time(NULL); + *(grp->metaData) = grpItem->meta; + grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; + + ok &= createGroup(grp, keySet); + + if (!ok) + { + std::cerr << "RsGenExchange::publishGrps() !ok ERROR After createGroup" << std::endl; + } + + RsGxsGroupId grpId = grp->grpId; + mDataAccess->addGroupData(grp); + + std::cerr << "RsGenExchange::publishGrps() ok -> pushing to notifies" << std::endl; + + // add to published to allow acknowledgement + mGrpNotify.insert(std::make_pair(mit->first, grpId)); + mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); + } + + if(!ok) + { #ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() failed to publish grp " << std::endl; #endif - delete grp; - continue; - } + std::cerr << "RsGenExchange::publishGrps() failed to publish grp " << std::endl; + delete grp; - delete grpItem; + // add to published to allow acknowledgement, grpid is empty as grp creation failed + mGrpNotify.insert(std::make_pair(mit->first, RsGxsGroupId(""))); + mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); + continue; + } - vit = mGrpsToPublish.erase(vit); - } + delete grpItem; + + } + + // clear grp list as we're done publishing them and entries + // are invalid + + + for(int i = 0; i < toRemove.size(); i++) + mGrpsToPublish.erase(toRemove[i]); +} + + + +uint32_t RsGenExchange::generatePublicToken() +{ + return mDataAccess->generatePublicToken(); +} + +bool RsGenExchange::updatePublicRequestStatus(const uint32_t &token, const uint32_t &status) +{ + return mDataAccess->updatePublicRequestStatus(token, status); +} + +bool RsGenExchange::disposeOfPublicToken(const uint32_t &token) +{ + return mDataAccess->disposeOfPublicToken(token); +} + +RsGeneralDataService* RsGenExchange::getDataStore() +{ + return mDataStore; +} + +bool RsGenExchange::getGroupKeys(const RsGxsGroupId &grpId, RsTlvSecurityKeySet &keySet) +{ + if(grpId.empty()) + return false; + + RsStackMutex stack(mGenMtx); + + std::map grpMeta; + grpMeta[grpId] = NULL; + mDataStore->retrieveGxsGrpMetaData(grpMeta); + + if(grpMeta.empty()) + return false; + + RsGxsGrpMetaData* meta = grpMeta[grpId]; + + if(meta == NULL) + return false; + + keySet = meta->keys; + return true; +} + +void RsGenExchange::createDummyGroup(RsGxsGrpItem *grpItem) +{ + RsStackMutex stack(mGenMtx); + + RsNxsGrp* grp = new RsNxsGrp(mServType); + uint32_t size = mSerialiser->size(grpItem); + char gData[size]; + bool ok = mSerialiser->serialise(grpItem, gData, &size); + grp->grp.setBinData(gData, size); + + RsTlvSecurityKeySet keySet; + generateGroupKeys(keySet, + !(grpItem->meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_PUBLIC)); + + // find private admin key + RsTlvSecurityKey privAdminKey; + std::map::iterator mit_keys = keySet.keys.begin(); + + bool privKeyFound = false; + for(; mit_keys != keySet.keys.end(); mit_keys++) + { + RsTlvSecurityKey& key = mit_keys->second; + + if(key.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) + { + privAdminKey = key; + privKeyFound = true; + } + } + + + if(privKeyFound) + { + // get group id from private admin key id + grpItem->meta.mGroupId = grp->grpId = privAdminKey.keyId; + } + else + { + ok = false; + } + + service_CreateGroup(grpItem, keySet); + + if(ok) + { + grp->metaData = new RsGxsGrpMetaData(); + grpItem->meta.mPublishTs = time(NULL); + *(grp->metaData) = grpItem->meta; + grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; + createGroup(grp, keySet); + + mDataAccess->addGroupData(grp); + } + + if(!ok) + { + +#ifdef GEN_EXCH_DEBUG +#endif + std::cerr << "RsGenExchange::createDummyGroup(); failed to publish grp " << std::endl; + delete grp; + } + + delete grpItem; +} + + +void RsGenExchange::processRecvdData() +{ + processRecvdGroups(); + + processRecvdMessages(); +} + + +void RsGenExchange::processRecvdMessages() +{ + RsStackMutex stack(mGenMtx); + + std::vector::iterator vit = mReceivedMsgs.begin(); + GxsMsgReq msgIds; + std::map msgs; + + std::map grpMetas; + + // coalesce group meta retrieval for performance + for(; vit != mReceivedMsgs.end(); vit++) + { + RsNxsMsg* msg = *vit; + grpMetas.insert(std::make_pair(msg->grpId, (RsGxsGrpMetaData*)NULL)); + } + + mDataStore->retrieveGxsGrpMetaData(grpMetas); + + for(vit = mReceivedMsgs.begin(); vit != mReceivedMsgs.end(); vit++) + { + RsNxsMsg* msg = *vit; + RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); + bool ok = meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len)); + + + if(ok) + { + std::map::iterator mit = grpMetas.find(msg->grpId); + + // validate msg + if(mit != grpMetas.end()){ + RsGxsGrpMetaData* grpMeta = mit->second; + ok = true; +// msg->metaData = meta; + // ok &= validateMsg(msg, grpMeta->mGroupFlags, grpMeta->keys); + // msg->metaData = NULL; + } + else + ok = false; + + if(ok) + { + meta->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; + msgs.insert(std::make_pair(msg, meta)); + msgIds[msg->grpId].push_back(msg->msgId); + } + } + + if(!ok) + { +#ifdef GXS_GENX_DEBUG + std::cerr << "failed to deserialise incoming meta, grpId: " + << msg->grpId << ", msgId: " << msg->msgId << std::endl; +#endif + delete msg; + delete meta; + } + } + + std::map::iterator mit = grpMetas.begin(); + + // clean up resources + for(; mit != grpMetas.end(); mit++) + { + delete mit->second; + } + + if(!msgIds.empty()) + { + mDataStore->storeMessage(msgs); + RsGxsMsgChange* c = new RsGxsMsgChange(); + c->msgChangeMap = msgIds; + mNotifications.push_back(c); + } + + mReceivedMsgs.clear(); +} + + +void RsGenExchange::processRecvdGroups() +{ + RsStackMutex stack(mGenMtx); + + std::vector::iterator vit = mReceivedGrps.begin(); + std::map grps; + + std::list grpIds; + + for(; vit != mReceivedGrps.end(); vit++) + { + RsNxsGrp* grp = *vit; + RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); + bool ok = meta->deserialise(grp->meta.bin_data, grp->meta.bin_len); + + if(ok) + { + meta->mGroupStatus = GXS_SERV::GXS_GRP_STATUS_UNPROCESSED | GXS_SERV::GXS_GRP_STATUS_UNREAD; + grps.insert(std::make_pair(grp, meta)); + grpIds.push_back(grp->grpId); + } + else + { +#ifdef GXS_GENX_DEBUG + std::cerr << "failed to deserialise incoming meta, grpId: " + << grp->grpId << std::endl; +#endif + delete grp; + delete meta; + } + } + + if(!grpIds.empty()) + { + RsGxsGroupChange* c = new RsGxsGroupChange(); + c->grpIdList = grpIds; + mNotifications.push_back(c); + mDataStore->storeGroup(grps); + } + + mReceivedGrps.clear(); } -void RsGenExchange::processRecvdData() { -} - - -void RsGenExchange::processRecvdMessages() { -} - - -void RsGenExchange::processRecvdGroups() { -} diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index ad2aa7e37..115738920 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -2,7 +2,7 @@ #define RSGENEXCHANGE_H /* - * libretroshare/src/retroshare: rsphoto.h + * libretroshare/src/gxs: rsgenexchange.h * * RetroShare C++ Interface. * @@ -27,17 +27,21 @@ */ #include +#include #include "rsgxs.h" #include "rsgds.h" #include "rsnxs.h" #include "rsgxsdataaccess.h" +#include "rsnxsobserver.h" #include "retroshare/rsgxsservice.h" #include "serialiser/rsnxsitems.h" typedef std::map > GxsMsgDataMap; typedef std::map GxsGroupDataMap; +typedef std::map > GxsMsgRelatedDataMap; typedef std::map > GxsMsgMetaMap; +typedef std::map > GxsMsgRelatedMetaMap; /*! * This should form the parent class to \n @@ -45,42 +49,49 @@ typedef std::map > GxsMsgMetaMap; * management/publishing/sync features * * Features: \n - * a. Data Access: - * Provided by handle to RsTokenService. This ensure consistency - * of requests and hiearchy of groups -> then messages which are - * sectioned by group ids. - * The one caveat is that redemption of tokens are done through - * the backend of this class - * b. Publishing: - * Methods are provided to publish msg and group items and also make - * changes to meta information of both item types - * c. Sync/Notification: - * Also notifications are made here on receipt of new data from + * a. Data Access: \n + * Provided by handle to RsTokenService. This ensure consistency \n + * of requests and hiearchy of groups -> then messages which are \n + * sectioned by group ids. \n + * The one caveat is that redemption of tokens are done through \n + * the backend of this class \n + * b. Publishing: \n + * Methods are provided to publish msg and group items and also make \n + * changes to meta information of both item types \n + * c. Sync/Notification: \n + * Also notifications are made here on receipt of new data from \n * connected peers */ -class RsGenExchange : public RsGxsService + +class RsGixs; + +class RsGenExchange : public RsGxsService, public RsNxsObserver, public RsThread { public: /*! - * Constructs a RsGenExchange object, the owner ship of gds, ns, and serviceserialiser passes + * Constructs a RsGenExchange object, the owner ship of gds, ns, and serviceserialiser passes \n * onto the constructed object * @param gds Data service needed to act as store of message * @param ns Network service needed to synchronise data with rs peers * @param serviceSerialiser The users service needs this \n * in order for gen exchange to deal with its data types + * @param mServType This should be service type used by the serialiser + * @param gixs This is used for verification of msgs and groups received by Gen Exchange using identities, set to NULL if \n + * identity verification is not wanted + * @param authenPolicy This determines the authentication used for verfying authorship of msgs and groups */ - RsGenExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, uint16_t mServType); + RsGenExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, + RsSerialType* serviceSerialiser, uint16_t mServType, RsGixs* gixs = NULL, uint32_t authenPolicy = 0); virtual ~RsGenExchange(); - /** S: Observer implementation **/ /*! * @param messages messages are deleted after function returns */ - void notifyNewMessages(std::vector messages); + void notifyNewMessages(std::vector& messages); /*! * @param messages messages are deleted after function returns @@ -96,14 +107,37 @@ public: */ void tick(); + /*! + * Any backgroup processing needed by + */ + virtual void service_tick() = 0; + + /*! * * @return handle to token service handle for making * request to this gxs service */ - RsTokenServiceV2* getTokenService(); + RsTokenService* getTokenService(); -protected: + void run(); + + /*! + * Policy bit pattern portion + */ + enum PrivacyBitPos { PUBLIC_GRP_BITS, RESTRICTED_GRP_BITS, PRIVATE_GRP_BITS, GRP_OPTION_BITS } ; + + /*! + * Convenience function for setting bit patterns of the individual privacy level authentication + * policy and group options + * @param flag the bit pattern (and policy) set for the privacy policy + * @param authenFlag Only the policy portion chosen will be modified with 'flag' + * @param pos The policy portion to modify + * @see PrivacyBitPos + */ + static bool setAuthenPolicyFlag(const uint8_t& flag, uint32_t& authenFlag, const PrivacyBitPos& pos); + +public: /** data access functions **/ @@ -119,14 +153,24 @@ protected: * Retrieve msg list for a given token sectioned by group Ids * @param token token to be redeemed * @param msgIds a map of grpId -> msgList (vector) + * @return false if could not redeem token */ bool getMsgList(const uint32_t &token, GxsMsgIdResult &msgIds); + /*! + * Retrieve msg list for a given token for message related info + * @param token token to be redeemed + * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) + * @return false if could not redeem token + */ + bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult& msgIds); + /*! * retrieve group meta data associated to a request token * @param token * @param groupInfo + * @return false if could not redeem token */ bool getGroupMeta(const uint32_t &token, std::list &groupInfo); @@ -137,12 +181,31 @@ protected: */ bool getMsgMeta(const uint32_t &token, GxsMsgMetaMap &msgInfo); + /*! + * Retrieve msg meta for a given token for message related info + * @param token token to be redeemed + * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) + * @return false if could not redeem token + */ + bool getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMap& msgMeta); + + + + +protected: + + /*! + * @param grpItem + * @deprecated only here temporarily for testing + */ + void createDummyGroup(RsGxsGrpItem* grpItem); + /*! * retrieves group data associated to a request token * @param token token to be redeemed for grpitem retrieval * @param grpItem the items to be retrieved for token are stored here */ - bool getGroupData(const uint32_t &token, std::vector grpItem); + bool getGroupData(const uint32_t &token, std::vector& grpItem); /*! * retrieves message data associated to a request token @@ -151,30 +214,210 @@ protected: */ bool getMsgData(const uint32_t &token, GxsMsgDataMap& msgItems); + /*! + * retrieves message related data associated to a request token + * @param token token to be redeemed for message item retrieval + * @param msgItems + */ + bool getMsgRelatedData(const uint32_t &token, GxsMsgRelatedDataMap& msgItems); + + /*! + * Convenience template function for retrieve + * msg related data from + * @param GxsMsgType This represent derived msg class type of the service (i.e. msg type that derives from RsGxsMsgItem + * @param MsgType Represents the final type the core data is converted to + * @param token token to be redeemed + */ + template + bool getMsgRelatedDataT(const uint32_t &token, std::map > &msgItems) + { + + RsStackMutex stack(mGenMtx); + NxsMsgRelatedDataResult msgResult; + bool ok = mDataAccess->getMsgRelatedData(token, msgResult); + NxsMsgRelatedDataResult::iterator mit = msgResult.begin(); + + if(ok) + { + for(; mit != msgResult.end(); mit++) + { + std::vector gxsMsgItems; + const RsGxsGrpMsgIdPair& msgId = mit->first; + std::vector& nxsMsgsV = mit->second; + std::vector::iterator vit + = nxsMsgsV.begin(); + for(; vit != nxsMsgsV.end(); vit++) + { + RsNxsMsg*& msg = *vit; + + RsItem* item = mSerialiser->deserialise(msg->msg.bin_data, + &msg->msg.bin_len); + GxsMsgType* mItem = dynamic_cast(item); + + if(mItem == NULL){ + delete msg; + continue; + } + + mItem->meta = *((*vit)->metaData); // get meta info from nxs msg + // GxsMsgType m = (*mItem); // doesn't work! don't know why, even with overloading done. + MsgType theServMsg = (MsgType)*mItem; + gxsMsgItems.push_back(theServMsg); + delete msg; + } + msgItems[msgId] = gxsMsgItems; + } + } + return ok; + } + + /*! + * Assigns a token value to passed integer + * The status of the token can still be queried from request status feature + * @warning the token space is shared with RsGenExchange backend, so do not + * modify tokens except does you have created by calling generatePublicToken() + * @return token + */ + uint32_t generatePublicToken(); + + /*! + * Updates the status of associate token + * @warning the token space is shared with RsGenExchange backend, so do not + * modify tokens except does you have created by calling generatePublicToken() + * @param token + * @param status + * @return false if token could not be found, true if token disposed of + */ + bool updatePublicRequestStatus(const uint32_t &token, const uint32_t &status); + + /*! + * This gets rid of a publicly issued token + * @param token + * @return false if token could not found, true if token is disposed of + */ + bool disposeOfPublicToken(const uint32_t &token); + + /*! + * This gives access to the data store which hold msgs and groups + * for the service + * @return Data store for retrieving msgs and groups + */ + RsGeneralDataService* getDataStore(); + + /*! + * Retrieve keys for a given group, \n + * call is blocking retrieval from underlying db + * @warning under normal circumstance a service should not need this + * @param grpId the id of the group to retrieve keys for + * @param keys this is set to the retrieved keys + * @return false if group does not exist or grpId is empty + */ + bool getGroupKeys(const RsGxsGroupId& grpId, RsTlvSecurityKeySet& keySet); + +public: + + /*! + * This allows the client service to acknowledge that their msgs has \n + * been created/modified and retrieve the create/modified msg ids + * @param token the token related to modification/create request + * @param msgIds map of grpid->msgIds of message created/modified + * @return true if token exists false otherwise + */ + bool acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId); + + /*! + * This allows the client service to acknowledge that their grps has \n + * been created/modified and retrieve the create/modified grp ids + * @param token the token related to modification/create request + * @param msgIds vector of ids of groups created/modified + * @return true if token exists false otherwise + */ + bool acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId); + protected: /** Modifications **/ /*! - * Enables publication of a group item - * If the item exists already this is simply versioned - * This will induce a related change message - * Ownership of item passes to this rsgenexchange + * Enables publication of a group item \n + * If the item exists already this is simply versioned \n + * This will induce a related change message \n + * Ownership of item passes to this rsgenexchange \n + * @param token * @param grpItem - * @param */ - bool publishGroup(RsGxsGrpItem* grpItem); + void publishGroup(uint32_t& token, RsGxsGrpItem* grpItem); /*! - * Enables publication of a message item - * If the item exists already this is simply versioned - * This will induce a related a change message + * Enables publication of a message item \n + * Setting mOrigMsgId meta member to blank \n + * leads to this msg being an original msg \n + * if mOrigMsgId is not blank the msgId then this msg is \n + * considered a versioned msg \n * Ownership of item passes to this rsgenexchange + * @param token * @param msgItem - * @return false if msg creation failed. */ - bool publishMsg(RsGxsMsgItem* msgItem); + void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem); + /*! + * This represents the group before its signature is calculated + * Reimplement this function if you need to access keys to further extend + * security of your group items using keyset properties + * @warning do not modify keySet! + * @param grp The group which is stored by GXS prior + * service can make specific modifications need + * in particular access to its keys and meta + * @param keySet this is the key set used to define the group + * contains private and public admin and publish keys + * (use key flags to distinguish) + */ + virtual void service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); + +public: + + /*! + * sets the group subscribe flag + * @param token this is set to token value associated to this request + * @param grpId Id of group whose subscribe file will be changed + * @param status + * @param mask + */ + void setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); + + /*! + * sets the group subscribe flag + * @param token this is set to token value associated to this request + * @param grpId Id of group whose subscribe file will be changed + * @param status + * @param mask + */ + void setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); + + /*! + * sets the group service string + * @param token this is set to token value associated to this request + * @param grpId Id of group whose subscribe file will be changed + * @param servString + */ + void setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); + + /*! + * sets the msg status flag + * @param token this is set to token value associated to this request + * @param grpId Id of group whose subscribe file will be changed + * @param status + * @param mask Mask to apply to status flag + */ + void setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask); + + /*! + * sets the message service string + * @param token this is set to token value associated to this request + * @param msgId Id of message whose service string will be changed + * @param servString The service string to set msg to + */ + void setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); protected: @@ -187,11 +430,16 @@ protected: * as it is called by the backend GXS system to \n * update client of changes which should \n * instigate client to retrieve new content from the system + * Note! For newly received message and groups, bit 0xf00 is set to + * GXS_SERV::GXS_MSG_STATUS_UNPROCESSED and GXS_SERV::GXS_MSG_STATUS_UNREAD * @param changes the changes that have occured to data held by this service */ virtual void notifyChanges(std::vector& changes) = 0; -public: + + + +private: void processRecvdData(); @@ -203,6 +451,82 @@ public: void publishMsgs(); + /*! + * processes msg local meta changes + */ + void processMsgMetaChanges(); + + /*! + * Processes group local meta changes + */ + void processGrpMetaChanges(); + + /*! + * Convenience function for properly applying masks for status and subscribe flag + * of a group. + * @warning mask entry is removed from grpCv + */ + bool processGrpMask(const RsGxsGroupId& grpId, ContentValue& grpCv); + + /*! + * This completes the creation of an instance on RsNxsGrp + * by assigning it a groupId and signature via SHA1 and EVP_sign respectively \n + * Meta is serialised and stored in group at this point also + * @param grp Nxs group to create + */ + bool createGroup(RsNxsGrp* grp, RsTlvSecurityKeySet& keySet); + + /*! + * This completes the creation of an instance on RsNxsMsg + * by assigning it a groupId and signature via SHA1 and EVP_sign respectively + * What signatures are calculated are based on the authentication policy + * of the service + * @param msg the Nxs message to create + */ + bool createMessage(RsNxsMsg* msg); + + /*! + * convenience function to create sign + * @param signSet signatures are stored here + * @param msgData message data to be signed + * @param grpMeta the meta data for group the message belongs to + * @return false if signature creation for any required signature fails, true otherwise + */ + bool createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& msgData, + const RsGxsMsgMetaData& msgMeta, RsGxsGrpMetaData& grpMeta); + + /*! + * check meta change is legal + * @return false if meta change is not legal + */ + bool locked_validateGrpMetaChange(GrpLocMetaData&); + + /*! + * Generate a set of keys that can define a GXS group + * @param keySet this is set generated keys + * @param genPublicKeys should public keys also be generated + */ + void generateGroupKeys(RsTlvSecurityKeySet& keySet, bool genPublishKeys); + + /*! + * Attempts to validate msg + * @param msg message to be validated + * @param grpFlag the flag for the group the message belongs to + * @param grpKeySet + * @return true if msg validates, false otherwise + */ + bool validateMsg(RsNxsMsg* msg, const uint32_t& grpFlag, RsTlvSecurityKeySet& grpKeySet); + + /*! + * Checks flag against a given privacy bit block + * @param pos Determines 8 bit wide privacy block to check + * @param flag the flag to and(&) against + * @param the result of the (bit-block & flag) + */ + bool checkMsgAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const; + + void groupShareKeys(std::list peers); + private: RsMutex mGenMtx; @@ -210,18 +534,29 @@ private: RsGeneralDataService* mDataStore; RsNetworkExchangeService *mNetService; RsSerialType *mSerialiser; + RsGixs* mGixs; std::vector mReceivedMsgs; std::vector mReceivedGrps; - std::vector mGrpsToPublish; - std::vector mMsgsToPublish; + std::map mGrpsToPublish; + std::map mMsgsToPublish; + + std::map mMsgNotify; + std::map mGrpNotify; + + // for loc meta changes + std::map mGrpLocMetaMap; + std::map mMsgLocMetaMap; std::vector mNotifications; /// service type uint16_t mServType; + /// authentication policy + uint32_t mAuthenPolicy; + private: diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h index baeb4b138..6a3d91372 100644 --- a/libretroshare/src/gxs/rsgixs.h +++ b/libretroshare/src/gxs/rsgixs.h @@ -27,9 +27,11 @@ */ #include "gxs/rsgxs.h" +#include "gxs/rsgenexchange.h" -#include -#include +#include "retroshare/rsgxscircles.h" + +#include "serialiser/rstlvkeys.h" /*! * GIXP: General Identity Exchange Service. @@ -60,116 +62,93 @@ */ -/*! - * Storage class for private and public publish keys +/****** + * More notes. The ideas above have been crystalised somewhat. * + * The Identity service will now serve two roles: + * 1) validating msgs. + * 2) reputation of identity. + * + * The identity will be equivalent to a Group Definition. + * and the reputation contained in the group's messages. + * + * + * Group + * MetaData: + * Public Key + * Signatures. (Admin & optional GPG). + * RealData: + * Nickname. + * GPGHash + * + * The GPGHash will allow people to identify the real gpg user behind the identity. + * We must make sure that the Hash input has enough entropy that it cannot be brute-forced (e.g. like password hashes). + * + * The Identity service only has to provide hooks to access the Keys for each group. + * All the key definitions are exactly the same as for GroupMetaData. + * + * The Interface is split into three parts. + * 1) Internal interface used by GXS to verify signatures. + * 2) Internal interface used by GXS to help decide if we get a message or not. + * 3) External interface to access nicknames, generate new identities etc. + * + * The actual implementation will cache frequently used keys and nicknames, + * as these will be used very frequently. + *****/ + +typedef std::string PeerId; // SHOULD BE REMOVED => RsPeerId (SSLID) +typedef std::string RsPgpId; +typedef std::string RsGxsId; + +// +//// External Interface - +//class RsIdentityService +//{ +// enum IdentityType { Pseudonym, Signed, Anonymous }; +// +// virtual bool loadId(const GxsId &id) = 0; +// +// virtual bool getNickname(const GxsId &id, std::string &nickname) = 0; +// +// virtual bool createKey(RsGixsProfile& profile, uint32_t type) = 0; /* fills in mKeyId, and signature */ +// +// virtual RsGixsProfile* getProfile(const KeyRef& keyref) = 0; +// +// // modify reputation. +// +//}; + + +/* Identity Interface for GXS Message Verification. */ -class GixsKey -{ - KeyRef mKeyId; - - /// public key - EVP_PKEY *mPubKey; - - /// NULL if non-existant */ - EVP_PKEY *mPrivKey; -}; - -/*! - * - * - */ -class KeyRef { - - std::string refId; - -}; - - -class KeyRefSet { - std::set mKeyRefSet; -}; - -class SignatureSet { - std::set mSignatureSet; -}; - -/*! - * - * - */ -class RsGxsSignature { - - KeyRef mKeyRef; -}; - -/*! - * This is the actual identity \n - * In a sense the group description with the GixsKey the "message" - */ -class RsGixsProfile { - -public: - - KeyRef mKeyRef; - std::string name; - - /// may be superseded by newer timestamps - time_t mTimeStamp; - uint32_t mProfileType; - - // TODO: add permissions members - - RsGxsSignature mSignature; - -}; - -/*! - * Retroshare general identity exchange service - * - * Purpose: \n - * Provides a means to distribute identities among peers \n - * Also provides encyption, decryption, verification, \n - * and signing functionality using any created or received identities \n - * - * This may best be implemented as a singleton like current AuthGPG? \n - * - */ -class RsIdentityExchangeService : RsGxsService +class RsGixs { public: - - enum IdentityType { Pseudonym, Signed, Anonymous }; - - RsGixs(); - - /*! - * creates gixs profile and shares it - * @param profile - * @param type the type of profile to create, self signed, anonymous, and GPG signed - */ - virtual bool createKey(RsGixsProfile& profile, uint32_t type) = 0; /* fills in mKeyId, and signature */ - + // Key related interface - used for validating msgs and groups. /*! * Use to query a whether given key is available by its key reference * @param keyref the keyref of key that is being checked for * @return true if available, false otherwise */ - virtual bool haveKey(const KeyRef& keyref) = 0; + virtual bool haveKey(const RsGxsId &id) = 0; /*! * Use to query whether private key member of the given key reference is available * @param keyref the KeyRef of the key being checked for * @return true if private key is held here, false otherwise */ - virtual bool havePrivateKey(const KeyRef& keyref) = 0; + virtual bool havePrivateKey(const RsGxsId &id) = 0; + // The fetchKey has an optional peerList.. this is people that had the msg with the signature. + // These same people should have the identity - so we ask them first. /*! * Use to request a given key reference * @param keyref the KeyRef of the key being requested * @return will */ - virtual bool requestKey(const KeyRef& keyref) = 0; + virtual bool requestKey(const RsGxsId &id, const std::list &peers) = 0; + virtual bool requestPrivateKey(const RsGxsId &id) = 0; + /*! * Retrieves a key identity @@ -177,53 +156,68 @@ public: * @return a pointer to a valid profile if successful, otherwise NULL * */ - virtual RsGixsProfile* getProfile(const KeyRef& keyref) = 0; + virtual int getKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; + virtual int getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; // For signing outgoing messages. - /*** process data ***/ +}; - /*! - * Use to sign data with a given key - * @param keyref the key to sign the data with - * @param data the data to be signed - * @param dataLen the length of the data - * @param signature is set with the signature from signing with keyref - * @return false if signing failed, true otherwise - */ - virtual bool sign(const KeyRef& keyref, unsigned char* data, uint32_t dataLen, std::string& signature) = 0; +class GixsReputation +{ + public: + RsGxsId id; + int score; +}; - /*! - * Verify that the data is signed by the key owner - * @param keyref - * @param data - * @param dataLen - * @param signature - * @return false if verification failed, false otherwise - */ - virtual bool verify(const KeyRef& keyref, unsigned char* data, int dataLen, std::string& signature) = 0; - /*! - * Attempt to decrypt data with a given key - * @param keyref - * @param data data to be decrypted - * @param dataLen length of data - * @param decryptedData decrypted data - * @param decryptDataLen length of decrypted data - * @return false - */ - virtual bool decrypt(const KeyRef& keyref, unsigned char* data, int dataLen, - unsigned char*& decryptedData, uint32_t& decyptDataLen) = 0; +class RsGixsReputation +{ +public: + // get Reputation. + virtual bool getReputation(const RsGxsId &id, const GixsReputation &rep) = 0; +}; - /*! - * Attempt to encrypt data with a given key - * @param keyref - * @param data data to be encrypted - * @param dataLen length of data - * @param encryptedData encrypted data - * @param encryptDataLen length of encrypted data - */ - virtual bool encrypt(const KeyRef& keyref, unsigned char* data, int dataLen, - unsigned char*& encryptedData, uint32_t& encryptDataLen) = 0; + +/*** This Class pulls all the GXS Interfaces together ****/ + +class RsGxsIdExchange: + public RsGenExchange, + public RsGixsReputation, + public RsGixs +{ +public: + RsGxsIdExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, uint16_t mServType) + :RsGenExchange(gds,ns,serviceSerialiser,mServType, this) { return; } +virtual ~RsGxsIdExchange() { return; } + +}; + + + + +/* For Circles Too */ + +class RsGcxs +{ + public: + + /* GXS Interface - for working out who can receive */ + virtual bool isLoaded(const RsGxsCircleId &circleId) = 0; + virtual bool loadCircle(const RsGxsCircleId &circleId) = 0; + + virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id) = 0; + virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist) = 0; +}; + + + +class RsGxsCircleExchange: public RsGenExchange, public RsGcxs +{ +public: + RsGxsCircleExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, + uint16_t mServType, RsGixs* gixs, uint32_t authenPolicy) + :RsGenExchange(gds,ns,serviceSerialiser,mServType, gixs, authenPolicy) { return; } +virtual ~RsGxsCircleExchange() { return; } }; diff --git a/libretroshare/src/gxs/rsgxs.h b/libretroshare/src/gxs/rsgxs.h index dfa565a32..6ef240f6c 100644 --- a/libretroshare/src/gxs/rsgxs.h +++ b/libretroshare/src/gxs/rsgxs.h @@ -4,10 +4,7 @@ /* * libretroshare/src/gxs : rsgxs.h * - * GXS interface for RetroShare. - * Convenience header - * - * Copyright 2011 Christopher Evi-Parker + * Copyright 2012 Christopher Evi-Parker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,34 +22,36 @@ * * Please report all bugs and problems to "retroshare@lunamutt.com". * - * This is *THE* auth manager. It provides the web-of-trust via - * gpgme, and authenticates the certificates that are managed - * by the sublayer AuthSSL. * */ +#include "gxs/rsgxsdata.h" #include #include #include #include #include +#include -#include "rsnxsobserver.h" +/* data types used throughout Gxs from netservice to genexchange */ typedef std::map > GxsMsgReq; typedef std::map > GxsMsgIdResult; typedef std::map > GxsMsgMetaResult; -typedef std::map > NxsMsgDataResult; -typedef std::map > GxsMsgResult; // +typedef std::map > MsgMetaResult; +typedef std::map > MsgRelatedMetaResult; +typedef std::map > MsgRelatedIdResult; -class RsGxsService : public RsNxsObserver + + +class RsGxsService { public: - RsGxsService(); - virtual ~RsGxsService(); + RsGxsService(){} + virtual ~RsGxsService(){} virtual void tick() = 0; diff --git a/libretroshare/src/gxs/rsgxsdata.cc b/libretroshare/src/gxs/rsgxsdata.cc index f8f733fb0..d60e5f24a 100644 --- a/libretroshare/src/gxs/rsgxsdata.cc +++ b/libretroshare/src/gxs/rsgxsdata.cc @@ -1,10 +1,36 @@ +/* + * libretroshare/src/gxs: rsgxsdata.cc + * + * Gxs Data types used to specific services + * + * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + #include "rsgxsdata.h" #include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" RsGxsGrpMetaData::RsGxsGrpMetaData() { - + clear(); } uint32_t RsGxsGrpMetaData::serial_size() @@ -17,9 +43,11 @@ uint32_t RsGxsGrpMetaData::serial_size() s += 4; s += 4; s += GetTlvStringSize(mAuthorId); - s += adminSign.TlvSize(); + s += GetTlvStringSize(mServiceString); + s += signSet.TlvSize(); s += keys.TlvSize(); - s += idSign.TlvSize(); + s += 4; // for mCircleType + s += GetTlvStringSize(mCircleId); return s; } @@ -30,6 +58,7 @@ void RsGxsGrpMetaData::clear(){ mOrigGrpId.clear(); mAuthorId.clear(); mGroupName.clear(); + mServiceString.clear(); mPublishTs = 0; mGroupFlags = 0; mPop = 0; @@ -37,10 +66,13 @@ void RsGxsGrpMetaData::clear(){ mGroupStatus = 0; mLastPost = 0; mSubscribeFlags = 0; - - adminSign.TlvClear(); + signSet.TlvClear(); keys.TlvClear(); - idSign.TlvClear(); + mCircleId.clear(); + mInternalCircle.clear(); + mOriginator.clear(); + mCircleType = 0; + } bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize) @@ -72,11 +104,13 @@ bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize) ok &= SetTlvString(data, tlvsize, &offset, 0, mGroupName); ok &= setRawUInt32(data, tlvsize, &offset, mGroupFlags); ok &= setRawUInt32(data, tlvsize, &offset, mPublishTs); + ok &= setRawUInt32(data, tlvsize, &offset, mCircleType); ok &= SetTlvString(data, tlvsize, &offset, 0, mAuthorId); - - ok &= adminSign.SetTlv(data, tlvsize, &offset); + ok &= SetTlvString(data, tlvsize, &offset, 0, mServiceString); + ok &= SetTlvString(data, tlvsize, &offset, 0, mCircleId); + ok &= signSet.SetTlv(data, tlvsize, &offset); ok &= keys.SetTlv(data, tlvsize, &offset); - ok &= idSign.SetTlv(data, tlvsize, &offset); + return ok; } @@ -98,11 +132,13 @@ bool RsGxsGrpMetaData::deserialise(void *data, uint32_t &pktsize) ok &= GetTlvString(data, pktsize, &offset, 0, mGroupName); ok &= getRawUInt32(data, pktsize, &offset, &mGroupFlags); ok &= getRawUInt32(data, pktsize, &offset, &mPublishTs); + ok &= getRawUInt32(data, pktsize, &offset, &mCircleType); ok &= GetTlvString(data, pktsize, &offset, 0, mAuthorId); - - ok &= adminSign.GetTlv(data, pktsize, &offset); + ok &= GetTlvString(data, pktsize, &offset, 0, mServiceString); + ok &= GetTlvString(data, pktsize, &offset, 0, mCircleId); + ok &= signSet.GetTlv(data, pktsize, &offset); ok &= keys.GetTlv(data, pktsize, &offset); - ok &= idSign.GetTlv(data, pktsize, &offset); + return ok; } @@ -123,8 +159,7 @@ uint32_t RsGxsMsgMetaData::serial_size() s += GetTlvStringSize(mOrigMsgId); s += GetTlvStringSize(mAuthorId); - s += pubSign.TlvSize(); - s += idSign.TlvSize(); + s += signSet.TlvSize(); s += GetTlvStringSize(mMsgName); s += 4; s += 4; @@ -141,10 +176,9 @@ void RsGxsMsgMetaData::clear() mAuthorId.clear(); mOrigMsgId.clear(); mMsgName.clear(); + mServiceString.clear(); - pubSign.TlvClear(); - idSign.TlvClear(); - + signSet.TlvClear(); mPublishTs = 0; mMsgFlags = 0; mMsgStatus = 0; @@ -181,8 +215,7 @@ bool RsGxsMsgMetaData::serialise(void *data, uint32_t *size) ok &= SetTlvString(data, *size, &offset, 0, mOrigMsgId); ok &= SetTlvString(data, *size, &offset, 0, mAuthorId); - ok &= pubSign.SetTlv(data, *size, &offset); - ok &= idSign.SetTlv(data, *size, &offset); + ok &= signSet.SetTlv(data, *size, &offset); ok &= SetTlvString(data, *size, &offset, 0, mMsgName); ok &= setRawUInt32(data, *size, &offset, mPublishTs); ok &= setRawUInt32(data, *size, &offset, mMsgFlags); @@ -209,8 +242,7 @@ bool RsGxsMsgMetaData::deserialise(void *data, uint32_t *size) ok &= GetTlvString(data, *size, &offset, 0, mOrigMsgId); ok &= GetTlvString(data, *size, &offset, 0, mAuthorId); - ok &= pubSign.GetTlv(data, *size, &offset); - ok &= idSign.GetTlv(data, *size, &offset); + ok &= signSet.GetTlv(data, *size, &offset); ok &= GetTlvString(data, *size, &offset, 0, mMsgName); uint32_t t; ok &= getRawUInt32(data, *size, &offset, &t); @@ -232,6 +264,12 @@ void RsGxsGrpMetaData::operator =(const RsGroupMetaData& rMeta) this->mPublishTs = rMeta.mPublishTs; this->mSubscribeFlags = rMeta.mSubscribeFlags; this->mGroupName = rMeta.mGroupName; + this->mServiceString = rMeta.mServiceString; + this->mSignFlags = rMeta.mSignFlags; + this->mCircleId = rMeta.mCircleId; + this->mCircleType = rMeta.mCircleType; + this->mInternalCircle = rMeta.mInternalCircle; + this->mOriginator = rMeta.mOriginator; } void RsGxsMsgMetaData::operator =(const RsMsgMetaData& rMeta) @@ -247,6 +285,7 @@ void RsGxsMsgMetaData::operator =(const RsMsgMetaData& rMeta) this->mParentId = rMeta.mParentId ; this->mPublishTs = rMeta.mPublishTs ; this->mThreadId = rMeta.mThreadId; -} - + this->mServiceString = rMeta.mServiceString; +} + diff --git a/libretroshare/src/gxs/rsgxsdata.h b/libretroshare/src/gxs/rsgxsdata.h index 8eb686e6b..9452c364b 100644 --- a/libretroshare/src/gxs/rsgxsdata.h +++ b/libretroshare/src/gxs/rsgxsdata.h @@ -1,10 +1,33 @@ #ifndef RSGXSMETA_H #define RSGXSMETA_H -#include +/* + * libretroshare/src/gxs: rsgxsdata.h + * + * Gxs Data types used to specific services + * + * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ +#include #include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" #include "serialiser/rstlvtypes.h" #include "serialiser/rstlvkeys.h" #include "serialiser/rsgxsitems.h" @@ -32,14 +55,17 @@ public: std::string mGroupName; uint32_t mGroupFlags; uint32_t mPublishTs; + uint32_t mSignFlags; std::string mAuthorId; + std::string mCircleId; + uint32_t mCircleType; - RsTlvKeySignature adminSign; + + RsTlvKeySignatureSet signSet; RsTlvSecurityKeySet keys; - RsTlvKeySignature idSign; - + std::string mServiceString; // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. @@ -50,7 +76,8 @@ public: time_t mLastPost; // ??? uint32_t mGroupStatus; - + std::string mOriginator; + std::string mInternalCircle; }; @@ -75,8 +102,9 @@ public: RsGxsMessageId mOrigMsgId; std::string mAuthorId; - RsTlvKeySignature pubSign; - RsTlvKeySignature idSign; + RsTlvKeySignatureSet signSet; + + std::string mServiceString; std::string mMsgName; time_t mPublishTs; @@ -84,8 +112,10 @@ public: // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. // normally READ / UNREAD flags. LOCAL Data. + uint32_t mMsgStatus; time_t mChildTs; + bool validated; }; diff --git a/libretroshare/src/gxs/rsgxsdataaccess.cc b/libretroshare/src/gxs/rsgxsdataaccess.cc index 2ea9e7129..f132148d6 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.cc +++ b/libretroshare/src/gxs/rsgxsdataaccess.cc @@ -1,923 +1,1650 @@ -/* - * libretroshare/src/retroshare: rsgxsdataaccess.cc - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Robert Fernie, Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "rsgxsdataaccess.h" - -// This bit will be filled out over time. -#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId. -#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group. -#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs. - -#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group. -#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs. - -#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId - - -// Status Filtering... should it be a different Option Field. -#define RS_TOKREQOPT_GROUP_UPDATED 0x0100 // GROUPLIST: Groups that have been updated. -#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups. -#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups. - - - -// Read Status. -#define RS_TOKREQOPT_READ 0x0001 -#define RS_TOKREQOPT_UNREAD 0x0002 - -#define RS_TOKREQ_ANSTYPE_LIST 0x0001 -#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002 -#define RS_TOKREQ_ANSTYPE_DATA 0x0003 - - const uint8_t RsTokenServiceV2::GXS_REQUEST_STATUS_FAILED = 0; - const uint8_t RsTokenServiceV2::GXS_REQUEST_STATUS_PENDING = 1; - const uint8_t RsTokenServiceV2::GXS_REQUEST_STATUS_PARTIAL = 2; - const uint8_t RsTokenServiceV2::GXS_REQUEST_STATUS_FINISHED_INCOMPLETE = 3; - const uint8_t RsTokenServiceV2::GXS_REQUEST_STATUS_COMPLETE = 4; - const uint8_t RsTokenServiceV2::GXS_REQUEST_STATUS_DONE = 5; // ONCE ALL DATA RETRIEVED. - -RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds) - : mDataStore(ds), mDataMutex("RsGxsDataAccess") -{ -} - - -bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, - const std::list &groupIds) -{ - GxsRequest* req = NULL; - uint32_t reqType = opts.mReqType; - - if(reqType & GXS_REQUEST_TYPE_GROUP_META) - { - GroupMetaReq* gmr = new GroupMetaReq(); - gmr->mGroupIds = groupIds; - req = gmr; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) - { - GroupDataReq* gdr = new GroupDataReq(); - gdr->mGroupIds = groupIds; - req = gdr; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) - { - GroupIdReq* gir = new GroupIdReq(); - gir->mGroupIds = groupIds; - req = gir; - } - - if(req == NULL) - { - std::cerr << "RsGxsDataAccess::requestMsgInfo() request type not recognised, type " - << reqType << std::endl; - return false; - }else - { - generateToken(token); - std::cerr << "RsGxsDataAccess::requestMsgInfo() gets Token: " << token << std::endl; - } - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - -void RsGxsDataAccess::generateToken(uint32_t &token) -{ - RsStackMutex stack(mDataMutex); /****** LOCKED *****/ - - token = mNextToken++; - - return; -} - - -bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, - const RsTokReqOptions &opts, const GxsMsgReq &msgIds) -{ - - GxsRequest* req = NULL; - uint32_t reqType = opts.mReqType; - - if(reqType & GXS_REQUEST_TYPE_MSG_META) - { - MsgMetaReq* mmr = new MsgMetaReq(); - mmr->mMsgIds = msgIds; - req = mmr; - }else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) - { - MsgDataReq* mdr = new MsgDataReq(); - mdr->mMsgIds = msgIds; - req = mdr; - }else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) - { - MsgIdReq* mir = new MsgIdReq(); - req = mir; - } - - if(req == NULL) - { - std::cerr << "RsGxsDataAccess::requestMsgInfo() request type not recognised, type " - << reqType << std::endl; - return false; - }else - { - generateToken(token); - std::cerr << "RsGxsDataAccess::requestMsgInfo() gets Token: " << token << std::endl; - } - - setReq(req, token, ansType, opts); - storeRequest(req); - return true; -} - -bool RsGxsDataAccess::requestSetGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId &grpId, uint32_t subscribeFlags, - uint32_t subscribeMask) -{ - - generateToken(token); - - GroupSetFlagReq* req = new GroupSetFlagReq(); - - req->flag = subscribeFlags; - req->flagMask = subscribeMask; - req->grpId = grpId; - - std::cerr << "RsGxsDataAccess::requestSetGroupSubscribeFlags() gets Token: " << token << std::endl; - storeRequest(req); - - return false; -} - -bool RsGxsDataAccess::requestSetGroupStatus(uint32_t& token, const RsGxsGroupId& grpId, uint32_t status, uint32_t statusMask) -{ - - generateToken(token); - - GroupSetFlagReq* req = new GroupSetFlagReq(); - - req->flag = status; - req->flagMask = statusMask; - req->grpId = grpId; - - std::cerr << "RsGxsDataAccess::requestSetGroupStatus() gets Token: " << token << std::endl; - storeRequest(req); - - return true; -} - -bool RsGxsDataAccess::requestSetMessageStatus(uint32_t& token, const RsGxsGrpMsgIdPair &msgId, uint32_t status, - uint32_t statusMask) -{ - - generateToken(token); - - MessageSetFlagReq* req = new MessageSetFlagReq(); - - req->flag = status; - req->flagMask = statusMask; - req->msgId = msgId; - - std::cerr << "RsGxsDataAccess::requestSetGroupStatus() gets Token: " << token << std::endl; - storeRequest(req); - - return true; -} - -void RsGxsDataAccess::setReq(GxsRequest* req, const uint32_t& token, const uint32_t& ansType, const RsTokReqOptions& opts) const -{ - req->token = token; - req->ansType = ansType; - req->Options = opts; - return; -} -void RsGxsDataAccess::storeRequest(GxsRequest* req) -{ - RsStackMutex stack(mDataMutex); /****** LOCKED *****/ - - mRequests[req->token] = req; - - return; -} - -uint32_t RsGxsDataAccess::requestStatus(uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - return status; -} - - - - - -bool RsGxsDataAccess::cancelRequest(const uint32_t& token) -{ - return clearRequest(token); -} - -bool RsGxsDataAccess::clearRequest(const uint32_t& token) -{ - RsStackMutex stack(mDataMutex); /****** LOCKED *****/ - - std::map::iterator it; - - it = mRequests.find(token); - if (it == mRequests.end()) - { - return false; - } - - delete it->second; - mRequests.erase(it->first); - - return true; -} - -bool RsGxsDataAccess::getGroupSummary(const uint32_t& token, std::list& groupInfo) -{ - - GxsRequest* req = retrieveRequest(token); - - if(req == NULL){ - - std::cerr << "RsGxsDataAccess::getGroupSummary() Unable to retrieve group summary" << std::endl; - return false; - }else if(req->token == GXS_REQUEST_STATUS_COMPLETE){ - - GroupMetaReq* gmreq = dynamic_cast(req); - - if(gmreq) - { - groupInfo = gmreq->mGroupMetaData; - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - }else{ - std::cerr << "RsGxsDataAccess::getGroupSummary() Req found, failed caste" << std::endl; - return false; - } - }else{ - std::cerr << "RsGxsDataAccess::getGroupSummary() Req not ready" << std::endl; - return false; - } - - return true; -} - -bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list& grpData) -{ - - GxsRequest* req = retrieveRequest(token); - - if(req == NULL){ - - std::cerr << "RsGxsDataAccess::getGroupData() Unable to retrieve group data" << std::endl; - return false; - }else if(req->token == GXS_REQUEST_STATUS_COMPLETE){ - - GroupDataReq* gmreq = dynamic_cast(req); - - if(gmreq) - { - grpData = gmreq->mGroupData; - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - }else{ - std::cerr << "RsGxsDataAccess::getGroupData() Req found, failed caste" << std::endl; - return false; - } - }else{ - std::cerr << "RsGxsDataAccess::getGroupData() Req not ready" << std::endl; - return false; - } - - return true; -} - -bool RsGxsDataAccess::getMsgData(const uint32_t& token, NxsMsgDataResult& msgData) -{ - GxsRequest* req = retrieveRequest(token); - - if(req == NULL){ - - std::cerr << "RsGxsDataAccess::getMsgData() Unable to retrieve group data" << std::endl; - return false; - }else if(req->token == GXS_REQUEST_STATUS_COMPLETE){ - - MsgDataReq* mdreq = dynamic_cast(req); - - if(mdreq) - { - msgData = mdreq->mMsgData; - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - }else{ - std::cerr << "RsGxsDataAccess::getMsgData() Req found, failed caste" << std::endl; - return false; - } - }else{ - std::cerr << "RsGxsDataAccess::getMsgData() Req not ready" << std::endl; - return false; - } - - return true; -} - -bool RsGxsDataAccess::getMsgSummary(const uint32_t& token, GxsMsgMetaResult& msgInfo) -{ - GxsRequest* req = retrieveRequest(token); - - if(req == NULL){ - - std::cerr << "RsGxsDataAccess::getMsgSummary() Unable to retrieve group data" << std::endl; - return false; - }else if(req->token == GXS_REQUEST_STATUS_COMPLETE){ - - MsgMetaReq* mmreq = dynamic_cast(req); - - if(mmreq) - { - msgInfo = mmreq->mMsgMetaData; - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - }else{ - std::cerr << "RsGxsDataAccess::getMsgSummary() Req found, failed caste" << std::endl; - return false; - } - }else{ - std::cerr << "RsGxsDataAccess::getMsgSummary() Req not ready" << std::endl; - return false; - } - - return true; -} - -bool RsGxsDataAccess::getMsgList(const uint32_t& token, GxsMsgIdResult& msgIds) -{ - GxsRequest* req = retrieveRequest(token); - - if(req == NULL){ - - std::cerr << "RsGxsDataAccess::getMsgList() Unable to retrieve group data" << std::endl; - return false; - }else if(req->token == GXS_REQUEST_STATUS_COMPLETE){ - - MsgIdReq* mireq = dynamic_cast(req); - - if(mireq) - { - msgIds = mireq->mMsgIdResult; - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - }else{ - std::cerr << "RsGxsDataAccess::getMsgList() Req found, failed caste" << std::endl; - return false; - } - }else{ - std::cerr << "RsGxsDataAccess::getMsgList() Req not ready" << std::endl; - return false; - } - - return true; -} - -bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list& groupIds) -{ - GxsRequest* req = retrieveRequest(token); - - if(req == NULL){ - - std::cerr << "RsGxsDataAccess::getGroupList() Unable to retrieve group data," - "\nRequest does not exist" << std::endl; - return false; - }else if(req->token == GXS_REQUEST_STATUS_COMPLETE){ - - GroupIdReq* gireq = dynamic_cast(req); - - if(gireq) - { - groupIds = gireq->mGroupIdResult; - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - }else{ - std::cerr << "RsGxsDataAccess::getGroupList() Req found, failed caste" << std::endl; - return false; - } - }else{ - std::cerr << "RsGxsDataAccess::getGroupList() Req not ready" << std::endl; - return false; - } - - return true; -} - - -GxsRequest* RsGxsDataAccess::retrieveRequest(const uint32_t& token) -{ - - RsStackMutex stack(mDataMutex); - - if(mRequests.find(token) == mRequests.end()) return NULL; - - GxsRequest* req = mRequests[token]; - - return req; -} - -#define MAX_REQUEST_AGE 10 - -void RsGxsDataAccess::processRequests() -{ - - std::list toClear; - std::list::iterator cit; - time_t now = time(NULL); - - { - RsStackMutex stack(mDataMutex); /******* LOCKED *******/ - - std::map::iterator it; - - GroupMetaReq* gmr; - GroupDataReq* gdr; - GroupIdReq* gir; - - MsgMetaReq* mmr; - MsgDataReq* mdr; - MsgIdReq* mir; - - for(it = mRequests.begin(); it != mRequests.end(); it++) - { - - GxsRequest* req = it->second; - if (req->status == GXS_REQUEST_STATUS_PENDING) - { - std::cerr << "p3GxsDataService::fakeprocessrequests() Processing Token: " << req->token << " Status: " - << req->status << " ReqType: " << req->reqType << " Age: " - << now - req->reqTime << std::endl; - - req->status = GXS_REQUEST_STATUS_PARTIAL; - - /* PROCESS REQUEST! */ - - if((gmr = dynamic_cast(req)) != NULL) - { - getGroupSummary(gmr); - } - else if((gdr = dynamic_cast(req)) != NULL) - { - getGroupData(gdr); - } - else if((gir = dynamic_cast(req)) != NULL) - { - getGroupList(gir); - } - else if((mmr = dynamic_cast(req)) != NULL) - { - getMsgSummary(mmr); - } - else if((mdr = dynamic_cast(req)) != NULL) - { - getMsgData(mdr); - } - else if((mir = dynamic_cast(req)) != NULL) - { - getMsgList(mir); - } - else - { - #ifdef GXSDATA_SERVE_DEBUG - std::cerr << "RsGxsDataAccess::processRequests() Failed to process request, token: " - << req->token << std::endl; - #endif - - req->status = GXS_REQUEST_STATUS_FAILED; - } - } - else if (req->status == GXS_REQUEST_STATUS_PARTIAL) - { - req->status = GXS_REQUEST_STATUS_COMPLETE; - } - else if (req->status == GXS_REQUEST_STATUS_DONE) - { - std::cerr << "RsGxsDataAccess::processrequests() Clearing Done Request Token: " - << req->token; - std::cerr << std::endl; - toClear.push_back(req->token); - } - else if (now - req->reqTime > MAX_REQUEST_AGE) - { - std::cerr << "RsGxsDataAccess::processrequests() Clearing Old Request Token: " << req->token; - std::cerr << std::endl; - toClear.push_back(req->token); - } - } - - } // END OF MUTEX. - - for(cit = toClear.begin(); cit != toClear.end(); cit++) - { - clearRequest(*cit); - } - - return; -} - - -bool RsGxsDataAccess::getGroupData(GroupDataReq* req) -{ - - std::map grpData; - mDataStore->retrieveNxsGrps(grpData, true, true); - - std::map::iterator mit = grpData.begin(); - for(; mit != grpData.end(); mit++) - req->mGroupData.push_back(mit->second); - - return true; -} - -bool RsGxsDataAccess::getGroupSummary(GroupMetaReq* req) -{ - - std::map grpMeta; - - std::list::const_iterator lit = req->mGroupIds.begin(); - - for(; lit != req->mGroupIds.end(); lit++) - grpMeta[*lit] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - std::map::iterator mit = grpMeta.begin(); - - for(; mit != grpMeta.end(); mit++) - req->mGroupMetaData.push_back(mit->second); - - return true; -} - -bool RsGxsDataAccess::getGroupList(GroupIdReq* req) -{ - std::map grpMeta; - - std::list::const_iterator lit = req->mGroupIds.begin(); - - for(; lit != req->mGroupIds.end(); lit++) - grpMeta[*lit] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - std::map::iterator mit = grpMeta.begin(); - - for(; mit != grpMeta.end(); mit++) - { - req->mGroupIdResult.push_back(mit->first); - delete mit->second; // so wasteful!! - } - - return true; -} - -bool RsGxsDataAccess::getMsgData(MsgDataReq* req) -{ - - - GxsMsgResult result; - mDataStore->retrieveNxsMsgs(req->mMsgIds, result, true); - - req->mMsgData = result; - - return true; -} - - -bool RsGxsDataAccess::getMsgSummary(MsgMetaReq* req) -{ - GxsMsgMetaResult result; - std::vector groupIds; - GxsMsgReq::iterator mit = req->mMsgIds.begin(); - for(; mit != req->mMsgIds.end(); mit++) - groupIds.push_back(mit->first); - - mDataStore->retrieveGxsMsgMetaData(groupIds, result); - - req->mMsgMetaData = result; - - return true; -} - -bool RsGxsDataAccess::getMsgList(MsgIdReq* req) -{ - GxsMsgMetaResult result; - std::vector groupIds; - GxsMsgReq::iterator mit = req->mMsgIds.begin(); - - const RsTokReqOptions& opts = req->Options; - - for(; mit != req->mMsgIds.end(); mit++) - groupIds.push_back(mit->first); - - { - RsStackMutex stack(mDataMutex); - mDataStore->retrieveGxsMsgMetaData(groupIds, result); - } - - - /* CASEs this handles. - * Input is groupList + Flags. - * 1) No Flags => All Messages in those Groups. - * - */ - std::cerr << "RsGxsDataAccess::getMsgList()"; - std::cerr << std::endl; - - - bool onlyOrigMsgs = false; - bool onlyLatestMsgs = false; - bool onlyThreadHeadMsgs = false; - - // Can only choose one of these two. - if (opts.mOptions & RS_TOKREQOPT_MSG_ORIGMSG) - { - std::cerr << "RsGxsDataAccess::getMsgList() MSG_ORIGMSG"; - std::cerr << std::endl; - onlyOrigMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { - std::cerr << "RsGxsDataAccess::getMsgList() MSG_LATEST"; - std::cerr << std::endl; - onlyLatestMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { - std::cerr << "RsGxsDataAccess::getMsgList() MSG_THREAD"; - std::cerr << std::endl; - onlyThreadHeadMsgs = true; - } - - GxsMsgMetaResult::iterator meta_it; - MsgMetaFilter metaFilter; - - for(meta_it = result.begin(); meta_it != result.end(); meta_it++) - { - const RsGxsGroupId& grpId = meta_it->first; - - metaFilter[grpId] = std::map(); - - const std::vector& metaV = meta_it->second; - if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP. - { - std::vector::const_iterator vit = metaV.begin(); - - - // RUN THROUGH ALL MSGS... in map origId -> TS. - std::map > origMsgTs; - std::map >::iterator oit; - - for(; vit != metaV.end(); vit++) - { - RsGxsMsgMetaData* msgMeta = *vit; - - /* if we are grabbing thread Head... then parentId == empty. */ - if (onlyThreadHeadMsgs) - { - if (!(msgMeta->mParentId.empty())) - { - continue; - } - } - - - oit = origMsgTs.find(msgMeta->mOrigMsgId); - bool addMsg = false; - if (oit == origMsgTs.end()) - { - std::cerr << "RsGxsDataAccess::getMsgList() Found New OrigMsgId: "; - std::cerr << msgMeta->mOrigMsgId; - std::cerr << " MsgId: " << msgMeta->mMsgId; - std::cerr << " TS: " << msgMeta->mPublishTs; - std::cerr << std::endl; - - addMsg = true; - } - // check timestamps. - else if (oit->second.second < msgMeta->mPublishTs) - { - std::cerr << "RsGxsDataAccess::getMsgList() Found Later Msg. OrigMsgId: "; - std::cerr << msgMeta->mOrigMsgId; - std::cerr << " MsgId: " << msgMeta->mMsgId; - std::cerr << " TS: " << msgMeta->mPublishTs; - - addMsg = true; - } - - if (addMsg) - { - // add as latest. (overwriting if necessary) - origMsgTs[msgMeta->mOrigMsgId] = std::make_pair(msgMeta->mMsgId, msgMeta->mPublishTs); - metaFilter[grpId].insert(std::make_pair(msgMeta->mMsgId, msgMeta)); - } - } - - // Add the discovered Latest Msgs. - for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) - { - req->mMsgIds[grpId].push_back(oit->second.first); - - } - - } - else // ALL OTHER CASES. - { - std::vector::const_iterator vit = metaV.begin(); - - for(; vit != metaV.end(); vit++) - { - RsGxsMsgMetaData* msgMeta = *vit; - bool add = false; - - /* if we are grabbing thread Head... then parentId == empty. */ - if (onlyThreadHeadMsgs) - { - if (!(msgMeta->mParentId.empty())) - { - continue; - } - } - - - if (onlyOrigMsgs) - { - if (msgMeta->mMsgId == msgMeta->mOrigMsgId) - { - add = true; - } - } - else - { - add = true; - } - - if (add) - { - req->mMsgIdResult[grpId].push_back(msgMeta->mMsgId); - } - - } - } - } - - filterMsgList(req->mMsgIdResult, opts, metaFilter); - return true; -} - -void RsGxsDataAccess::filterMsgList(GxsMsgIdResult& msgIds, const RsTokReqOptions& opts, - const MsgMetaFilter& msgMetas) const -{ - - GxsMsgIdResult::iterator mit = msgIds.begin(); - for(;mit != msgIds.end(); mit++) - { - - MsgMetaFilter::const_iterator cit = msgMetas.find(mit->first); - - if(cit == msgMetas.end()) - continue; - - std::vector& msgs = mit->second; - std::vector::iterator vit = msgs.begin(); - const std::map& meta = cit->second; - std::map::const_iterator cit2; - - for(; vit != msgs.end();) - { - - bool keep = false; - if( (cit2 = meta.find(*vit)) != meta.end() ) - { - keep = checkMsgFilter(opts, cit2->second); - } - - if(keep) - { - vit++; - }else - { - vit = msgs.erase(vit); - } - } - } -} - - -bool RsGxsDataAccess::checkRequestStatus(const uint32_t& token, - uint32_t& status, uint32_t& reqtype, uint32_t& anstype, time_t& ts) -{ - - GxsRequest* req = retrieveRequest(token); - - RsStackMutex stack(mDataMutex); - - if(!req) - return false; - - anstype = req->ansType; - reqtype = req->reqType; - status = req->status; - ts = req->reqTime; - - return true; -} - -bool RsGxsDataAccess::addGroupData(RsNxsGrp* grp) { - - RsStackMutex stack(mDataMutex); - - std::map grpM; - grpM.insert(std::make_pair(grp, grp->metaData)); - return mDataStore->storeGroup(grpM); -} - - - -bool RsGxsDataAccess::addMsgData(RsNxsMsg* msg) { - - RsStackMutex stack(mDataMutex); - - std::map msgM; - msgM.insert(std::make_pair(msg, msg->metaData)); - return mDataStore->storeMessage(msgM); -} - - - -void RsGxsDataAccess::tokenList(std::list& tokens) { - - RsStackMutex stack(mDataMutex); - - std::map::iterator mit = mRequests.begin(); - - for(; mit != mRequests.end(); mit++) - { - tokens.push_back(mit->first); - } -} - -bool RsGxsDataAccess::checkMsgFilter(const RsTokReqOptions& opts, const RsGxsMsgMetaData* meta) const -{ - bool statusMatch = false; - if (opts.mStatusMask) - { - // Exact Flags match required. - if ((opts.mStatusMask & opts.mStatusFilter) == (opts.mStatusMask & meta->mMsgStatus)) - { - std::cerr << "checkMsgFilter() Accepting Msg as StatusMatches: "; - std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; - std::cerr << " MsgStatus: " << meta->mMsgStatus << " MsgId: " << meta->mMsgId; - std::cerr << std::endl; - - statusMatch = true; - } - else - { - std::cerr << "checkMsgFilter() Dropping Msg due to !StatusMatch "; - std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; - std::cerr << " MsgStatus: " << meta->mMsgStatus << " MsgId: " << meta->mMsgId; - std::cerr << std::endl; - } - } - else - { - // no status comparision, - statusMatch = true; - } - return statusMatch; -} +/* + * libretroshare/src/retroshare: rsgxsdataaccess.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie, Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsgxsdataaccess.h" + +// This bit will be filled out over time. +#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId. +#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group. +#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs. + +#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group. +#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs. + +#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId + + +// Status Filtering... should it be a different Option Field. +#define RS_TOKREQOPT_GROUP_UPDATED 0x0100 // GROUPLIST: Groups that have been updated. +#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups. +#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups. + +// Read Status. +#define RS_TOKREQOPT_READ 0x0001 +#define RS_TOKREQOPT_UNREAD 0x0002 + +#define RS_TOKREQ_ANSTYPE_LIST 0x0001 +#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002 +#define RS_TOKREQ_ANSTYPE_DATA 0x0003 + + const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_FAILED = 0; + const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_PENDING = 1; + const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_PARTIAL = 2; + const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_FINISHED_INCOMPLETE = 3; + const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE = 4; + const uint8_t RsTokenService::GXS_REQUEST_V2_STATUS_DONE = 5; // ONCE ALL DATA RETRIEVED. + +RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds) + : mDataStore(ds), mDataMutex("RsGxsDataAccess"), mNextToken(0) +{ +} + + +bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, + const std::list &groupIds) +{ + if(groupIds.empty()) + { + std::cerr << "Group Id list is empty" << std::endl; + return false; + } + + GxsRequest* req = NULL; + uint32_t reqType = opts.mReqType; + + if(reqType & GXS_REQUEST_TYPE_GROUP_META) + { + GroupMetaReq* gmr = new GroupMetaReq(); + gmr->mGroupIds = groupIds; + req = gmr; + } + else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) + { + GroupDataReq* gdr = new GroupDataReq(); + gdr->mGroupIds = groupIds; + req = gdr; + } + else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) + { + GroupIdReq* gir = new GroupIdReq(); + gir->mGroupIds = groupIds; + req = gir; + } + + if(req == NULL) + { + std::cerr << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type " + << reqType << std::endl; + return false; + }else + { + generateToken(token); + std::cerr << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl; + } + + setReq(req, token, ansType, opts); + storeRequest(req); + + return true; +} + +bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) +{ + + GxsRequest* req = NULL; + uint32_t reqType = opts.mReqType; + + if(reqType & GXS_REQUEST_TYPE_GROUP_META) + { + GroupMetaReq* gmr = new GroupMetaReq(); + req = gmr; + } + else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) + { + GroupDataReq* gdr = new GroupDataReq(); + req = gdr; + } + else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) + { + GroupIdReq* gir = new GroupIdReq(); + req = gir; + } + + if(req == NULL) + { + std::cerr << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type " + << reqType << std::endl; + return false; + }else + { + generateToken(token); + std::cerr << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl; + } + + setReq(req, token, ansType, opts); + storeRequest(req); + + return true; +} + +void RsGxsDataAccess::generateToken(uint32_t &token) +{ + RsStackMutex stack(mDataMutex); /****** LOCKED *****/ + + token = mNextToken++; + + return; +} + + +bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, + const RsTokReqOptions &opts, const GxsMsgReq &msgIds) +{ + + GxsRequest* req = NULL; + uint32_t reqType = opts.mReqType; + + // remove all empty grpId entries + GxsMsgReq::const_iterator mit = msgIds.begin(); + std::vector toRemove; + + for(; mit != msgIds.end(); mit++) + { + if(mit->second.empty()) + toRemove.push_back(mit->first); + } + + std::vector::const_iterator vit = toRemove.begin(); + + GxsMsgReq filteredMsgIds = msgIds; + + for(; vit != toRemove.end(); vit++) + filteredMsgIds.erase(*vit); + + if(reqType & GXS_REQUEST_TYPE_MSG_META) + { + MsgMetaReq* mmr = new MsgMetaReq(); + mmr->mMsgIds = filteredMsgIds; + req = mmr; + + }else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) + { + MsgDataReq* mdr = new MsgDataReq(); + mdr->mMsgIds = filteredMsgIds; + req = mdr; + + }else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) + { + MsgIdReq* mir = new MsgIdReq(); + mir->mMsgIds = filteredMsgIds; + req = mir; + + } + + if(req == NULL) + { + std::cerr << "RsGxsDataAccess::requestMsgInfo() request type not recognised, type " + << reqType << std::endl; + return false; + }else + { + generateToken(token); + std::cerr << "RsGxsDataAccess::requestMsgInfo() gets Token: " << token << std::endl; + } + + setReq(req, token, ansType, opts); + storeRequest(req); + return true; +} + +bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, + const RsTokReqOptions &opts, const std::list& grpIds) +{ + GxsRequest* req = NULL; + uint32_t reqType = opts.mReqType; + + std::list::const_iterator lit = grpIds.begin(); + + if(reqType & GXS_REQUEST_TYPE_MSG_META) + { + MsgMetaReq* mmr = new MsgMetaReq(); + + for(; lit != grpIds.end(); lit++) + mmr->mMsgIds[*lit] = std::vector(); + + req = mmr; + }else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) + { + MsgDataReq* mdr = new MsgDataReq(); + + for(; lit != grpIds.end(); lit++) + mdr->mMsgIds[*lit] = std::vector(); + + req = mdr; + }else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) + { + MsgIdReq* mir = new MsgIdReq(); + + for(; lit != grpIds.end(); lit++) + mir->mMsgIds[*lit] = std::vector(); + + req = mir; + } + + if(req == NULL) + { + std::cerr << "RsGxsDataAccess::requestMsgInfo() request type not recognised, type " + << reqType << std::endl; + return false; + }else + { + generateToken(token); + std::cerr << "RsGxsDataAccess::requestMsgInfo() gets Token: " << token << std::endl; + } + + setReq(req, token, ansType, opts); + storeRequest(req); + return true; +} + +bool RsGxsDataAccess::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, + const std::vector &msgIds) +{ + + MsgRelatedInfoReq* req = new MsgRelatedInfoReq(); + req->mMsgIds = msgIds; + + generateToken(token); + + setReq(req, token, ansType, opts); + storeRequest(req); + + return true; +} + + +void RsGxsDataAccess::setReq(GxsRequest* req, const uint32_t& token, const uint32_t& ansType, const RsTokReqOptions& opts) const +{ + req->token = token; + req->ansType = ansType; + req->Options = opts; + return; +} +void RsGxsDataAccess::storeRequest(GxsRequest* req) +{ + RsStackMutex stack(mDataMutex); /****** LOCKED *****/ + + req->status = GXS_REQUEST_V2_STATUS_PENDING; + req->reqTime = time(NULL); + mRequests[req->token] = req; + + return; +} + +uint32_t RsGxsDataAccess::requestStatus(uint32_t token) +{ + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + + { + RsStackMutex stack(mDataMutex); + + // first check public tokens + if(mPublicToken.find(token) != mPublicToken.end()) + return mPublicToken[token]; + } + checkRequestStatus(token, status, reqtype, anstype, ts); + + return status; +} + + + + + +bool RsGxsDataAccess::cancelRequest(const uint32_t& token) +{ + return clearRequest(token); +} + +bool RsGxsDataAccess::clearRequest(const uint32_t& token) +{ + RsStackMutex stack(mDataMutex); /****** LOCKED *****/ + + std::map::iterator it; + + it = mRequests.find(token); + if (it == mRequests.end()) + { + return false; + } + + delete it->second; + mRequests.erase(it->first); + + return true; +} + +bool RsGxsDataAccess::getGroupSummary(const uint32_t& token, std::list& groupInfo) +{ + + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getGroupSummary() Unable to retrieve group summary" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + GroupMetaReq* gmreq = dynamic_cast(req); + + if(gmreq) + { + groupInfo = gmreq->mGroupMetaData; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + }else{ + std::cerr << "RsGxsDataAccess::getGroupSummary() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getGroupSummary() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list& grpData) +{ + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getGroupData() Unable to retrieve group data" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + GroupDataReq* gmreq = dynamic_cast(req); + + if(gmreq) + { + grpData = gmreq->mGroupData; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + }else{ + std::cerr << "RsGxsDataAccess::getGroupData() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getGroupData() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getMsgData(const uint32_t& token, NxsMsgDataResult& msgData) +{ + + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgData() Unable to retrieve group data" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + MsgDataReq* mdreq = dynamic_cast(req); + + if(mdreq) + { + msgData = mdreq->mMsgData; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + } + else + { + std::cerr << "RsGxsDataAccess::getMsgData() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getMsgData() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getMsgRelatedData(const uint32_t &token, NxsMsgRelatedDataResult &msgData) +{ + + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgRelatedData() Unable to retrieve group data" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + MsgRelatedInfoReq* mrireq = dynamic_cast(req); + + if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_DATA) + return false; + + if(mrireq) + { + msgData = mrireq->mMsgDataResult; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + } + else + { + std::cerr << "RsGxsDataAccess::getMsgRelatedData() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getMsgRelatedData() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getMsgSummary(const uint32_t& token, GxsMsgMetaResult& msgInfo) +{ + + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgSummary() Unable to retrieve group data" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + MsgMetaReq* mmreq = dynamic_cast(req); + + if(mmreq) + { + msgInfo = mmreq->mMsgMetaData; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + + } + else + { + std::cerr << "RsGxsDataAccess::getMsgSummary() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getMsgSummary() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getMsgRelatedSummary(const uint32_t &token, MsgRelatedMetaResult &msgMeta) +{ + + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgRelatedSummary() Unable to retrieve message summary" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_META) + return false; + + MsgRelatedInfoReq* mrireq = dynamic_cast(req); + + if(mrireq) + { + msgMeta = mrireq->mMsgMetaResult; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + } + else + { + std::cerr << "RsGxsDataAccess::getMsgRelatedSummary() Req found, failed caste" << std::endl; + return false; + } + } + else + { + std::cerr << "RsGxsDataAccess::getMsgRelatedSummary() Req not ready" << std::endl; + return false; + } + + return true; +} + + +bool RsGxsDataAccess::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) +{ + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgRelatedList() Unable to retrieve message data" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_IDS) + return false; + + MsgRelatedInfoReq* mrireq = dynamic_cast(req); + + if(mrireq) + { + msgIds = mrireq->mMsgIdResult; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + } + else{ + std::cerr << "RsGxsDataAccess::getMsgRelatedList() Req found, failed caste" << std::endl; + return false; + } + } + else + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getMsgList(const uint32_t& token, GxsMsgIdResult& msgIds) +{ + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getMsgList() Unable to retrieve msg Ids" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + MsgIdReq* mireq = dynamic_cast(req); + + if(mireq) + { + msgIds = mireq->mMsgIdResult; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + } + else{ + std::cerr << "RsGxsDataAccess::getMsgList() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getMsgList() Req not ready" << std::endl; + return false; + } + + return true; +} + +bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list& groupIds) +{ + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL){ + + std::cerr << "RsGxsDataAccess::getGroupList() Unable to retrieve group Ids," + "\nRequest does not exist" << std::endl; + return false; + }else if(req->status == GXS_REQUEST_V2_STATUS_COMPLETE){ + + GroupIdReq* gireq = dynamic_cast(req); + + if(gireq) + { + groupIds = gireq->mGroupIdResult; + locked_updateRequestStatus(token, GXS_REQUEST_V2_STATUS_DONE); + + }else{ + std::cerr << "RsGxsDataAccess::getGroupList() Req found, failed caste" << std::endl; + return false; + } + }else{ + std::cerr << "RsGxsDataAccess::getGroupList() Req not ready" << std::endl; + return false; + } + + return true; +} + + +GxsRequest* RsGxsDataAccess::locked_retrieveRequest(const uint32_t& token) +{ + + if(mRequests.find(token) == mRequests.end()) return NULL; + + GxsRequest* req = mRequests[token]; + + return req; +} + +#define MAX_REQUEST_AGE 30 + +void RsGxsDataAccess::processRequests() +{ + + std::list toClear; + std::list::iterator cit; + time_t now = time(NULL); + + { + RsStackMutex stack(mDataMutex); /******* LOCKED *******/ + + std::map::iterator it; + + GroupMetaReq* gmr; + GroupDataReq* gdr; + GroupIdReq* gir; + + MsgMetaReq* mmr; + MsgDataReq* mdr; + MsgIdReq* mir; + MsgRelatedInfoReq* mri; + + for(it = mRequests.begin(); it != mRequests.end(); it++) + { + + GxsRequest* req = it->second; + if (req->status == GXS_REQUEST_V2_STATUS_PENDING) + { + std::cerr << "RsGxsDataAccess::processRequests() Processing Token: " << req->token << " Status: " + << req->status << " ReqType: " << req->reqType << " Age: " + << now - req->reqTime << std::endl; + + req->status = GXS_REQUEST_V2_STATUS_PARTIAL; + + /* PROCESS REQUEST! */ + + if((gmr = dynamic_cast(req)) != NULL) + { + getGroupSummary(gmr); + } + else if((gdr = dynamic_cast(req)) != NULL) + { + getGroupData(gdr); + } + else if((gir = dynamic_cast(req)) != NULL) + { + getGroupList(gir); + } + else if((mmr = dynamic_cast(req)) != NULL) + { + getMsgSummary(mmr); + } + else if((mdr = dynamic_cast(req)) != NULL) + { + getMsgData(mdr); + } + else if((mir = dynamic_cast(req)) != NULL) + { + getMsgList(mir); + } + else if((mri = dynamic_cast(req)) != NULL) + { + getMsgRelatedInfo(mri); + } + else + { + #ifdef GXSDATA_SERVE_DEBUG + std::cerr << "RsGxsDataAccess::processRequests() Failed to process request, token: " + << req->token << std::endl; + #endif + + req->status = GXS_REQUEST_V2_STATUS_FAILED; + } + } + else if (req->status == GXS_REQUEST_V2_STATUS_PARTIAL) + { + req->status = GXS_REQUEST_V2_STATUS_COMPLETE; + } + else if (req->status == GXS_REQUEST_V2_STATUS_DONE) + { + std::cerr << "RsGxsDataAccess::processrequests() Clearing Done Request Token: " + << req->token; + std::cerr << std::endl; + toClear.push_back(req->token); + } + else if (now - req->reqTime > MAX_REQUEST_AGE) + { + std::cerr << "RsGxsDataAccess::processrequests() Clearing Old Request Token: " << req->token; + std::cerr << std::endl; + toClear.push_back(req->token); + } + } + + } // END OF MUTEX. + + for(cit = toClear.begin(); cit != toClear.end(); cit++) + { + clearRequest(*cit); + } + + return; +} + + +bool RsGxsDataAccess::getGroupData(GroupDataReq* req) +{ + std::map grpData; + std::list grpIdsOut; + + getGroupList(req->mGroupIds, req->Options, grpIdsOut); + + if(grpIdsOut.empty()) + return true; + + std::list::iterator lit = grpIdsOut.begin(), + lit_end = grpIdsOut.end(); + + for(; lit != lit_end; lit++) + { + grpData[*lit] = NULL; + } + + bool ok = mDataStore->retrieveNxsGrps(grpData, true, true); + + std::map::iterator mit = grpData.begin(); + for(; mit != grpData.end(); mit++) + req->mGroupData.push_back(mit->second); + + return ok; +} + +bool RsGxsDataAccess::getGroupSummary(GroupMetaReq* req) +{ + + std::map grpMeta; + + std::list grpIdsOut; + + getGroupList(req->mGroupIds, req->Options, grpIdsOut); + + if(grpIdsOut.empty()) + return true; + + std::list::const_iterator lit = grpIdsOut.begin(); + + for(; lit != grpIdsOut.end(); lit++) + grpMeta[*lit] = NULL; + + mDataStore->retrieveGxsGrpMetaData(grpMeta); + + std::map::iterator mit = grpMeta.begin(); + + for(; mit != grpMeta.end(); mit++) + req->mGroupMetaData.push_back(mit->second); + + return true; +} + +bool RsGxsDataAccess::getGroupList(GroupIdReq* req) +{ + getGroupList(req->mGroupIds, req->Options, req->mGroupIdResult); + + return true; +} + +bool RsGxsDataAccess::getGroupList(const std::list& grpIdsIn, const RsTokReqOptions& opts, std::list& grpIdsOut) +{ + std::map grpMeta; + + std::list::const_iterator lit = grpIdsIn.begin(); + + for(; lit != grpIdsIn.end(); lit++) + grpMeta[*lit] = NULL; + + mDataStore->retrieveGxsGrpMetaData(grpMeta); + + std::map::iterator mit = grpMeta.begin(); + + for(; mit != grpMeta.end(); mit++) + { + grpIdsOut.push_back(mit->first); + } + + filterGrpList(grpIdsOut, opts, grpMeta); + + for(mit = grpMeta.begin(); mit != grpMeta.end(); mit++) + { + delete mit->second; // so wasteful!! + } + + return true; +} + +bool RsGxsDataAccess::getMsgData(MsgDataReq* req) +{ + GxsMsgResult result; + + GxsMsgReq msgIdOut; + + // filter based on options + getMsgList(req->mMsgIds, req->Options, msgIdOut); + + mDataStore->retrieveNxsMsgs(msgIdOut, result, true, true); + + req->mMsgData = result; + return true; +} + + +bool RsGxsDataAccess::getMsgSummary(MsgMetaReq* req) +{ + GxsMsgMetaResult result; + + GxsMsgReq msgIdOut; + + // filter based on options + getMsgList(req->mMsgIds, req->Options, msgIdOut); + + mDataStore->retrieveGxsMsgMetaData(msgIdOut, result); + req->mMsgMetaData = result; + + return true; +} + + +bool RsGxsDataAccess::getMsgList(const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgReq& msgIdsOut) +{ + GxsMsgMetaResult result; + + mDataStore->retrieveGxsMsgMetaData(msgIds, result); + + /* CASEs this handles. + * Input is groupList + Flags. + * 1) No Flags => All Messages in those Groups. + * + */ + std::cerr << "RsGxsDataAccess::getMsgList()"; + std::cerr << std::endl; + + + bool onlyOrigMsgs = false; + bool onlyLatestMsgs = false; + bool onlyThreadHeadMsgs = false; + + // Can only choose one of these two. + if (opts.mOptions & RS_TOKREQOPT_MSG_ORIGMSG) + { + std::cerr << "RsGxsDataAccess::getMsgList() MSG_ORIGMSG"; + std::cerr << std::endl; + onlyOrigMsgs = true; + } + else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) + { + std::cerr << "RsGxsDataAccess::getMsgList() MSG_LATEST"; + std::cerr << std::endl; + onlyLatestMsgs = true; + } + + if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) + { + std::cerr << "RsGxsDataAccess::getMsgList() MSG_THREAD"; + std::cerr << std::endl; + onlyThreadHeadMsgs = true; + } + + GxsMsgMetaResult::iterator meta_it; + MsgMetaFilter metaFilter; + + for(meta_it = result.begin(); meta_it != result.end(); meta_it++) + { + const RsGxsGroupId& grpId = meta_it->first; + + metaFilter[grpId] = std::map(); + + const std::vector& metaV = meta_it->second; + if (onlyLatestMsgs) // THIS ONE IS HARD -> LOTS OF COMP. + { + std::vector::const_iterator vit = metaV.begin(); + + // RUN THROUGH ALL MSGS... in map origId -> TS. + std::map > origMsgTs; + std::map >::iterator oit; + + for(; vit != metaV.end(); vit++) + { + RsGxsMsgMetaData* msgMeta = *vit; + + /* if we are grabbing thread Head... then parentId == empty. */ + if (onlyThreadHeadMsgs) + { + if (!(msgMeta->mParentId.empty())) + { + continue; + } + } + + + oit = origMsgTs.find(msgMeta->mOrigMsgId); + bool addMsg = false; + if (oit == origMsgTs.end()) + { + std::cerr << "RsGxsDataAccess::getMsgList() Found New OrigMsgId: "; + std::cerr << msgMeta->mOrigMsgId; + std::cerr << " MsgId: " << msgMeta->mMsgId; + std::cerr << " TS: " << msgMeta->mPublishTs; + std::cerr << std::endl; + + addMsg = true; + } + // check timestamps. + else if (oit->second.second < msgMeta->mPublishTs) + { + std::cerr << "RsGxsDataAccess::getMsgList() Found Later Msg. OrigMsgId: "; + std::cerr << msgMeta->mOrigMsgId; + std::cerr << " MsgId: " << msgMeta->mMsgId; + std::cerr << " TS: " << msgMeta->mPublishTs; + + addMsg = true; + } + + if (addMsg) + { + // add as latest. (overwriting if necessary) + origMsgTs[msgMeta->mOrigMsgId] = std::make_pair(msgMeta->mMsgId, msgMeta->mPublishTs); + metaFilter[grpId].insert(std::make_pair(msgMeta->mMsgId, msgMeta)); + } + } + + // Add the discovered Latest Msgs. + for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) + { + msgIdsOut[grpId].push_back(oit->second.first); + } + + } + else // ALL OTHER CASES. + { + std::vector::const_iterator vit = metaV.begin(); + + for(; vit != metaV.end(); vit++) + { + RsGxsMsgMetaData* msgMeta = *vit; + bool add = false; + + /* if we are grabbing thread Head... then parentId == empty. */ + if (onlyThreadHeadMsgs) + { + if (!(msgMeta->mParentId.empty())) + { + continue; + } + } + + + if (onlyOrigMsgs) + { + if (msgMeta->mMsgId == msgMeta->mOrigMsgId) + { + add = true; + } + } + else + { + add = true; + } + + if (add) + { + msgIdsOut[grpId].push_back(msgMeta->mMsgId); + metaFilter[grpId].insert(std::make_pair(msgMeta->mMsgId, msgMeta)); + } + + } + } + } + + filterMsgList(msgIdsOut, opts, metaFilter); + + metaFilter.clear(); + + // delete meta data + cleanseMsgMetaMap(result); + + return true; +} + +bool RsGxsDataAccess::getMsgRelatedInfo(MsgRelatedInfoReq *req) +{ + /* CASEs this handles. + * Input is msgList + Flags. + * 1) No Flags => return nothing + */ + + std::cerr << "RsGxsDataAccess::getMsgRelatedList()"; + std::cerr << std::endl; + + const RsTokReqOptions& opts = req->Options; + + bool onlyLatestMsgs = false; + bool onlyAllVersions = false; + bool onlyChildMsgs = false; + bool onlyThreadMsgs = false; + + if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() MSG_LATEST"; + std::cerr << std::endl; + onlyLatestMsgs = true; + } + else if (opts.mOptions & RS_TOKREQOPT_MSG_VERSIONS) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() MSG_VERSIONS"; + std::cerr << std::endl; + onlyAllVersions = true; + } + + if (opts.mOptions & RS_TOKREQOPT_MSG_PARENT) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() MSG_PARENTS"; + std::cerr << std::endl; + onlyChildMsgs = true; + } + + if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() MSG_THREAD"; + std::cerr << std::endl; + onlyThreadMsgs = true; + } + + if (onlyAllVersions && onlyChildMsgs) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & PARENT)"; + std::cerr << std::endl; + + return false; + } + + if (onlyAllVersions && onlyThreadMsgs) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & THREAD)"; + std::cerr << std::endl; + + return false; + } + + if ((!onlyLatestMsgs) && onlyChildMsgs) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & PARENT)"; + std::cerr << std::endl; + + return false; + } + + if ((!onlyLatestMsgs) && onlyThreadMsgs) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & THREAD)"; + std::cerr << std::endl; + + return false; + } + + if (onlyChildMsgs && onlyThreadMsgs) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() ERROR Incompatible FLAGS (PARENT & THREAD)"; + std::cerr << std::endl; + + return false; + } + + + /* FALL BACK OPTION */ + if ((!onlyLatestMsgs) && (!onlyAllVersions) && (!onlyChildMsgs) && (!onlyThreadMsgs)) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() FALLBACK -> NO FLAGS -> SIMPLY RETURN nothing"; + std::cerr << std::endl; + + return true; + } + + std::vector::iterator vit_msgIds = req->mMsgIds.begin(); + + for(; vit_msgIds != req->mMsgIds.end(); vit_msgIds++) + { + MsgMetaFilter filterMap; + + + const RsGxsGrpMsgIdPair& grpMsgIdPair = *vit_msgIds; + + // get meta data for all in group + GxsMsgMetaResult result; + GxsMsgReq msgIds; + msgIds.insert(std::make_pair(grpMsgIdPair.first, std::vector())); + mDataStore->retrieveGxsMsgMetaData(msgIds, result); + std::vector& metaV = result[grpMsgIdPair.first]; + std::vector::iterator vit_meta; + + // msg id to relate to + const RsGxsMessageId& msgId = grpMsgIdPair.second; + const RsGxsGroupId& grpId = grpMsgIdPair.first; + + std::vector outMsgIds; + + RsGxsMsgMetaData* origMeta = NULL; + for(vit_meta = metaV.begin(); vit_meta != metaV.end(); vit_meta++) + { + RsGxsMsgMetaData* meta = *vit_meta; + + if(msgId == meta->mMsgId) + { + origMeta = meta; + break; + } + } + + if(!origMeta) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedInfo(): Cannot find meta of msgId (to relate to)!" + << std::endl; + cleanseMsgMetaMap(result); + return false; + } + + const RsGxsMessageId& origMsgId = origMeta->mOrigMsgId; + std::map& metaMap = filterMap[grpId]; + + if (onlyLatestMsgs) + { + if (onlyChildMsgs || onlyThreadMsgs) + { + // RUN THROUGH ALL MSGS... in map origId -> TS. + std::map > origMsgTs; + std::map >::iterator oit; + for(vit_meta = metaV.begin(); vit_meta != metaV.end(); vit_meta++) + { + + RsGxsMsgMetaData* meta = *vit_meta; + + // skip msgs that aren't children. + if (onlyChildMsgs) + { + if (meta->mParentId != origMsgId) + { + continue; + } + } + else /* onlyThreadMsgs */ + { + if (meta->mThreadId != msgId) + { + continue; + } + } + + + oit = origMsgTs.find(meta->mOrigMsgId); + + bool addMsg = false; + if (oit == origMsgTs.end()) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() Found New OrigMsgId: "; + std::cerr << meta->mOrigMsgId; + std::cerr << " MsgId: " << meta->mMsgId; + std::cerr << " TS: " << meta->mPublishTs; + std::cerr << std::endl; + + addMsg = true; + } + // check timestamps. + else if (oit->second.second < meta->mPublishTs) + { + std::cerr << "RsGxsDataAccess::getMsgRelatedList() Found Later Msg. OrigMsgId: "; + std::cerr << meta->mOrigMsgId; + std::cerr << " MsgId: " << meta->mMsgId; + std::cerr << " TS: " << meta->mPublishTs; + + addMsg = true; + } + + if (addMsg) + { + // add as latest. (overwriting if necessary) + origMsgTs[meta->mOrigMsgId] = std::make_pair(meta->mMsgId, meta->mPublishTs); + metaMap.insert(std::make_pair(meta->mMsgId, meta)); + } + } + + // Add the discovered Latest Msgs. + for(oit = origMsgTs.begin(); oit != origMsgTs.end(); oit++) + { + outMsgIds.push_back(oit->second.first); + } + } + else + { + + /* first guess is potentially better than Orig (can't be worse!) */ + time_t latestTs = 0; + RsGxsMessageId latestMsgId; + RsGxsMsgMetaData* latestMeta; + + for(vit_meta = metaV.begin(); vit_meta != metaV.end(); vit_meta++) + { + RsGxsMsgMetaData* meta = *vit_meta; + + if (meta->mOrigMsgId == origMsgId) + { + if (meta->mPublishTs > latestTs) + { + latestTs = meta->mPublishTs; + latestMsgId = meta->mMsgId; + latestMeta = meta; + } + } + } + outMsgIds.push_back(latestMsgId); + metaMap.insert(std::make_pair(latestMsgId, latestMeta)); + } + } + else if (onlyAllVersions) + { + for(vit_meta = metaV.begin(); vit_meta != metaV.end(); vit_meta++) + { + RsGxsMsgMetaData* meta = *vit_meta; + + if (meta->mOrigMsgId == origMsgId) + { + outMsgIds.push_back(meta->mMsgId); + metaMap.insert(std::make_pair(meta->mMsgId, meta)); + } + } + } + + GxsMsgIdResult filteredOutMsgIds; + filteredOutMsgIds[grpId] = outMsgIds; + filterMsgList(filteredOutMsgIds, opts, filterMap); + + if(!filteredOutMsgIds[grpId].empty()) + { + if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_IDS) + { + req->mMsgIdResult[grpMsgIdPair] = filteredOutMsgIds[grpId]; + } + else if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_META) + { + GxsMsgMetaResult metaResult; + mDataStore->retrieveGxsMsgMetaData(filteredOutMsgIds, metaResult); + req->mMsgMetaResult[grpMsgIdPair] = metaResult[grpId]; + } + else if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_DATA) + { + GxsMsgResult msgResult; + mDataStore->retrieveNxsMsgs(filteredOutMsgIds, msgResult, false, true); + req->mMsgDataResult[grpMsgIdPair] = msgResult[grpId]; + } + } + + outMsgIds.clear(); + filteredOutMsgIds.clear(); + + cleanseMsgMetaMap(result); + } + return true; +} + +bool RsGxsDataAccess::getMsgList(MsgIdReq* req) +{ + + GxsMsgMetaResult result; + + mDataStore->retrieveGxsMsgMetaData(req->mMsgIds, result); + + + GxsMsgMetaResult::iterator mit = result.begin(), mit_end = result.end(); + + for(; mit != mit_end; mit++) + { + const RsGxsGroupId grpId = mit->first; + std::vector& metaV = mit->second; + std::vector::iterator vit = metaV.begin(), + vit_end = metaV.end(); + + for(; vit != vit_end; vit++) + { + RsGxsMsgMetaData* meta = *vit; + req->mMsgIdResult[grpId].push_back(meta->mMsgId); + delete meta; // discard meta data mem + } + } + + GxsMsgReq msgIdOut; + + // filter based on options + getMsgList(req->mMsgIdResult, req->Options, msgIdOut); + req->mMsgIdResult = msgIdOut; + + return true; +} + +void RsGxsDataAccess::cleanseMsgMetaMap(GxsMsgMetaResult& result) +{ + GxsMsgMetaResult::iterator mit = result.begin(); + + for(; mit !=result.end(); mit++) + { + + std::vector& msgMetaV = mit->second; + std::vector::iterator vit = msgMetaV.begin(); + for(; vit != msgMetaV.end(); vit++) + { + delete *vit; + } + } + + result.clear(); + return; +} + +void RsGxsDataAccess::filterMsgList(GxsMsgIdResult& msgIds, const RsTokReqOptions& opts, + const MsgMetaFilter& msgMetas) const +{ + + GxsMsgIdResult::iterator mit = msgIds.begin(); + for(;mit != msgIds.end(); mit++) + { + + MsgMetaFilter::const_iterator cit = msgMetas.find(mit->first); + + if(cit == msgMetas.end()) + continue; + + std::vector& msgs = mit->second; + std::vector::iterator vit = msgs.begin(); + const std::map& meta = cit->second; + std::map::const_iterator cit2; + + for(; vit != msgs.end();) + { + + bool keep = false; + if( (cit2 = meta.find(*vit)) != meta.end() ) + { + keep = checkMsgFilter(opts, cit2->second); + } + + if(keep) + { + vit++; + }else + { + vit = msgs.erase(vit); + } + } + } +} + +void RsGxsDataAccess::filterGrpList(std::list &grpIds, const RsTokReqOptions &opts, const GrpMetaFilter &meta) const +{ + std::list::iterator lit = grpIds.begin(); + + for(; lit != grpIds.end(); ) + { + GrpMetaFilter::const_iterator cit = meta.find(*lit); + + bool keep = false; + + if(cit != meta.end()) + { + keep = checkGrpFilter(opts, cit->second); + } + + if(keep) + { + lit++; + }else + { + lit = grpIds.erase(lit); + } + + } +} + + +bool RsGxsDataAccess::checkRequestStatus(const uint32_t& token, + uint32_t& status, uint32_t& reqtype, uint32_t& anstype, time_t& ts) +{ + + RsStackMutex stack(mDataMutex); + + GxsRequest* req = locked_retrieveRequest(token); + + if(req == NULL) + return false; + + anstype = req->ansType; + reqtype = req->reqType; + status = req->status; + ts = req->reqTime; + + return true; +} + +bool RsGxsDataAccess::addGroupData(RsNxsGrp* grp) { + + RsStackMutex stack(mDataMutex); + + std::map grpM; + grpM.insert(std::make_pair(grp, grp->metaData)); + return mDataStore->storeGroup(grpM); +} + + + +bool RsGxsDataAccess::addMsgData(RsNxsMsg* msg) { + + RsStackMutex stack(mDataMutex); + + std::map msgM; + msgM.insert(std::make_pair(msg, msg->metaData)); + return mDataStore->storeMessage(msgM); +} + + + +void RsGxsDataAccess::tokenList(std::list& tokens) +{ + + RsStackMutex stack(mDataMutex); + + std::map::iterator mit = mRequests.begin(); + + for(; mit != mRequests.end(); mit++) + { + tokens.push_back(mit->first); + } +} + +bool RsGxsDataAccess::locked_updateRequestStatus(const uint32_t& token, + const uint32_t& status) +{ + + GxsRequest* req = locked_retrieveRequest(token); + + if(req) + req->status = status; + else + return false; + + return true; +} + +uint32_t RsGxsDataAccess::generatePublicToken() +{ + + uint32_t token; + generateToken(token); + + { + RsStackMutex stack(mDataMutex); + mPublicToken[token] = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING; + } + + return token; +} + + + +bool RsGxsDataAccess::updatePublicRequestStatus(const uint32_t& token, + const uint32_t& status) +{ + RsStackMutex stack(mDataMutex); + std::map::iterator mit = mPublicToken.find(token); + + if(mit != mPublicToken.end()) + { + mit->second = status; + } + else + { + return false; + } + + return true; +} + + + +bool RsGxsDataAccess::disposeOfPublicToken(const uint32_t& token) +{ + RsStackMutex stack(mDataMutex); + std::map::iterator mit = mPublicToken.find(token); + + if(mit != mPublicToken.end()) + { + mPublicToken.erase(mit); + } + else + { + return false; + } + + return true; +} + +bool RsGxsDataAccess::checkGrpFilter(const RsTokReqOptions &opts, const RsGxsGrpMetaData *meta) const +{ + + bool subscribeMatch = false; + + if(opts.mSubscribeMask) + { + // Exact Flags match required. + if ((opts.mSubscribeMask & opts.mSubscribeFilter) == (opts.mSubscribeMask & meta->mSubscribeFlags)) + { + subscribeMatch = true; + } + } + else + { + subscribeMatch = true; + } + + return subscribeMatch; +} +bool RsGxsDataAccess::checkMsgFilter(const RsTokReqOptions& opts, const RsGxsMsgMetaData* meta) const +{ + bool statusMatch = false; + if (opts.mStatusMask) + { + // Exact Flags match required. + if ((opts.mStatusMask & opts.mStatusFilter) == (opts.mStatusMask & meta->mMsgStatus)) + { + std::cerr << "checkMsgFilter() Accepting Msg as StatusMatches: "; + std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; + std::cerr << " MsgStatus: " << meta->mMsgStatus << " MsgId: " << meta->mMsgId; + std::cerr << std::endl; + + statusMatch = true; + } + else + { + std::cerr << "checkMsgFilter() Dropping Msg due to !StatusMatch "; + std::cerr << " Mask: " << opts.mStatusMask << " StatusFilter: " << opts.mStatusFilter; + std::cerr << " MsgStatus: " << meta->mMsgStatus << " MsgId: " << meta->mMsgId; + std::cerr << std::endl; + } + } + else + { + // no status comparision, + statusMatch = true; + } + + bool flagMatch = false; + + if(opts.mMsgFlagMask) + { + // Exact Flags match required. + if ((opts.mMsgFlagMask & opts.mMsgFlagFilter) == (opts.mMsgFlagMask & meta->mMsgFlags)) + { + std::cerr << "checkMsgFilter() Accepting Msg as FlagMatches: "; + std::cerr << " Mask: " << opts.mMsgFlagMask << " FlagFilter: " << opts.mMsgFlagFilter; + std::cerr << " MsgFlag: " << meta->mMsgFlags << " MsgId: " << meta->mMsgId; + std::cerr << std::endl; + + flagMatch = true; + } + else + { + std::cerr << "checkMsgFilter() Dropping Msg due to !FlagMatch "; + std::cerr << " Mask: " << opts.mMsgFlagMask << " FlagFilter: " << opts.mMsgFlagFilter; + std::cerr << " MsgFlag: " << meta->mMsgFlags << " MsgId: " << meta->mMsgId; + std::cerr << std::endl; + + flagMatch = false; + } + }else{ + flagMatch = true; + } + + return statusMatch && flagMatch; +} + diff --git a/libretroshare/src/gxs/rsgxsdataaccess.h b/libretroshare/src/gxs/rsgxsdataaccess.h index 27904d749..1d6dbe920 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.h +++ b/libretroshare/src/gxs/rsgxsdataaccess.h @@ -1,323 +1,420 @@ -#ifndef RSGXSDATAACCESS_H -#define RSGXSDATAACCESS_H - -/* - * libretroshare/src/retroshare: rsgxsdataaccess.cc - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Robert Fernie, Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "rstokenservice.h" -#include "rsgxsrequesttypes.h" -#include "rsgds.h" - - -typedef std::map< RsGxsGroupId, std::map > MsgMetaFilter; - -class RsGxsDataAccess : public RsTokenServiceV2 -{ -public: - RsGxsDataAccess(RsGeneralDataService* ds); - virtual ~RsGxsDataAccess() { return ;} - -public: - - /** S: RsTokenService **/ - - /*! - * - * @param token - * @param ansType - * @param opts - * @param groupIds - * @return - */ - bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); - - /*! - * For requesting info on all messages of one or more groups - * @param token - * @param ansType - * @param opts - * @param groupIds - * @return - */ - bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq&); - - /*! - * This sets the status of the message - * @param msgId the message id to set status for - * @param status status - * @param statusMask the mask for the settings targetted - * @return true if request made successfully, false otherwise - */ - bool requestSetMessageStatus(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, - const uint32_t status, const uint32_t statusMask); - - /*! - * - * @param token - * @param grpId - * @param status - * @param statusMask - * @return true if request made successfully, false otherwise - */ - bool requestSetGroupStatus(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t status, - const uint32_t statusMask); - - /*! - * Use request status to find out if successfully set - * @param groupId - * @param subscribeFlags - * @param subscribeMask - * @return true if request made successfully, false otherwise - */ - bool requestSetGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId &groupId, uint32_t subscribeFlags, - uint32_t subscribeMask); - - - /* Poll */ - uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ - bool cancelRequest(const uint32_t &token); - - /** E: RsTokenService **/ - - -public: - - /*! - * This adds a groups to the gxs data base, this is a blocking call - * Responsibility for grp still lies with callee \n - * If function returns successfully DataAccess can be queried for grp - * @param grp the group to add, responsibility grp passed lies with callee - * @return false if group cound not be added - */ - bool addGroupData(RsNxsGrp* grp); - - /*! - * This adds a group to the gxs data base, this is a blocking call \n - * Responsibility for msg still lies with callee \n - * If function returns successfully DataAccess can be queried for msg - * @param msg the msg to add - * @return false if msg could not be added, true otherwise - */ - bool addMsgData(RsNxsMsg* msg); - -public: - - /*! - * This must be called periodically to progress requests - */ - void processRequests(); - - /*! - * Retrieve group list for a given token - * @param token request token to be redeemed - * @param groupIds - * @param msgIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupList(const uint32_t &token, std::list &groupIds); - - /*! - * - * @param token request token to be redeemed - * @param msgIds - */ - bool getMsgList(const uint32_t &token, GxsMsgIdResult &msgIds); - - - /*! - * @param token request token to be redeemed - * @param groupInfo - */ - bool getGroupSummary(const uint32_t &token, std::list &groupInfo); - - /*! - * - * @param token request token to be redeemed - * @param msgInfo - */ - bool getMsgSummary(const uint32_t &token, GxsMsgMetaResult &msgInfo); - - /*! - * - * @param token request token to be redeemed - * @param grpData - */ - bool getGroupData(const uint32_t &token, std::list& grpData); - - /*! - * - * @param token request token to be redeemed - * @param msgData - * @return false if data cannot be found for token - */ - bool getMsgData(const uint32_t &token, NxsMsgDataResult& msgData); - -private: - - /** helper functions to implement token service **/ - - /*! - * Assigns a token value to passed integer - * @param token is assigned a unique token value - */ - void generateToken(uint32_t &token); - - /*! - * - * @param token the value of the token for the request object handle wanted - * @return the request associated to this token - */ - GxsRequest* retrieveRequest(const uint32_t& token); - - /*! - * Add a gxs request to queue - * @param req gxs request to add - */ - void storeRequest(GxsRequest* req); - - /*! - * convenience function to setting members of request - * @param req - * @param token - * @param ansType - * @param opts - */ - void setReq(GxsRequest* req,const uint32_t &token, const uint32_t& ansType, const RsTokReqOptions &opts) const; - - /*! - * Remove request for request queue - * Request is deleted - * @param token the token associated to the request - * @return true if token successfully cleared, false if token does not exist - */ - bool clearRequest(const uint32_t &token); - - /*! - * Updates the status flag of a request - * @param token the token value of the request to set - * @param status the status to set - * @return - */ - bool updateRequestStatus(const uint32_t &token, const uint32_t &status); - - /*! - * Use to query the status and other values of a given token - * @param token the toke of the request to check for - * @param status set to current status of request - * @param reqtype set to request type of request - * @param anstype set to to anstype of request - * @param ts time stamp - * @return false if token does not exist, true otherwise - */ - bool checkRequestStatus(const uint32_t &token, uint32_t &status, uint32_t &reqtype, uint32_t &anstype, time_t &ts); - - // special ones for testing (not in final design) - /*! - * Get list of active tokens of this token service - * @param tokens sets to list of token contained in this tokenservice - */ - void tokenList(std::list &tokens); - - -private: - - /* These perform the actual blocking retrieval of data */ - - /*! - * Attempts to retrieve group id list from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getGroupList(GroupIdReq* req); - - /*! - * Attempts to retrieve msg id list from data store - * Computationally/CPU-Bandwidth expensive - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getMsgList(MsgIdReq* req); - - - /*! - * Attempts to retrieve group meta data from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getGroupSummary(GroupMetaReq* req); - - /*! - * Attempts to retrieve msg meta data from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getMsgSummary(MsgMetaReq* req); - - /*! - * Attempts to retrieve group data from data store - * @param req The request specifying data to retrieve - * @return false if unsuccessful, true otherwise - */ - bool getGroupData(GroupDataReq* req); - - /*! - * Attempts to retrieve message data from data store - * @param req The request specifying data to retrieve - * @return false if unsuccessful, true otherwise - */ - bool getMsgData(MsgDataReq* req); - - /*! - * This filter msgs based of options supplied (at the moment just status masks) - * @param msgIds The msgsIds to filter - * @param opts the request options set by user - * @param meta The accompanying meta information for msg, ids - */ - void filterMsgList(GxsMsgIdResult& msgIds, const RsTokReqOptions& opts, const MsgMetaFilter& meta) const; - - - /*! - * This applies the options to the meta to find out if the given message satisfies - * them - * @param opts options containing filters to check - * @param meta meta containing currently defined options for msg - * @return true if msg meta passes all options - */ - bool checkMsgFilter(const RsTokReqOptions& opts, const RsGxsMsgMetaData* meta) const; - -private: - - RsGeneralDataService* mDataStore; - uint32_t mNextToken; - std::map mRequests; - - RsMutex mDataMutex; - - -}; - -#endif // RSGXSDATAACCESS_H +#ifndef RSGXSDATAACCESS_H +#define RSGXSDATAACCESS_H + +/* + * libretroshare/src/retroshare: rsgxsdataaccess.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie, Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstokenservice.h" +#include "rsgxsrequesttypes.h" +#include "rsgds.h" + + +typedef std::map< RsGxsGroupId, std::map > MsgMetaFilter; +typedef std::map< RsGxsGroupId, RsGxsGrpMetaData* > GrpMetaFilter; + +class RsGxsDataAccess : public RsTokenService +{ +public: + RsGxsDataAccess(RsGeneralDataService* ds); + virtual ~RsGxsDataAccess() { return ;} + +public: + + /** S: RsTokenService **/ + + /*! + * Use this to request group related information + * @param token The token returned for the request, store this value to pool for request completion + * @param ansType The type of result (e.g. group data, meta, ids) + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds group id to request info for + * @return + */ + bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); + + /*! + * Use this to request all group related info + * @param token The token returned for the request, store this value to pool for request completion + * @param ansType The type of result (e.g. group data, meta, ids) + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @return + */ + bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts); + + /*! + * Use this to get msg information (id, meta, or data), store token value to poll for request completion + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs + * @return true if request successful false otherwise + */ + bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds); + + /*! + * Use this to get message information (id, meta, or data), store token value to poll for request completion + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, this retrieve all the msgs info for each grpId in list, if group Id list is empty \n + * all messages for all groups are retrieved + * @return true if request successful false otherwise + */ + bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds); + + /*! + * For requesting msgs related to a given msg id within a group + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs + * @return true if request successful false otherwise + */ + bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector &msgIds); + + /* Poll */ + uint32_t requestStatus(const uint32_t token); + + /* Cancel Request */ + bool cancelRequest(const uint32_t &token); + + /** E: RsTokenService **/ + +public: + + /*! + * This adds a groups to the gxs data base, this is a blocking call + * Responsibility for grp still lies with callee \n + * If function returns successfully DataAccess can be queried for grp + * @param grp the group to add, responsibility grp passed lies with callee + * @return false if group cound not be added + */ + bool addGroupData(RsNxsGrp* grp); + + /*! + * This adds a group to the gxs data base, this is a blocking call \n + * Responsibility for msg still lies with callee \n + * If function returns successfully DataAccess can be queried for msg + * @param msg the msg to add + * @return false if msg could not be added, true otherwise + */ + bool addMsgData(RsNxsMsg* msg); + +public: + + /*! + * This must be called periodically to progress requests + */ + void processRequests(); + + /*! + * Retrieve group list for a given token + * @param token request token to be redeemed + * @param groupIds + * @param msgIds + * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready + */ + bool getGroupList(const uint32_t &token, std::list &groupIds); + + /*! + * + * @param token request token to be redeemed + * @param msgIds + */ + bool getMsgList(const uint32_t &token, GxsMsgIdResult &msgIds); + + /*! + * Retrieve msg list for a given token for message related info + * @param token token to be redeemed + * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) + * @return false if could not redeem token + */ + bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult& msgIds); + + + /*! + * @param token request token to be redeemed + * @param groupInfo + */ + bool getGroupSummary(const uint32_t &token, std::list &groupInfo); + + /*! + * + * @param token request token to be redeemed + * @param msgInfo + */ + bool getMsgSummary(const uint32_t &token, GxsMsgMetaResult &msgInfo); + + + /*! + * Retrieve msg meta for a given token for message related info + * @param token token to be redeemed + * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) + * @return false if could not redeem token + */ + bool getMsgRelatedSummary(const uint32_t &token, MsgRelatedMetaResult& msgMeta); + + /*! + * + * @param token request token to be redeemed + * @param grpData + */ + bool getGroupData(const uint32_t &token, std::list& grpData); + + /*! + * + * @param token request token to be redeemed + * @param msgData + * @return false if data cannot be found for token + */ + bool getMsgData(const uint32_t &token, NxsMsgDataResult& msgData); + + /*! + * + * @param token request token to be redeemed + * @param msgData + * @return false if data cannot be found for token + */ + bool getMsgRelatedData(const uint32_t &token, NxsMsgRelatedDataResult& msgData); + +private: + + /** helper functions to implement token service **/ + + /*! + * Assigns a token value to passed integer + * @param token is assigned a unique token value + */ + void generateToken(uint32_t &token); + + /*! + * + * @param token the value of the token for the request object handle wanted + * @return the request associated to this token + */ + GxsRequest* locked_retrieveRequest(const uint32_t& token); + + /*! + * Add a gxs request to queue + * @param req gxs request to add + */ + void storeRequest(GxsRequest* req); + + /*! + * convenience function to setting members of request + * @param req + * @param token + * @param ansType + * @param opts + */ + void setReq(GxsRequest* req,const uint32_t &token, const uint32_t& ansType, const RsTokReqOptions &opts) const; + + /*! + * Remove request for request queue + * Request is deleted + * @param token the token associated to the request + * @return true if token successfully cleared, false if token does not exist + */ + bool clearRequest(const uint32_t &token); + + /*! + * Updates the status flag of a request + * @param token the token value of the request to set + * @param status the status to set + * @return + */ + bool locked_updateRequestStatus(const uint32_t &token, const uint32_t &status); + + /*! + * Use to query the status and other values of a given token + * @param token the toke of the request to check for + * @param status set to current status of request + * @param reqtype set to request type of request + * @param anstype set to to anstype of request + * @param ts time stamp + * @return false if token does not exist, true otherwise + */ + bool checkRequestStatus(const uint32_t &token, uint32_t &status, uint32_t &reqtype, uint32_t &anstype, time_t &ts); + + // special ones for testing (not in final design) + /*! + * Get list of active tokens of this token service + * @param tokens sets to list of token contained in this tokenservice + */ + void tokenList(std::list &tokens); + + /*! + * Convenience function to delete the ids + * @param filter the meta filter to clean + */ + void cleanseMsgMetaMap(GxsMsgMetaResult& result); + +public: + + /*! + * Assigns a token value to passed integer + * The status of the token can still be queried from request status feature + * @param token is assigned a unique token value + */ + uint32_t generatePublicToken(); + + /*! + * Updates the status of associate token + * @param token + * @param status + * @return false if token could not be found, true if token disposed of + */ + bool updatePublicRequestStatus(const uint32_t &token, const uint32_t &status); + + /*! + * This gets rid of a publicly issued token + * @param token + * @return false if token could not found, true if token disposed of + */ + bool disposeOfPublicToken(const uint32_t &token); + +private: + + /* These perform the actual blocking retrieval of data */ + + /*! + * Attempts to retrieve group id list from data store + * @param req + * @return false if unsuccessful, true otherwise + */ + bool getGroupList(GroupIdReq* req); + + /*! + * convenience function for filtering grpIds + * @param grpIdsIn The ids to filter with opts + * @param opts the filter options + * @param grpIdsOut grpIdsIn filtered with opts + */ + bool getGroupList(const std::list& grpIdsIn, const RsTokReqOptions& opts, std::list& grpIdsOut); + + /*! + * Attempts to retrieve msg id list from data store + * Computationally/CPU-Bandwidth expensive + * @param req + * @return false if unsuccessful, true otherwise + */ + bool getMsgList(MsgIdReq* req); + + + /*! + * Attempts to retrieve group meta data from data store + * @param req + * @return false if unsuccessful, true otherwise + */ + bool getGroupSummary(GroupMetaReq* req); + + /*! + * Attempts to retrieve msg meta data from data store + * @param req + * @return false if unsuccessful, true otherwise + */ + bool getMsgSummary(MsgMetaReq* req); + + /*! + * Attempts to retrieve group data from data store + * @param req The request specifying data to retrieve + * @return false if unsuccessful, true otherwise + */ + bool getGroupData(GroupDataReq* req); + + /*! + * Attempts to retrieve message data from data store + * @param req The request specifying data to retrieve + * @return false if unsuccessful, true otherwise + */ + bool getMsgData(MsgDataReq* req); + + + /*! + * Attempts to retrieve messages related to msgIds of associated equest + * @param token request token to be redeemed + * @param msgIds + * @return false if data cannot be found for token + */ + bool getMsgRelatedInfo(MsgRelatedInfoReq* req); + + /*! + * This filter msgs based of options supplied (at the moment just status masks) + * @param msgIds The msgsIds to filter + * @param opts the request options set by user + * @param meta The accompanying meta information for msg, ids + */ + void filterMsgList(GxsMsgIdResult& msgIds, const RsTokReqOptions& opts, const MsgMetaFilter& meta) const; + + /*! + * This filter msgs based of options supplied (at the moment just status masks) + * @param grpIds The group ids to filter + * @param opts the request options containing mask set by user + * @param meta The accompanying meta information for group ids + */ + void filterGrpList(std::list& msgIds, const RsTokReqOptions& opts, const GrpMetaFilter& meta) const; + + + /*! + * This applies the options to the meta to find out if the given message satisfies + * them + * @param opts options containing filters to check + * @param meta meta containing currently defined options for msg + * @return true if msg meta passes all options + */ + bool checkMsgFilter(const RsTokReqOptions& opts, const RsGxsMsgMetaData* meta) const; + + /*! + * This applies the options to the meta to find out if the given group satisfies + * them + * @param opts options containing filters to check + * @param meta meta containing currently defined options for group + * @return true if group meta passes all options + */ + bool checkGrpFilter(const RsTokReqOptions& opts, const RsGxsGrpMetaData* meta) const; + + + /*! + * This is a filter method which applies the request options to the list of ids + * requested + * @param msgIds the msg ids for filter to be applied to + * @param opts the options used to parameterise the id filter + * @param msgIdsOut the left overs ids after filter is applied to msgIds + */ + bool getMsgList(const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgReq& msgIdsOut); + +private: + + RsGeneralDataService* mDataStore; + uint32_t mNextToken; + std::map mPublicToken; + std::map mRequests; + + RsMutex mDataMutex; + + +}; + +#endif // RSGXSDATAACCESS_H diff --git a/libretroshare/src/gxs/rsgxsflags.h b/libretroshare/src/gxs/rsgxsflags.h index c85d7a033..a30c663d9 100644 --- a/libretroshare/src/gxs/rsgxsflags.h +++ b/libretroshare/src/gxs/rsgxsflags.h @@ -3,51 +3,105 @@ #include "inttypes.h" +/** + * The GXS_SERV namespace serves a single point of reference for definining grp and msg flags + * Declared and defined here are: + * - privacy flags which define the level of privacy that can be given \n + * to a group + * - authentication types which defined types of authentication needed for a given message to + * confirm its authenticity + * - subscription flags: This used only locally by the peer to subscription status to a \n + * a group + * - + */ namespace GXS_SERV { - /*** GROUP FLAGS ***/ - /* type of group */ + /** START privacy **/ - static const uint32_t FLAG_GRP_TYPE_MASK; + static const uint32_t FLAG_PRIVACY_MASK = 0x0000000f; // pub key encrypted - static const uint32_t FLAG_GRP_TYPE_PRIVATE; + static const uint32_t FLAG_PRIVACY_PRIVATE = 0x00000001; - // single publisher, read only - static const uint32_t FLAG_GRP_TYPE_RESTRICTED; + // publish private key needed to publish + static const uint32_t FLAG_PRIVACY_RESTRICTED = 0x00000002; - // anyone can publish - static const uint32_t FLAG_GRP_TYPE_PUBLIC; + // anyone can publish, publish key pair not needed + static const uint32_t FLAG_PRIVACY_PUBLIC = 0x00000004; + /** END privacy **/ - /* type of msgs allowed */ + /** START authentication **/ - static const uint32_t FLAG_MSG_TYPE_MASK; + static const uint32_t FLAG_AUTHEN_MASK = 0x000000f0; - // only signee can edit, and sign required - static const uint32_t FLAG_MSG_TYPE_SIGNED; + // identity + static const uint32_t FLAG_AUTHEN_IDENTITY = 0x000000010; - // no sign required, but signee can edit if signed - static const uint32_t FLAG_MSG_TYPE_ANON; + // publish key + static const uint32_t FLAG_AUTHEN_PUBLISH = 0x000000020; - // anyone can mod but sign must be provided (needed for wikis) - static const uint32_t FLAG_MSG_TYPE_SIGNED_SHARED; + // admin key + static const uint32_t FLAG_AUTHEN_ADMIN = 0x00000040; - /*** GROUP FLAGS ***/ + // pgp sign identity + static const uint32_t FLAG_AUTHEN_PGP_IDENTITY = 0x00000080; + /** END authentication **/ + /** START msg authentication flags **/ - /*** MESSAGE FLAGS ***/ + static const uint8_t MSG_AUTHEN_MASK = 0x0f; - // indicates message edits an existing message - static const uint32_t FLAG_MSG_EDIT; + static const uint8_t MSG_AUTHEN_ROOT_PUBLISH_SIGN = 0x01; - // indicates msg is id signed - static const uint32_t FLAG_MSG_ID_SIGNED; + static const uint8_t MSG_AUTHEN_CHILD_PUBLISH_SIGN = 0x02; - /*** MESSAGE FLAGS ***/ + static const uint8_t MSG_AUTHEN_ROOT_AUTHOR_SIGN = 0x04; + + static const uint8_t MSG_AUTHEN_CHILD_AUTHOR_SIGN = 0x08; + + /** END msg authentication flags **/ + + /** START group options flag **/ + + static const uint8_t GRP_OPTION_AUTHEN_AUTHOR_SIGN = 0x01; + + /** END group options flag **/ + + /** START Subscription Flags. (LOCAL) **/ + + static const uint32_t GROUP_SUBSCRIBE_ADMIN = 0x01; + + static const uint32_t GROUP_SUBSCRIBE_PUBLISH = 0x02; + + static const uint32_t GROUP_SUBSCRIBE_SUBSCRIBED = 0x04; + + static const uint32_t GROUP_SUBSCRIBE_NOT_SUBSCRIBED = 0x08; + + static const uint32_t GROUP_SUBSCRIBE_MASK = 0x0000000f; + + /** END Subscription Flags. (LOCAL) **/ + + /** START GXS Msg status flags **/ + + static const uint32_t GXS_MSG_STATUS_UNPROCESSED = 0x000000100; + + static const uint32_t GXS_MSG_STATUS_UNREAD = 0x00000200; + + static const uint32_t GXS_MSG_STATUS_READ = 0x00000400; + + /** END GXS Msg status flags **/ + + /** START GXS Grp status flags **/ + + static const uint32_t GXS_GRP_STATUS_UNPROCESSED = 0x000000100; + + static const uint32_t GXS_GRP_STATUS_UNREAD = 0x00000200; + + /** END GXS Grp status flags **/ } diff --git a/libretroshare/src/gxs/rsgxsifaceimpl.cc b/libretroshare/src/gxs/rsgxsifaceimpl.cc new file mode 100644 index 000000000..c3162f034 --- /dev/null +++ b/libretroshare/src/gxs/rsgxsifaceimpl.cc @@ -0,0 +1,170 @@ + +/* + * libretroshare/src/gxs/rsgxsifaceimpl.cc: rsgxsifaceimpl.cc + * + * RetroShare GXS. + * + * Copyright 2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsgxsifaceimpl.h" +#include "gxs/rsgxs.h" +#include "gxs/rsgxsflags.h" + +RsGxsIfaceImpl::RsGxsIfaceImpl(RsGenExchange *gxs) + : mGxsIfaceMutex("RsGxsIfaceImpl"), mGxs(gxs) +{ +} + + + +void RsGxsIfaceImpl::groupsChanged(std::list &grpIds) +{ + RsStackMutex stack(mGxsIfaceMutex); + + while(!mGroupChange.empty()) + { + RsGxsGroupChange* gc = mGroupChange.back(); + std::list& gList = gc->grpIdList; + std::list::iterator lit = gList.begin(); + for(; lit != gList.end(); lit++) + grpIds.push_back(*lit); + + mGroupChange.pop_back(); + delete gc; + } +} + +bool RsGxsIfaceImpl::updated() +{ + RsStackMutex stack(mGxsIfaceMutex); + + bool changed = (!mGroupChange.empty() || !mMsgChange.empty()); + + return changed; +} + +void RsGxsIfaceImpl::msgsChanged(std::map > &msgs) +{ + RsStackMutex stack(mGxsIfaceMutex); + + while(!mMsgChange.empty()) + { + RsGxsMsgChange* mc = mMsgChange.back(); + msgs = mc->msgChangeMap; + mMsgChange.pop_back(); + delete mc; + } +} + +void RsGxsIfaceImpl::receiveChanges(std::vector &changes) +{ + + RsStackMutex stack(mGxsIfaceMutex); + + std::vector::iterator vit = changes.begin(); + + for(; vit != changes.end(); vit++) + { + RsGxsNotify* n = *vit; + RsGxsGroupChange* gc; + RsGxsMsgChange* mc; + if((mc = dynamic_cast(n)) != NULL) + { + mMsgChange.push_back(mc); + } + else if((gc = dynamic_cast(n)) != NULL) + { + mGroupChange.push_back(gc); + } + else + { + delete n; + } + } +} + +RsTokenService* RsGxsIfaceImpl::getTokenService() +{ + return mGxs->getTokenService(); +} + +bool RsGxsIfaceImpl::getGroupList(const uint32_t &token, + std::list &groupIds) +{ + + return mGxs->getGroupList(token, groupIds); +} + +bool RsGxsIfaceImpl::getMsgList(const uint32_t &token, + GxsMsgIdResult& msgIds) +{ + + return mGxs->getMsgList(token, msgIds); +} + +bool RsGxsIfaceImpl::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) +{ + return mGxs->getMsgRelatedList(token, msgIds); +} + +/* Generic Summary */ +bool RsGxsIfaceImpl::getGroupSummary(const uint32_t &token, + std::list &groupInfo) +{ + + return mGxs->getGroupMeta(token, groupInfo); +} + +bool RsGxsIfaceImpl::getMsgSummary(const uint32_t &token, + GxsMsgMetaMap &msgInfo) +{ + + return mGxs->getMsgMeta(token, msgInfo); +} + +bool RsGxsIfaceImpl::getMsgrelatedSummary(const uint32_t &token, GxsMsgRelatedMetaMap &msgInfo) +{ + return mGxs->getMsgRelatedMeta(token, msgInfo); +} + + + +bool RsGxsIfaceImpl::subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) +{ + if(subscribe) + mGxs->setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED, GXS_SERV::GROUP_SUBSCRIBE_MASK); + else + mGxs->setGroupSubscribeFlags(token, grpId, 0, GXS_SERV::GROUP_SUBSCRIBE_MASK); + + return true; +} + + +bool RsGxsIfaceImpl::acknowledgeMsg(const uint32_t& token, std::pair& msgId) +{ + + return mGxs->acknowledgeTokenMsg(token, msgId); +} + +bool RsGxsIfaceImpl::acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) +{ + return mGxs->acknowledgeTokenGrp(token, grpId); +} diff --git a/libretroshare/src/gxs/rsgxsifaceimpl.h b/libretroshare/src/gxs/rsgxsifaceimpl.h new file mode 100644 index 000000000..73d314259 --- /dev/null +++ b/libretroshare/src/gxs/rsgxsifaceimpl.h @@ -0,0 +1,181 @@ +#ifndef RSGXSIFACEIMPL_H +#define RSGXSIFACEIMPL_H + +/* + * libretroshare/src/gxs/: rsgxsifaceimpl.h + * + * RetroShare GXS. Convenience interface implementation + * + * Copyright 2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "gxs/rsgenexchange.h" + +/*! + * The simple idea of this class is to implement the simple interface functions + * of gen exchange. + * This class provides convenience implementations of: + * - Handle msg and group changes (client class must pass changes sent by RsGenExchange to it) + * - subscription to groups + * - retrieval of msgs and group ids and meta info + */ +class RsGxsIfaceImpl +{ +public: + + /*! + * + * @param gxs handle to RsGenExchange instance of service (Usually the service class itself) + */ + RsGxsIfaceImpl(RsGenExchange* gxs); + + /*! + * Gxs services should call this for automatic handling of + * changes, send + * @param changes + */ + void receiveChanges(std::vector& changes); + + /*! + * Checks to see if a change has been received for + * for a message or group + * @return true if a change has occured for msg or group + */ + virtual bool updated(); + +public: + + /*! + * The groups changed. \n + * class can reimplement to use to tailor + * the group actually set for ui notification. + * If receivedChanges is not passed RsGxsNotify changes + * this function does nothing + * @param grpIds + */ + virtual void groupsChanged(std::list& grpIds); + + /*! + * The msg changed. \n + * class can reimplement to use to tailor + * the msg actually set for ui notification. + * If receivedChanges is not passed RsGxsNotify changes + * this function does nothing + * @param msgs + */ + virtual void msgsChanged(std::map >& msgs); + + /*! + * @return handle to token service for this GXS service + */ + RsTokenService* getTokenService(); + + /* Generic Lists */ + + /*! + * Retrieve list of group ids associated to a request token + * @param token token to be redeemed for this request + * @param groupIds the ids return for given request token + * @return false if request token is invalid, check token status for error report + */ + bool getGroupList(const uint32_t &token, + std::list &groupIds); + + /*! + * Retrieves list of msg ids associated to a request token + * @param token token to be redeemed for this request + * @param msgIds the ids return for given request token + * @return false if request token is invalid, check token status for error report + */ + bool getMsgList(const uint32_t &token, + GxsMsgIdResult& msgIds); + + /*! + * Retrieves list of msg related ids associated to a request token + * @param token token to be redeemed for this request + * @param msgIds the ids return for given request token + * @return false if request token is invalid, check token status for error report + */ + bool getMsgRelatedList(const uint32_t &token, + MsgRelatedIdResult& msgIds); + + /*! + * @param token token to be redeemed for group summary request + * @param groupInfo the ids returned for given request token + * @return false if request token is invalid, check token status for error report + */ + bool getGroupSummary(const uint32_t &token, + std::list &groupInfo); + + /*! + * @param token token to be redeemed for message summary request + * @param msgInfo the message metadata returned for given request token + * @return false if request token is invalid, check token status for error report + */ + bool getMsgSummary(const uint32_t &token, + GxsMsgMetaMap &msgInfo); + + /*! + * @param token token to be redeemed for message related summary request + * @param msgInfo the message metadata returned for given request token + * @return false if request token is invalid, check token status for error report + */ + bool getMsgrelatedSummary(const uint32_t &token, + GxsMsgRelatedMetaMap &msgInfo); + + /*! + * subscribes to group, and returns token which can be used + * to be acknowledged to get group Id + * @param token token to redeem for acknowledgement + * @param grpId the id of the group to subscribe to + */ + virtual bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe); + + /*! + * This allows the client service to acknowledge that their msgs has + * been created/modified and retrieve the create/modified msg ids + * @param token the token related to modification/create request + * @param msgIds map of grpid->msgIds of message created/modified + * @return true if token exists false otherwise + */ + bool acknowledgeMsg(const uint32_t& token, std::pair& msgId); + + /*! + * This allows the client service to acknowledge that their grps has + * been created/modified and retrieve the create/modified grp ids + * @param token the token related to modification/create request + * @param msgIds vector of ids of groups created/modified + * @return true if token exists false otherwise + */ + bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId); + + +private: + + RsGenExchange* mGxs; + + std::vector mGroupChange; + std::vector mMsgChange; + + RsMutex mGxsIfaceMutex; +}; + +#endif // RSGXSIFACEIMPL_H diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index ee6429e4a..cca02d0fc 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -1,4 +1,31 @@ + +/* + * libretroshare/src/gxs: rsgxnetservice.cc + * + * Access to rs network and synchronisation service implementation + * + * Copyright 2012-2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + #include "rsgxsnetservice.h" +#include "rsgxsflags.h" #define NXS_NET_DEBUG @@ -10,7 +37,7 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs) : p3Config(servType), p3ThreadedService(servType), mTransactionTimeOut(TRANSAC_TIMEOUT), mServType(servType), mDataStore(gds), mTransactionN(0), - mObserver(nxsObs), mNxsMutex("RsGxsNetService"), mNetMgr(netMgr), mSYNC_PERIOD(SYNC_PERIOD) + mObserver(nxsObs), mNxsMutex("RsGxsNetService"), mNetMgr(netMgr), mSYNC_PERIOD(SYNC_PERIOD), mSyncTs(0) { addSerialType(new RsNxsSerialiser(mServType)); @@ -31,8 +58,9 @@ int RsGxsNetService::tick(){ recvNxsItemQueue(); uint32_t now = time(NULL); + uint32_t elapsed = mSYNC_PERIOD + mSyncTs; - if((mSYNC_PERIOD + mSyncTs) < now) + if((elapsed) < now) { syncWithPeers(); mSyncTs = now; @@ -49,17 +77,55 @@ void RsGxsNetService::syncWithPeers() std::set::iterator sit = peers.begin(); - // for now just grps - for(; sit != peers.end(); sit++) - { - RsNxsSyncGrp *grp = new RsNxsSyncGrp(mServType); - grp->clear(); - grp->PeerId(*sit); - sendItem(grp); - } + // for now just grps + for(; sit != peers.end(); sit++) + { + RsNxsSyncGrp *grp = new RsNxsSyncGrp(mServType); + grp->clear(); + grp->PeerId(*sit); + sendItem(grp); + } - // TODO msgs +#ifdef GXS_ENABLE_SYNC_MSGS + std::map grpMeta; + mDataStore->retrieveGxsGrpMetaData(grpMeta); + + std::map::iterator + mit = grpMeta.begin(); + + std::vector grpIds; + + for(; mit != grpMeta.end(); mit++) + { + RsGxsGrpMetaData* meta = mit->second; + + if(meta->mSubscribeFlags & (GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED | + GXS_SERV::GROUP_SUBSCRIBE_ADMIN) ) + grpIds.push_back(mit->first); + + delete meta; + } + + sit = peers.begin(); + + // synchronise group msg for groups which we're subscribed to + for(; sit != peers.end(); sit++) + { + RsStackMutex stack(mNxsMutex); + + std::vector::iterator vit = grpIds.begin(); + + for(; vit != grpIds.end(); vit++) + { + RsNxsSyncMsg* msg = new RsNxsSyncMsg(mServType); + msg->clear(); + msg->PeerId(*sit); + msg->grpId = *vit; + sendItem(msg); + } + } +#endif } bool RsGxsNetService::loadList(std::list& load) @@ -300,7 +366,8 @@ void RsGxsNetService::run(){ bool RsGxsNetService::locked_checkTransacTimedOut(NxsTransaction* tr) { - return tr->mTimeOut < ((uint32_t) time(NULL)); + return tr->mTimeOut < ((uint32_t) time(NULL)); + // return false; } void RsGxsNetService::processTransactions(){ @@ -570,10 +637,11 @@ void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) // notify listener of grps mObserver->notifyNewGroups(grps); + + }else if(flag & RsNxsTransac::FLAG_TYPE_MSGS) { - std::list::iterator lit = tr->mItems.begin(); std::vector msgs; while(tr->mItems.size() > 0) @@ -697,14 +765,16 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) } } + if(msgItemL.empty()) + return; // get grp id for this transaction RsNxsSyncMsgItem* item = msgItemL.front(); const std::string& grpId = item->grpId; - std::vector grpIdV; - grpIdV.push_back(grpId); + GxsMsgReq reqIds; + reqIds[grpId] = std::vector(); GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(grpIdV, result); + mDataStore->retrieveGxsMsgMetaData(reqIds, result); std::vector &msgMetaV = result[grpId]; std::vector::const_iterator vit = msgMetaV.begin(); @@ -722,6 +792,8 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) std::list::iterator llit = msgItemL.begin(); std::list reqList; + const std::string peerFrom = tr->mTransaction->PeerId(); + for(; llit != msgItemL.end(); llit++) { const std::string& msgId = (*llit)->msgId; @@ -732,35 +804,39 @@ void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) msgItem->msgId = msgId; msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; msgItem->transactionNumber = transN; + msgItem->PeerId(peerFrom); reqList.push_back(msgItem); } } + if(!reqList.empty()) + { - RsNxsTransac* transac = new RsNxsTransac(mServType); - transac->transactFlag = RsNxsTransac::FLAG_TYPE_MSG_LIST_REQ - | RsNxsTransac::FLAG_BEGIN_P1; - transac->timestamp = 0; - transac->nItems = reqList.size(); - transac->PeerId(tr->mTransaction->PeerId()); - transac->transactionNumber = transN; + RsNxsTransac* transac = new RsNxsTransac(mServType); + transac->transactFlag = RsNxsTransac::FLAG_TYPE_MSG_LIST_REQ + | RsNxsTransac::FLAG_BEGIN_P1; + transac->timestamp = 0; + transac->nItems = reqList.size(); + transac->PeerId(tr->mTransaction->PeerId()); + transac->transactionNumber = transN; - NxsTransaction* newTrans = new NxsTransaction(); - newTrans->mItems = reqList; - newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; + NxsTransaction* newTrans = new NxsTransaction(); + newTrans->mItems = reqList; + newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; + newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - // create transaction copy with your id to indicate - // its an outgoing transaction - newTrans->mTransaction = new RsNxsTransac(*transac); - newTrans->mTransaction->PeerId(mOwnId); + // create transaction copy with your id to indicate + // its an outgoing transaction + newTrans->mTransaction = new RsNxsTransac(*transac); + newTrans->mTransaction->PeerId(mOwnId); - sendItem(transac); + sendItem(transac); - { - if(!locked_addTransaction(newTrans)) - delete newTrans; - } + { + if(!locked_addTransaction(newTrans)) + delete newTrans; + } + } } void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) @@ -806,7 +882,7 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) if(grpMetaMap.find(grpId) == grpMetaMap.end()){ RsNxsSyncGrpItem* grpItem = new RsNxsSyncGrpItem(mServType); - + grpItem->PeerId(tr->mTransaction->PeerId()); grpItem->grpId = grpId; grpItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; grpItem->transactionNumber = transN; @@ -815,26 +891,36 @@ void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) } - RsNxsTransac* transac = new RsNxsTransac(mServType); - transac->transactFlag = RsNxsTransac::FLAG_TYPE_GRP_LIST_REQ - | RsNxsTransac::FLAG_BEGIN_P1; - transac->timestamp = 0; - transac->nItems = reqList.size(); - transac->PeerId(tr->mTransaction->PeerId()); - transac->transactionNumber = transN; + if(!reqList.empty()) + { - NxsTransaction* newTrans = new NxsTransaction(); - newTrans->mItems = reqList; - newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - newTrans->mTransaction = new RsNxsTransac(*transac); - newTrans->mTransaction->PeerId(mOwnId); + RsNxsTransac* transac = new RsNxsTransac(mServType); + transac->transactFlag = RsNxsTransac::FLAG_TYPE_GRP_LIST_REQ + | RsNxsTransac::FLAG_BEGIN_P1; + transac->timestamp = 0; + transac->nItems = reqList.size(); + transac->PeerId(tr->mTransaction->PeerId()); + transac->transactionNumber = transN; - sendItem(transac); + NxsTransaction* newTrans = new NxsTransaction(); + newTrans->mItems = reqList; + newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; + newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; + newTrans->mTransaction = new RsNxsTransac(*transac); + newTrans->mTransaction->PeerId(mOwnId); - if(!locked_addTransaction(newTrans)) - delete newTrans; + sendItem(transac); + if(!locked_addTransaction(newTrans)) + delete newTrans; + + } + + // clean up meta data + std::map::iterator mit = grpMetaMap.begin(); + + for(; mit != grpMetaMap.end(); mit++) + delete mit->second; } void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) @@ -858,8 +944,13 @@ void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) grps[item->grpId] = NULL; } - mDataStore->retrieveNxsGrps(grps, false, false); - + if(!grps.empty()) + { + mDataStore->retrieveNxsGrps(grps, false, false); + } + else{ + return; + } NxsTransaction* newTr = new NxsTransaction(); newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; @@ -871,7 +962,7 @@ void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) std::string peerId = tr->mTransaction->PeerId(); for(;mit != grps.end(); mit++) { - mit->second->PeerId(peerId); // set so it gets send to right peer + mit->second->PeerId(peerId); // set so it gets sent to right peer mit->second->transactionNumber = transN; newTr->mItems.push_back(mit->second); } @@ -887,6 +978,7 @@ void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) ntr->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 | RsNxsTransac::FLAG_TYPE_GRPS; ntr->nItems = grps.size(); + ntr->PeerId(tr->mTransaction->PeerId()); newTr->mTransaction = new RsNxsTransac(*ntr); newTr->mTransaction->PeerId(mOwnId); @@ -903,6 +995,77 @@ void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr) { +#ifdef NXS_NET_DEBUG + std::cerr << "locked_genSendMsgsTransaction()" << std::endl; + std::cerr << "Generating Msg data send fron TransN: " << tr->mTransaction->transactionNumber + << std::endl; +#endif + + // go groups requested in transaction tr + + std::list::iterator lit = tr->mItems.begin(); + + GxsMsgReq msgIds; + GxsMsgResult msgs; + + if(tr->mItems.empty()){ + return; + } + + for(;lit != tr->mItems.end(); lit++) + { + RsNxsSyncMsgItem* item = dynamic_cast(*lit); + msgIds[item->grpId].push_back(item->msgId); + } + + mDataStore->retrieveNxsMsgs(msgIds, msgs, false, false); + + NxsTransaction* newTr = new NxsTransaction(); + newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; + + uint32_t transN = locked_getTransactionId(); + + // store msg items to send in transaction + GxsMsgResult::iterator mit = msgs.begin(); + std::string peerId = tr->mTransaction->PeerId(); + uint32_t msgSize = 0; + + for(;mit != msgs.end(); mit++) + { + std::vector& msgV = mit->second; + std::vector::iterator vit = msgV.begin(); + + for(; vit != msgV.end(); vit++) + { + RsNxsMsg* msg = *vit; + msg->PeerId(peerId); + msg->transactionNumber = transN; + newTr->mItems.push_back(msg); + msgSize++; + } + } + + if(newTr->mItems.empty()){ + delete newTr; + return; + } + + RsNxsTransac* ntr = new RsNxsTransac(mServType); + ntr->transactionNumber = transN; + ntr->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 | + RsNxsTransac::FLAG_TYPE_MSGS; + ntr->nItems = msgSize; + ntr->PeerId(peerId); + + newTr->mTransaction = new RsNxsTransac(*ntr); + newTr->mTransaction->PeerId(mOwnId); + newTr->mTimeOut = time(NULL) + mTransactionTimeOut; + + ntr->PeerId(tr->mTransaction->PeerId()); + sendItem(ntr); + + locked_addTransaction(newTr); + return; } uint32_t RsGxsNetService::locked_getTransactionId() @@ -956,7 +1119,6 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrp* item) if(grp.empty()) return; - std::vector grpSyncItems; std::map::iterator mit = grp.begin(); @@ -975,6 +1137,7 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrp* item) gItem->PeerId(peer); gItem->transactionNumber = transN; itemL.push_back(gItem); + delete mit->second; // release resource } tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; @@ -1003,6 +1166,61 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrp* item) void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsg* item) { RsStackMutex stack(mNxsMutex); + + const std::string& peer = item->PeerId(); + + GxsMsgMetaResult metaResult; + GxsMsgReq req; + req[item->grpId] = std::vector(); + mDataStore->retrieveGxsMsgMetaData(req, metaResult); + + std::vector& msgMeta = metaResult[item->grpId]; + + if(req.empty()){ + return; + } + + std::vector::iterator vit = msgMeta.begin(); + + NxsTransaction* tr = new NxsTransaction(); + std::list& itemL = tr->mItems; + + uint32_t transN = locked_getTransactionId(); + + for(; vit != msgMeta.end(); vit++) + { + RsGxsMsgMetaData* m = *vit; + RsNxsSyncMsgItem* mItem = new + RsNxsSyncMsgItem(mServType); + mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; + mItem->grpId = m->mGroupId; + mItem->msgId = m->mMsgId; + mItem->PeerId(peer); + mItem->transactionNumber = transN; + itemL.push_back(mItem); + } + + tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; + RsNxsTransac* trItem = new RsNxsTransac(mServType); + trItem->transactFlag = RsNxsTransac::FLAG_BEGIN_P1 + | RsNxsTransac::FLAG_TYPE_MSG_LIST_RESP; + + trItem->nItems = itemL.size(); + + trItem->timestamp = 0; + trItem->PeerId(peer); + trItem->transactionNumber = transN; + + // also make a copy for the resident transaction + tr->mTransaction = new RsNxsTransac(*trItem); + tr->mTransaction->PeerId(mOwnId); + tr->mTimeOut = time(NULL) + mTransactionTimeOut; + + // signal peer to prepare for transaction + sendItem(trItem); + + locked_addTransaction(tr); + return; } @@ -1047,3 +1265,40 @@ NxsTransaction::~NxsTransaction(){ delete mTransaction; mTransaction = NULL; } + + +/* Net Manager */ + +RsNxsNetMgrImpl::RsNxsNetMgrImpl(p3LinkMgr *lMgr) + : mLinkMgr(lMgr), mNxsNetMgrMtx("RsNxsNetMgrImpl") +{ + +} + + +std::string RsNxsNetMgrImpl::getOwnId() +{ + RsStackMutex stack(mNxsNetMgrMtx); + return mLinkMgr->getOwnId(); +} + +void RsNxsNetMgrImpl::getOnlineList(std::set &ssl_peers) +{ + ssl_peers.clear(); + + std::list pList; + { + RsStackMutex stack(mNxsNetMgrMtx); + mLinkMgr->getOnlineList(pList); + } + + std::list::const_iterator lit = pList.begin(); + + for(; lit != pList.end(); lit++) + ssl_peers.insert(*lit); +} + + + + + diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h index 6d12d5119..f555dd5d4 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ b/libretroshare/src/gxs/rsgxsnetservice.h @@ -1,6 +1,31 @@ #ifndef RSGXSNETSERVICE_H #define RSGXSNETSERVICE_H +/* + * libretroshare/src/gxs: rsgxnetservice.h + * + * Access to rs network and synchronisation service implementation + * + * Copyright 2012-2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + #include #include @@ -65,17 +90,22 @@ public: }; -//class RsNxsNetMgrImpl : public RsNxsNetMgrImpl -//{ +class RsNxsNetMgrImpl : public RsNxsNetMgr +{ -//public: +public: -// RsNxsNetMgrImpl(p3LinkMgr* lMgr); + RsNxsNetMgrImpl(p3LinkMgr* lMgr); -// std::string getOwnId(); -// void getOnlineList(std::set& ssl_peers); + std::string getOwnId(); + void getOnlineList(std::set& ssl_peers); -//}; +private: + + p3LinkMgr* mLinkMgr; + RsMutex mNxsNetMgrMtx; + +}; /// keep track of transaction number @@ -265,44 +295,44 @@ private: * of msgs received from peer stored in passed transaction * @param tr transaction responsible for generating msg request */ - void locked_genReqMsgTransaction(NxsTransaction* tr); + void locked_genReqMsgTransaction(NxsTransaction* tr); /*! * Generates new transaction to send grp requests based on list * of grps received from peer stored in passed transaction * @param tr transaction responsible for generating grp request */ - void locked_genReqGrpTransaction(NxsTransaction* tr); + void locked_genReqGrpTransaction(NxsTransaction* tr); - /*! - * Generates new transaction to send msg data based on list - * of grpids received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genSendMsgsTransaction(NxsTransaction* tr); + /*! + * Generates new transaction to send msg data based on list + * of grpids received from peer stored in passed transaction + * @param tr transaction responsible for generating grp request + */ + void locked_genSendMsgsTransaction(NxsTransaction* tr); - /*! - * Generates new transaction to send grp data based on list - * of grps received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genSendGrpsTransaction(NxsTransaction* tr); + /*! + * Generates new transaction to send grp data based on list + * of grps received from peer stored in passed transaction + * @param tr transaction responsible for generating grp request + */ + void locked_genSendGrpsTransaction(NxsTransaction* tr); - /*! - * convenience function to add a transaction to list - * @param tr transaction to add - */ - bool locked_addTransaction(NxsTransaction* tr); + /*! + * convenience function to add a transaction to list + * @param tr transaction to add + */ + bool locked_addTransaction(NxsTransaction* tr); - void cleanTransactionItems(NxsTransaction* tr) const; + void cleanTransactionItems(NxsTransaction* tr) const; - /*! - * @param tr the transaction to check for timeout - * @return false if transaction has timed out, true otherwise - */ - bool locked_checkTransacTimedOut(NxsTransaction* tr); + /*! + * @param tr the transaction to check for timeout + * @return false if transaction has timed out, true otherwise + */ + bool locked_checkTransacTimedOut(NxsTransaction* tr); - /** E: Transaction processing **/ + /** E: Transaction processing **/ /** S: item handlers **/ @@ -370,6 +400,7 @@ private: RsMutex mNxsMutex; uint32_t mSyncTs; + const uint32_t mSYNC_PERIOD; }; diff --git a/libretroshare/src/gxs/rsgxsrequesttypes.h b/libretroshare/src/gxs/rsgxsrequesttypes.h index 293584ab2..7d2f6977f 100644 --- a/libretroshare/src/gxs/rsgxsrequesttypes.h +++ b/libretroshare/src/gxs/rsgxsrequesttypes.h @@ -1,13 +1,33 @@ -/* - * rsgxsrequesttypes.h - * - * Created on: 21 Jul 2012 - * Author: crispy - */ - #ifndef RSGXSREQUESTTYPES_H_ #define RSGXSREQUESTTYPES_H_ +/* + * libretroshare/src/gxs: rgxsrequesttypes.h + * + * Type introspect request types for data access request implementation + * + * Copyright 2012-2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "gxs/rstokenservice.h" +#include "gxs/rsgds.h" class GxsRequest { @@ -21,7 +41,7 @@ public: uint32_t ansType; uint32_t reqType; - RsTokReqOptions Options; + RsTokReqOptions Options; uint32_t status; }; @@ -46,7 +66,7 @@ class GroupDataReq : public GxsRequest { public: - std::list mGroupIds; + std::list mGroupIds; std::list mGroupData; }; @@ -76,6 +96,16 @@ public: NxsMsgDataResult mMsgData; }; +class MsgRelatedInfoReq : public GxsRequest +{ + +public: + std::vector mMsgIds; + MsgRelatedIdResult mMsgIdResult; + MsgRelatedMetaResult mMsgMetaResult; + NxsMsgRelatedDataResult mMsgDataResult; +}; + class GroupSetFlagReq : public GxsRequest { public: diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h index 67a3f4279..0c201a737 100644 --- a/libretroshare/src/gxs/rsnxs.h +++ b/libretroshare/src/gxs/rsnxs.h @@ -2,7 +2,7 @@ #define RSGNP_H /* - * libretroshare/src/gxs: rsgnp.h + * libretroshare/src/gxs: rsnxs.h * * Network Exchange Service interface for RetroShare. * diff --git a/libretroshare/src/gxs/rsnxsobserver.h b/libretroshare/src/gxs/rsnxsobserver.h index 67ff2f799..627080ae7 100644 --- a/libretroshare/src/gxs/rsnxsobserver.h +++ b/libretroshare/src/gxs/rsnxsobserver.h @@ -2,9 +2,9 @@ #define RSNXSOBSERVER_H /* - * libretroshare/src/gxp: gxp.h + * libretroshare/src/gxs: rsnxsobserver.h * - * Observer, interface for RetroShare. + * Observer interface used by nxs to transport new messages to clients * * Copyright 2011-2012 by Robert Fernie, Evi-Parker Christopher * diff --git a/libretroshare/src/gxs/rstokenservice.h b/libretroshare/src/gxs/rstokenservice.h index 7b7acc1b6..c8ccb76a8 100644 --- a/libretroshare/src/gxs/rstokenservice.h +++ b/libretroshare/src/gxs/rstokenservice.h @@ -40,6 +40,34 @@ #define GXS_REQUEST_TYPE_MSG_META 0x00100000 #define GXS_REQUEST_TYPE_MSG_IDS 0x00200000 +#define GXS_REQUEST_TYPE_MSG_RELATED_DATA 0x00400000 +#define GXS_REQUEST_TYPE_MSG_RELATED_META 0x00800000 +#define GXS_REQUEST_TYPE_MSG_RELATED_IDS 0x01000000 + + + +// This bit will be filled out over time. +#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId. +#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group. +#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs. + +#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group. +#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs. + +#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId + +// Read Status. +#define RS_TOKREQOPT_READ 0x0001 +#define RS_TOKREQOPT_UNREAD 0x0002 + +#define RS_TOKREQ_ANSTYPE_LIST 0x0001 +#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002 +#define RS_TOKREQ_ANSTYPE_DATA 0x0003 +#define RS_TOKREQ_ANSTYPE_ACK 0x0004 + + + + /*! * This class provides useful generic support for GXS style services. * I expect much of this will be incorporated into the base GXS. @@ -50,7 +78,9 @@ public: RsTokReqOptions() { mOptions = 0; - mStatusFilter = 0; mStatusMask = 0; mSubscribeFilter = 0; + mStatusFilter = 0; mStatusMask = 0; mSubscribeFilter = 0; + mSubscribeMask = 0; + mMsgFlagMask = 0; mMsgFlagFilter = 0; mBefore = 0; mAfter = 0; mReqType = 0; } @@ -61,97 +91,95 @@ uint32_t mOptions; uint32_t mStatusFilter; uint32_t mStatusMask; +// use +uint32_t mMsgFlagMask, mMsgFlagFilter; + uint32_t mReqType; -uint32_t mSubscribeFilter; // Only for Groups. +uint32_t mSubscribeFilter, mSubscribeMask; // Only for Groups. // Time range... again applied after Options. time_t mBefore; time_t mAfter; }; +std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta); +std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta); /*! * A proxy class for requesting generic service data for GXS * This seperates the request mechanism from the actual retrieval of data */ -class RsTokenServiceV2 +class RsTokenService { public: - static const uint8_t GXS_REQUEST_STATUS_FAILED; - static const uint8_t GXS_REQUEST_STATUS_PENDING; - static const uint8_t GXS_REQUEST_STATUS_PARTIAL; - static const uint8_t GXS_REQUEST_STATUS_FINISHED_INCOMPLETE; - static const uint8_t GXS_REQUEST_STATUS_COMPLETE; - static const uint8_t GXS_REQUEST_STATUS_DONE; // ONCE ALL DATA RETRIEVED. + static const uint8_t GXS_REQUEST_V2_STATUS_FAILED; + static const uint8_t GXS_REQUEST_V2_STATUS_PENDING; + static const uint8_t GXS_REQUEST_V2_STATUS_PARTIAL; + static const uint8_t GXS_REQUEST_V2_STATUS_FINISHED_INCOMPLETE; + static const uint8_t GXS_REQUEST_V2_STATUS_COMPLETE; + static const uint8_t GXS_REQUEST_V2_STATUS_DONE; // ONCE ALL DATA RETRIEVED. public: - RsTokenServiceV2() { return; } - virtual ~RsTokenServiceV2() { return; } + RsTokenService() { return; } + virtual ~RsTokenService() { return; } - /* Data Requests */ + /* Data Requests */ /*! * Use this to request group related information * @param token The token returned for the request, store this value to pool for request completion * @param ansType The type of result (e.g. group data, meta, ids) * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds group id to request info for. Leave empty to get info on all groups, + * @param groupIds group id to request info for * @return */ virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) = 0; + /*! + * Use this to request all group related info + * @param token The token returned for the request, store this value to pool for request completion + * @param ansType The type of result (e.g. group data, meta, ids) + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @return + */ + virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) = 0; + /*! * Use this to get msg related information, store this value to pole for request completion * @param token The token returned for the request * @param ansType The type of result wanted * @param opts Additional option that affect outcome of request. Please see specific services, for valid values * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return + * @return true if request successful false otherwise */ virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds) = 0; - + /*! + * Use this to get msg related information, store this value to pole for request completion + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, this retrieves all the msgs info for each grpId in list + * @return true if request successful false otherwise + */ + virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) = 0; /*! - * This sets the status of the message - * @param msgId the message id to set status for - * @param status status - * @param statusMask the mask for the settings targetted - * @return true if request made successfully, false otherwise + * For requesting msgs related to a given msg id within a group + * @param token The token returned for the request + * @param ansType The type of result wanted + * @param opts Additional option that affect outcome of request. Please see specific services, for valid values + * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs + * @return true if request successful false otherwise */ - virtual bool requestSetMessageStatus(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, - const uint32_t status, const uint32_t statusMask) = 0; - - /*! - * Set the status of a group given by group Id - * @param token The token returned for this request - * @param grpId The Id of the group to apply status change to - * @param status The status to apply - * @param statusMask The status mask (target particular type of status) - * @return true if request made successfully, false otherwise - */ - virtual bool requestSetGroupStatus(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t status, - const uint32_t statusMask) = 0; - - /*! - * Use request status to find out if successfully set - * @param groupId - * @param subscribeFlags - * @param subscribeMask - * @return true if request made successfully, false otherwise - */ - virtual bool requestSetGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) = 0; + virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector& msgIds) = 0; - // (FUTURE WORK). - //virtual bool groupRestoreKeys(const std::string &groupId) = 0; - //virtual bool groupShareKeys(const std::string &groupId, std::list& peers) = 0; - - /* Poll */ + /* Poll */ /*! * Request the status of ongoing request. diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 192baeabf..414b6c0bf 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -1,6 +1,4 @@ TEMPLATE = lib -#CONFIG += staticlib release -#CONFIG += staticlib testnetwork CONFIG += staticlib bitdht CONFIG -= qt TARGET = retroshare @@ -8,8 +6,8 @@ TARGET = retroshare CONFIG += test_voip # GXS Stuff. -#CONFIG += newcache -#CONFIG += newservices +# This should be disabled for releases until further notice. +#CONFIG += gxs # Beware: All data of the stripped services are lost DEFINES *= PQI_DISABLE_TUNNEL @@ -20,39 +18,10 @@ profiling { QMAKE_CXXFLAGS *= -pg -g -fno-omit-frame-pointer } -release { - # UDP and TUNNEL dont work anymore. - #DEFINES *= PQI_DISABLE_UDP -} - # treat warnings as error for better removing #QMAKE_CFLAGS += -Werror #QMAKE_CXXFLAGS += -Werror -testnetwork { - # used in rsserver/rsinit.cc Enabled Port Restrictions, and makes Proxy Port next to Dht Port. - DEFINES *= LOCALNET_TESTING - - # used in tcponudp/udprelay.cc Debugging Info for Relays. - DEFINES *= DEBUG_UDP_RELAY - - # used in tcponudp/udpstunner.[h | cc] enables local stun (careful - modifies class variables). - DEFINES *= UDPSTUN_ALLOW_LOCALNET - - # used in pqi/p3linkmgr.cc prints out extra debug. - DEFINES *= LINKMGR_DEBUG_LINKTYPE - - # used in dht/connectstatebox to reduce connection times and display debug. - # DEFINES *= TESTING_PERIODS - # DEFINES *= DEBUG_CONNECTBOX - - QMAKE_CXXFLAGS -= -fomit-frame-pointer - QMAKE_CXXFLAGS -= -O2 - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer - -} - - #CONFIG += debug debug { # DEFINES *= DEBUG @@ -68,6 +37,7 @@ debug { QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer } + bitdht { HEADERS += dht/p3bitdht.h \ @@ -97,45 +67,16 @@ SOURCES += tcponudp/udppeer.cc \ tcponudp/udpstunner.cc \ tcponudp/udprelay.cc \ -# These two aren't actually used (and don't compile) .... -# but could be useful later -# -# tcponudp/udpstunner.h \ -# tcponudp/udpstunner.cc \ -# - BITDHT_DIR = ../../libbitdht/src INCLUDEPATH += . $${BITDHT_DIR} - # The next line if for compliance with debian packages. Keep it! + # The next line is for compliance with debian packages. Keep it! INCLUDEPATH += ../libbitdht DEFINES *= RS_USE_BITDHT } -test_bitdht { - # DISABLE TCP CONNECTIONS... - DEFINES *= P3CONNMGR_NO_TCP_CONNECTIONS - - # NO AUTO CONNECTIONS??? FOR TESTING DHT STATUS. - DEFINES *= P3CONNMGR_NO_AUTO_CONNECTION - - # ENABLED UDP NOW. -} - - - - -use_blogs { - - HEADERS += services/p3blogs.h - SOURCES += services/p3blogs.cc - - DEFINES *= RS_USE_BLOGS -} - - PUBLIC_HEADERS = retroshare/rsblogs.h \ retroshare/rschannels.h \ @@ -161,14 +102,14 @@ PUBLIC_HEADERS = retroshare/rsblogs.h \ retroshare/rsconfig.h HEADERS += plugins/pluginmanager.h \ - plugins/dlfcn_win32.h \ - serialiser/rspluginitems.h + plugins/dlfcn_win32.h \ + serialiser/rspluginitems.h HEADERS += $$PUBLIC_HEADERS # public headers to be... -HEADERS += retroshare/rsgame.h \ - retroshare/rsphoto.h +HEADERS += retroshare/rsgame.h \ + retroshare/rsphoto.h ################################# Linux ########################################## linux-* { @@ -204,22 +145,23 @@ linux-* { message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) } - #libupnp implementation files - HEADERS += upnp/UPnPBase.h - SOURCES += upnp/UPnPBase.cpp - # where to put the shared library itself target.path = $$LIB_DIR INSTALLS *= target - # where to put the library's interface + # where to put the librarys interface include_rsiface.path = $${INC_DIR} include_rsiface.files = $$PUBLIC_HEADERS INSTALLS += include_rsiface #CONFIG += version_detail_bash_script - # Check if the system's libupnp has been Debian-patched + + # linux/bsd can use either - libupnp is more complete and packaged. + #CONFIG += upnp_miniupnpc + CONFIG += upnp_libupnp + + # Check if the systems libupnp has been Debian-patched system(grep -E 'char[[:space:]]+PublisherUrl' $${UPNP_DIR}/upnp.h >/dev/null 2>&1) { # Normal libupnp } else { @@ -258,9 +200,7 @@ win32-x-g++ { QMAKE_AR = i586-mingw32msvc-ar DEFINES *= STATICLIB WIN32 - #miniupnp implementation files - HEADERS += upnp/upnputil.h - SOURCES += upnp/upnputil.c + CONFIG += upnp_miniupnpc SSL_DIR=../../../../openssl UPNPC_DIR = ../../../../miniupnpc-1.3 @@ -296,9 +236,7 @@ win32 { DEFINES += USE_CMD_ARGS - #miniupnp implementation files - HEADERS += upnp/upnputil.h - SOURCES += upnp/upnputil.c + CONFIG += upnp_miniupnpc UPNPC_DIR = ../../../miniupnpc-1.3 @@ -308,6 +246,13 @@ win32 { OPENPGPSDK_DIR = ../../openpgpsdk/src INCLUDEPATH += . $${SSL_DIR}/include $${UPNPC_DIR} $${PTHREADS_DIR} $${ZLIB_DIR} $${OPENPGPSDK_DIR} + + # SQLite include path is required to compile GXS. + gxs { + SQLITE_DIR = ../../../../Libraries/sqlite/sqlite-autoconf-3070900 + INCLUDEPATH += $${SQLITE_DIR} + } + } @@ -321,9 +266,7 @@ mac { #DEFINES *= MINIUPNPC_VERSION=13 DESTDIR = lib - #miniupnp implementation files - HEADERS += upnp/upnputil.h - SOURCES += upnp/upnputil.c + CONFIG += upnp_miniupnpc # zeroconf disabled at the end of libretroshare.pro (but need the code) CONFIG += zeroconf @@ -353,9 +296,10 @@ freebsd-* { QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen - #libupnp implementation files - HEADERS += upnp/UPnPBase.h - SOURCES += upnp/UPnPBase.cpp + # linux/bsd can use either - libupnp is more complete and packaged. + #CONFIG += upnp_miniupnpc + CONFIG += upnp_libupnp + DESTDIR = lib } @@ -482,7 +426,6 @@ HEADERS += turtle/p3turtle.h \ turtle/rsturtleitem.h \ turtle/turtletypes.h -HEADERS += upnp/upnphandler.h HEADERS += util/folderiterator.h \ util/rsdebug.h \ @@ -500,6 +443,8 @@ HEADERS += util/folderiterator.h \ util/rsrandom.h \ util/radix64.h \ util/pugiconfig.h \ + util/rsmemcache.h \ + util/rstickevent.h \ SOURCES += dbase/cachestrapper.cc \ dbase/fimonitor.cc \ @@ -624,7 +569,6 @@ SOURCES += turtle/p3turtle.cc \ # turtle/turtlesearch.cc \ # turtle/turtletunnels.cc -SOURCES += upnp/upnphandler.cc SOURCES += util/folderiterator.cc \ util/rsdebug.cc \ @@ -640,6 +584,21 @@ SOURCES += util/folderiterator.cc \ util/rsversion.cc \ util/rswin.cc \ util/rsrandom.cc \ + util/rstickevent.cc \ + + +upnp_miniupnpc { + HEADERS += upnp/upnputil.h upnp/upnphandler_miniupnp.h + SOURCES += upnp/upnputil.c upnp/upnphandler_miniupnp.cc +} + +upnp_libupnp { + HEADERS += upnp/UPnPBase.h upnp/upnphandler_linux.h + SOURCES += upnp/UPnPBase.cpp upnp/upnphandler_linux.cc + DEFINES *= RS_USE_LIBUPNP +} + + zeroconf { @@ -666,67 +625,151 @@ SOURCES += zeroconf/p3zcnatassist.cc \ } - # new gxs cache system -newcache { +# new gxs cache system +# this should be disabled for releases until further notice. +gxs { + DEFINES *= RS_ENABLE_GXS -HEADERS += serialiser/rsnxsitems.h \ - gxs/rsgds.h \ - gxs/rsgxs.h \ - gxs/rsdataservice.h \ - gxs/rsgxsnetservice.h \ - gxs/rsgxsflags.h \ - gxs/rsgenexchange.h \ - gxs/rsnxsobserver.h \ - gxs/rsgxsdata.h \ - gxs/rstokenservice.h \ - gxs/rsgxsdataaccess.h \ - retroshare/rsgxsservice.h \ - serialiser/rsgxsitems.h \ - util/retrodb.h - -SOURCES += serialiser/rsnxsitems.cc \ - gxs/rsdataservice.cc \ - gxs/rsgenexchange.cc \ - gxs/rsgxsnetservice.cc \ - gxs/rsgxsdata.cc \ - services/p3photoserviceV2.cc \ - gxs/rsgxsdataaccess.cc \ - util/retrodb.cc -} + HEADERS += serialiser/rsnxsitems.h \ + gxs/rsgds.h \ + gxs/rsgxs.h \ + gxs/rsdataservice.h \ + gxs/rsgxsnetservice.h \ + gxs/rsgxsflags.h \ + gxs/rsgenexchange.h \ + gxs/rsnxsobserver.h \ + gxs/rsgxsdata.h \ + gxs/rstokenservice.h \ + gxs/rsgxsdataaccess.h \ + retroshare/rsgxsservice.h \ + serialiser/rsgxsitems.h \ + util/retrodb.h \ + util/contentvalue.h \ + gxs/gxscoreserver.h \ + gxs/gxssecurity.h \ + gxs/rsgxsifaceimpl.h \ + gxs/gxstokenqueue.h \ + SOURCES += serialiser/rsnxsitems.cc \ + gxs/rsdataservice.cc \ + gxs/rsgenexchange.cc \ + gxs/rsgxsnetservice.cc \ + gxs/rsgxsdata.cc \ + serialiser/rsgxsitems.cc \ + gxs/rsgxsdataaccess.cc \ + util/retrodb.cc \ + util/contentvalue.cc \ + gxs/gxscoreserver.cc \ + gxs/gxssecurity.cc \ + gxs/rsgxsifaceimpl.cc \ + gxs/gxstokenqueue.cc \ -newservices { - -HEADERS += services/p3photoservice.h \ - serialiser/rsphotoitems.h \ - retroshare/rsphoto.h \ - services/p3gxsservice.h \ - retroshare/rsidentity.h \ - services/p3wikiservice.h \ - retroshare/rswiki.h \ - retroshare/rswire.h \ - services/p3wire.h \ + # Identity Service + HEADERS += retroshare/rsidentity.h \ + gxs/rsgixs.h \ services/p3idservice.h \ - retroshare/rsforumsv2.h \ - services/p3forumsv2.h \ + serialiser/rsgxsiditems.h + + SOURCES += services/p3idservice.cc \ + serialiser/rsgxsiditems.cc \ + + # GxsCircles Service + HEADERS += services/p3gxscircles.h \ + serialiser/rsgxscircleitems.h \ + retroshare/rsgxscircles.h \ + + SOURCES += services/p3gxscircles.cc \ + serialiser/rsgxscircleitems.cc \ + + # GxsForums Service + HEADERS += retroshare/rsgxsforums.h \ + services/p3gxsforums.h \ + serialiser/rsgxsforumitems.h + + SOURCES += services/p3gxsforums.cc \ + serialiser/rsgxsforumitems.cc \ + + # Wiki Service + HEADERS += retroshare/rswiki.h \ + services/p3wiki.h \ + serialiser/rswikiitems.h + + SOURCES += services/p3wiki.cc \ + serialiser/rswikiitems.cc \ + + # Wiki Service + HEADERS += retroshare/rswire.h \ + services/p3wire.h \ + serialiser/rswireitems.h + + SOURCES += services/p3wire.cc \ + serialiser/rswireitems.cc \ + + # Posted Service + HEADERS += services/p3posted.h \ retroshare/rsposted.h \ - services/p3posted.h \ - services/p3photoserviceV2.h \ - retroshare/rsphotoV2.h \ - + serialiser/rsposteditems.h -SOURCES += services/p3photoservice.cc \ + SOURCES += services/p3posted.cc \ + serialiser/rsposteditems.cc + + #Photo Service + HEADERS += services/p3photoservice.h \ + retroshare/rsphoto.h \ + serialiser/rsphotoitems.h \ + + SOURCES += services/p3photoservice.cc \ serialiser/rsphotoitems.cc \ - services/p3gxsservice.cc \ - services/p3wikiservice.cc \ - services/p3wire.cc \ - services/p3idservice.cc \ - services/p3forumsv2.cc \ - services/p3posted.cc \ - -# Other Old Code. -# rsserver/p3photo.cc \ } + + + + +########################################################################################################### +# OLD CONFIG OPTIONS. +# Not used much - but might be useful one day. +# + +testnetwork { + # used in rsserver/rsinit.cc Enabled Port Restrictions, and makes Proxy Port next to Dht Port. + DEFINES *= LOCALNET_TESTING + + # used in tcponudp/udprelay.cc Debugging Info for Relays. + DEFINES *= DEBUG_UDP_RELAY + + # used in tcponudp/udpstunner.[h | cc] enables local stun (careful - modifies class variables). + DEFINES *= UDPSTUN_ALLOW_LOCALNET + + # used in pqi/p3linkmgr.cc prints out extra debug. + DEFINES *= LINKMGR_DEBUG_LINKTYPE + + # used in dht/connectstatebox to reduce connection times and display debug. + # DEFINES *= TESTING_PERIODS + # DEFINES *= DEBUG_CONNECTBOX +} + + +test_bitdht { + # DISABLE TCP CONNECTIONS... + DEFINES *= P3CONNMGR_NO_TCP_CONNECTIONS + + # NO AUTO CONNECTIONS??? FOR TESTING DHT STATUS. + DEFINES *= P3CONNMGR_NO_AUTO_CONNECTION + + # ENABLED UDP NOW. +} + + + + +use_blogs { + + HEADERS += services/p3blogs.h + SOURCES += services/p3blogs.cc + + DEFINES *= RS_USE_BLOGS +} + diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc index 32f7a0888..eb87ca733 100644 --- a/libretroshare/src/pgp/pgphandler.cc +++ b/libretroshare/src/pgp/pgphandler.cc @@ -8,6 +8,7 @@ #ifdef WINDOWS_SYS #include "util/rsstring.h" +#include "util/rswin.h" #endif extern "C" { diff --git a/libretroshare/src/plugins/pluginmanager.cc b/libretroshare/src/plugins/pluginmanager.cc index 363e8f302..0bb798ea2 100644 --- a/libretroshare/src/plugins/pluginmanager.cc +++ b/libretroshare/src/plugins/pluginmanager.cc @@ -168,6 +168,21 @@ void RsPluginManager::loadPlugins(const std::vector& plugin_directo saveConfiguration(); } +void RsPluginManager::stopPlugins() +{ + std::cerr << " Stopping plugins." << std::endl; + + for (uint32_t i = 0; i < _plugins.size(); ++i) + { + if (_plugins[i].plugin != NULL) + { + _plugins[i].plugin->stop(); +// delete _plugins[i].plugin; +// _plugins[i].plugin = NULL; + } + } +} + void RsPluginManager::getPluginStatus(int i,uint32_t& status,std::string& file_name,std::string& hash,uint32_t& svn_revision,std::string& error_string) const { if((uint32_t)i >= _plugins.size()) diff --git a/libretroshare/src/plugins/pluginmanager.h b/libretroshare/src/plugins/pluginmanager.h index aeea3c814..48aa3d932 100644 --- a/libretroshare/src/plugins/pluginmanager.h +++ b/libretroshare/src/plugins/pluginmanager.h @@ -93,6 +93,8 @@ class RsPluginManager: public RsPluginHandler, public p3Config // void loadPlugins(const std::vector& explicit_plugin_entries) ; + void stopPlugins(); + void registerCacheServices() ; void registerClientServices(p3ServiceServer *pqih) ; diff --git a/libretroshare/src/pqi/authgpg.h b/libretroshare/src/pqi/authgpg.h index e4576cb4b..6b32a8991 100644 --- a/libretroshare/src/pqi/authgpg.h +++ b/libretroshare/src/pqi/authgpg.h @@ -39,7 +39,6 @@ #ifndef RS_GPG_AUTH_HEADER #define RS_GPG_AUTH_HEADER -#include "util/rswin.h" #include #include #include "util/rsthreads.h" diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc index b083d9ba6..bd8fd9a25 100644 --- a/libretroshare/src/pqi/authssl.cc +++ b/libretroshare/src/pqi/authssl.cc @@ -28,6 +28,10 @@ * */ +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif // WINDOWS_SYS + #include "authssl.h" #include "sslfns.h" diff --git a/libretroshare/src/pqi/authssl.h b/libretroshare/src/pqi/authssl.h index bc3e0919f..ec4340798 100644 --- a/libretroshare/src/pqi/authssl.h +++ b/libretroshare/src/pqi/authssl.h @@ -39,8 +39,6 @@ * */ -#include "util/rswin.h" - #include #include diff --git a/libretroshare/src/pqi/pqiassist.h b/libretroshare/src/pqi/pqiassist.h index 06cb5d434..3bf984f8d 100644 --- a/libretroshare/src/pqi/pqiassist.h +++ b/libretroshare/src/pqi/pqiassist.h @@ -64,6 +64,20 @@ virtual int tick() { return 0; } /* for internal accounting */ }; + +#define PFP_TYPE_UDP 0x0001 +#define PFP_TYPE_TCP 0x0002 + +class PortForwardParams +{ + public: + uint32_t fwdId; + uint32_t status; + uint32_t typeFlags; + struct sockaddr_in intAddr; + struct sockaddr_in extaddr; +}; + class pqiNetAssistFirewall: public pqiNetAssist { public: @@ -78,6 +92,12 @@ virtual void setExternalPort(unsigned short eport_in) = 0; virtual bool getInternalAddress(struct sockaddr_in &addr) = 0; virtual bool getExternalAddress(struct sockaddr_in &addr) = 0; + + /* New Port Forward interface to support as many ports as necessary */ +virtual bool requestPortForward(const PortForwardParams ¶ms) = 0; +virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams ¶ms) = 0; + + }; diff --git a/libretroshare/src/pqi/pqihash.h b/libretroshare/src/pqi/pqihash.h index bf87f9d2f..7e08868ff 100644 --- a/libretroshare/src/pqi/pqihash.h +++ b/libretroshare/src/pqi/pqihash.h @@ -23,10 +23,14 @@ * */ +#ifndef PQI_HASH_ +#define PQI_HASH_ + #include #include #include #include "util/rsstring.h" +#include class pqihash { @@ -85,4 +89,4 @@ void Complete(std::string &hash) SHA_CTX *sha_ctx; }; - +#endif diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index 080b6fd35..3a59a2351 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -23,8 +23,10 @@ * */ - - +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#include +#endif // WINDOWS_SYS #include "pqi/pqinetwork.h" #include "util/rsnet.h" diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index 52cb4f6d5..10bdcdb7e 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -45,12 +45,10 @@ #else -#include "util/rswin.h" #include "util/rsnet.h" /* more generic networking header */ #include -#include typedef int socklen_t; //typedef unsigned long in_addr_t; diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h index b32eec8c9..988ae1e0d 100644 --- a/libretroshare/src/pqi/pqissl.h +++ b/libretroshare/src/pqi/pqissl.h @@ -28,8 +28,6 @@ #ifndef MRK_PQI_SSL_HEADER #define MRK_PQI_SSL_HEADER -#include "util/rswin.h" - #include // operating system specific network header. diff --git a/libretroshare/src/pqi/pqissludp.h b/libretroshare/src/pqi/pqissludp.h index f5044fbd4..f07632dd4 100644 --- a/libretroshare/src/pqi/pqissludp.h +++ b/libretroshare/src/pqi/pqissludp.h @@ -28,8 +28,6 @@ #ifndef MRK_PQI_SSL_UDP_HEADER #define MRK_PQI_SSL_UDP_HEADER -#include "util/rswin.h" - #include // operating system specific network header. diff --git a/libretroshare/src/pqi/sslfns.h b/libretroshare/src/pqi/sslfns.h index f4c693f7e..98e3b2c0e 100644 --- a/libretroshare/src/pqi/sslfns.h +++ b/libretroshare/src/pqi/sslfns.h @@ -33,8 +33,6 @@ /******************** notify of new Cert **************************/ -#include "util/rswin.h" - #include #include #include diff --git a/libretroshare/src/retroshare/rsforumsv2.h b/libretroshare/src/retroshare/rsforumsv2.h deleted file mode 100644 index 7a6da888d..000000000 --- a/libretroshare/src/retroshare/rsforumsv2.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef RETROSHARE_FORUMV2_GUI_INTERFACE_H -#define RETROSHARE_FORUMV2_GUI_INTERFACE_H - -/* - * libretroshare/src/retroshare: rsforumv2.h - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include - -#include - -/* The Main Interface Class - for information about your Peers */ -class RsForumsV2; -extern RsForumsV2 *rsForumsV2; - -class RsForumV2Group -{ - public: - - // All the MetaData is Stored here: - RsGroupMetaData mMeta; - - // THESE ARE IN THE META DATA. - //std::string mGroupId; - //std::string mName; - - std::string mDescription; - - // THESE ARE CURRENTLY UNUSED. - //std::string mCategory; - //std::string mHashTags; -}; - -class RsForumV2Msg -{ - public: - - // All the MetaData is Stored here: - RsMsgMetaData mMeta; - - // THESE ARE IN THE META DATA. - //std::string mGroupId; - //std::string mMsgId; - //std::string mOrigMsgId; - //std::string mThreadId; - //std::string mParentId; - //std::string mName; (aka. Title) - - std::string mMsg; // all the text is stored here. - - // THESE ARE CURRENTLY UNUSED. - //std::string mHashTags; -}; - -class RsForumsV2: public RsTokenService -{ - public: - - RsForumsV2() { return; } -virtual ~RsForumsV2() { return; } - - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsForumV2Group &group) = 0; -virtual bool getMsgData(const uint32_t &token, RsForumV2Msg &msg) = 0; - - - // ONES THAT WE ARE NOT IMPLEMENTING. (YET!) -//virtual bool getMessageStatus(const std::string& fId, const std::string& mId, uint32_t& status) = 0; - -// THINK WE CAN GENERALISE THIS TO: a list function, and you can just count the list entries... -// requestGroupList(groupId, UNREAD, ...) -//virtual bool getMessageCount(const std::string &groupId, unsigned int &newCount, unsigned int &unreadCount) = 0; - - -/* details are updated in group - to choose GroupID */ -virtual bool createGroup(uint32_t &token, RsForumV2Group &group, bool isNew) = 0; -virtual bool createMsg(uint32_t &token, RsForumV2Msg &msg, bool isNew) = 0; - -}; - - - -#endif diff --git a/libretroshare/src/retroshare/rsgxscircles.h b/libretroshare/src/retroshare/rsgxscircles.h new file mode 100644 index 000000000..8a1134040 --- /dev/null +++ b/libretroshare/src/retroshare/rsgxscircles.h @@ -0,0 +1,127 @@ +#ifndef RETROSHARE_GXSCIRCLES_INTERFACE_H +#define RETROSHARE_GXSCIRCLES_INTERFACE_H + +/* + * libretroshare/src/retroshare: rsgxscircles.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +#include "gxs/rstokenservice.h" +#include "gxs/rsgxsifaceimpl.h" + +#include "retroshare/rsidentity.h" + + +/* The Main Interface Class - for information about your Peers */ +class RsGxsCircles; +extern RsGxsCircles *rsGxsCircles; + + +typedef std::string RsGxsCircleId; +typedef std::string RsPeerId; // SSL ID. +typedef std::string RsPgpId; +typedef std::string RsCircleInternalId; + +#define GXS_CIRCLE_TYPE_PUBLIC 0x0001 +#define GXS_CIRCLE_TYPE_EXTERNAL 0x0002 +#define GXS_CIRCLE_TYPE_YOUREYESONLY 0x0003 + +/* Permissions is part of GroupMetaData + */ + +class GxsPermissions +{ +public: + uint32_t mCircleType; // PUBLIC, EXTERNAL or YOUREYESONLY. + RsGxsCircleId mCircleId; // If EXTERNAL, otherwise Blank. + + // BELOW IS NOT SERIALISED - BUT MUST BE STORED LOCALLY BY GXS. (If YOUREYESONLY) + RsPeerId mOriginator; + RsCircleInternalId mInternalCircle; // if Originator == ownId, otherwise blank. +}; + + +class RsGxsCircleGroup +{ + public: + RsGroupMetaData mMeta; // includes GxsPermissions, for control of group distribution. + + std::list mInvitedMembers; + std::list mSubCircles; + + // Not Serialised. + // Internally inside rsCircles, this will be turned into: + // std::list mAllowedFriends; +}; + +class RsGxsCircleMsg +{ + public: + RsMsgMetaData mMeta; + + // Signature by user signifying that they want to be part of the group. + // maybe Phase 3. + std::string stuff; +}; + +class RsGxsCircleDetails +{ + public: + RsGxsCircleId mCircleId; + std::string mCircleName; + std::set mUnknownPeers; + std::map > mAllowedPeers; +}; + + + + +class RsGxsCircles: public RsGxsIfaceImpl +{ + public: + + RsGxsCircles(RsGenExchange *gxs) + :RsGxsIfaceImpl(gxs) { return; } +virtual ~RsGxsCircles() { return; } + + + /* External Interface (Cached stuff) */ +virtual bool getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &details) = 0; +virtual bool getCircleIdList(std::list &circleIds) = 0; + + /* standard load */ +virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; + + /* make new group */ +virtual bool createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0; + + +}; + + + +#endif diff --git a/libretroshare/src/retroshare/rsgxsforums.h b/libretroshare/src/retroshare/rsgxsforums.h new file mode 100644 index 000000000..cf51dce06 --- /dev/null +++ b/libretroshare/src/retroshare/rsgxsforums.h @@ -0,0 +1,97 @@ +#ifndef RETROSHARE_GXS_FORUM_GUI_INTERFACE_H +#define RETROSHARE_GXS_FORUM_GUI_INTERFACE_H + +/* + * libretroshare/src/retroshare: rsgxsforum.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +#include "gxs/rstokenservice.h" +#include "gxs/rsgxsifaceimpl.h" + + +#define IS_MSG_NEW(status) (status & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) +#define IS_MSG_UNREAD(status) (status & GXS_SERV::GXS_MSG_STATUS_UNREAD) +#define IS_GROUP_ADMIN(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) +#define IS_GROUP_SUBSCRIBED(subscribeFlags) (subscribeFlags & (GXS_SERV::GROUP_SUBSCRIBE_ADMIN | GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)) + + + +/* The Main Interface Class - for information about your Peers */ +class RsGxsForums; +extern RsGxsForums *rsGxsForums; + +class RsGxsForumGroup +{ + public: + RsGroupMetaData mMeta; + std::string mDescription; +}; + +class RsGxsForumMsg +{ + public: + RsMsgMetaData mMeta; + std::string mMsg; +}; + + +//typedef std::map > GxsForumMsgResult; + +std::ostream &operator<<(std::ostream &out, const RsGxsForumGroup &group); +std::ostream &operator<<(std::ostream &out, const RsGxsForumMsg &msg); + +class RsGxsForums: public RsGxsIfaceImpl +{ + public: + + RsGxsForums(RsGenExchange *gxs) + :RsGxsIfaceImpl(gxs) { return; } +virtual ~RsGxsForums() { return; } + + /* Specific Service Data */ +virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; +virtual bool getMsgData(const uint32_t &token, std::vector &msgs) = 0; +virtual bool getRelatedMessages(const uint32_t &token, std::vector &msgs) = 0; + + ////////////////////////////////////////////////////////////////////////////// +virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; + +//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); +//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); + +//virtual bool groupRestoreKeys(const std::string &groupId); +//virtual bool groupShareKeys(const std::string &groupId, std::list& peers); + +virtual bool createGroup(uint32_t &token, RsGxsForumGroup &group) = 0; +virtual bool createMsg(uint32_t &token, RsGxsForumMsg &msg) = 0; + +}; + + + +#endif diff --git a/libretroshare/src/retroshare/rsgxsservice.h b/libretroshare/src/retroshare/rsgxsservice.h index 96ba495af..d9df811c1 100644 --- a/libretroshare/src/retroshare/rsgxsservice.h +++ b/libretroshare/src/retroshare/rsgxsservice.h @@ -17,6 +17,7 @@ class RsGxsNotify { public: RsGxsNotify(){ return; } + virtual ~RsGxsNotify() {return; } }; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 1e0164e70..b5eee52d9 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -10,7 +10,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. + * License Version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -30,332 +30,19 @@ #include #include -// FLAGS WILL BE REUSED FROM RSDISTRIB -> FOR NOW. -#include - -/********** Generic Token Request Interface *********************** - * This is packaged here, as most TokenServices will require ID Services too. - * The requests can be generic, but the reponses are service specific (dependent on data types). - */ - -// This bit will be filled out over time. -#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId. -#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group. -#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs. - -#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group. -#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs. - -#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId - - -// Status Filtering... should it be a different Option Field. -#define RS_TOKREQOPT_GROUP_UPDATED 0x0100 // GROUPLIST: Groups that have been updated. -#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups. -#define RS_TOKREQOPT_MSG_UPDATED 0x0200 // MSGLIST: Msg that have been updated from specified groups. - - - -// Read Status. -#define RS_TOKREQOPT_READ 0x0001 -#define RS_TOKREQOPT_UNREAD 0x0002 - -#define RS_TOKREQ_ANSTYPE_LIST 0x0001 -#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002 -#define RS_TOKREQ_ANSTYPE_DATA 0x0003 - - - - -class RsTokReqOptions -{ - public: - RsTokReqOptions() - { - mOptions = 0; - mStatusFilter = 0; mStatusMask = 0; mSubscribeFilter = 0; - mBefore = 0; mAfter = 0; - } - - uint32_t mOptions; - - // Request specific matches with Group / Message Status. - // Should be usable with any Options... applied afterwards. - uint32_t mStatusFilter; - uint32_t mStatusMask; - - uint32_t mSubscribeFilter; // Only for Groups. - - // Time range... again applied after Options. - time_t mBefore; - time_t mAfter; -}; - - -/********************************************************* - * Documentation for Groups Definitions. - * - * A Group is defined by: - * - TWO RSA Keys. (Admin Key & Publish Key) - * - Publish TS: Used to select the latest definition. - * - * - Operating Mode: - * - Circle (Public, External, Private). - * - Publish Mode: Encrypted / All-Signed / Only ThreadHead / None Required. - * - AuthorId: GPG Required / Any Required / Only if no Publish Signature. - * - * - Description: - * - Name & Description. - * - Optional AuthorId. - * - * Most of this information is contained inside the GroupMetaData. - * except for Actual Admin / Publish Keys, which are maintained internally. - * - ******* - * - Group Definition must be signed by Admin Key, otherwise invalid. - * - Circle Definition controls distribution of Group and Messages, see section on this for more details. - * - Public parts of Keys are distributed with Definition. - * - Private parts can be distributed to select people via alternative channels. - * - A Message Requires at least one signature: publish or Author. This signature will be used as MsgId. - * - * Groups will operate in the following modes: - * 1) Public Forum: PublishMode = None Required, AuthorId: Required. - * 2) Closed Forum: PublishMode = All-Signed, AuthorId: Required. - * 3) Private Forum: PublishMode = Encrypted, AuthorId: Required. - * - * 4) Anon Channel: PublishMode = All-Signed, AuthorId: None. - * 5) Anon Channel with Comments: PublishMode = Only ThreadHead, AuthorId: If No Publish Signature. - * 6) Private Channel: PublishMode = Encrypted. - * - * 7) Personal Photos - with comments: PublishMode = Only ThreadHead, AuthorId: Required. - * 8) Personal Photos - no comments: PublishMode = All-Signed, AuthorId: Required. - * - * 9 ) Public Wiki: PublishMode = None Required, AuthorId: Required. - * 10) Closed Wiki: PublishMode = All-Signed, AuthorId: Required. - * 11) Private Wiki: PublishMode = Encrypted, AuthorId: Required. - * - * 12) Twitter: PublishMode = Only ThreadHead, AuthorId: Required. - * - * 13) Posted: PublishMode = None Required, AuthorId: Required. - * - * - ****** - * - * Additionally to this information. The MetaData also contains several fields which can - * be used to store local information for the benefit of the service. - * - * In Particular: MsgStatus & GroupStatus inform the service if the user has read the message or if anything has changed. - * - ***/ - - -// Control of Publish Signatures. -#define RSGXS_GROUP_SIGN_PUBLISH_MASK 0x000000ff -#define RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED 0x00000001 -#define RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED 0x00000002 -#define RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD 0x00000004 -#define RSGXS_GROUP_SIGN_PUBLISH_NONEREQ 0x00000008 - -// Author Signature. -#define RSGXS_GROUP_SIGN_AUTHOR_MASK 0x0000ff00 -#define RSGXS_GROUP_SIGN_AUTHOR_GPG 0x00000100 -#define RSGXS_GROUP_SIGN_AUTHOR_REQUIRED 0x00000200 -#define RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN 0x00000400 -#define RSGXS_GROUP_SIGN_AUTHOR_NONE 0x00000800 - -// NB: That one signature is required... -// so some combinations are not possible. e.g. -// SIGN_PUBLISH_NONEREQ && SIGN_AUTHOR_NONE is not allowed. -// SIGN_PUBLISH_THREADHEAD && SIGN_AUTHOR_NONE is also invalid. - -#define RSGXS_GROUP_SIGN_RESERVED_MASK 0xffff0000 - - -// STATUS FLAGS: There is space here for Service specific flags - if they so desire. -// -// Msgs: UNREAD_BY_USER & PROCESSED are useful. -// Groups: NEW_MESSAGES & GROUP_UPDATED. - -#define RSGXS_MSG_STATUS_MASK 0x0000000f -#define RSGXS_MSG_STATUS_READ 0x00000001 // New or Not New -#define RSGXS_MSG_STATUS_UNREAD_BY_USER 0x00000002 -#define RSGXS_MSG_STATUS_UNPROCESSED 0x00000004 // By the Service. - -#define RSGXS_MSG_STATUS_SERVICE_MASK 0xffff0000 - -#define RSGXS_GROUP_STATUS_MASK 0x0000000f -#define RSGXS_GROUP_STATUS_UPDATED 0x00000001 -#define RSGXS_GROUP_STATUS_NEWGROUP 0x00000002 -#define RSGXS_GROUP_STATUS_NEWMSG 0x00000004 - -#define RSGXS_GROUP_STATUS_SERVICE_MASK 0xffff0000 - - - -// Subscription Flags. (LOCAL) -#define RSGXS_GROUP_SUBSCRIBE_MASK 0x0000000f -#define RSGXS_GROUP_SUBSCRIBE_ADMIN 0x00000001 -#define RSGXS_GROUP_SUBSCRIBE_PUBLISH 0x00000002 -#define RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED 0x00000004 -#define RSGXS_GROUP_SUBSCRIBE_MONITOR 0x00000008 - - -// Some MACROS for EASE OF USE. (USED BY FORUMSV2 At the moment. -#define IS_MSG_UNREAD(status) ((status & RSGXS_MSG_STATUS_READ) == 0 || (status & RSGXS_MSG_STATUS_UNREAD_BY_USER)) -#define IS_GROUP_ADMIN(subscribeFlags) (subscribeFlags & RSGXS_GROUP_SUBSCRIBE_ADMIN) -#define IS_GROUP_SUBSCRIBED(subscribeFlags) (subscribeFlags & (RSGXS_GROUP_SUBSCRIBE_ADMIN | RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED)) - - - -#define RSGXS_MAX_SERVICE_STRING 200 // Sensible limit for dbase usage. - - -class RsGroupMetaData -{ - public: - - RsGroupMetaData() - { - mGroupFlags = 0; - mSignFlags = 0; - mSubscribeFlags = 0; - - mPop = 0; - mMsgCount = 0; - mLastPost = 0; - mGroupStatus = 0; - - //mPublishTs = 0; - } - - std::string mGroupId; - std::string mGroupName; - uint32_t mGroupFlags; // Service Specific Options ???? - uint32_t mSignFlags; // Combination of RSGXS_GROUP_SIGN_PUBLISH_MASK & RSGXS_GROUP_SIGN_AUTHOR_MASK. - - time_t mPublishTs; // Mandatory. - std::string mAuthorId; // Optional. - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - - uint32_t mSubscribeFlags; - - uint32_t mPop; // HOW DO WE DO THIS NOW. - uint32_t mMsgCount; // ??? - time_t mLastPost; // ??? - - uint32_t mGroupStatus; - - std::string mServiceString; // Service Specific Free-Form extra storage. -}; - - - - -class RsMsgMetaData -{ - public: - - RsMsgMetaData() - { - mPublishTs = 0; - mMsgFlags = 0; - mMsgStatus = 0; - mChildTs = 0; - } - - std::string mGroupId; - std::string mMsgId; - - std::string mThreadId; - std::string mParentId; - std::string mOrigMsgId; - - std::string mAuthorId; - - std::string mMsgName; - time_t mPublishTs; - - uint32_t mMsgFlags; // Whats this for? (Optional Service Specific - e.g. flag MsgType) - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - // normally READ / UNREAD flags. LOCAL Data. - uint32_t mMsgStatus; - time_t mChildTs; - - std::string mServiceString; // Service Specific Free-Form extra storage. - -}; - -std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta); -std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta); - -class RsTokenService -{ - public: - - RsTokenService() { return; } -virtual ~RsTokenService() { return; } - - /* changed? */ -virtual bool updated() = 0; - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) = 0; -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) = 0; -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) = 0; - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds) = 0; -virtual bool getMsgList( const uint32_t &token, std::list &msgIds) = 0; - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo) = 0; -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo) = 0; - - /* Actual Data -> specific to Interface */ - - - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token) = 0; - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token) = 0; - - - ////////////////////////////////////////////////////////////////////////////// - /* Functions from Forums -> need to be implemented generically */ - // Groups Changed is now part of requestGroupInfo request. -//virtual bool groupsChanged(std::list &groupIds) = 0; - - // Message/Group Status - is retrived via requests... - // These operations could have a token, but for the moment we are going to assume - // they are async and always succeed - (or fail silently). -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) = 0; -virtual bool setGroupStatus(const std::string &grpId, const uint32_t status, const uint32_t statusMask) = 0; - -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) = 0; - -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str) = 0; -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str) = 0; - - // (FUTURE WORK). -virtual bool groupRestoreKeys(const std::string &groupId) = 0; -virtual bool groupShareKeys(const std::string &groupId, std::list& peers) = 0; - - - - -}; - - - +#include "gxs/rstokenservice.h" +#include "gxs/rsgxsifaceimpl.h" /* The Main Interface Class - for information about your Peers */ class RsIdentity; extern RsIdentity *rsIdentity; + +// GroupFlags: Only one so far: +#define RSGXSID_GROUPFLAG_REALID 0x0001 + + +// THESE ARE FLAGS FOR INTERFACE. #define RSID_TYPE_MASK 0xff00 #define RSID_RELATION_MASK 0x00ff @@ -370,9 +57,10 @@ extern RsIdentity *rsIdentity; std::string rsIdTypeToString(uint32_t idtype); -class RsIdGroup +class RsGxsIdGroup { public: + RsGxsIdGroup():mPgpKnown(false) { return; } RsGroupMetaData mMeta; @@ -380,22 +68,28 @@ class RsIdGroup // In GroupMetaData. //std::string mNickname; (mGroupName) //std::string mKeyId; (mGroupId) + //uint32_t mIdType; (mGroupFlags) - uint32_t mIdType; + // SHA(KeyId + Gpg Fingerprint) -> can only be IDed if GPG known. + // The length of the input must be long enough to make brute force search implausible. - std::string mGpgIdHash; // SHA(KeyId + Gpg Fingerprint) -> can only be IDed if GPG known. + // Easy to do 1e9 SHA-1 hash computations per second on a GPU. + // We will need a minimum of 256 bits, ideally 1024 bits or 2048 bits. - // NOTE: These cannot be transmitted as part of underlying messages.... - // Must use ServiceString. - bool mGpgIdKnown; // if GpgIdHash has been identified. - std::string mGpgId; // if known. - std::string mGpgName; // if known. - std::string mGpgEmail; // if known. + // Actually PgpIdHash is SHA1(.mMeta.mGroupId + PGPHandler->GpgFingerprint(ownId)) + // ??? 160 bits. + + std::string mPgpIdHash; + std::string mPgpIdSign; // Need a signature as proof - otherwise anyone could add others Hashes. + + // Not Serialised - for GUI's benefit. + bool mPgpKnown; + std::string mPgpId; }; -class RsIdMsg +class RsGxsIdOpinion { public: @@ -405,7 +99,11 @@ class RsIdMsg //std::string mKeyId; (mGroupId) //std::string mPeerId; (mAuthorId) ??? - int mOpinion; + uint32_t mOpinion; + + + // NOT SERIALISED YET! + double mReputation; //int mRating; //int mPeersRating; @@ -413,11 +111,18 @@ class RsIdMsg }; +// This will probably be dropped. +class RsGxsIdComment +{ + public: -std::ostream &operator<<(std::ostream &out, const RsIdGroup &meta); -std::ostream &operator<<(std::ostream &out, const RsIdMsg &meta); + RsMsgMetaData mMeta; + std::string mComment; +}; +std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &group); +std::ostream &operator<<(std::ostream &out, const RsGxsIdOpinion &msg); #if 0 class RsIdReputation @@ -448,80 +153,84 @@ class RsIdOpinion #endif -class RsIdentity: public RsTokenService +// DATA TYPE FOR EXTERNAL INTERFACE. + +typedef std::string RsGxsId; // TMP. => + +class RsIdentityDetails { public: + RsIdentityDetails() + :mIsOwnId(false), mPgpLinked(false), mPgpKnown(false), + mOpinion(0), mReputation(0) { return; } - RsIdentity() { return; } -virtual ~RsIdentity() { return; } + RsGxsId mId; + // identity details. + std::string mNickname; + bool mIsOwnId; - /* INCLUDES INTERFACE FROM RS TOKEN SERVICE */ - ////////////////////////////////////////////////////////////////////////////// - - - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsIdGroup &group) = 0; -virtual bool getMsgData(const uint32_t &token, RsIdMsg &msg) = 0; - -virtual bool createGroup(uint32_t &token, RsIdGroup &group, bool isNew) = 0; -virtual bool createMsg(uint32_t &token, RsIdMsg &msg, bool isNew) = 0; - - /* In the Identity System - You don't access the Messages Directly. - * as they represent idividuals opinions.... - * This is reflected in the TokenService calls returning false. - * - * Below is the additional interface to look at reputation. - */ - - /* So we will want to cache much of the identity stuff, so that we have quick access to the results. - * The following bits of data will not use the request/response interface, and should be available immediately. - * - * ID => Nickname, knownGPG, reputation. - * - * This will require quite a bit of data... - * 20 Bytes + 50 + 1 + 4 Bytes? (< 100 Bytes). - * x 10,000 IDs. => ~1 MB of cache (Good). - * x 100,000 IDs. => ~10 MB of cache (Good). - * x 1,000,000 IDs. => ~100 MB of cache (Too Big). - * - * We also need to store quick access to your OwnIds. - */ - -//virtual uint32_t getIdDetails(const std::string &id, std::string &nickname, bool &isGpgKnown, -// uint32_t &ownOpinion, float &reputation); -//virtual uint32_t getOwnIds(std::list &ownIds); -//virtual bool setOpinion(const std::string &id, uint32_t opinion); - - -virtual void generateDummyData() = 0; - -#if 0 - - /* Data Requests */ -virtual bool requestIdentityList(uint32_t &token) = 0; -virtual bool requestIdentities(uint32_t &token, const std::list &ids) = 0; -virtual bool requestIdReputations(uint32_t &token, const std::list &ids) = 0; -virtual bool requestIdPeerOpinion(uint32_t &token, const std::string &aboutId, const std::string &peerId) = 0; -//virtual bool requestIdGpgDetails(uint32_t &token, const std::list &ids) = 0; - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token) = 0; - - /* Retrieve Data */ -virtual bool getIdentityList(const uint32_t token, std::list &ids) = 0; -virtual bool getIdentity(const uint32_t token, RsIdData &data) = 0; -virtual bool getIdReputation(const uint32_t token, RsIdReputation &reputation) = 0; -virtual bool getIdPeerOpinion(const uint32_t token, RsIdOpinion &opinion) = 0; - - /* Updates */ -virtual bool updateIdentity(RsIdData &data) = 0; -virtual bool updateOpinion(RsIdOpinion &opinion) = 0; - -#endif + // PGP Stuff. + bool mPgpLinked; + bool mPgpKnown; + std::string mPgpId; + // reputation details. + double mOpinion; + double mReputation; }; +class RsIdOpinion +{ + public: + RsGxsId id; + int rating; +}; + -#endif +class RsIdentityParameters +{ + public: + RsIdentityParameters(): isPgpLinked(false) { return; } + bool isPgpLinked; + std::string nickname; +}; + + +class RsIdentity: public RsGxsIfaceImpl +{ + +public: + + RsIdentity(RsGenExchange *gxs): RsGxsIfaceImpl(gxs) { return; } + virtual ~RsIdentity() { return; } + +/********************************************************************************************/ +/********************************************************************************************/ + + // For Other Services.... + // It should be impossible for them to get a message which we don't have the identity. + // Its a major error if we don't have the identity. + + // We cache all identities, and provide alternative (instantaneous) + // functions to extract info, rather than the standard Token system. + +//virtual bool getNickname(const RsGxsId &id, std::string &nickname) = 0; +virtual bool getIdDetails(const RsGxsId &id, RsIdentityDetails &details) = 0; +virtual bool getOwnIds(std::list &ownIds) = 0; + + // +virtual bool submitOpinion(uint32_t& token, RsIdOpinion &opinion) = 0; +virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) = 0; + + // Specific RsIdentity Functions.... + /* Specific Service Data */ + /* We expose these initially for testing / GUI purposes. + */ + +virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; + +}; + +#endif // RETROSHARE_IDENTITY_GUI_INTERFACE_H diff --git a/libretroshare/src/retroshare/rsphoto.h b/libretroshare/src/retroshare/rsphoto.h index 15f8a4f9c..7d3c1ae09 100644 --- a/libretroshare/src/retroshare/rsphoto.h +++ b/libretroshare/src/retroshare/rsphoto.h @@ -1,179 +1,347 @@ -#ifndef RETROSHARE_PHOTO_GUI_INTERFACE_H -#define RETROSHARE_PHOTO_GUI_INTERFACE_H - -/* - * libretroshare/src/retroshare: rsphoto.h - * - * RetroShare C++ Interface. - * - * Copyright 2008-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsPhoto; -extern RsPhoto *rsPhoto; - -/******************* NEW STUFF FOR NEW CACHE SYSTEM *********/ - -#define RSPHOTO_MODE_NEW 1 -#define RSPHOTO_MODE_OWN 2 -#define RSPHOTO_MODE_REMOTE 3 - -class RsPhotoThumbnail -{ - public: - RsPhotoThumbnail() - :data(NULL), size(0), type("N/A") { return; } - - bool deleteImage(); - bool copyFrom(const RsPhotoThumbnail &nail); - - // Holds Thumbnail image. - uint8_t *data; - int size; - std::string type; -}; - - -/* If these flags are no set - the Photo inherits values from the Album - */ - -#define RSPHOTO_FLAGS_ATTRIB_TITLE 0x0001 -#define RSPHOTO_FLAGS_ATTRIB_CAPTION 0x0002 -#define RSPHOTO_FLAGS_ATTRIB_DESC 0x0004 -#define RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER 0x0008 -#define RSPHOTO_FLAGS_ATTRIB_WHERE 0x0010 -#define RSPHOTO_FLAGS_ATTRIB_WHEN 0x0020 -#define RSPHOTO_FLAGS_ATTRIB_OTHER 0x0040 -#define RSPHOTO_FLAGS_ATTRIB_CATEGORY 0x0080 -#define RSPHOTO_FLAGS_ATTRIB_HASHTAGS 0x0100 -#define RSPHOTO_FLAGS_ATTRIB_ORDER 0x0200 -#define RSPHOTO_FLAGS_ATTRIB_THUMBNAIL 0x0400 -#define RSPHOTO_FLAGS_ATTRIB_MODE 0x0800 -#define RSPHOTO_FLAGS_ATTRIB_AUTHOR 0x1000 // PUSH UP ORDER -#define RSPHOTO_FLAGS_ATTRIB_PHOTO 0x2000 // PUSH UP ORDER. - - -class RsPhotoPhoto -{ - public: - - RsMsgMetaData mMeta; - - RsPhotoPhoto(); - - // THESE ARE IN THE META DATA. - //std::string mAlbumId; - //std::string mId; - //std::string mTitle; // only used by Album. - std::string mCaption; - std::string mDescription; - std::string mPhotographer; - std::string mWhere; - std::string mWhen; - std::string mOther; - std::string mCategory; - - std::string mHashTags; - - uint32_t mSetFlags; - - int mOrder; - - RsPhotoThumbnail mThumbnail; - - int mMode; - - // These are not saved. - std::string path; // if in Mode NEW. - uint32_t mModFlags; -}; - -class RsPhotoAlbumShare -{ - public: - - uint32_t mShareType; - std::string mShareGroupId; - std::string mPublishKey; - uint32_t mCommentMode; - uint32_t mResizeMode; -}; - -class RsPhotoAlbum -{ - public: - RsPhotoAlbum(); - - RsGroupMetaData mMeta; - - // THESE ARE IN THE META DATA. - //std::string mAlbumId; - //std::string mTitle; // only used by Album. - - std::string mCaption; - std::string mDescription; - std::string mPhotographer; - std::string mWhere; - std::string mWhen; - std::string mOther; - std::string mCategory; - - std::string mHashTags; - - RsPhotoThumbnail mThumbnail; - - int mMode; - - std::string mPhotoPath; - RsPhotoAlbumShare mShareOptions; - - // These aren't saved. - uint32_t mSetFlags; - uint32_t mModFlags; -}; - -std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo); -std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album); - - -class RsPhoto: public RsTokenService -{ - public: - - RsPhoto() { return; } -virtual ~RsPhoto() { return; } - - /* Specific Service Data */ -virtual bool getAlbum(const uint32_t &token, RsPhotoAlbum &album) = 0; -virtual bool getPhoto(const uint32_t &token, RsPhotoPhoto &photo) = 0; - -virtual bool submitAlbumDetails(uint32_t &token, RsPhotoAlbum &album, bool isNew) = 0; -virtual bool submitPhoto(uint32_t &token, RsPhotoPhoto &photo, bool isNew) = 0; - -}; - - -#endif +#ifndef RSPHOTOV2_H +#define RSPHOTOV2_H + +/* + * libretroshare/src/retroshare: rsphoto.h + * + * RetroShare C++ Interface. + * + * Copyright 2008-2012 by Robert Fernie, Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include "rsgxsservice.h" + +/* The Main Interface Class - for information about your Peers */ +class RsPhoto; +extern RsPhoto *rsPhoto; + +/******************* NEW STUFF FOR NEW CACHE SYSTEM *********/ + +#define RSPHOTO_MODE_NEW 1 +#define RSPHOTO_MODE_OWN 2 +#define RSPHOTO_MODE_REMOTE 3 + +class RsPhotoThumbnail +{ + public: + RsPhotoThumbnail() + :data(NULL), size(0), type("N/A") { return; } + + bool deleteImage(); + bool copyFrom(const RsPhotoThumbnail &nail); + + // Holds Thumbnail image. + uint8_t *data; + int size; + std::string type; +}; + +/* If these flags are no set - the Photo inherits values from the Album + */ + +#define RSPHOTO_FLAGS_ATTRIB_TITLE 0x0001 +#define RSPHOTO_FLAGS_ATTRIB_CAPTION 0x0002 +#define RSPHOTO_FLAGS_ATTRIB_DESC 0x0004 +#define RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER 0x0008 +#define RSPHOTO_FLAGS_ATTRIB_WHERE 0x0010 +#define RSPHOTO_FLAGS_ATTRIB_WHEN 0x0020 +#define RSPHOTO_FLAGS_ATTRIB_OTHER 0x0040 +#define RSPHOTO_FLAGS_ATTRIB_CATEGORY 0x0080 +#define RSPHOTO_FLAGS_ATTRIB_HASHTAGS 0x0100 +#define RSPHOTO_FLAGS_ATTRIB_ORDER 0x0200 +#define RSPHOTO_FLAGS_ATTRIB_THUMBNAIL 0x0400 +#define RSPHOTO_FLAGS_ATTRIB_MODE 0x0800 +#define RSPHOTO_FLAGS_ATTRIB_AUTHOR 0x1000 // PUSH UP ORDER +#define RSPHOTO_FLAGS_ATTRIB_PHOTO 0x2000 // PUSH UP ORDER. + +class RsPhotoPhoto +{ + public: + + RsMsgMetaData mMeta; + + RsPhotoPhoto(); + + // THESE ARE IN THE META DATA. + //std::string mAlbumId; + //std::string mId; + //std::string mTitle; // only used by Album. + std::string mCaption; + std::string mDescription; + std::string mPhotographer; + std::string mWhere; + std::string mWhen; + std::string mOther; + std::string mCategory; + + std::string mHashTags; + + uint32_t mSetFlags; + + int mOrder; + + RsPhotoThumbnail mThumbnail; + + int mMode; + + // These are not saved. + std::string path; // if in Mode NEW. + uint32_t mModFlags; +}; + +class RsPhotoAlbumShare +{ + public: + + uint32_t mShareType; + std::string mShareGroupId; + std::string mPublishKey; + uint32_t mCommentMode; + uint32_t mResizeMode; +}; + +class RsPhotoAlbum +{ + public: + RsPhotoAlbum(); + + RsGroupMetaData mMeta; + + // THESE ARE IN THE META DATA. + //std::string mAlbumId; + //std::string mTitle; // only used by Album. + + std::string mCaption; + std::string mDescription; + std::string mPhotographer; + std::string mWhere; + std::string mWhen; + std::string mOther; + std::string mCategory; + + std::string mHashTags; + + RsPhotoThumbnail mThumbnail; + + int mMode; + + std::string mPhotoPath; + RsPhotoAlbumShare mShareOptions; + + // These aren't saved. + uint32_t mSetFlags; + uint32_t mModFlags; +}; + +class RsGxsPhotoCommentItem; +class RsPhotoComment +{ +public: + RsPhotoComment(); + + RsPhotoComment(const RsGxsPhotoCommentItem& comment); + + RsPhotoComment& operator=(const RsGxsPhotoCommentItem& comment); + + RsMsgMetaData mMeta; + + std::string mComment; + uint32_t mCommentFlag; +}; + +std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo); +std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album); + +typedef std::map > PhotoResult; +typedef std::map > PhotoCommentResult; +typedef std::map > PhotoRelatedCommentResult; + +class RsPhoto +{ + +public: + + static const uint32_t FLAG_MSG_TYPE_PHOTO_POST; + static const uint32_t FLAG_MSG_TYPE_PHOTO_COMMENT; + static const uint32_t FLAG_MSG_TYPE_MASK; + + + RsPhoto() { return; } + + virtual ~RsPhoto() { return; } + + /*! + * Use to enquire if groups or msgs have changed + * Poll regularly, particularly after a photo submission + * @return true if msgs or groups have changed + */ + virtual bool updated() = 0; + + /*! + * + * @param grpIds + */ + virtual void groupsChanged(std::list& grpIds) = 0; + + /*! + * + * @param msgs + */ + virtual void msgsChanged(GxsMsgIdResult& msgs) = 0; + + /*! + * To acquire a handle to token service handler + * needed to make requests to the service + * @return handle to token service for this gxs service + */ + virtual RsTokenService* getTokenService() = 0; + + /* Generic Lists */ + + /*! + * + * @param token token to be redeemed for this request + * @param groupIds the ids return for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getGroupList(const uint32_t &token, + std::list &groupIds) = 0; + + /*! + * @param token token to be redeemed for this request + * @param msgIds the ids return for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getMsgList(const uint32_t &token, + GxsMsgIdResult &msgIds) = 0; + + /* Generic Summary */ + + /*! + * @param token token to be redeemed for group summary request + * @param groupInfo the ids returned for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getGroupSummary(const uint32_t &token, + std::list &groupInfo) = 0; + + /*! + * @param token token to be redeemed for message summary request + * @param msgInfo the message metadata returned for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getMsgSummary(const uint32_t &token, + MsgMetaResult &msgInfo) = 0; + + /* Specific Service Data */ + + /*! + * @param token token to be redeemed for album request + * @param album the album returned for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getAlbum(const uint32_t &token, std::vector &album) = 0; + + /*! + * @param token token to be redeemed for photo request + * @param photo the photo returned for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getPhoto(const uint32_t &token, + PhotoResult &photo) = 0; + + /* details are updated in album - to choose Album ID, and storage path */ + + /*! + * @param token token to be redeemed for photo request + * @param photo the photo returned for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getPhotoComment(const uint32_t &token, + PhotoCommentResult& comments) = 0; + /*! + * @param token token to be redeemed for photo request + * @param photo the photo returned for given request token + * @return false if request token is invalid, check token status for error report + */ + virtual bool getPhotoRelatedComment(const uint32_t &token, PhotoRelatedCommentResult &comments) = 0; + + /*! + * submits album, which returns a token that needs + * to be acknowledge to get album grp id + * @param token token to redeem for acknowledgement + * @param album album to be submitted + */ + virtual bool submitAlbumDetails(uint32_t& token, RsPhotoAlbum &album) = 0; + + /*! + * submits photo, which returns a token that needs + * to be acknowledged to get photo msg-grp id pair + * @param token token to redeem for acknowledgement + * @param photo photo to be submitted + */ + virtual bool submitPhoto(uint32_t& token, RsPhotoPhoto &photo) = 0; + + /*! + * submits photo comment, which returns a token that needs + * to be acknowledged to get photo msg-grp id pair + * The mParentId needs to be set to an existing msg for which + * commenting is enabled + * @param token token to redeem for acknowledgement + * @param comment comment to be submitted + */ + virtual bool submitComment(uint32_t& token, RsPhotoComment &photo) = 0; + + /*! + * subscribes to group, and returns token which can be used + * to be acknowledged to get group Id + * @param token token to redeem for acknowledgement + * @param grpId the id of the group to subscribe to + */ + virtual bool subscribeToAlbum(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) = 0; + + /*! + * This allows the client service to acknowledge that their msgs has + * been created/modified and retrieve the create/modified msg ids + * @param token the token related to modification/create request + * @param msgIds map of grpid->msgIds of message created/modified + * @return true if token exists false otherwise + */ + virtual bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) = 0; + + + + /*! + * This allows the client service to acknowledge that their grps has + * been created/modified and retrieve the create/modified grp ids + * @param token the token related to modification/create request + * @param msgIds vector of ids of groups created/modified + * @return true if token exists false otherwise + */ + virtual bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) = 0; + + +}; + + +#endif // RSPHOTOV2_H diff --git a/libretroshare/src/retroshare/rsphotoV2.h b/libretroshare/src/retroshare/rsphotoV2.h deleted file mode 100644 index c69c2db91..000000000 --- a/libretroshare/src/retroshare/rsphotoV2.h +++ /dev/null @@ -1,277 +0,0 @@ -#ifndef RSPHOTOV2_H -#define RSPHOTOV2_H - -/* - * libretroshare/src/retroshare: rsphoto.h - * - * RetroShare C++ Interface. - * - * Copyright 2008-2012 by Robert Fernie, Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include -#include "rsgxsservice.h" - -/* The Main Interface Class - for information about your Peers */ -class RsPhoto; -extern RsPhoto *rsPhoto; - -/******************* NEW STUFF FOR NEW CACHE SYSTEM *********/ - -#define RSPHOTO_MODE_NEW 1 -#define RSPHOTO_MODE_OWN 2 -#define RSPHOTO_MODE_REMOTE 3 - -class RsPhotoThumbnail -{ - public: - RsPhotoThumbnail() - :data(NULL), size(0), type("N/A") { return; } - - bool deleteImage(); - bool copyFrom(const RsPhotoThumbnail &nail); - - // Holds Thumbnail image. - uint8_t *data; - int size; - std::string type; -}; - - -/* If these flags are no set - the Photo inherits values from the Album - */ - -#define RSPHOTO_FLAGS_ATTRIB_TITLE 0x0001 -#define RSPHOTO_FLAGS_ATTRIB_CAPTION 0x0002 -#define RSPHOTO_FLAGS_ATTRIB_DESC 0x0004 -#define RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER 0x0008 -#define RSPHOTO_FLAGS_ATTRIB_WHERE 0x0010 -#define RSPHOTO_FLAGS_ATTRIB_WHEN 0x0020 -#define RSPHOTO_FLAGS_ATTRIB_OTHER 0x0040 -#define RSPHOTO_FLAGS_ATTRIB_CATEGORY 0x0080 -#define RSPHOTO_FLAGS_ATTRIB_HASHTAGS 0x0100 -#define RSPHOTO_FLAGS_ATTRIB_ORDER 0x0200 -#define RSPHOTO_FLAGS_ATTRIB_THUMBNAIL 0x0400 -#define RSPHOTO_FLAGS_ATTRIB_MODE 0x0800 -#define RSPHOTO_FLAGS_ATTRIB_AUTHOR 0x1000 // PUSH UP ORDER -#define RSPHOTO_FLAGS_ATTRIB_PHOTO 0x2000 // PUSH UP ORDER. - - -class RsPhotoPhoto -{ - public: - - RsMsgMetaData mMeta; - - RsPhotoPhoto(); - - // THESE ARE IN THE META DATA. - //std::string mAlbumId; - //std::string mId; - //std::string mTitle; // only used by Album. - std::string mCaption; - std::string mDescription; - std::string mPhotographer; - std::string mWhere; - std::string mWhen; - std::string mOther; - std::string mCategory; - - std::string mHashTags; - - uint32_t mSetFlags; - - int mOrder; - - RsPhotoThumbnail mThumbnail; - - int mMode; - - // These are not saved. - std::string path; // if in Mode NEW. - uint32_t mModFlags; -}; - -class RsPhotoAlbumShare -{ - public: - - uint32_t mShareType; - std::string mShareGroupId; - std::string mPublishKey; - uint32_t mCommentMode; - uint32_t mResizeMode; -}; - -class RsPhotoAlbum -{ - public: - RsPhotoAlbum(); - - RsGroupMetaData mMeta; - - // THESE ARE IN THE META DATA. - //std::string mAlbumId; - //std::string mTitle; // only used by Album. - - std::string mCaption; - std::string mDescription; - std::string mPhotographer; - std::string mWhere; - std::string mWhen; - std::string mOther; - std::string mCategory; - - std::string mHashTags; - - RsPhotoThumbnail mThumbnail; - - int mMode; - - std::string mPhotoPath; - RsPhotoAlbumShare mShareOptions; - - // These aren't saved. - uint32_t mSetFlags; - uint32_t mModFlags; -}; - -std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo); -std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album); - -typedef std::map > PhotoResult; -typedef std::map > MsgMetaResult; - -class RsPhotoV2 -{ - -public: - - - RsPhotoV2() { return; } - - virtual ~RsPhotoV2() { return; } - - /*! - * Use to enquire if groups or msgs have changed - * Poll regularly, particularly after a photo submission - * @return true if msgs or groups have changed - */ - virtual bool updated() = 0; - - /*! - * - * @param grpIds - */ - virtual void groupsChanged(std::list& grpIds) = 0; - - /*! - * - * @param msgs - */ - virtual void msgsChanged(GxsMsgIdResult& msgs) = 0; - - /*! - * To acquire a handle to token service handler - * needed to make requests to the service - * @return handle to token service for this gxs service - */ - virtual RsTokenServiceV2* getTokenService() = 0; - - /* Generic Lists */ - - /*! - * - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupList(const uint32_t &token, - std::list &groupIds) = 0; - - /*! - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgList(const uint32_t &token, - GxsMsgIdResult &msgIds) = 0; - - /* Generic Summary */ - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupSummary(const uint32_t &token, - std::list &groupInfo) = 0; - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgSummary(const uint32_t &token, - MsgMetaResult &msgInfo) = 0; - - /* Specific Service Data */ - - /*! - * @param token token to be redeemed for album request - * @param album the album returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getAlbum(const uint32_t &token, std::vector &album) = 0; - - /*! - * @param token token to be redeemed for photo request - * @param photo the photo returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getPhoto(const uint32_t &token, - PhotoResult &photo) = 0; - - /* details are updated in album - to choose Album ID, and storage path */ - - /*! - * This RsGenExchange service will be alerted to this album as \n - * a new album. Do not keep the submitted album as representative, wait for - * notification telling of successful submission - * @param album The album to be submitted - * @return false if submission failed - */ - virtual bool submitAlbumDetails(RsPhotoAlbum &album) = 0; - - /*! - * This RsGenExchange service will be alerted to this photo as \n - * a new photo. Do not keep the submitted photo as representative, wait for new photo - * returned - * @param photo photo to submit - * @return - */ - virtual bool submitPhoto(RsPhotoPhoto &photo) = 0; - -}; - - -#endif // RSPHOTOV2_H diff --git a/libretroshare/src/retroshare/rsplugin.h b/libretroshare/src/retroshare/rsplugin.h index 87ee520a7..b83c34d6e 100644 --- a/libretroshare/src/retroshare/rsplugin.h +++ b/libretroshare/src/retroshare/rsplugin.h @@ -105,6 +105,9 @@ class RsPlugin virtual RsPQIService *rs_pqi_service() const { return NULL ; } virtual uint16_t rs_service_id() const { return 0 ; } + // Shutdown + virtual void stop() {} + // Filename used for saving the specific plugin configuration. Both RsCacheService and RsPQIService // derive from p3Config, which means that the service provided by the plugin can load/save its own // config by deriving loadList() and saveList() from p3Config. diff --git a/libretroshare/src/retroshare/rsposted.h b/libretroshare/src/retroshare/rsposted.h index 83f497582..ec6aa6f43 100644 --- a/libretroshare/src/retroshare/rsposted.h +++ b/libretroshare/src/retroshare/rsposted.h @@ -1,140 +1,187 @@ -#ifndef RETROSHARE_POSTED_GUI_INTERFACE_H -#define RETROSHARE_POSTED_GUI_INTERFACE_H - -/* - * libretroshare/src/retroshare: rsposted.h - * - * RetroShare C++ Interface. - * - * Copyright 2008-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsPosted; -extern RsPosted *rsPosted; - - -class RsPostedGroup -{ - public: - RsGroupMetaData mMeta; - RsPostedGroup() { return; } -}; - -class RsPostedMsg -{ - public: - RsPostedMsg(uint32_t t) - :postedType(t) { return; } - - RsMsgMetaData mMeta; - uint32_t postedType; -}; - -#define RSPOSTED_MSGTYPE_POST 0x0001 -#define RSPOSTED_MSGTYPE_VOTE 0x0002 -#define RSPOSTED_MSGTYPE_COMMENT 0x0004 - -#define RSPOSTED_PERIOD_YEAR 1 -#define RSPOSTED_PERIOD_MONTH 2 -#define RSPOSTED_PERIOD_WEEK 3 -#define RSPOSTED_PERIOD_DAY 4 -#define RSPOSTED_PERIOD_HOUR 5 - -#define RSPOSTED_VIEWMODE_LATEST 1 -#define RSPOSTED_VIEWMODE_TOP 2 -#define RSPOSTED_VIEWMODE_HOT 3 -#define RSPOSTED_VIEWMODE_COMMENTS 4 - - -class RsPostedPost: public RsPostedMsg -{ - public: - RsPostedPost(): RsPostedMsg(RSPOSTED_MSGTYPE_POST) - { - mMeta.mMsgFlags = RSPOSTED_MSGTYPE_POST; - return; - } -}; - - -class RsPostedVote: public RsPostedMsg -{ - public: - RsPostedVote(): RsPostedMsg(RSPOSTED_MSGTYPE_VOTE) - { - mMeta.mMsgFlags = RSPOSTED_MSGTYPE_VOTE; - return; - } -}; - - -class RsPostedComment: public RsPostedMsg -{ - public: - RsPostedComment(): RsPostedMsg(RSPOSTED_MSGTYPE_COMMENT) - { - mMeta.mMsgFlags = RSPOSTED_MSGTYPE_COMMENT; - return; - } -}; - - -std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group); -std::ostream &operator<<(std::ostream &out, const RsPostedPost &post); -std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote); -std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment); - - -class RsPosted: public RsTokenService -{ - public: - - RsPosted() { return; } -virtual ~RsPosted() { return; } - - /* Specific Service Data */ -virtual bool getGroup(const uint32_t &token, RsPostedGroup &group) = 0; -virtual bool getPost(const uint32_t &token, RsPostedPost &post) = 0; -virtual bool getComment(const uint32_t &token, RsPostedComment &comment) = 0; - -virtual bool submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew) = 0; -virtual bool submitPost(uint32_t &token, RsPostedPost &post, bool isNew) = 0; -virtual bool submitVote(uint32_t &token, RsPostedVote &vote, bool isNew) = 0; -virtual bool submitComment(uint32_t &token, RsPostedComment &comment, bool isNew) = 0; - - // Special Ranking Request. -virtual bool requestRanking(uint32_t &token, std::string groupId) = 0; -virtual bool getRankedPost(const uint32_t &token, RsPostedPost &post) = 0; - -virtual bool extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments) = 0; - - // exposed for testing... -virtual float calcPostScore(const RsMsgMetaData &meta) = 0; - -}; - - -#endif +#ifndef RSPOSTED_H +#define RSPOSTED_H + + +/* + * libretroshare/src/retroshare: rsposted.h + * + * RetroShare C++ Interface. + * + * Copyright 2008-2012 by Robert Fernie, Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include "gxs/rstokenservice.h" +#include "gxs/rsgxsifaceimpl.h" + +class RsPosted; +extern RsPosted *rsPosted; + +/* The Main Interface Class - for information about your Peers */ + +class RsPostedGroup +{ + public: + RsGroupMetaData mMeta; + std::string mDescription; + RsPostedGroup() { return; } +}; + +//#define RSPOSTED_MSGTYPE_POST 0x0001 +//#define RSPOSTED_MSGTYPE_VOTE 0x0002 +//#define RSPOSTED_MSGTYPE_COMMENT 0x0004 + +#define RSPOSTED_PERIOD_YEAR 1 +#define RSPOSTED_PERIOD_MONTH 2 +#define RSPOSTED_PERIOD_WEEK 3 +#define RSPOSTED_PERIOD_DAY 4 +#define RSPOSTED_PERIOD_HOUR 5 + +#define RSPOSTED_VIEWMODE_LATEST 1 +#define RSPOSTED_VIEWMODE_TOP 2 +#define RSPOSTED_VIEWMODE_HOT 3 +#define RSPOSTED_VIEWMODE_COMMENTS 4 + +class RsPostedPost; +class RsPostedComment; +class RsPostedVote; +class RsPostedPostRanking; + +typedef std::map > PostedPostResult; +typedef std::map > PostedCommentResult; +typedef std::map > PostedVoteResult; +typedef std::map > PostedRelatedCommentResult; +typedef std::pair GroupRank; +typedef std::map PostedRanking; + +std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group); +std::ostream &operator<<(std::ostream &out, const RsPostedPost &post); +std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote); +std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment); + + + +class RsPosted : public RsGxsIfaceImpl +{ + public: + + enum RankType {TopRankType, HotRankType, NewRankType }; + + static const uint32_t FLAG_MSGTYPE_POST; + static const uint32_t FLAG_MSGTYPE_VOTE; + static const uint32_t FLAG_MSGTYPE_COMMENT; + static const uint32_t FLAG_MSGTYPE_MASK; + + + RsPosted(RsGenExchange* gxs) : RsGxsIfaceImpl(gxs) { return; } +virtual ~RsPosted() { return; } + + /* Specific Service Data */ + + virtual bool getGroup(const uint32_t &token, std::vector &group) = 0; + virtual bool getPost(const uint32_t &token, PostedPostResult &post) = 0; + virtual bool getComment(const uint32_t &token, PostedCommentResult &comment) = 0; + virtual bool getRelatedComment(const uint32_t& token, PostedRelatedCommentResult& comments) = 0; + virtual bool getPostRanking(const uint32_t& token, RsPostedPostRanking& ranking) = 0; + + virtual bool submitGroup(uint32_t &token, RsPostedGroup &group) = 0; + virtual bool submitPost(uint32_t &token, RsPostedPost &post) = 0; + virtual bool submitVote(uint32_t &token, RsPostedVote &vote) = 0; + virtual bool submitComment(uint32_t &token, RsPostedComment &comment) = 0; + + virtual bool retrieveScores(const std::string& serviceString, uint32_t& upVotes, uint32_t& downVotes, uint32_t& nComments) const = 0; + + // Special Ranking Request. + /*! + * Makes request for posts of a topic + * @param token + * @param rType + * @param groupId + */ + virtual bool requestPostRankings(uint32_t &token, const RankType& rType, const RsGxsGroupId& groupId) = 0; + + /*! + * Makes request for ranking of comments for a post + * @param token + * @param rType type of ranking to collect + * @param msgId message id of post as groupid-messageid pair + */ + virtual bool requestCommentRankings(uint32_t &token, const RankType& rType, const RsGxsGrpMsgIdPair& msgId) = 0; + +}; + +class RsPostedPost +{ + public: + RsPostedPost() + { + mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_POST; + mMeta.mServiceString = " 0 0 0"; + return; + } + + RsMsgMetaData mMeta; + std::string mLink; + std::string mNotes; +}; + +class RsGxsPostedVoteItem; + +class RsPostedVote +{ +public: + + RsPostedVote(const RsGxsPostedVoteItem&); + RsPostedVote() + { + mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_VOTE; + return; + } + uint8_t mDirection; + RsMsgMetaData mMeta; +}; + +class RsGxsPostedCommentItem; + +class RsPostedComment +{ + public: + RsPostedComment() + { + mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_COMMENT; + return; + } + + RsPostedComment(const RsGxsPostedCommentItem& ); + std::string mComment; + RsMsgMetaData mMeta; +}; + +class RsPostedPostRanking +{ +public: + + RsGxsGroupId grpId; + PostedRanking ranking; + RsPosted::RankType rType; +}; +#endif // RSPOSTED_H diff --git a/libretroshare/src/retroshare/rspostedVEG.h b/libretroshare/src/retroshare/rspostedVEG.h new file mode 100644 index 000000000..af617f10e --- /dev/null +++ b/libretroshare/src/retroshare/rspostedVEG.h @@ -0,0 +1,151 @@ +#ifndef RETROSHARE_POSTED_GUI_INTERFACE_H +#define RETROSHARE_POSTED_GUI_INTERFACE_H + +/* + * libretroshare/src/retroshare: rsposted.h + * + * RetroShare C++ Interface. + * + * Copyright 2008-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include + +/* The Main Interface Class - for information about your Peers */ +class RsPostedVEG; +extern RsPostedVEG *rsPostedVEG; + + +class RsPostedGroup +{ + public: + RsGroupMetaData mMeta; + RsPostedGroup() { return; } +}; + +class RsPostedMsg +{ + public: + RsPostedMsg(uint32_t t) + :postedType(t) { return; } + + RsMsgMetaData mMeta; + uint32_t postedType; +}; + +#define RSPOSTED_MSGTYPE_POST 0x0001 +#define RSPOSTED_MSGTYPE_VOTE 0x0002 +#define RSPOSTED_MSGTYPE_COMMENT 0x0004 + +#define RSPOSTED_PERIOD_YEAR 1 +#define RSPOSTED_PERIOD_MONTH 2 +#define RSPOSTED_PERIOD_WEEK 3 +#define RSPOSTED_PERIOD_DAY 4 +#define RSPOSTED_PERIOD_HOUR 5 + +#define RSPOSTED_VIEWMODE_LATEST 1 +#define RSPOSTED_VIEWMODE_TOP 2 +#define RSPOSTED_VIEWMODE_HOT 3 +#define RSPOSTED_VIEWMODE_COMMENTS 4 + + +class RsPostedPost: public RsPostedMsg +{ + public: + RsPostedPost(): RsPostedMsg(RSPOSTED_MSGTYPE_POST) + { + mMeta.mMsgFlags = RSPOSTED_MSGTYPE_POST; + return; + } + + std::string mLink; + std::string mNotes; +}; + + +class RsPostedVote: public RsPostedMsg +{ + public: + RsPostedVote(): RsPostedMsg(RSPOSTED_MSGTYPE_VOTE) + { + mMeta.mMsgFlags = RSPOSTED_MSGTYPE_VOTE; + return; + } +}; + + +class RsPostedComment: public RsPostedMsg +{ + public: + RsPostedComment(): RsPostedMsg(RSPOSTED_MSGTYPE_COMMENT) + { + mMeta.mMsgFlags = RSPOSTED_MSGTYPE_COMMENT; + return; + } + + std::string mComment; +}; + + +std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group); +std::ostream &operator<<(std::ostream &out, const RsPostedPost &post); +std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote); +std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment); + + +class RsPostedVEG: public RsTokenServiceVEG +{ + public: + + RsPostedVEG() { return; } +virtual ~RsPostedVEG() { return; } + + /* Specific Service Data */ +virtual bool getGroup(const uint32_t &token, RsPostedGroup &group) = 0; +virtual bool getPost(const uint32_t &token, RsPostedPost &post) = 0; +virtual bool getComment(const uint32_t &token, RsPostedComment &comment) = 0; + +virtual bool submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew) = 0; +virtual bool submitPost(uint32_t &token, RsPostedPost &post, bool isNew) = 0; +virtual bool submitVote(uint32_t &token, RsPostedVote &vote, bool isNew) = 0; +virtual bool submitComment(uint32_t &token, RsPostedComment &comment, bool isNew) = 0; + + // Special Ranking Request. +virtual bool requestRanking(uint32_t &token, std::string groupId) = 0; +virtual bool getRankedPost(const uint32_t &token, RsPostedPost &post) = 0; + +virtual bool extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments) = 0; + + + // Control Ranking Calculations. +virtual bool setViewMode(uint32_t mode) = 0; +virtual bool setViewPeriod(uint32_t period) = 0; +virtual bool setViewRange(uint32_t first, uint32_t count) = 0; + + // exposed for testing... +virtual float calcPostScore(const RsMsgMetaData &meta) = 0; + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rswiki.h b/libretroshare/src/retroshare/rswiki.h index 5d4d98e1c..7dce2f361 100644 --- a/libretroshare/src/retroshare/rswiki.h +++ b/libretroshare/src/retroshare/rswiki.h @@ -30,77 +30,107 @@ #include #include -#include +#include "gxs/rstokenservice.h" +#include "gxs/rsgxsifaceimpl.h" /* The Main Interface Class - for information about your Peers */ class RsWiki; extern RsWiki *rsWiki; -class RsWikiGroupShare + +/* so the basic idea of Wiki is a set of Collections about subjects. + * + * Collection: RS + * - page: DHT + * - edit + * - edit + * - official revision. (new version of thread head). + * + * A collection will be moderated by it creator - important to prevent stupid changes. + * We need a way to swap out / replace / fork collections if moderator is rubbish. + * + * This should probably be done that the collection level. + * and enable all the references to be modified. + * + * Collection1 (RS DHT) + * : Turtle Link: Collection 0x54e4dafc34 + * - Page 1 + * - Page 2 + * - Link to Self:Page 1 + * - Link to Turtle:Page 1 + * + * + */ + +#define FLAG_MSG_TYPE_WIKI_SNAPSHOT 0x0001 +#define FLAG_MSG_TYPE_WIKI_COMMENT 0x0002 + +class CollectionRef { public: - uint32_t mShareType; - std::string mShareGroupId; - std::string mPublishKey; - uint32_t mCommentMode; - uint32_t mResizeMode; + std::string KeyWord; + std::string CollectionId; }; -class RsWikiGroup + +class RsWikiCollection { public: RsGroupMetaData mMeta; - //std::string mGroupId; - //std::string mName; - std::string mDescription; std::string mCategory; std::string mHashTags; - RsWikiGroupShare mShareOptions; + //std::map linkReferences; }; -class RsWikiPage + +class RsWikiSnapshot { public: RsMsgMetaData mMeta; - // IN META DATA. - //std::string mGroupId; - //std::string mOrigPageId; - //std::string mPageId; - //std::string mName; - - // WE SHOULD SWITCH TO USING THREAD/PARENT IDS HERE.... - std::string mPrevId; - std::string mPage; // all the text is stored here. - std::string mHashTags; }; -class RsWiki: public RsTokenService + +class RsWikiComment { public: - RsWiki() { return; } + RsMsgMetaData mMeta; + std::string mComment; +}; + +std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group); +std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot); +std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment); + + +class RsWiki: public RsGxsIfaceImpl +{ + public: + + RsWiki(RsGenExchange *gxs): RsGxsIfaceImpl(gxs) { return; } virtual ~RsWiki() { return; } /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsWikiGroup &group) = 0; -virtual bool getMsgData(const uint32_t &token, RsWikiPage &page) = 0; +virtual bool getCollections(const uint32_t &token, std::vector &collections) = 0; +virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) = 0; +virtual bool getComments(const uint32_t &token, std::vector &comments) = 0; -virtual bool createGroup(uint32_t &token, RsWikiGroup &group, bool isNew) = 0; -virtual bool createPage(uint32_t &token, RsWikiPage &page, bool isNew) = 0; +virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) = 0; +virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) = 0; +virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) = 0; +virtual bool submitComment(uint32_t &token, RsWikiComment &comment) = 0; }; - - #endif diff --git a/libretroshare/src/retroshare/rswire.h b/libretroshare/src/retroshare/rswire.h index 0a5e1fda4..d30b496fa 100644 --- a/libretroshare/src/retroshare/rswire.h +++ b/libretroshare/src/retroshare/rswire.h @@ -30,74 +30,94 @@ #include #include -#include +#include "gxs/rstokenservice.h" +#include "gxs/rsgxsifaceimpl.h" + /* The Main Interface Class - for information about your Peers */ class RsWire; extern RsWire *rsWire; -class RsWireGroupShare -{ - public: - - uint32_t mShareType; - std::string mShareGroupId; - std::string mPublishKey; - uint32_t mCommentMode; - uint32_t mResizeMode; -}; - class RsWireGroup { public: RsGroupMetaData mMeta; - - //std::string mGroupId; - //std::string mName; - std::string mDescription; - std::string mCategory; - - std::string mHashTags; - - RsWireGroupShare mShareOptions; }; + + +/*********************************************************************** + * So pulses operate in the following modes. + * + * => Standard, a post to your own group. + * => @User, gets duplicated on each user's group. + * => RT, duplicated as child of original post. + * + * From Twitter: + * twitter can be: embedded, replied to, favourited, unfavourited, + * retweeted, unretweeted and deleted + * + * See: https://dev.twitter.com/docs/platform-objects + * + * Format of message: .... + * + * #HashTags. + * @68769381495134 => ID of Sender. + * + * + ***********************************************************************/ + +class RsWirePlace +{ + public: + + + +}; + + class RsWirePulse { public: RsMsgMetaData mMeta; - //std::string mGroupId; - //std::string mOrigPageId; - //std::string mPrevId; - //std::string mPageId; - //std::string mName; + std::string mPulseText; // all the text is stored here. + std::string mHashTags; - std::string mPulse; // all the text is stored here. +// These will be added at some point. +// std::string mInReplyPulse; - std::string mHashTags; +// uint32_t mPulseFlags; + +// std::list mMentions; +// std::list mHashTags; +// std::list mUrls; + +// RsWirePlace mPlace; }; -class RsWire: public RsTokenService + +std::ostream &operator<<(std::ostream &out, const RsWireGroup &group); +std::ostream &operator<<(std::ostream &out, const RsWirePulse &pulse); + + +class RsWire: public RsGxsIfaceImpl { public: - RsWire() { return; } + RsWire(RsGenExchange *gxs): RsGxsIfaceImpl(gxs) { return; } virtual ~RsWire() { return; } /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsWireGroup &group) = 0; -virtual bool getMsgData(const uint32_t &token, RsWirePulse &pulse) = 0; +virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; +virtual bool getPulseData(const uint32_t &token, std::vector &pulses) = 0; - /* Create Stuff */ -virtual bool createGroup(uint32_t &token, RsWireGroup &group, bool isNew) = 0; -virtual bool createPulse(uint32_t &token, RsWirePulse &pulse, bool isNew) = 0; +virtual bool createGroup(uint32_t &token, RsWireGroup &group) = 0; +virtual bool createPulse(uint32_t &token, RsWirePulse &pulse) = 0; }; - - #endif diff --git a/libretroshare/src/rsserver/p3face-config.cc b/libretroshare/src/rsserver/p3face-config.cc index ed01ea5a3..f28db3cd3 100644 --- a/libretroshare/src/rsserver/p3face-config.cc +++ b/libretroshare/src/rsserver/p3face-config.cc @@ -31,6 +31,7 @@ #include "pqi/authssl.h" #include "pqi/authgpg.h" #include "retroshare/rsinit.h" +#include "plugins/pluginmanager.h" #include "util/rsdebug.h" const int p3facemsgzone = 11453; @@ -41,6 +42,19 @@ const int p3facemsgzone = 11453; #include "pqi/p3netmgr.h" +// TO SHUTDOWN THREADS. +#ifdef RS_ENABLE_GXS + +#include "services/p3idservice.h" +#include "services/p3gxscircles.h" +#include "services/p3wiki.h" +#include "services/p3posted.h" +#include "services/p3photoservice.h" +#include "services/p3gxsforums.h" +#include "services/p3wire.h" + +#endif + /****************************************/ /* RsIface Config */ /* Config */ @@ -134,10 +148,28 @@ void RsServer::rsGlobalShutDown() join(); ftserver->StopThreads(); + mPluginsManager->stopPlugins(); + // stop the p3distrib threads + mForums->join(); mChannels->join(); + + +#ifdef RS_ENABLE_GXS + if(mGxsCircles) mGxsCircles->join(); + if(mGxsForums) mGxsForums->join(); + if(mGxsIdService) mGxsIdService->join(); + if(mPosted) mPosted->join(); + if(mPhoto) mPhoto->join(); + if(mWiki) mWiki->join(); + if(mWire) mWire->join(); +#endif + + + + #ifdef RS_USE_BLOGS mBlogs->join(); #endif diff --git a/libretroshare/src/rsserver/p3face-server.cc b/libretroshare/src/rsserver/p3face-server.cc index 9a4a582a1..625e11ff2 100644 --- a/libretroshare/src/rsserver/p3face-server.cc +++ b/libretroshare/src/rsserver/p3face-server.cc @@ -62,6 +62,8 @@ RsServer::RsServer(RsIface &i, NotifyBase &callback) pqih = NULL; + mPluginsManager = NULL; + /* services */ ad = NULL; msgSrv = NULL; @@ -74,6 +76,18 @@ RsServer::RsServer(RsIface &i, NotifyBase &callback) /* Config */ mConfigMgr = NULL; mGeneralConfig = NULL; + + /* GXS - Amazingly we can still initialise these + * even without knowing the data-types (they are just pointers???) + */ + mPhoto = NULL; + mWiki = NULL; + mPosted = NULL; + mGxsCircles = NULL; + mGxsIdService = NULL; + mGxsForums = NULL; + mWire = NULL; + } RsServer::~RsServer() diff --git a/libretroshare/src/rsserver/p3face.h b/libretroshare/src/rsserver/p3face.h index 9d938f397..58588fb01 100644 --- a/libretroshare/src/rsserver/p3face.h +++ b/libretroshare/src/rsserver/p3face.h @@ -45,10 +45,23 @@ #include "services/p3channels.h" #include "services/p3forums.h" +/* GXS Classes - just declare the classes. + so we don't have to totally recompile to switch */ + +class p3IdService; +class p3GxsCircles; +class p3GxsForums; +class p3Wiki; +class p3Posted; +class p3PhotoService; +class p3Wire; + + class p3PeerMgrIMPL; class p3LinkMgrIMPL; class p3NetMgrIMPL; class p3HistoryMgr; +class RsPluginManager; /* The Main Interface Class - for controlling the server */ @@ -159,6 +172,8 @@ class RsServer: public RsControl, public RsThread pqipersongrp *pqih; + RsPluginManager *mPluginsManager; + //sslroot *sslr; /* services */ @@ -170,6 +185,15 @@ class RsServer: public RsControl, public RsThread p3Forums *mForums; /* caches (that need ticking) */ + /* GXS */ + p3Wiki *mWiki; + p3Posted *mPosted; + p3PhotoService *mPhoto; + p3GxsCircles *mGxsCircles; + p3IdService *mGxsIdService; + p3GxsForums *mGxsForums; + p3Wire *mWire; + /* Config */ p3ConfigMgr *mConfigMgr; p3GeneralConfig *mGeneralConfig; diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 0c9398df6..fe72946b2 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -28,9 +28,11 @@ #include -// for locking instances #ifndef WINDOWS_SYS +// for locking instances #include +#else +#include "util/rswin.h" #endif #include "util/rsdebug.h" @@ -1804,7 +1806,11 @@ RsTurtle *rsTurtle = NULL ; #ifdef RS_ENABLE_ZCNATASSIST #include "zeroconf/p3zcnatassist.h" #else - #include "upnp/upnphandler.h" + #ifdef RS_USE_LIBUPNP + #include "upnp/upnphandler_linux.h" + #else + #include "upnp/upnphandler_miniupnp.h" + #endif #endif #include "services/p3disc.h" @@ -1817,14 +1823,22 @@ RsTurtle *rsTurtle = NULL ; #include "services/p3blogs.h" #include "turtle/p3turtle.h" -#ifdef ENABLE_GXS_SERVICES -#include "services/p3photoservice.h" -#include "services/p3wikiservice.h" -#include "services/p3wire.h" +#ifdef RS_ENABLE_GXS +// NEW GXS SYSTEMS. +#include "gxs/gxscoreserver.h" +#include "gxs/rsdataservice.h" +#include "gxs/rsgxsnetservice.h" +#include "gxs/rsgxsflags.h" + #include "services/p3idservice.h" -#include "services/p3forumsv2.h" +#include "services/p3gxscircles.h" +#include "services/p3wiki.h" #include "services/p3posted.h" -#endif +#include "services/p3photoservice.h" +#include "services/p3gxsforums.h" +#include "services/p3wire.h" + +#endif // RS_ENABLE_GXS #ifndef PQI_DISABLE_TUNNEL #include "services/p3tunnel.h" @@ -2187,7 +2201,7 @@ int RsServer::StartupRetroShare() // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. #endif - RsPluginManager *mPluginsManager = new RsPluginManager(RsInitConfig::main_executable_hash) ; + mPluginsManager = new RsPluginManager(RsInitConfig::main_executable_hash) ; rsPlugins = mPluginsManager ; mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager); @@ -2266,31 +2280,184 @@ int RsServer::StartupRetroShare() mPluginsManager->registerClientServices(pqih) ; mPluginsManager->registerCacheServices() ; -#ifdef ENABLE_GXS_SERVICES - // Testing New Cache Services. - p3PhotoService *mPhotos = new p3PhotoService(RS_SERVICE_TYPE_PHOTO); - pqih -> addService(mPhotos); - // Testing New Cache Services. - p3WikiService *mWikis = new p3WikiService(RS_SERVICE_TYPE_WIKI); - pqih -> addService(mWikis); +#ifdef RS_ENABLE_GXS - // Testing New Cache Services. - p3Wire *mWire = new p3Wire(RS_SERVICE_TYPE_WIRE); - pqih -> addService(mWire); + // The idea is that if priorGxsDir is non + // empty and matches an exist directory location + // the given ssl user id then this directory is cleaned + // and deleted + std::string priorGxsDir = "./" + mLinkMgr->getOwnId() + "/"; + std::string currGxsDir = RsInitConfig::configDir + "/GXS_phase1"; + bool cleanUpGxsDir = false; - // Testing New Cache Services. - p3IdService *mIdentity = new p3IdService(RS_SERVICE_TYPE_IDENTITY); - pqih -> addService(mIdentity); + if(!priorGxsDir.empty()) + cleanUpGxsDir = RsDirUtil::checkDirectory(priorGxsDir); - // Testing New Cache Services. - p3ForumsV2 *mForumsV2 = new p3ForumsV2(RS_SERVICE_TYPE_FORUMSV2); - pqih -> addService(mForumsV2); + std::list filesToKeep; + bool cleanUpSuccess = RsDirUtil::cleanupDirectory(priorGxsDir, filesToKeep); - // Testing New Cache Services. - p3PostedService *mPosted = new p3PostedService(RS_SERVICE_TYPE_POSTED); - pqih -> addService(mPosted); -#endif // ENABLE_GXS_SERVICES + if(!cleanUpSuccess) + std::cerr << "RsInit::StartupRetroShare() Clean up of Old Gxs Dir Failed!"; + else + rmdir(priorGxsDir.c_str()); + + // TODO: temporary to store GXS service data, remove + RsDirUtil::checkCreateDirectory(currGxsDir); + + RsNxsNetMgr* nxsMgr = new RsNxsNetMgrImpl(mLinkMgr); + + /**** Identity service ****/ + + RsGeneralDataService* gxsid_ds = new RsDataService(currGxsDir + "/", "gxsid_db", + RS_SERVICE_GXSV1_TYPE_GXSID, NULL); + + gxsid_ds->resetDataStore(); + + // init gxs services + mGxsIdService = new p3IdService(gxsid_ds, NULL); + + // create GXS photo service + RsGxsNetService* gxsid_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_GXSID, gxsid_ds, nxsMgr, mGxsIdService); + + /**** GxsCircle service ****/ + + + RsGeneralDataService* gxscircles_ds = new RsDataService(currGxsDir + "/", "gxscircles_db", + RS_SERVICE_GXSV1_TYPE_GXSCIRCLE, NULL); + + gxscircles_ds->resetDataStore(); + + // init gxs services + mGxsCircles = new p3GxsCircles(gxscircles_ds, NULL, mGxsIdService); + + // create GXS Circle service + RsGxsNetService* gxscircles_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_GXSCIRCLE, gxscircles_ds, nxsMgr, mGxsCircles); + + + /**** Photo service ****/ + // create photo authentication policy + uint32_t photoAuthenPolicy = 0; + + uint8_t flag = 0; + + flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, photoAuthenPolicy, + RsGenExchange::RESTRICTED_GRP_BITS); + +// Re-enable later, photo not using gixs yet +// flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; +// RsGenExchange::setAuthenPolicyFlag(flag, photoAuthenPolicy, +// RsGenExchange::RESTRICTED_GRP_BITS); + + flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, photoAuthenPolicy, + RsGenExchange::GRP_OPTION_BITS); + + + RsGeneralDataService* photo_ds = new RsDataService(currGxsDir + "/", "photoV2_db", + RS_SERVICE_GXSV1_TYPE_PHOTO, NULL); + + photo_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing + + + // init gxs services + mPhoto = new p3PhotoService(photo_ds, NULL, mGxsIdService, photoAuthenPolicy); + + // create GXS photo service + RsGxsNetService* photo_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_PHOTO, photo_ds, nxsMgr, mPhoto); + + /**** Posted GXS service ****/ + + + + RsGeneralDataService* posted_ds = new RsDataService(currGxsDir + "/", "posted_db", + RS_SERVICE_GXSV1_TYPE_POSTED); + + posted_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing + + mPosted = new p3Posted(posted_ds, NULL); + + // create GXS photo service + RsGxsNetService* posted_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_POSTED, posted_ds, nxsMgr, mPosted); + + + /**** Wiki GXS service ****/ + + + + RsGeneralDataService* wiki_ds = new RsDataService(currGxsDir + "/", "wiki_db", + RS_SERVICE_GXSV1_TYPE_WIKI); + + wiki_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing + + mWiki = new p3Wiki(wiki_ds, NULL); + + // create GXS photo service + RsGxsNetService* wiki_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_WIKI, wiki_ds, nxsMgr, mWiki); + + + /**** Wire GXS service ****/ + + + RsGeneralDataService* wire_ds = new RsDataService(currGxsDir + "/", "wire_db", + RS_SERVICE_GXSV1_TYPE_WIRE); + + wire_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing + + mWire = new p3Wire(wire_ds, NULL); + + // create GXS photo service + RsGxsNetService* wire_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_WIRE, wire_ds, nxsMgr, mWire); + + + /**** Forum GXS service ****/ + + RsGeneralDataService* gxsforums_ds = new RsDataService(currGxsDir + "/", "gxsforums_db", + RS_SERVICE_GXSV1_TYPE_FORUMS); + + gxsforums_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing + + mGxsForums = new p3GxsForums(gxsforums_ds, NULL); + + // create GXS photo service + RsGxsNetService* gxsforums_ns = new RsGxsNetService( + RS_SERVICE_GXSV1_TYPE_FORUMS, gxsforums_ds, nxsMgr, mGxsForums); + + + /*** start up GXS core runner ***/ + createThread(*mGxsIdService); + createThread(*mGxsCircles); + createThread(*mPhoto); + createThread(*mPosted); + createThread(*mWiki); + createThread(*mWire); + createThread(*mGxsForums); + + // cores ready start up GXS net servers + createThread(*gxsid_ns); + createThread(*gxscircles_ns); + createThread(*photo_ns); + createThread(*posted_ns); + createThread(*wiki_ns); + createThread(*wire_ns); + createThread(*gxsforums_ns); + + // now add to p3service + pqih->addService(gxsid_ns); + pqih->addService(gxscircles_ns); + pqih->addService(photo_ns); + pqih->addService(posted_ns); + pqih->addService(wiki_ns); + pqih->addService(gxsforums_ns); + +#endif // RS_ENABLE_GXS. #ifndef RS_RELEASE @@ -2548,15 +2715,17 @@ int RsServer::StartupRetroShare() rsForums = mForums; rsChannels = mChannels; -#ifdef ENABLE_GXS_SERVICES - // Testing of new cache system interfaces. - rsIdentity = mIdentity; - rsPhoto = mPhotos; - rsWiki = mWikis; - rsWire = mWire; - rsForumsV2 = mForumsV2; - rsPosted = mPosted; -#endif // ENABLE_GXS_SERVICES +#ifdef RS_ENABLE_GXS + + rsIdentity = mGxsIdService; + rsGxsCircles = mGxsCircles; + rsWiki = mWiki; + rsPosted = mPosted; + rsPhoto = mPhoto; + rsGxsForums = mGxsForums; + rsWire = mWire; + +#endif // RS_ENABLE_GXS #ifdef RS_USE_BLOGS @@ -2571,7 +2740,6 @@ int RsServer::StartupRetroShare() rsGameLauncher = NULL; #endif - /* put a welcome message in! */ if (RsInitConfig::firsttime_run) { diff --git a/libretroshare/src/serialiser/itempriorities.h b/libretroshare/src/serialiser/itempriorities.h index 812ffb40c..c1e78c31d 100644 --- a/libretroshare/src/serialiser/itempriorities.h +++ b/libretroshare/src/serialiser/itempriorities.h @@ -90,3 +90,6 @@ const uint8_t QOS_PRIORITY_RS_BWCTRL_ALLOWED_ITEM = 9 ; const uint8_t QOS_PRIORITY_RS_DSDV_ROUTE = 4 ; const uint8_t QOS_PRIORITY_RS_DSDV_DATA = 2 ; +// GXS +// +const uint8_t QOS_PRIORITY_RS_GXS_NET = 3 ; diff --git a/libretroshare/src/serialiser/rsgxscircleitems.cc b/libretroshare/src/serialiser/rsgxscircleitems.cc new file mode 100644 index 000000000..6fddb2d92 --- /dev/null +++ b/libretroshare/src/serialiser/rsgxscircleitems.cc @@ -0,0 +1,422 @@ +/* + * libretroshare/src/serialiser: rswikiitems.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "rsgxscircleitems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +#define CIRCLE_DEBUG 1 + + +uint32_t RsGxsCircleSerialiser::size(RsItem *item) +{ + RsGxsCircleGroupItem* grp_item = NULL; + RsGxsCircleMsgItem* snap_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return sizeGxsCircleGroupItem(grp_item); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return sizeGxsCircleMsgItem(snap_item); + } + return NULL; +} + +bool RsGxsCircleSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsGxsCircleGroupItem* grp_item = NULL; + RsGxsCircleMsgItem* snap_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsCircleGroupItem(grp_item, data, size); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsCircleMsgItem(snap_item, data, size); + } + return false; +} + +RsItem* RsGxsCircleSerialiser::deserialise(void* data, uint32_t* size) +{ + +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSCIRCLE != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM: + return deserialiseGxsCircleGroupItem(data, size); + break; + case RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM: + return deserialiseGxsCircleMsgItem(data, size); + break; + default: +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; +#endif + break; + } + return NULL; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsCircleGroupItem::clear() +{ + gxsIdSet.TlvClear(); + subCircleSet.TlvClear(); +} + +bool RsGxsCircleGroupItem::convertFrom(const RsGxsCircleGroup &group) +{ + clear(); + + meta = group.mMeta; + gxsIdSet.ids = group.mInvitedMembers; + subCircleSet.ids = group.mSubCircles; + return true; +} + +bool RsGxsCircleGroupItem::convertTo(RsGxsCircleGroup &group) const +{ + group.mMeta = meta; + group.mInvitedMembers = gxsIdSet.ids; + group.mSubCircles = subCircleSet.ids; + return true; +} + + +std::ostream& RsGxsCircleGroupItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsCircleGroupItem", indent); + uint16_t int_Indent = indent + 2; + + gxsIdSet.print(out, int_Indent); + subCircleSet.print(out, int_Indent); + + printRsItemEnd(out ,"RsGxsCircleGroupItem", indent); + return out; +} + + +uint32_t RsGxsCircleSerialiser::sizeGxsCircleGroupItem(RsGxsCircleGroupItem *item) +{ + uint32_t s = 8; // header + + s += item->gxsIdSet.TlvSize(); + s += item->subCircleSet.TlvSize(); + + return s; +} + +bool RsGxsCircleSerialiser::serialiseGxsCircleGroupItem(RsGxsCircleGroupItem *item, void *data, uint32_t *size) +{ + +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleGroupItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsCircleGroupItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleGroupItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsCircleGroupItem */ + ok &= item->gxsIdSet.SetTlv(data, tlvsize, &offset); + ok &= item->subCircleSet.SetTlv(data, tlvsize, &offset); + + if(offset != tlvsize) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleGroupItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef CIRCLE_DEBUG + if (!ok) + { + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleGroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsCircleGroupItem* RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem(void *data, uint32_t *size) +{ + +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSCIRCLE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM != getRsItemSubType(rstype))) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsCircleGroupItem* item = new RsGxsCircleGroupItem(); + /* skip the header */ + offset += 8; + + ok &= item->gxsIdSet.GetTlv(data, rssize, &offset); + ok &= item->subCircleSet.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleGroupItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsCircleMsgItem::clear() +{ + msg.stuff.clear(); +} + +std::ostream& RsGxsCircleMsgItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsCircleMsgItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Stuff: " << msg.stuff << std::endl; + + printRsItemEnd(out ,"RsGxsCircleMsgItem", indent); + return out; +} + + +uint32_t RsGxsCircleSerialiser::sizeGxsCircleMsgItem(RsGxsCircleMsgItem *item) +{ + + const RsGxsCircleMsg &msg = item->msg; + uint32_t s = 8; // header + + s += GetTlvStringSize(msg.stuff); + + return s; +} + +bool RsGxsCircleSerialiser::serialiseGxsCircleMsgItem(RsGxsCircleMsgItem *item, void *data, uint32_t *size) +{ + +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleMsgItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsCircleMsgItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleMsgItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsCircleMsgItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->msg.stuff); + + if(offset != tlvsize) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleMsgItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef CIRCLE_DEBUG + if (!ok) + { + std::cerr << "RsGxsCircleSerialiser::serialiseGxsCircleMsgItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsCircleMsgItem* RsGxsCircleSerialiser::deserialiseGxsCircleMsgItem(void *data, uint32_t *size) +{ + +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleMsgItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSCIRCLE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM != getRsItemSubType(rstype))) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleMsgItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleMsgItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsCircleMsgItem* item = new RsGxsCircleMsgItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->msg.stuff); + + if (offset != rssize) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleMsgItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef CIRCLE_DEBUG + std::cerr << "RsGxsCircleSerialiser::deserialiseGxsCircleMsgItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsgxscircleitems.h b/libretroshare/src/serialiser/rsgxscircleitems.h new file mode 100644 index 000000000..1bfca6a35 --- /dev/null +++ b/libretroshare/src/serialiser/rsgxscircleitems.h @@ -0,0 +1,102 @@ +/* + * libretroshare/src/serialiser: rsgxscircleitems.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RS_GXSCIRCLE_ITEMS_H +#define RS_GXSCIRCLE_ITEMS_H + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "rsgxsitems.h" +#include "retroshare/rsgxscircles.h" + +const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM = 0x03; + +const uint16_t GXSCIRCLE_GXSIDSET = 0x0001; +const uint16_t GXSCIRCLE_SUBCIRCLESET = 0x0002; + +class RsGxsCircleGroupItem : public RsGxsGrpItem +{ + +public: + + RsGxsCircleGroupItem(): RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_GXSCIRCLE, + RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM), + gxsIdSet(GXSCIRCLE_GXSIDSET), + subCircleSet(GXSCIRCLE_SUBCIRCLESET) { return;} + virtual ~RsGxsCircleGroupItem() { return;} + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + bool convertFrom(const RsGxsCircleGroup &group); + bool convertTo(RsGxsCircleGroup &group) const; + + // DIFFERENT FROM OTHER ONES, as stupid serialisation otherwise. + RsTlvStringSet gxsIdSet; + RsTlvStringSet subCircleSet; +}; + +class RsGxsCircleMsgItem : public RsGxsMsgItem +{ +public: + + RsGxsCircleMsgItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_GXSCIRCLE, + RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM) {return; } + virtual ~RsGxsCircleMsgItem() { return;} + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsGxsCircleMsg msg; +}; + +class RsGxsCircleSerialiser : public RsSerialType +{ +public: + + RsGxsCircleSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_GXSCIRCLE) + { return; } + virtual ~RsGxsCircleSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + private: + + uint32_t sizeGxsCircleGroupItem(RsGxsCircleGroupItem *item); + bool serialiseGxsCircleGroupItem (RsGxsCircleGroupItem *item, void *data, uint32_t *size); + RsGxsCircleGroupItem * deserialiseGxsCircleGroupItem(void *data, uint32_t *size); + + uint32_t sizeGxsCircleMsgItem(RsGxsCircleMsgItem *item); + bool serialiseGxsCircleMsgItem (RsGxsCircleMsgItem *item, void *data, uint32_t *size); + RsGxsCircleMsgItem * deserialiseGxsCircleMsgItem(void *data, uint32_t *size); +}; + +#endif /* RS_GXSCIRCLE_ITEMS_H */ diff --git a/libretroshare/src/serialiser/rsgxsforumitems.cc b/libretroshare/src/serialiser/rsgxsforumitems.cc new file mode 100644 index 000000000..9423ce058 --- /dev/null +++ b/libretroshare/src/serialiser/rsgxsforumitems.cc @@ -0,0 +1,402 @@ +/* + * libretroshare/src/serialiser: rsgxsforumitems.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "rsgxsforumitems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +#define GXSFORUM_DEBUG 1 + + +uint32_t RsGxsForumSerialiser::size(RsItem *item) +{ + RsGxsForumGroupItem* grp_item = NULL; + RsGxsForumMsgItem* op_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return sizeGxsForumGroupItem(grp_item); + } + else if((op_item = dynamic_cast(item)) != NULL) + { + return sizeGxsForumMsgItem(op_item); + } + std::cerr << "RsGxsForumSerialiser::size() ERROR invalid item" << std::endl; + return 0; +} + +bool RsGxsForumSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsGxsForumGroupItem* grp_item = NULL; + RsGxsForumMsgItem* op_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsForumGroupItem(grp_item, data, size); + } + else if((op_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsForumMsgItem(op_item, data, size); + } + std::cerr << "RsGxsForumSerialiser::serialise() ERROR invalid item" << std::endl; + return false; +} + +RsItem* RsGxsForumSerialiser::deserialise(void* data, uint32_t* size) +{ + +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_FORUMS != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM: + return deserialiseGxsForumGroupItem(data, size); + break; + case RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM: + return deserialiseGxsForumMsgItem(data, size); + break; + default: +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; +#endif + break; + } + return NULL; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsForumGroupItem::clear() +{ + mGroup.mDescription.clear(); +} + +std::ostream& RsGxsForumGroupItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsForumGroupItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Description: " << mGroup.mDescription << std::endl; + + printRsItemEnd(out ,"RsGxsForumGroupItem", indent); + return out; +} + + +uint32_t RsGxsForumSerialiser::sizeGxsForumGroupItem(RsGxsForumGroupItem *item) +{ + + const RsGxsForumGroup& group = item->mGroup; + uint32_t s = 8; // header + + s += GetTlvStringSize(group.mDescription); + + return s; +} + +bool RsGxsForumSerialiser::serialiseGxsForumGroupItem(RsGxsForumGroupItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumGroupItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsForumGroupItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumGroupItem() Size too small" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsForumGroupItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mGroup.mDescription); + + if(offset != tlvsize) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumGroupItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSFORUM_DEBUG + if (!ok) + { + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumGroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsForumGroupItem* RsGxsForumSerialiser::deserialiseGxsForumGroupItem(void *data, uint32_t *size) +{ + +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumGroupItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_FORUMS != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumGroupItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumGroupItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsForumGroupItem* item = new RsGxsForumGroupItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->mGroup.mDescription); + + if (offset != rssize) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumGroupItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumGroupItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsForumMsgItem::clear() +{ + mMsg.mMsg.clear(); +} + +std::ostream& RsGxsForumMsgItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsForumMsgItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Msg: " << mMsg.mMsg << std::endl; + + printRsItemEnd(out ,"RsGxsForumMsgItem", indent); + return out; +} + + +uint32_t RsGxsForumSerialiser::sizeGxsForumMsgItem(RsGxsForumMsgItem *item) +{ + + const RsGxsForumMsg& msg = item->mMsg; + uint32_t s = 8; // header + + s += GetTlvStringSize(msg.mMsg); // mMsg. + + return s; +} + +bool RsGxsForumSerialiser::serialiseGxsForumMsgItem(RsGxsForumMsgItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumMsgItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsForumMsgItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumMsgItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsForumMsgItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mMsg.mMsg); + + if(offset != tlvsize) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumMsgItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSFORUM_DEBUG + if (!ok) + { + std::cerr << "RsGxsForumSerialiser::serialiseGxsForumGroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsForumMsgItem* RsGxsForumSerialiser::deserialiseGxsForumMsgItem(void *data, uint32_t *size) +{ + +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumMsgItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_FORUMS != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumMsgItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumMsgItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsForumMsgItem* item = new RsGxsForumMsgItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->mMsg.mMsg); + + if (offset != rssize) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumMsgItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSFORUM_DEBUG + std::cerr << "RsGxsForumSerialiser::deserialiseGxsForumMsgItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsgxsforumitems.h b/libretroshare/src/serialiser/rsgxsforumitems.h new file mode 100644 index 000000000..3729f3a91 --- /dev/null +++ b/libretroshare/src/serialiser/rsgxsforumitems.h @@ -0,0 +1,95 @@ +/* + * libretroshare/src/serialiser: rsgxsforumitems.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RS_GXS_FORUM_ITEMS_H +#define RS_GXS_FORUM_ITEMS_H + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "rsgxsitems.h" +#include "retroshare/rsgxsforums.h" + +const uint8_t RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM = 0x03; + +class RsGxsForumGroupItem : public RsGxsGrpItem +{ + +public: + + RsGxsForumGroupItem(): RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_FORUMS, + RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM) { return;} + virtual ~RsGxsForumGroupItem() { return;} + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + + RsGxsForumGroup mGroup; +}; + +class RsGxsForumMsgItem : public RsGxsMsgItem +{ +public: + + RsGxsForumMsgItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_FORUMS, + RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM) {return; } + virtual ~RsGxsForumMsgItem() { return;} + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsGxsForumMsg mMsg; +}; + +class RsGxsForumSerialiser : public RsSerialType +{ +public: + + RsGxsForumSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_FORUMS) + { return; } + virtual ~RsGxsForumSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + private: + + uint32_t sizeGxsForumGroupItem(RsGxsForumGroupItem *item); + bool serialiseGxsForumGroupItem (RsGxsForumGroupItem *item, void *data, uint32_t *size); + RsGxsForumGroupItem * deserialiseGxsForumGroupItem(void *data, uint32_t *size); + + uint32_t sizeGxsForumMsgItem(RsGxsForumMsgItem *item); + bool serialiseGxsForumMsgItem (RsGxsForumMsgItem *item, void *data, uint32_t *size); + RsGxsForumMsgItem * deserialiseGxsForumMsgItem(void *data, uint32_t *size); + +}; + +#endif /* RS_GXS_FORUM_ITEMS_H */ diff --git a/libretroshare/src/serialiser/rsgxsiditems.cc b/libretroshare/src/serialiser/rsgxsiditems.cc new file mode 100644 index 000000000..02e316bec --- /dev/null +++ b/libretroshare/src/serialiser/rsgxsiditems.cc @@ -0,0 +1,576 @@ +/* + * libretroshare/src/serialiser: rsgxsiditems.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "rsgxsiditems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +#define GXSID_DEBUG 1 + + +uint32_t RsGxsIdSerialiser::size(RsItem *item) +{ + RsGxsIdGroupItem* grp_item = NULL; + RsGxsIdOpinionItem* op_item = NULL; + RsGxsIdCommentItem* com_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return sizeGxsIdGroupItem(grp_item); + } + else if((op_item = dynamic_cast(item)) != NULL) + { + return sizeGxsIdOpinionItem(op_item); + } + else if((com_item = dynamic_cast(item)) != NULL) + { + return sizeGxsIdCommentItem(com_item); + } + std::cerr << "RsGxsIdSerialiser::size() ERROR invalid item" << std::endl; + return 0; +} + +bool RsGxsIdSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsGxsIdGroupItem* grp_item = NULL; + RsGxsIdOpinionItem* op_item = NULL; + RsGxsIdCommentItem* com_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsIdGroupItem(grp_item, data, size); + } + else if((op_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsIdOpinionItem(op_item, data, size); + } + else if((com_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsIdCommentItem(com_item, data, size); + } + std::cerr << "RsGxsIdSerialiser::serialise() ERROR invalid item" << std::endl; + return false; +} + +RsItem* RsGxsIdSerialiser::deserialise(void* data, uint32_t* size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSID != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_GXSID_GROUP_ITEM: + return deserialiseGxsIdGroupItem(data, size); + break; + case RS_PKT_SUBTYPE_GXSID_OPINION_ITEM: + return deserialiseGxsIdOpinionItem(data, size); + break; + case RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM: + return deserialiseGxsIdCommentItem(data, size); + break; + default: +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; +#endif + break; + } + return NULL; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsIdGroupItem::clear() +{ + group.mPgpIdHash.clear(); + group.mPgpIdSign.clear(); + + group.mPgpKnown = false; + group.mPgpId.clear(); + +} + +std::ostream& RsGxsIdGroupItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsIdGroupItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "PgpIdHash: " << group.mPgpIdHash << std::endl; + printIndent(out, int_Indent); + out << "PgpIdSign: " << group.mPgpIdSign << std::endl; + + printRsItemEnd(out ,"RsGxsIdGroupItem", indent); + return out; +} + + +uint32_t RsGxsIdSerialiser::sizeGxsIdGroupItem(RsGxsIdGroupItem *item) +{ + + const RsGxsIdGroup& group = item->group; + uint32_t s = 8; // header + + s += GetTlvStringSize(group.mPgpIdHash); + s += GetTlvStringSize(group.mPgpIdSign); + + return s; +} + +bool RsGxsIdSerialiser::serialiseGxsIdGroupItem(RsGxsIdGroupItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsIdGroupItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem() Size too small" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsIdGroupItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mPgpIdHash); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mPgpIdSign); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsIdGroupItem* RsGxsIdSerialiser::deserialiseGxsIdGroupItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSID != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSID_GROUP_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->group.mPgpIdHash); + ok &= GetTlvString(data, rssize, &offset, 1, item->group.mPgpIdSign); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsIdOpinionItem::clear() +{ + opinion.mOpinion = 0; + + // Others that aren't serialised. - but should be cleared anyway + opinion.mReputation = 0; +} + +std::ostream& RsGxsIdOpinionItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsIdOpinionItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Opinion: " << opinion.mOpinion << std::endl; + + printRsItemEnd(out ,"RsGxsIdOpinionItem", indent); + return out; +} + + +uint32_t RsGxsIdSerialiser::sizeGxsIdOpinionItem(RsGxsIdOpinionItem *item) +{ + + const RsGxsIdOpinion& opinion = item->opinion; + uint32_t s = 8; // header + + s += 4; // mOpinion. + + return s; +} + +bool RsGxsIdSerialiser::serialiseGxsIdOpinionItem(RsGxsIdOpinionItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdOpinionItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsIdOpinionItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdOpinionItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsIdOpinionItem */ + ok &= setRawUInt32(data, tlvsize, &offset, item->opinion.mOpinion); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdOpinionItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsIdOpinionItem* RsGxsIdSerialiser::deserialiseGxsIdOpinionItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdOpinionItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSID != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSID_OPINION_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdOpinionItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdOpinionItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsIdOpinionItem* item = new RsGxsIdOpinionItem(); + /* skip the header */ + offset += 8; + + ok &= getRawUInt32(data, rssize, &offset, &(item->opinion.mOpinion)); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdOpinionItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdOpinionItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsIdCommentItem::clear() +{ + comment.mComment.clear(); +} + +std::ostream& RsGxsIdCommentItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsIdCommentItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Comment: " << comment.mComment << std::endl; + + printRsItemEnd(out ,"RsGxsIdCommentItem", indent); + return out; +} + + +uint32_t RsGxsIdSerialiser::sizeGxsIdCommentItem(RsGxsIdCommentItem *item) +{ + + const RsGxsIdComment& comment = item->comment; + uint32_t s = 8; // header + + s += GetTlvStringSize(comment.mComment); + + return s; +} + +bool RsGxsIdSerialiser::serialiseGxsIdCommentItem(RsGxsIdCommentItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdCommentItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsIdCommentItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdCommentItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsIdCommentItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->comment.mComment); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdCommentItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsIdCommentItem* RsGxsIdSerialiser::deserialiseGxsIdCommentItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdCommentItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_GXSID != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdCommentItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdCommentItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsIdCommentItem* item = new RsGxsIdCommentItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->comment.mComment); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdCommentItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdCommentItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsgxsiditems.h b/libretroshare/src/serialiser/rsgxsiditems.h new file mode 100644 index 000000000..a07e52732 --- /dev/null +++ b/libretroshare/src/serialiser/rsgxsiditems.h @@ -0,0 +1,112 @@ +/* + * libretroshare/src/serialiser: rsgxsiditems.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RS_GXS_IDENTITY_ITEMS_H +#define RS_GXS_IDENTITY_ITEMS_H + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "rsgxsitems.h" +#include "retroshare/rsidentity.h" + +const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_GXSID_OPINION_ITEM = 0x03; +const uint8_t RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM = 0x04; + +class RsGxsIdGroupItem : public RsGxsGrpItem +{ + +public: + + RsGxsIdGroupItem(): RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_GXSID, + RS_PKT_SUBTYPE_GXSID_GROUP_ITEM) { return;} + virtual ~RsGxsIdGroupItem() { return;} + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + + RsGxsIdGroup group; +}; + +class RsGxsIdOpinionItem : public RsGxsMsgItem +{ +public: + + RsGxsIdOpinionItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_GXSID, + RS_PKT_SUBTYPE_GXSID_OPINION_ITEM) {return; } + virtual ~RsGxsIdOpinionItem() { return;} + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsGxsIdOpinion opinion; +}; + +class RsGxsIdCommentItem : public RsGxsMsgItem +{ +public: + + RsGxsIdCommentItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_GXSID, + RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM) { return; } + virtual ~RsGxsIdCommentItem() { return; } + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsGxsIdComment comment; + +}; + +class RsGxsIdSerialiser : public RsSerialType +{ +public: + + RsGxsIdSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_GXSID) + { return; } + virtual ~RsGxsIdSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + private: + + uint32_t sizeGxsIdGroupItem(RsGxsIdGroupItem *item); + bool serialiseGxsIdGroupItem (RsGxsIdGroupItem *item, void *data, uint32_t *size); + RsGxsIdGroupItem * deserialiseGxsIdGroupItem(void *data, uint32_t *size); + + uint32_t sizeGxsIdOpinionItem(RsGxsIdOpinionItem *item); + bool serialiseGxsIdOpinionItem (RsGxsIdOpinionItem *item, void *data, uint32_t *size); + RsGxsIdOpinionItem * deserialiseGxsIdOpinionItem(void *data, uint32_t *size); + + uint32_t sizeGxsIdCommentItem(RsGxsIdCommentItem *item); + bool serialiseGxsIdCommentItem (RsGxsIdCommentItem *item, void *data, uint32_t *size); + RsGxsIdCommentItem * deserialiseGxsIdCommentItem(void *data, uint32_t *size); + +}; + +#endif /* RS_GXS_IDENTITY_ITEMS_H */ diff --git a/libretroshare/src/serialiser/rsgxsitems.cc b/libretroshare/src/serialiser/rsgxsitems.cc index 6b05d22fb..00fc2b100 100644 --- a/libretroshare/src/serialiser/rsgxsitems.cc +++ b/libretroshare/src/serialiser/rsgxsitems.cc @@ -8,6 +8,7 @@ #include "rsgxsitems.h" #include "gxs/rsgxsdata.h" +#include void RsMsgMetaData::operator =(const RsGxsMsgMetaData& rGxsMeta) { @@ -22,6 +23,8 @@ this->mParentId = rGxsMeta.mParentId; this->mPublishTs = rGxsMeta.mPublishTs; this->mThreadId = rGxsMeta.mThreadId; + this->mServiceString = rGxsMeta.mServiceString; + } @@ -37,4 +40,31 @@ this->mPublishTs = rGxsMeta.mPublishTs; this->mSubscribeFlags = rGxsMeta.mSubscribeFlags; this->mGroupName = rGxsMeta.mGroupName; + this->mServiceString = rGxsMeta.mServiceString; + this->mSignFlags = rGxsMeta.mSignFlags; + this->mCircleId = rGxsMeta.mCircleId; + this->mCircleType = rGxsMeta.mCircleType; + this->mInternalCircle = rGxsMeta.mInternalCircle; + this->mOriginator = rGxsMeta.mOriginator; } + + +std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta) +{ + out << "[ GroupId: " << meta.mGroupId << " Name: " << meta.mGroupName << " ]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta) +{ + out << "[ GroupId: " << meta.mGroupId << " MsgId: " << meta.mMsgId; + out << " Name: " << meta.mMsgName; + out << " OrigMsgId: " << meta.mOrigMsgId; + out << " ThreadId: " << meta.mThreadId; + out << " ParentId: " << meta.mParentId; + out << " AuthorId: " << meta.mAuthorId; + out << " Name: " << meta.mMsgName << " ]"; + return out; +} + + diff --git a/libretroshare/src/serialiser/rsgxsitems.h b/libretroshare/src/serialiser/rsgxsitems.h index f13ca774b..346cc14a1 100644 --- a/libretroshare/src/serialiser/rsgxsitems.h +++ b/libretroshare/src/serialiser/rsgxsitems.h @@ -28,48 +28,62 @@ #include "serialiser/rsserviceids.h" #include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" #include "serialiser/rstlvtypes.h" #include "serialiser/rstlvkeys.h" class RsGxsGrpMetaData; class RsGxsMsgMetaData; + class RsGroupMetaData { - public: +public: - RsGroupMetaData() - { - mGroupFlags = 0; - mSubscribeFlags = 0; + RsGroupMetaData() + { + mGroupFlags = 0; + mSubscribeFlags = 0; - mPop = 0; - mMsgCount = 0; - mLastPost = 0; - mGroupStatus = 0; + mPop = 0; + mMsgCount = 0; + mLastPost = 0; - //mPublishTs = 0; - } + mGroupStatus = 0; + mCircleType = 0; - void operator =(const RsGxsGrpMetaData& rGxsMeta); + //mPublishTs = 0; + } - std::string mGroupId; - std::string mGroupName; - uint32_t mGroupFlags; + void operator =(const RsGxsGrpMetaData& rGxsMeta); - time_t mPublishTs; // Mandatory. - std::string mAuthorId; // Optional. + std::string mGroupId; + std::string mGroupName; + uint32_t mGroupFlags; + uint32_t mSignFlags; // Combination of RSGXS_GROUP_SIGN_PUBLISH_MASK & RSGXS_GROUP_SIGN_AUTHOR_MASK. + + time_t mPublishTs; // Mandatory. + std::string mAuthorId; // Optional. + + // for circles + std::string mCircleId; + uint32_t mCircleType; + + // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. + + uint32_t mSubscribeFlags; + + uint32_t mPop; // HOW DO WE DO THIS NOW. + uint32_t mMsgCount; // ??? + time_t mLastPost; // ??? + + uint32_t mGroupStatus; + std::string mServiceString; // Service Specific Free-Form extra storage. + std::string mOriginator; + std::string mInternalCircle; - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - uint32_t mSubscribeFlags; - uint32_t mPop; // HOW DO WE DO THIS NOW. - uint32_t mMsgCount; // ??? - time_t mLastPost; // ??? - uint32_t mGroupStatus; }; @@ -78,40 +92,50 @@ class RsGroupMetaData class RsMsgMetaData { - public: - RsMsgMetaData() - { - mPublishTs = 0; - mMsgFlags = 0; - mMsgStatus = 0; - mChildTs = 0; - } +public: - void operator =(const RsGxsMsgMetaData& rGxsMeta); + RsMsgMetaData() + { + mPublishTs = 0; + mMsgFlags = 0; + + mMsgStatus = 0; + mChildTs = 0; + } + + void operator =(const RsGxsMsgMetaData& rGxsMeta); - std::string mGroupId; - std::string mMsgId; + std::string mGroupId; + std::string mMsgId; - std::string mThreadId; - std::string mParentId; - std::string mOrigMsgId; + std::string mThreadId; + std::string mParentId; + std::string mOrigMsgId; - std::string mAuthorId; + std::string mAuthorId; - std::string mMsgName; - time_t mPublishTs; + std::string mMsgName; + time_t mPublishTs; - uint32_t mMsgFlags; // Whats this for? + /// the first 16 bits for service, last 16 for GXS + uint32_t mMsgFlags; - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - // normally READ / UNREAD flags. LOCAL Data. - uint32_t mMsgStatus; - time_t mChildTs; + // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. + // normally READ / UNREAD flags. LOCAL Data. + + /// the first 16 bits for service, last 16 for GXS + uint32_t mMsgStatus; + + time_t mChildTs; + std::string mServiceString; // Service Specific Free-Form extra storage. }; +std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta); +std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta); + class RsGxsGrpItem : public RsItem { @@ -122,6 +146,7 @@ public: : RsItem(RS_PKT_VERSION_SERVICE, service, subtype) { return; } virtual ~RsGxsGrpItem(){} + RsGroupMetaData meta; }; diff --git a/libretroshare/src/serialiser/rsnxsitems.h b/libretroshare/src/serialiser/rsnxsitems.h index 02a5fdafe..1a7f72fcd 100644 --- a/libretroshare/src/serialiser/rsnxsitems.h +++ b/libretroshare/src/serialiser/rsnxsitems.h @@ -34,7 +34,6 @@ #include "serialiser/rstlvbase.h" #include "serialiser/rstlvtypes.h" #include "serialiser/rstlvkeys.h" - #include "gxs/rsgxsdata.h" @@ -69,7 +68,11 @@ class RsNxsItem : public RsItem public: RsNxsItem(uint16_t servtype, uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0) { return; } + : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0) + { + setPriorityLevel(QOS_PRIORITY_RS_VOIP_PING); + return; + } virtual void clear() = 0; virtual std::ostream &print(std::ostream &out, uint16_t indent = 0) = 0; @@ -196,7 +199,7 @@ public: RsTlvBinaryData grp; /// actual group data /*! - * This should contains all the data + * This should contains all data * which is not specific to the Gxs service data */ RsTlvBinaryData meta; @@ -259,7 +262,9 @@ class RsNxsMsg : public RsNxsItem { public: - RsNxsMsg(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_MSG), msg(servtype), meta(servtype) { clear(); return; } + RsNxsMsg(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_MSG), meta(servtype), msg(servtype), + metaData(NULL) { clear(); return; } + ~RsNxsMsg() { if(metaData) delete metaData; } virtual void clear(); virtual std::ostream &print(std::ostream &out, uint16_t indent); @@ -294,7 +299,7 @@ public: virtual ~RsNxsSearchReq() { return;} virtual void clear() { return;} - virtual std::ostream &print(std::ostream &out, uint16_t indent) { return out; } + virtual std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } uint8_t nHops; /// how many peers to jump to uint32_t token; // search token @@ -332,7 +337,7 @@ public: RsNxsSearchResultMsg() : context(0) { return;} void clear() {} - std::ostream &print(std::ostream &out, uint16_t indent) { return out; } + std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } uint32_t token; // search token to be redeemed RsTlvBinaryData context; // used by client service @@ -353,7 +358,7 @@ public: RsNxsSearchResultGrp(); void clear() {} - std::ostream &print(std::ostream &out, uint16_t indent) { return out; } + std::ostream &print(std::ostream &out, uint16_t /*indent*/) { return out; } uint32_t token; // search token to be redeemed diff --git a/libretroshare/src/serialiser/rsphotoitems.cc b/libretroshare/src/serialiser/rsphotoitems.cc index 7216f95b4..7d08c6373 100644 --- a/libretroshare/src/serialiser/rsphotoitems.cc +++ b/libretroshare/src/serialiser/rsphotoitems.cc @@ -1,10 +1,9 @@ - /* - * libretroshare/src/serialiser: rsphotoitems.cc + * libretroshare/src/retroshare: rsphoto.h * - * RetroShare Serialiser. + * RetroShare C++ Interface. * - * Copyright 2007-2008 by Robert Fernie. + * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,267 +23,631 @@ * */ -#include "serialiser/rsbaseserial.h" -#include "serialiser/rsphotoitems.h" -#include "serialiser/rstlvbase.h" - -#define RSSERIAL_DEBUG 1 #include -/*************************************************************************/ +#include "rsphotoitems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" -void RsPhotoItem::clear() +#define GXS_PHOTO_SERIAL_DEBUG + + +uint32_t RsGxsPhotoSerialiser::size(RsItem* item) { - srcId.clear(); - photoId.clear(); - size = 0; + RsGxsPhotoPhotoItem* ppItem = NULL; + RsGxsPhotoAlbumItem* paItem = NULL; + RsGxsPhotoCommentItem* cItem = NULL; - name.clear(); - comment.clear(); - - location.clear(); - date.clear(); - - /* not serialised */ - isAvailable = false; - path.clear(); -} - -std::ostream &RsPhotoItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsPhotoItem", indent); - uint16_t int_Indent = indent + 2; - printIndent(out, int_Indent); - out << "srcId: " << srcId << std::endl; - printIndent(out, int_Indent); - out << "photoId: " << photoId << std::endl; - printIndent(out, int_Indent); - out << "size: " << size << std::endl; - - printIndent(out, int_Indent); - out << "name: " << name << std::endl; - - printIndent(out, int_Indent); - std::string cnv_comment(comment.begin(), comment.end()); - out << "msg: " << cnv_comment << std::endl; - - printIndent(out, int_Indent); - out << "location: " << location << std::endl; - printIndent(out, int_Indent); - out << "date: " << date << std::endl; - - printIndent(out, int_Indent); - out << "(NS) isAvailable: " << isAvailable << std::endl; - printIndent(out, int_Indent); - out << "(NS) path: " << path << std::endl; - - printRsItemEnd(out, "RsPhotoItem", indent); - return out; -} - -/*************************************************************************/ -/*************************************************************************/ - -void RsPhotoShowItem::clear() -{ - showId.clear(); - name.clear(); - comment.clear(); - - location.clear(); - date.clear(); - - photos.clear(); -} - -std::ostream &RsPhotoShowItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsPhotoShowItem", indent); - uint16_t int_Indent = indent + 2; - uint16_t int_Indent2 = int_Indent + 2; - - printIndent(out, int_Indent); - out << "showId: " << showId << std::endl; - printIndent(out, int_Indent); - out << "name: " << name << std::endl; - - printIndent(out, int_Indent); - std::string cnv_comment(comment.begin(), comment.end()); - out << "msg: " << cnv_comment << std::endl; - - printIndent(out, int_Indent); - out << "location: " << location << std::endl; - printIndent(out, int_Indent); - out << "date: " << date << std::endl; - - printIndent(out, int_Indent); - out << "Photos in Show: " << photos.size() << std::endl; - - std::list::iterator it; - for(it = photos.begin(); it != photos.end(); it++) + if((ppItem = dynamic_cast(item)) != NULL) { - printIndent(out, int_Indent2); - out << "PhotoId: " << it->photoId << std::endl; - printIndent(out, int_Indent2 + 2); - std::string cnv_comment2(it->altComment.begin(), it->altComment.end()); - out << "AltComment: " << cnv_comment2 << std::endl; - printIndent(out, int_Indent2 + 2); - out << "Delta T: " << it->deltaT << std::endl; + return sizeGxsPhotoPhotoItem(ppItem); + } + else if((paItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPhotoAlbumItem(paItem); + } + else if((cItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPhotoCommentItem(cItem); + } + else + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + +#endif + return NULL; } - printRsItemEnd(out, "RsPhotoShowItem", indent); - return out; } -RsPhotoRefItem::RsPhotoRefItem() - :deltaT(0) +bool RsGxsPhotoSerialiser::serialise(RsItem* item, void* data, uint32_t* size) { - return; + + RsGxsPhotoPhotoItem* ppItem = NULL; + RsGxsPhotoAlbumItem* paItem = NULL; + RsGxsPhotoCommentItem* cItem = NULL; + + if((ppItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPhotoPhotoItem(ppItem, data, size); + } + else if((paItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPhotoAlbumItem(paItem, data, size); + }else if((cItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPhotoCommentItem(cItem, data, size); + } + else + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + +#endif + return false; + } + } -/*************************************************************************/ -/*************************************************************************/ -/*************************************************************************/ - -/* TODO serialiser */ - -#if 0 - -uint32_t RsPhotoSerialiser::sizeLink(RsPhotoLinkMsg *item) +RsItem* RsGxsPhotoSerialiser::deserialise(void* data, uint32_t* size) { - uint32_t s = 8; /* header */ - s += GetTlvStringSize(item->rid); - s += 4; /* timestamp */ - s += GetTlvWideStringSize(item->title); - s += GetTlvWideStringSize(item->comment); - s += 4; /* linktype */ - s += GetTlvWideStringSize(item->link); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_PHOTO != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM: + return deserialiseGxsPhotoPhotoItem(data, size); + case RS_PKT_SUBTYPE_PHOTO_ITEM: + return deserialiseGxsPhotoAlbumItem(data, size); + case RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM: + return deserialiseGxsPhotoCommentItem(data, size); + default: + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialise(): subtype could not be dealt with" + << std::endl; +#endif + break; + } + } + return NULL; +} + +uint32_t RsGxsPhotoSerialiser::sizeGxsPhotoAlbumItem(RsGxsPhotoAlbumItem* item) +{ + + const RsPhotoAlbum& album = item->album; + uint32_t s = 8; // header + + s += GetTlvStringSize(album.mCaption); + s += GetTlvStringSize(album.mCategory); + s += GetTlvStringSize(album.mDescription); + s += GetTlvStringSize(album.mHashTags); + s += GetTlvStringSize(album.mOther); + s += GetTlvStringSize(album.mPhotoPath); + s += GetTlvStringSize(album.mPhotographer); + s += GetTlvStringSize(album.mWhen); + s += GetTlvStringSize(album.mWhere); + + RsTlvBinaryData b(item->PacketService()); // TODO, need something more persisitent + b.setBinData(album.mThumbnail.data, album.mThumbnail.size); + s += GetTlvStringSize(album.mThumbnail.type); + s += b.TlvSize(); return s; } -/* serialise the data to the buffer */ -bool RsPhotoSerialiser::serialiseLink(RsPhotoLinkMsg *item, void *data, uint32_t *pktsize) +uint32_t RsGxsPhotoSerialiser::sizeGxsPhotoCommentItem(RsGxsPhotoCommentItem *item) { - uint32_t tlvsize = sizeLink(item); - uint32_t offset = 0; - if (*pktsize < tlvsize) - return false; /* not enough space */ + const RsPhotoComment& comment = item->comment; + uint32_t s = 8; // header - *pktsize = tlvsize; + s += GetTlvStringSize(comment.mComment); + s += 4; // mflags - bool ok = true; + return s; - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Header: " << ok << std::endl; - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Size: " << tlvsize << std::endl; - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->rid); - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() rid: " << ok << std::endl; - - ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() timestamp: " << ok << std::endl; - - ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_TITLE, item->title); - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Title: " << ok << std::endl; - ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Comment: " << ok << std::endl; - - ok &= setRawUInt32(data, tlvsize, &offset, item->linktype); - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() linktype: " << ok << std::endl; - - ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_LINK, item->link); - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Link: " << ok << std::endl; - - if (offset != tlvsize) - { - ok = false; - std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Size Error! " << std::endl; - } - - return ok; } -RsPhotoLinkMsg *RsPhotoSerialiser::deserialiseLink(void *data, uint32_t *pktsize) +bool RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem(RsGxsPhotoAlbumItem* item, void* data, + uint32_t* size) { - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_RANK != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_RANK_LINK != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*pktsize < rssize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *pktsize = rssize; - - bool ok = true; - - /* ready to load */ - RsPhotoLinkMsg *item = new RsPhotoLinkMsg(); - item->clear(); - - /* skip the header */ - offset += 8; - - /* get mandatory parts first */ - ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GENID, item->rid); - ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); - ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_TITLE, item->title); - ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); - ok &= getRawUInt32(data, rssize, &offset, &(item->linktype)); - ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_LINK, item->link); - - if (offset != rssize) - { - /* error */ - delete item; - return NULL; - } - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - - -uint32_t RsPhotoSerialiser::size(RsItem *item) -{ - return sizeLink((RsPhotoLinkMsg *) item); -} - -bool RsPhotoSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) -{ - return serialiseLink((RsPhotoLinkMsg *) item, data, pktsize); -} - -RsItem *RsPhotoSerialiser::deserialise(void *data, uint32_t *pktsize) -{ - return deserialiseLink(data, pktsize); -} - +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem()" << std::endl; #endif + uint32_t tlvsize = sizeGxsPhotoAlbumItem(item); + uint32_t offset = 0; -/*************************************************************************/ + if(*size < tlvsize){ +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsPhotoAlbumItem */ + + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mCaption); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mCategory); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mDescription); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mHashTags); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mOther); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mPhotoPath); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mPhotographer); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mWhen); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mWhere); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mThumbnail.type); + RsTlvBinaryData b(RS_SERVICE_GXSV1_TYPE_PHOTO); // TODO, need something more persisitent + b.setBinData(item->album.mThumbnail.data, item->album.mThumbnail.size); + ok &= b.SetTlv(data, tlvsize, &offset); + + if(offset != tlvsize) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_PHOTO_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem() NOK" << std::endl; + } +#endif + + return ok; +} + +RsGxsPhotoAlbumItem* RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem(void* data, + uint32_t* size) +{ + + +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_PHOTO != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_PHOTO_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPhotoAlbumItem* item = new RsGxsPhotoAlbumItem(); + /* skip the header */ + offset += 8; + + + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mCaption); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mCategory); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mDescription); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mHashTags); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mOther); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mPhotoPath); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mPhotographer); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mWhen); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mWhere); + ok &= GetTlvString(data, rssize, &offset, 1, item->album.mThumbnail.type); + + RsTlvBinaryData b(RS_SERVICE_GXSV1_TYPE_PHOTO); // TODO, need something more persisitent + ok &= b.GetTlv(data, rssize, &offset); + item->album.mThumbnail.data = (uint8_t*)b.bin_data; + item->album.mThumbnail.size = b.bin_len; + b.TlvShallowClear(); + + if (offset != rssize) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +uint32_t RsGxsPhotoSerialiser::sizeGxsPhotoPhotoItem(RsGxsPhotoPhotoItem* item) +{ + + const RsPhotoPhoto& photo = item->photo; + + uint32_t s = 8; // header size + s += GetTlvStringSize(photo.mCaption); + s += GetTlvStringSize(photo.mCategory); + s += GetTlvStringSize(photo.mDescription); + s += GetTlvStringSize(photo.mHashTags); + s += GetTlvStringSize(photo.mOther); + s += GetTlvStringSize(photo.mPhotographer); + s += GetTlvStringSize(photo.mWhen); + s += GetTlvStringSize(photo.mWhere); + + RsTlvBinaryData b(item->PacketService()); // TODO, need something more persisitent + b.setBinData(photo.mThumbnail.data, photo.mThumbnail.size); + s += GetTlvStringSize(photo.mThumbnail.type); + s += b.TlvSize(); + + return s; +} + +bool RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem(RsGxsPhotoPhotoItem* item, void* data, + uint32_t* size) +{ + + +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsPhotoPhotoItem(item); + uint32_t offset = 0; + + if(*size < tlvsize){ +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsPhotoAlbumItem */ + + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mCaption); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mCategory); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mDescription); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mHashTags); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mOther); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mPhotographer); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mWhen); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mWhere); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mThumbnail.type); + RsTlvBinaryData b(RS_SERVICE_GXSV1_TYPE_PHOTO); // TODO, need something more persisitent + b.setBinData(item->photo.mThumbnail.data, item->photo.mThumbnail.size); + ok &= b.SetTlv(data, tlvsize, &offset); + + if(offset != tlvsize) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_PHOTO_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem() NOK" << std::endl; + } +#endif + + return ok; +} + +RsGxsPhotoPhotoItem* RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem(void* data, + uint32_t* size) +{ + + +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_PHOTO != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPhotoPhotoItem* item = new RsGxsPhotoPhotoItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mCaption); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mCategory); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mDescription); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mHashTags); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mOther); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mPhotographer); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mWhen); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mWhere); + ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mThumbnail.type); + + RsTlvBinaryData b(RS_SERVICE_GXSV1_TYPE_PHOTO); // TODO, need something more persisitent + ok &= b.GetTlv(data, rssize, &offset); + item->photo.mThumbnail.data = (uint8_t*)(b.bin_data); + item->photo.mThumbnail.size = b.bin_len; + b.TlvShallowClear(); + + if (offset != rssize) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +bool RsGxsPhotoSerialiser::serialiseGxsPhotoCommentItem (RsGxsPhotoCommentItem *item, void *data, uint32_t *size) +{ + + +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoCommentItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsPhotoCommentItem(item); + uint32_t offset = 0; + + if(*size < tlvsize){ +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoCommentItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsPhotoAlbumItem */ + + ok &= SetTlvString(data, tlvsize, &offset, 0, item->comment.mComment); + ok &= setRawUInt32(data, tlvsize, &offset, item->comment.mCommentFlag); + + if(offset != tlvsize) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoCommentItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_PHOTO_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoCommentItem() NOK" << std::endl; + } +#endif + + return ok; +} + +RsGxsPhotoCommentItem * RsGxsPhotoSerialiser::deserialiseGxsPhotoCommentItem(void *data, uint32_t *size) +{ + + +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_PHOTO != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoCommentItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoCommentItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPhotoCommentItem* item = new RsGxsPhotoCommentItem(); + + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 0, item->comment.mComment); + ok &= getRawUInt32(data, rssize, &offset, &(item->comment.mCommentFlag)); + + if (offset != rssize) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoCommentItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_PHOTO_SERIAL_DEBUG + std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoCommentItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +void RsGxsPhotoAlbumItem::clear() +{ + album.mCaption.clear(); + album.mCategory.clear(); + album.mDescription.clear(); + album.mHashTags.clear(); + album.mOther.clear(); + album.mPhotoPath.clear(); + album.mPhotographer.clear(); + album.mWhen.clear(); + album.mWhere.clear(); + album.mThumbnail.deleteImage(); +} + +void RsGxsPhotoCommentItem::clear() +{ + comment.mComment.clear(); + comment.mCommentFlag = 0; +} + +std::ostream& RsGxsPhotoCommentItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsPhotoCommentItem", indent); + uint16_t int_Indent = indent + 2; + + + printRsItemEnd(out ,"RsGxsPhotoCommentItem", indent); + return out; +} + +std::ostream& RsGxsPhotoAlbumItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsPhotoAlbumItem", indent); + uint16_t int_Indent = indent + 2; + + out << album << std::endl; + + printRsItemEnd(out ,"RsGxsPhotoAlbumItem", indent); + return out; +} + +void RsGxsPhotoPhotoItem::clear() +{ + photo.mCaption.clear(); + photo.mCategory.clear(); + photo.mDescription.clear(); + photo.mHashTags.clear(); + photo.mOther.clear(); + photo.mPhotographer.clear(); + photo.mWhen.clear(); + photo.mWhere.clear(); + photo.mThumbnail.deleteImage(); +} + +std::ostream& RsGxsPhotoPhotoItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsPhotoPhotoItem", indent); + uint16_t int_Indent = indent + 2; + + + printRsItemEnd(out ,"RsGxsPhotoPhotoItem", indent); + return out; +} diff --git a/libretroshare/src/serialiser/rsphotoitems.h b/libretroshare/src/serialiser/rsphotoitems.h index 8281af2f1..f03135340 100644 --- a/libretroshare/src/serialiser/rsphotoitems.h +++ b/libretroshare/src/serialiser/rsphotoitems.h @@ -1,12 +1,9 @@ -#ifndef P3_PHOTO_ITEMS_H -#define P3_PHOTO_ITEMS_H - /* - * libretroshare/src/serialiser: rsphotoitems.h + * libretroshare/src/retroshare: rsphoto.h * - * RetroShare Serialiser. + * RetroShare C++ Interface. * - * Copyright 2007-2008 by Robert Fernie. + * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,113 +23,91 @@ * */ +#ifndef RSPHOTOV2ITEMS_H_ +#define RSPHOTOV2ITEMS_H_ + #include #include "serialiser/rsserviceids.h" #include "serialiser/rsserial.h" #include "serialiser/rstlvtypes.h" +#include "rsgxsitems.h" +#include "retroshare/rsphoto.h" + const uint8_t RS_PKT_SUBTYPE_PHOTO_ITEM = 0x02; const uint8_t RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM = 0x03; const uint8_t RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM = 0x04; -/**************************************************************************/ - -class RsPhotoItem; -class RsPhotoShowItem; -class RsPhotoCommentItem; - -class RsPhotoItem: public RsItem +class RsGxsPhotoAlbumItem : public RsGxsGrpItem { - public: - RsPhotoItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO, - RS_PKT_SUBTYPE_PHOTO_ITEM) { return; } -virtual ~RsPhotoItem() { return; } -virtual void clear(); -virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); +public: - std::string srcId; - std::string photoId; /* same as hash */ - uint64_t size; /* file size */ + RsGxsPhotoAlbumItem(): RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_PHOTO, + RS_PKT_SUBTYPE_PHOTO_ITEM) { return;} + virtual ~RsGxsPhotoAlbumItem() { return;} - std::string name; - std::wstring comment; + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); - std::string location; /* TODO: change to TLV */ - std::string date; /* TODO: change to TLV */ - /* not serialised */ - bool isAvailable; - std::string path; + RsPhotoAlbum album; }; -/* THIS must be turned into a TLV type + set (TOD) */ -class RsPhotoRefItem +class RsGxsPhotoPhotoItem : public RsGxsMsgItem { - public: - RsPhotoRefItem(); +public: - std::string photoId; - std::wstring altComment; - uint32_t deltaT; /* in 100ths of sec? */ + RsGxsPhotoPhotoItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_PHOTO, + RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM) {return; } + virtual ~RsGxsPhotoPhotoItem() { return;} + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsPhotoPhoto photo; }; -class RsPhotoShowItem: public RsItem +class RsGxsPhotoCommentItem : public RsGxsMsgItem { - public: - RsPhotoShowItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO, - RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM) { return; } +public: -virtual ~RsPhotoShowItem() { return; } -virtual void clear(); -virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + RsGxsPhotoCommentItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_PHOTO, + RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM) { return; } + virtual ~RsGxsPhotoCommentItem() { return; } + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsPhotoComment comment; - std::string showId; - std::string name; - std::wstring comment; - - std::string location; /* TODO -> TLV */ - std::string date; /* TODO -> TLV */ - std::list photos; /* list as ordered */ }; -class RsPhotoSerialiser: public RsSerialType +class RsGxsPhotoSerialiser : public RsSerialType { - public: - RsPhotoSerialiser() - :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO) +public: + + RsGxsPhotoSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_PHOTO) { return; } -virtual ~RsPhotoSerialiser() - { return; } - -virtual uint32_t size(RsItem *) { return 0; } -virtual bool serialise (RsItem */*item*/, void */*data*/, uint32_t */*size*/) { return false; } -virtual RsItem * deserialise(void */*data*/, uint32_t */*size*/) { return NULL; } + virtual ~RsGxsPhotoSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); private: - /* For RS_PKT_SUBTYPE_PHOTO_ITEM */ -//virtual uint32_t sizeLink(RsPhotoItem *); -//virtual bool serialiseLink (RsPhotoItem *item, void *data, uint32_t *size); -//virtual RsPhotoItem *deserialiseLink(void *data, uint32_t *size); + uint32_t sizeGxsPhotoAlbumItem(RsGxsPhotoAlbumItem *item); + bool serialiseGxsPhotoAlbumItem (RsGxsPhotoAlbumItem *item, void *data, uint32_t *size); + RsGxsPhotoAlbumItem * deserialiseGxsPhotoAlbumItem(void *data, uint32_t *size); - /* For RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM */ -//virtual uint32_t sizeLink(RsPhotoShowItem *); -//virtual bool serialiseLink (RsPhotoShowItem *item, void *data, uint32_t *size); -//virtual RsPhotoShowItem *deserialiseLink(void *data, uint32_t *size); + uint32_t sizeGxsPhotoPhotoItem(RsGxsPhotoPhotoItem *item); + bool serialiseGxsPhotoPhotoItem (RsGxsPhotoPhotoItem *item, void *data, uint32_t *size); + RsGxsPhotoPhotoItem * deserialiseGxsPhotoPhotoItem(void *data, uint32_t *size); - /* For RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM */ -//virtual uint32_t sizeLink(RsPhotoCommentItem *); -//virtual bool serialiseLink (RsPhotoCommentItem *item, void *data, uint32_t *size); -//virtual RsPhotoCommentItem *deserialiseLink(void *data, uint32_t *size); + uint32_t sizeGxsPhotoCommentItem(RsGxsPhotoCommentItem *item); + bool serialiseGxsPhotoCommentItem (RsGxsPhotoCommentItem *item, void *data, uint32_t *size); + RsGxsPhotoCommentItem * deserialiseGxsPhotoCommentItem(void *data, uint32_t *size); }; -/**************************************************************************/ - -#endif /* RS_PHOTO_ITEMS_H */ - +#endif /* RSPHOTOV2ITEMS_H_ */ diff --git a/libretroshare/src/serialiser/rsphotov2items.cc b/libretroshare/src/serialiser/rsphotov2items.cc deleted file mode 100644 index 921deca22..000000000 --- a/libretroshare/src/serialiser/rsphotov2items.cc +++ /dev/null @@ -1,491 +0,0 @@ -/* - * libretroshare/src/retroshare: rsphoto.h - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "rsphotov2items.h" - -#define GXS_PHOTO_SERIAL_DEBUG - - -uint32_t RsGxsPhotoSerialiser::size(RsItem* item) -{ - - RsGxsPhotoPhotoItem* ppItem = NULL; - RsGxsPhotoAlbumItem* paItem = NULL; - - if((ppItem = dynamic_cast(item)) != NULL) - { - return sizeGxsPhotoPhotoItem(ppItem); - } - else if((paItem = dynamic_cast(item)) != NULL) - { - return sizeGxsPhotoAlbumItem(paItem); - } - else - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - -#endif - return NULL; - } - -} - -bool RsGxsPhotoSerialiser::serialise(RsItem* item, void* data, uint32_t* size) -{ - - RsGxsPhotoPhotoItem* ppItem = NULL; - RsGxsPhotoAlbumItem* paItem = NULL; - - if((ppItem = dynamic_cast(item)) != NULL) - { - return serialiseGxsPhotoPhotoItem(ppItem, data, size); - } - else if((paItem = dynamic_cast(item)) != NULL) - { - return serialiseGxsPhotoAlbumItem(paItem, data, size); - } - else - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - -#endif - return false; - } - -} - -RsItem* RsGxsPhotoSerialiser::deserialise(void* data, uint32_t* size) -{ - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialise()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_PHOTO != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - - case RS_PKT_SUBTYPE_NXS_SYNC_GRP: - return deserialiseGxsPhotoPhotoItem(data, size); - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM: - return deserialiseGxsPhotoAlbumItem(data, size); - default: - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialise(): subtype could not be dealt with" - << std::endl; -#endif - break; - } - } - return NULL; -} - -uint32_t RsGxsPhotoSerialiser::sizeGxsPhotoAlbumItem(RsGxsPhotoAlbumItem* item) -{ - - const RsPhotoAlbum& album = item->album; - uint32_t s = 8; // header - - s += GetTlvStringSize(album.mCaption); - s += GetTlvStringSize(album.mCategory); - s += GetTlvStringSize(album.mDescription); - s += GetTlvStringSize(album.mHashTags); - s += GetTlvStringSize(album.mOther); - s += GetTlvStringSize(album.mPhotoPath); - s += GetTlvStringSize(album.mPhotographer); - s += GetTlvStringSize(album.mWhen); - s += GetTlvStringSize(album.mWhere); - - RsTlvBinaryData b(item->PacketService()); // TODO, need something more persisitent - b.setBinData(album.mThumbnail.data, album.mThumbnail.size); - s += GetTlvStringSize(album.mThumbnail.type); - s += b.TlvSize(); - - return s; -} - -bool RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem(RsGxsPhotoAlbumItem* item, void* data, - uint32_t* size) -{ - -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem()" << std::endl; -#endif - - uint32_t tlvsize = sizeGxsPhotoAlbumItem(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* GxsPhotoAlbumItem */ - - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mCaption); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mCategory); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mDescription); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mHashTags); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mOther); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mPhotoPath); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mPhotographer); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mWhen); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mWhere); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->album.mThumbnail.type); - RsTlvBinaryData b(item->PacketService()); // TODO, need something more persisitent - b.setBinData(item->album.mThumbnail.data, item->album.mThumbnail.size); - b.SetTlv(item->album.mThumbnail.data, tlvsize, &offset); - - if(offset != tlvsize) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef GXS_PHOTO_SERIAL_DEBUG - if (!ok) - { - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoAlbumItem() NOK" << std::endl; - } -#endif - - return ok; -} - -RsGxsPhotoAlbumItem* RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem(void* data, - uint32_t* size) -{ - - -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_PHOTO != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_PHOTO_ITEM != getRsItemSubType(rstype))) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsGxsPhotoAlbumItem* item = new RsGxsPhotoAlbumItem(); - /* skip the header */ - offset += 8; - - - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mCaption); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mCategory); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mDescription); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mHashTags); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mOther); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mPhotoPath); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mPhotographer); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mWhen); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mWhere); - ok &= GetTlvString(data, rssize, &offset, 1, item->album.mThumbnail.type); - - RsTlvBinaryData b(RS_SERVICE_TYPE_PHOTO); // TODO, need something more persisitent - ok &= b.GetTlv(data, rssize, &offset); - item->album.mThumbnail.data = (uint8_t*)b.bin_data; - item->album.mThumbnail.size = b.bin_len; - b.TlvShallowClear(); - - if (offset != rssize) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoAlbumItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - -uint32_t RsGxsPhotoSerialiser::sizeGxsPhotoPhotoItem(RsGxsPhotoPhotoItem* item) -{ - - const RsPhotoPhoto& photo = item->photo; - - uint32_t s = 8; // header size - s += GetTlvStringSize(photo.mCaption); - s += GetTlvStringSize(photo.mCategory); - s += GetTlvStringSize(photo.mDescription); - s += GetTlvStringSize(photo.mHashTags); - s += GetTlvStringSize(photo.mOther); - s += GetTlvStringSize(photo.mPhotographer); - s += GetTlvStringSize(photo.mWhen); - s += GetTlvStringSize(photo.mWhere); - - RsTlvBinaryData b(item->PacketService()); // TODO, need something more persisitent - b.setBinData(photo.mThumbnail.data, photo.mThumbnail.size); - s += GetTlvStringSize(photo.mThumbnail.type); - s += b.TlvSize(); - - return s; -} - -bool RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem(RsGxsPhotoPhotoItem* item, void* data, - uint32_t* size) -{ - - -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem()" << std::endl; -#endif - - uint32_t tlvsize = sizeGxsPhotoPhotoItem(item); - uint32_t offset = 0; - - if(*size < tlvsize){ -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* GxsPhotoAlbumItem */ - - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mCaption); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mCategory); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mDescription); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mHashTags); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mOther); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mPhotographer); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mWhen); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mWhere); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->photo.mThumbnail.type); - RsTlvBinaryData b(RS_SERVICE_TYPE_PHOTO); // TODO, need something more persisitent - b.setBinData(item->photo.mThumbnail.data, item->photo.mThumbnail.size); - b.SetTlv(item->photo.mThumbnail.data, tlvsize, &offset); - - if(offset != tlvsize) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef GXS_PHOTO_SERIAL_DEBUG - if (!ok) - { - std::cerr << "RsGxsPhotoSerialiser::serialiseGxsPhotoPhotoItem() NOK" << std::endl; - } -#endif - - return ok; -} - -RsGxsPhotoPhotoItem* RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem(void* data, - uint32_t* size) -{ - - -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_PHOTO != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM != getRsItemSubType(rstype))) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsGxsPhotoPhotoItem* item = new RsGxsPhotoPhotoItem(); - /* skip the header */ - offset += 8; - - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mCaption); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mCategory); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mDescription); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mHashTags); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mOther); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mPhotographer); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mWhen); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mWhere); - ok &= GetTlvString(data, rssize, &offset, 1, item->photo.mThumbnail.type); - - RsTlvBinaryData b(RS_SERVICE_TYPE_PHOTO); // TODO, need something more persisitent - ok &= b.GetTlv(data, rssize, &offset); - item->photo.mThumbnail.data = (uint8_t*)(b.bin_data); - item->photo.mThumbnail.size = b.bin_len; - b.TlvShallowClear(); - - if (offset != rssize) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef GXS_PHOTO_SERIAL_DEBUG - std::cerr << "RsGxsPhotoSerialiser::deserialiseGxsPhotoPhotoItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - -void RsGxsPhotoAlbumItem::clear() -{ - album.mCaption.clear(); - album.mCategory.clear(); - album.mDescription.clear(); - album.mHashTags.clear(); - album.mOther.clear(); - album.mPhotoPath.clear(); - album.mPhotographer.clear(); - album.mWhen.clear(); - album.mWhere.clear(); - album.mThumbnail.deleteImage(); -} - -std::ostream& RsGxsPhotoAlbumItem::print(std::ostream& out, uint16_t indent) -{ - printRsItemBase(out, "RsGxsPhotoAlbumItem", indent); - uint16_t int_Indent = indent + 2; - - - printRsItemEnd(out ,"RsGxsPhotoAlbumItem", indent); - return out; -} - -void RsGxsPhotoPhotoItem::clear() -{ - photo.mCaption.clear(); - photo.mCategory.clear(); - photo.mDescription.clear(); - photo.mHashTags.clear(); - photo.mOther.clear(); - photo.mPhotographer.clear(); - photo.mWhen.clear(); - photo.mWhere.clear(); - photo.mThumbnail.deleteImage(); -} - -std::ostream& RsGxsPhotoPhotoItem::print(std::ostream& out, uint16_t indent) -{ - printRsItemBase(out, "RsGxsPhotoPhotoItem", indent); - uint16_t int_Indent = indent + 2; - - - printRsItemEnd(out ,"RsGxsPhotoPhotoItem", indent); - return out; -} - diff --git a/libretroshare/src/serialiser/rsphotov2items.h b/libretroshare/src/serialiser/rsphotov2items.h deleted file mode 100644 index 89cc9c4f9..000000000 --- a/libretroshare/src/serialiser/rsphotov2items.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * libretroshare/src/retroshare: rsphoto.h - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RSPHOTOV2ITEMS_H_ -#define RSPHOTOV2ITEMS_H_ - -#include - -#include "serialiser/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvtypes.h" - -#include "rsgxsitems.h" -#include "rsphotoitems.h" -#include "retroshare/rsphotoV2.h" - - -class RsGxsPhotoAlbumItem : public RsGxsGrpItem -{ - -public: - - RsGxsPhotoAlbumItem(): RsGxsGrpItem(RS_SERVICE_TYPE_PHOTO, - RS_PKT_SUBTYPE_PHOTO_ITEM) { return;} - - virtual void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); - - - RsPhotoAlbum album; -}; - -class RsGxsPhotoPhotoItem : public RsGxsMsgItem -{ -public: - - RsGxsPhotoPhotoItem(): RsGxsMsgItem(RS_SERVICE_TYPE_PHOTO, - RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM) {return; } - - virtual void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); - RsPhotoPhoto photo; -}; - -class RsGxsPhotoSerialiser : public RsSerialType -{ -public: - - RsGxsPhotoSerialiser() - :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO) - { return; } - virtual ~RsGxsPhotoSerialiser() { return; } - - uint32_t size(RsItem *item); - bool serialise (RsItem *item, void *data, uint32_t *size); - RsItem * deserialise(void *data, uint32_t *size); - - private: - - uint32_t sizeGxsPhotoAlbumItem(RsGxsPhotoAlbumItem *item); - bool serialiseGxsPhotoAlbumItem (RsGxsPhotoAlbumItem *item, void *data, uint32_t *size); - RsGxsPhotoAlbumItem * deserialiseGxsPhotoAlbumItem(void *data, uint32_t *size); - - uint32_t sizeGxsPhotoPhotoItem(RsGxsPhotoPhotoItem *item); - bool serialiseGxsPhotoPhotoItem (RsGxsPhotoPhotoItem *item, void *data, uint32_t *size); - RsGxsPhotoPhotoItem * deserialiseGxsPhotoPhotoItem(void *data, uint32_t *size); - - -}; - -#endif /* RSPHOTOV2ITEMS_H_ */ diff --git a/libretroshare/src/serialiser/rsposteditems.cc b/libretroshare/src/serialiser/rsposteditems.cc new file mode 100644 index 000000000..3b8269628 --- /dev/null +++ b/libretroshare/src/serialiser/rsposteditems.cc @@ -0,0 +1,656 @@ + +/* + * libretroshare/src/gxs: rsopsteditems.cc + * + * RetroShare Serialiser. + * + * Copyright 2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsposteditems.h" +#include "rsbaseserial.h" + + +uint32_t RsGxsPostedSerialiser::size(RsItem *item) +{ + RsGxsPostedPostItem* ppItem = NULL; + RsGxsPostedCommentItem* pcItem = NULL; + RsGxsPostedVoteItem* pvItem = NULL; + RsGxsPostedGroupItem* pgItem = NULL; + + if((ppItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPostedPostItem(ppItem); + } + else if((pcItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPostedCommentItem(pcItem); + }else if((pvItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPostedVoteItem(pvItem); + }else if((pgItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPostedGroupItem(pgItem); + } + else + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::size() Failed" << std::endl; +#endif + return NULL; + } +} + +bool RsGxsPostedSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + + RsGxsPostedPostItem* ppItem = NULL; + RsGxsPostedCommentItem* pcItem = NULL; + RsGxsPostedVoteItem* pvItem = NULL; + RsGxsPostedGroupItem* pgItem = NULL; + + if((ppItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPostedPostItem(ppItem, data, size); + } + else if((pcItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPostedCommentItem(pcItem, data, size); + }else if((pvItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPostedVoteItem(pvItem, data, size); + }else if((pgItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPostedGroupItem(pgItem, data, size); + } + else + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialise() FAILED" << std::endl; +#endif + return false; + } +} + +RsItem* RsGxsPostedSerialiser::deserialise(void *data, uint32_t *size) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM: + return deserialiseGxsPostedCommentItem(data, size); + case RS_PKT_SUBTYPE_POSTED_GRP_ITEM: + return deserialiseGxsPostedGroupItem(data, size); + case RS_PKT_SUBTYPE_POSTED_POST_ITEM: + return deserialiseGxsPostedPostItem(data, size); + case RS_PKT_SUBTYPE_POSTED_VOTE_ITEM: + return deserialiseGxsPostedVoteItem(data, size); + default: + { +#ifdef RS_SSERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialise(): subtype could not be dealt with" + << std::endl; +#endif + break; + } + } + return NULL; +} + + +uint32_t RsGxsPostedSerialiser::sizeGxsPostedPostItem(RsGxsPostedPostItem* item) +{ + RsPostedPost& p = item->mPost; + + uint32_t s = 8; + + s += GetTlvStringSize(p.mLink); + s += GetTlvStringSize(p.mNotes); + + return s; +} + +uint32_t RsGxsPostedSerialiser::sizeGxsPostedCommentItem(RsGxsPostedCommentItem* item) +{ + RsPostedComment& c = item->mComment; + + uint32_t s = 8; + + s += GetTlvStringSize(c.mComment); + + return s; +} + +uint32_t RsGxsPostedSerialiser::sizeGxsPostedVoteItem(RsGxsPostedVoteItem* item) +{ + RsPostedVote& v = item->mVote; + + uint32_t s = 8; + s += 1; // for vote direction + + return s; +} + +uint32_t RsGxsPostedSerialiser::sizeGxsPostedGroupItem(RsGxsPostedGroupItem* item) +{ + RsPostedGroup& g = item->mGroup; + + uint32_t s = 8; + return s; +} + +bool RsGxsPostedSerialiser::serialiseGxsPostedPostItem(RsGxsPostedPostItem* item, void* data, uint32_t *size) +{ + +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsPostedPostItem(item); + uint32_t offset = 0; + + if(*size < tlvsize){ +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem()()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsPhotoAlbumItem */ + + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mPost.mLink); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mPost.mNotes); + + if(offset != tlvsize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_POSTED_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsGxsPostedSerialiser::serialiseGxsPostedCommentItem(RsGxsPostedCommentItem* item, void* data, uint32_t *size) +{ +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsPostedCommentItem(item); + uint32_t offset = 0; + + if(*size < tlvsize){ +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsPhotoAlbumItem */ + + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mComment.mComment); + + + if(offset != tlvsize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_POSTED_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsGxsPostedSerialiser::serialiseGxsPostedVoteItem(RsGxsPostedVoteItem* item, void* data, uint32_t *size) +{ + +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsPostedVoteItem(item); + uint32_t offset = 0; + + if(*size < tlvsize){ +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + ok &= setRawUInt8(data, tlvsize, &offset, item->mVote.mDirection); + + if(offset != tlvsize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_POSTED_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem() NOK" << std::endl; + } +#endif + + return ok; +} + +bool RsGxsPostedSerialiser::serialiseGxsPostedGroupItem(RsGxsPostedGroupItem* item, void* data, uint32_t *size) +{ + +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsPostedGroupItem(item); + uint32_t offset = 0; + + if(*size < tlvsize){ +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsPhotoAlbumItem */ + + if(offset != tlvsize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXS_POSTED_SERIAL_DEBUG + if (!ok) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem() NOK" << std::endl; + } +#endif + + return ok; +} + +RsGxsPostedPostItem* RsGxsPostedSerialiser::deserialiseGxsPostedPostItem(void *data, uint32_t *size) +{ + +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_POSTED_POST_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPostedPostItem* item = new RsGxsPostedPostItem(); + /* skip the header */ + offset += 8; + + + ok &= GetTlvString(data, rssize, &offset, 1, item->mPost.mLink); + ok &= GetTlvString(data, rssize, &offset, 1, item->mPost.mNotes); + + if (offset != rssize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +RsGxsPostedCommentItem* RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem(void *data, uint32_t *size) +{ +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPostedCommentItem* item = new RsGxsPostedCommentItem(); + /* skip the header */ + offset += 8; + + + ok &= GetTlvString(data, rssize, &offset, 1, item->mComment.mComment); + + if (offset != rssize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +RsGxsPostedVoteItem* RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem(void *data, uint32_t *size) +{ + +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_POSTED_VOTE_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPostedVoteItem* item = new RsGxsPostedVoteItem(); + /* skip the header */ + offset += 8; + + ok &= getRawUInt8(data, rssize, &offset, &(item->mVote.mDirection)); + + if (offset != rssize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +RsGxsPostedGroupItem* RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem(void *data, uint32_t *size) +{ + +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_POSTED_VOTE_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPostedGroupItem* item = new RsGxsPostedGroupItem(); + /* skip the header */ + offset += 8; + + if (offset != rssize) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXS_POSTED_SERIAL_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +void RsGxsPostedPostItem::clear() +{ + +} + +std::ostream & RsGxsPostedPostItem::print(std::ostream &out, uint16_t indent) +{ + return out; +} + +void RsGxsPostedVoteItem::clear() +{ + return; +} + +std::ostream & RsGxsPostedVoteItem::print(std::ostream &out, uint16_t indent) +{ + return out; +} + +void RsGxsPostedCommentItem::clear() +{ + return; +} + +std::ostream & RsGxsPostedCommentItem::print(std::ostream &out, uint16_t indent) +{ + return out; +} + +void RsGxsPostedGroupItem::clear() +{ + return; +} + +std::ostream & RsGxsPostedGroupItem::print(std::ostream &out, uint16_t indent) +{ + return out; + +} diff --git a/libretroshare/src/serialiser/rsposteditems.h b/libretroshare/src/serialiser/rsposteditems.h new file mode 100644 index 000000000..d7212c3f8 --- /dev/null +++ b/libretroshare/src/serialiser/rsposteditems.h @@ -0,0 +1,103 @@ +#ifndef RSPOSTEDITEMS_H +#define RSPOSTEDITEMS_H + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "rsgxsitems.h" +#include "retroshare/rsposted.h" + +const uint8_t RS_PKT_SUBTYPE_POSTED_GRP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_POSTED_POST_ITEM = 0x03; +const uint8_t RS_PKT_SUBTYPE_POSTED_VOTE_ITEM = 0x04; +const uint8_t RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM = 0x05; + +class RsGxsPostedPostItem : public RsGxsMsgItem +{ +public: + RsGxsPostedPostItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, + RS_PKT_SUBTYPE_POSTED_POST_ITEM) + {return ; } + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsPostedPost mPost; +}; + +class RsGxsPostedVoteItem : public RsGxsMsgItem +{ +public: + RsGxsPostedVoteItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, + RS_PKT_SUBTYPE_POSTED_VOTE_ITEM) + {return ;} + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsPostedVote mVote; +}; + +class RsGxsPostedCommentItem : public RsGxsMsgItem +{ +public: + RsGxsPostedCommentItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, + RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM) + { return; } + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsPostedComment mComment; +}; + +class RsGxsPostedGroupItem : public RsGxsGrpItem +{ +public: + RsGxsPostedGroupItem() : RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_POSTED, + RS_PKT_SUBTYPE_POSTED_GRP_ITEM) + { return; } + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsPostedGroup mGroup; +}; + +class RsGxsPostedSerialiser : public RsSerialType +{ + +public: + + RsGxsPostedSerialiser() + : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_PHOTO) + { return; } + + virtual ~RsGxsPostedSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise(RsItem *item, void *data, uint32_t *size); + RsItem* deserialise(void *data, uint32_t *size); + +private: + + uint32_t sizeGxsPostedPostItem(RsGxsPostedPostItem* item); + bool serialiseGxsPostedPostItem(RsGxsPostedPostItem* item, void* data, uint32_t *size); + RsGxsPostedPostItem* deserialiseGxsPostedPostItem(void *data, uint32_t *size); + + uint32_t sizeGxsPostedCommentItem(RsGxsPostedCommentItem* item); + bool serialiseGxsPostedCommentItem(RsGxsPostedCommentItem* item, void* data, uint32_t *size); + RsGxsPostedCommentItem* deserialiseGxsPostedCommentItem(void *data, uint32_t *size); + + uint32_t sizeGxsPostedVoteItem(RsGxsPostedVoteItem* item); + bool serialiseGxsPostedVoteItem(RsGxsPostedVoteItem* item, void* data, uint32_t *size); + RsGxsPostedVoteItem* deserialiseGxsPostedVoteItem(void *data, uint32_t *size); + + uint32_t sizeGxsPostedGroupItem(RsGxsPostedGroupItem* item); + bool serialiseGxsPostedGroupItem(RsGxsPostedGroupItem* item, void* data, uint32_t *size); + RsGxsPostedGroupItem* deserialiseGxsPostedGroupItem(void *data, uint32_t *size); +}; + + +#endif // RSPOSTEDITEMS_H diff --git a/libretroshare/src/serialiser/rsserviceids.h b/libretroshare/src/serialiser/rsserviceids.h index f5cbf16ab..c47dba6a4 100644 --- a/libretroshare/src/serialiser/rsserviceids.h +++ b/libretroshare/src/serialiser/rsserviceids.h @@ -65,6 +65,7 @@ const uint16_t RS_SERVICE_TYPE_STATUS = 0xf020; const uint16_t RS_SERVICE_TYPE_PLUGIN_ARADO_ID = 0x0401; const uint16_t RS_SERVICE_TYPE_PLUGIN_QCHESS_ID = 0x0402; +const uint16_t RS_SERVICE_TYPE_PLUGIN_FEEDREADER = 0x0403; /****************** BELOW ARE ONLY THEORETICAL (CAN BE CHANGED) *****/ @@ -107,13 +108,6 @@ const uint16_t RS_SERVICE_TYPE_DSDV = 0xf050; const uint16_t RS_SERVICE_TYPE_BWCTRL = 0xf060; - /* New Cache Services */ -const uint16_t RS_SERVICE_TYPE_IDENTITY = 0xf100; -const uint16_t RS_SERVICE_TYPE_PHOTO = 0xf101; -const uint16_t RS_SERVICE_TYPE_WIKI = 0xf102; -const uint16_t RS_SERVICE_TYPE_WIRE = 0xf103; -const uint16_t RS_SERVICE_TYPE_FORUMSV2 = 0xf104; -const uint16_t RS_SERVICE_TYPE_POSTED = 0xf105; //const uint16_t RS_SERVICE_TYPE_DISTRIB = 0xf110; //const uint16_t RS_SERVICE_TYPE_FORUM = 0xf120; @@ -133,9 +127,35 @@ const uint16_t RS_SERVICE_TYPE_GAME_QGO = 0xf212; const uint16_t RS_SERVICE_TYPE_GAME_BIGTWO = 0xf213; const uint16_t RS_SERVICE_TYPE_GAME_POKER = 0xf214; + /* New Cache Services */ /* Rs Network Exchange Service */ -const uint16_t RS_SERVICE_TYPE_NXS = 0xf300; +const uint16_t RS_SERVICE_TYPE_NXS = 0xf300; +const uint16_t RS_SERVICE_GXSV1_TYPE_GXSID = 0xf301; +const uint16_t RS_SERVICE_GXSV1_TYPE_PHOTO = 0xf302; +const uint16_t RS_SERVICE_GXSV1_TYPE_WIKI = 0xf303; +const uint16_t RS_SERVICE_GXSV1_TYPE_WIRE = 0xf304; +const uint16_t RS_SERVICE_GXSV1_TYPE_FORUMS = 0xf305; +const uint16_t RS_SERVICE_GXSV1_TYPE_POSTED = 0xf306; +const uint16_t RS_SERVICE_GXSV1_TYPE_CHANNELS = 0xf307; +const uint16_t RS_SERVICE_GXSV1_TYPE_GXSCIRCLE = 0xf307; + +const uint16_t RS_SERVICE_GXSV2_TYPE_GXSID = 0xf311; +const uint16_t RS_SERVICE_GXSV2_TYPE_GXSCIRCLE = 0xf312; +const uint16_t RS_SERVICE_GXSV2_TYPE_PHOTO = 0xf313; +const uint16_t RS_SERVICE_GXSV2_TYPE_WIKI = 0xf314; +const uint16_t RS_SERVICE_GXSV2_TYPE_WIRE = 0xf315; +const uint16_t RS_SERVICE_GXSV2_TYPE_FORUMS = 0xf316; +const uint16_t RS_SERVICE_GXSV2_TYPE_POSTED = 0xf317; +const uint16_t RS_SERVICE_GXSV2_TYPE_CHANNELS = 0xf318; + + /* Example Versions (VEG) of New Cache Services */ +const uint16_t RS_SERVICE_VEG_TYPE_IDENTITY = 0xf320; +const uint16_t RS_SERVICE_VEG_TYPE_PHOTO = 0xf321; +const uint16_t RS_SERVICE_VEG_TYPE_WIKI = 0xf322; +const uint16_t RS_SERVICE_VEG_TYPE_WIRE = 0xf323; +const uint16_t RS_SERVICE_VEG_TYPE_FORUMS = 0xf324; +const uint16_t RS_SERVICE_VEG_TYPE_POSTED = 0xf325; /***************** IDS ALLOCATED FOR PLUGINS ******************/ diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h index 72e1b4a4b..70698df64 100644 --- a/libretroshare/src/serialiser/rstlvbase.h +++ b/libretroshare/src/serialiser/rstlvbase.h @@ -207,6 +207,8 @@ const uint16_t TLV_TYPE_SECURITYKEY = 0x1040; const uint16_t TLV_TYPE_SECURITYKEYSET= 0x1041; const uint16_t TLV_TYPE_KEYSIGNATURE = 0x1050; +const uint16_t TLV_TYPE_KEYSIGNATURESET = 0x1051; +const uint16_t TLV_TYPE_KEYSIGNATURETYPE = 0x1052; const uint16_t TLV_TYPE_IMAGE = 0x1060; diff --git a/libretroshare/src/serialiser/rstlvkeys.cc b/libretroshare/src/serialiser/rstlvkeys.cc index 1a6f2663f..f2b39269b 100644 --- a/libretroshare/src/serialiser/rstlvkeys.cc +++ b/libretroshare/src/serialiser/rstlvkeys.cc @@ -34,7 +34,7 @@ #include #include -//#define TLV_DEBUG 1 +#define TLV_DEBUG 1 /************************************* RsTlvSecurityKey ************************************/ @@ -322,7 +322,7 @@ bool RsTlvSecurityKeySet::GetTlv(void *data, uint32_t size, uint32_t *offset) / if (ok) { keys[key.keyId] = key; - key.ShallowClear(); /* so that the Map can get control - should be ref counted*/ + key.TlvClear(); /* so that the Map can get control - should be ref counted*/ } } break; @@ -520,3 +520,170 @@ std::ostream &RsTlvKeySignature::print(std::ostream &out, uint16_t indent) return out; } + +/************************************* RsTlvKeySignatureSet ************************************/ + +RsTlvKeySignatureSet::RsTlvKeySignatureSet() +{ + +} + +std::ostream &RsTlvKeySignatureSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvKeySignatureSet", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + + std::map::iterator mit = keySignSet.begin(); + + for(; mit != keySignSet.end(); mit++) + { + out << "SignType: " << mit->first << std::endl; + RsTlvKeySignature& sign = mit->second; + sign.print(out, indent); + } + + out << std::endl; + + printEnd(out, "RsTlvKeySignatureSet", indent); + return out; +} + +void RsTlvKeySignatureSet::TlvClear() +{ + keySignSet.clear(); +} + +bool RsTlvKeySignatureSet::SetTlv(void *data, uint32_t size, uint32_t *offset) +{ + + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignatureSet::SetTlv() Failed not enough space"; + std::cerr << std::endl; +#endif + return false; /* not enough space */ + } + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURESET , tlvsize); + + + if(!keySignSet.empty()) + { + std::map::iterator it; + + for(it = keySignSet.begin(); it != keySignSet.end() ; ++it) + { + ok &= SetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, it->first); + ok &= (it->second).SetTlv(data, size, offset); + } + } + + +return ok; +} + +bool RsTlvKeySignatureSet::GetTlv(void *data, uint32_t size, uint32_t *offset) +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_KEYSIGNATURESET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + SignType sign_type = 0; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + SignType currType; + + switch(tlvsubtype) + { + case TLV_TYPE_KEYSIGNATURE: + { + RsTlvKeySignature sign; + ok &= sign.GetTlv(data, size, offset); + if (ok) + { + keySignSet[currType] = sign; + } + } + break; + case TLV_TYPE_KEYSIGNATURETYPE: + { + ok = GetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, &sign_type); + + if(ok) + currType = sign_type; + } + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + } + + if (!ok) + break; + } + + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignatureSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +uint32_t RsTlvKeySignatureSet::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; // header size + std::map::iterator it; + + for(it = keySignSet.begin(); it != keySignSet.end() ; ++it) + { + s += GetTlvUInt32Size(); // sign type + s += it->second.TlvSize(); // signature + } + + return s; +} diff --git a/libretroshare/src/serialiser/rstlvkeys.h b/libretroshare/src/serialiser/rstlvkeys.h index 35caca20c..6f3f9b46c 100644 --- a/libretroshare/src/serialiser/rstlvkeys.h +++ b/libretroshare/src/serialiser/rstlvkeys.h @@ -41,6 +41,7 @@ const uint32_t RSTLV_KEY_TYPE_SHARED = 0x0004; const uint32_t RSTLV_KEY_DISTRIB_PUBLIC = 0x0010; const uint32_t RSTLV_KEY_DISTRIB_PRIVATE = 0x0020; const uint32_t RSTLV_KEY_DISTRIB_ADMIN = 0x0040; +const uint32_t RSTLV_KEY_DISTRIB_IDENTITY = 0x0080; class RsTlvSecurityKey: public RsTlvItem @@ -98,6 +99,21 @@ virtual std::ostream &print(std::ostream &out, uint16_t indent); // NO Certificates in Signatures... add as separate data type. }; +typedef uint32_t SignType; + +class RsTlvKeySignatureSet : public RsTlvItem +{ +public: + RsTlvKeySignatureSet(); + virtual ~RsTlvKeySignatureSet() { return; } + virtual uint32_t TlvSize(); + virtual void TlvClear(); + virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ + virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ + virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::map keySignSet; // mandatory +}; #endif diff --git a/libretroshare/src/serialiser/rswikiitems.cc b/libretroshare/src/serialiser/rswikiitems.cc new file mode 100644 index 000000000..66c7f9309 --- /dev/null +++ b/libretroshare/src/serialiser/rswikiitems.cc @@ -0,0 +1,580 @@ +/* + * libretroshare/src/serialiser: rswikiitems.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "rswikiitems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +#define GXSID_DEBUG 1 + + +uint32_t RsGxsWikiSerialiser::size(RsItem *item) +{ + RsGxsWikiCollectionItem* grp_item = NULL; + RsGxsWikiSnapshotItem* snap_item = NULL; + RsGxsWikiCommentItem* com_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWikiCollectionItem(grp_item); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWikiSnapshotItem(snap_item); + } + else if((com_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWikiCommentItem(com_item); + } + return NULL; +} + +bool RsGxsWikiSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsGxsWikiCollectionItem* grp_item = NULL; + RsGxsWikiSnapshotItem* snap_item = NULL; + RsGxsWikiCommentItem* com_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWikiCollectionItem(grp_item, data, size); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWikiSnapshotItem(snap_item, data, size); + } + else if((com_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWikiCommentItem(com_item, data, size); + } + return false; +} + +RsItem* RsGxsWikiSerialiser::deserialise(void* data, uint32_t* size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM: + return deserialiseGxsWikiCollectionItem(data, size); + break; + case RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM: + return deserialiseGxsWikiSnapshotItem(data, size); + break; + case RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM: + return deserialiseGxsWikiCommentItem(data, size); + break; + default: +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; +#endif + break; + } + return NULL; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWikiCollectionItem::clear() +{ + collection.mDescription.clear(); + collection.mCategory.clear(); + collection.mHashTags.clear(); +} + +std::ostream& RsGxsWikiCollectionItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWikiCollectionItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Description: " << collection.mDescription << std::endl; + printIndent(out, int_Indent); + out << "Category: " << collection.mCategory << std::endl; + printIndent(out, int_Indent); + out << "HashTags: " << collection.mHashTags << std::endl; + + printRsItemEnd(out ,"RsGxsWikiCollectionItem", indent); + return out; +} + + +uint32_t RsGxsWikiSerialiser::sizeGxsWikiCollectionItem(RsGxsWikiCollectionItem *item) +{ + + const RsWikiCollection& collection = item->collection; + uint32_t s = 8; // header + + s += GetTlvStringSize(collection.mDescription); + s += GetTlvStringSize(collection.mCategory); + s += GetTlvStringSize(collection.mHashTags); + + return s; +} + +bool RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem(RsGxsWikiCollectionItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWikiCollectionItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWikiCollectionItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->collection.mDescription); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->collection.mCategory); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->collection.mHashTags); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCollectionItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWikiCollectionItem* RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWikiCollectionItem* item = new RsGxsWikiCollectionItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->collection.mDescription); + ok &= GetTlvString(data, rssize, &offset, 1, item->collection.mCategory); + ok &= GetTlvString(data, rssize, &offset, 1, item->collection.mHashTags); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCollectionItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWikiSnapshotItem::clear() +{ + snapshot.mPage.clear(); + snapshot.mHashTags.clear(); +} + +std::ostream& RsGxsWikiSnapshotItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWikiSnapshotItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Page: " << snapshot.mPage << std::endl; + + printIndent(out, int_Indent); + out << "HashTags: " << snapshot.mHashTags << std::endl; + + printRsItemEnd(out ,"RsGxsWikiSnapshotItem", indent); + return out; +} + + +uint32_t RsGxsWikiSerialiser::sizeGxsWikiSnapshotItem(RsGxsWikiSnapshotItem *item) +{ + + const RsWikiSnapshot& snapshot = item->snapshot; + uint32_t s = 8; // header + + s += GetTlvStringSize(snapshot.mPage); + s += GetTlvStringSize(snapshot.mHashTags); + + return s; +} + +bool RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem(RsGxsWikiSnapshotItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWikiSnapshotItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWikiSnapshotItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->snapshot.mPage); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->snapshot.mHashTags); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiSnapshotItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWikiSnapshotItem* RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWikiSnapshotItem* item = new RsGxsWikiSnapshotItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->snapshot.mPage); + ok &= GetTlvString(data, rssize, &offset, 1, item->snapshot.mHashTags); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiSnapshotItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWikiCommentItem::clear() +{ + comment.mComment.clear(); +} + +std::ostream& RsGxsWikiCommentItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWikiCommentItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Comment: " << comment.mComment << std::endl; + + printRsItemEnd(out ,"RsGxsWikiCommentItem", indent); + return out; +} + + +uint32_t RsGxsWikiSerialiser::sizeGxsWikiCommentItem(RsGxsWikiCommentItem *item) +{ + + const RsWikiComment& comment = item->comment; + uint32_t s = 8; // header + + s += GetTlvStringSize(comment.mComment); + + return s; +} + +bool RsGxsWikiSerialiser::serialiseGxsWikiCommentItem(RsGxsWikiCommentItem *item, void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWikiCommentItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWikiCommentItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->comment.mComment); + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsWikiSerialiser::serialiseGxsWikiCommentItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWikiCommentItem* RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem(void *data, uint32_t *size) +{ + +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIKI != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWikiCommentItem* item = new RsGxsWikiCommentItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->comment.mComment); + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsWikiSerialiser::deserialiseGxsWikiCommentItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + diff --git a/libretroshare/src/serialiser/rswikiitems.h b/libretroshare/src/serialiser/rswikiitems.h new file mode 100644 index 000000000..4b57c968d --- /dev/null +++ b/libretroshare/src/serialiser/rswikiitems.h @@ -0,0 +1,112 @@ +/* + * libretroshare/src/serialiser: rswikiitems.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RS_WIKI_ITEMS_H +#define RS_WIKI_ITEMS_H + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "rsgxsitems.h" +#include "retroshare/rswiki.h" + +const uint8_t RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM = 0x03; +const uint8_t RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM = 0x04; + +class RsGxsWikiCollectionItem : public RsGxsGrpItem +{ + +public: + + RsGxsWikiCollectionItem(): RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_WIKI, + RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM) { return;} + virtual ~RsGxsWikiCollectionItem() { return;} + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + + RsWikiCollection collection; +}; + +class RsGxsWikiSnapshotItem : public RsGxsMsgItem +{ +public: + + RsGxsWikiSnapshotItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_WIKI, + RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM) {return; } + virtual ~RsGxsWikiSnapshotItem() { return;} + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsWikiSnapshot snapshot; +}; + +class RsGxsWikiCommentItem : public RsGxsMsgItem +{ +public: + + RsGxsWikiCommentItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_WIKI, + RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM) { return; } + virtual ~RsGxsWikiCommentItem() { return; } + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsWikiComment comment; + +}; + +class RsGxsWikiSerialiser : public RsSerialType +{ +public: + + RsGxsWikiSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_WIKI) + { return; } + virtual ~RsGxsWikiSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + private: + + uint32_t sizeGxsWikiCollectionItem(RsGxsWikiCollectionItem *item); + bool serialiseGxsWikiCollectionItem (RsGxsWikiCollectionItem *item, void *data, uint32_t *size); + RsGxsWikiCollectionItem * deserialiseGxsWikiCollectionItem(void *data, uint32_t *size); + + uint32_t sizeGxsWikiSnapshotItem(RsGxsWikiSnapshotItem *item); + bool serialiseGxsWikiSnapshotItem (RsGxsWikiSnapshotItem *item, void *data, uint32_t *size); + RsGxsWikiSnapshotItem * deserialiseGxsWikiSnapshotItem(void *data, uint32_t *size); + + uint32_t sizeGxsWikiCommentItem(RsGxsWikiCommentItem *item); + bool serialiseGxsWikiCommentItem (RsGxsWikiCommentItem *item, void *data, uint32_t *size); + RsGxsWikiCommentItem * deserialiseGxsWikiCommentItem(void *data, uint32_t *size); + +}; + +#endif /* RS_WIKI_ITEMS_H */ diff --git a/libretroshare/src/serialiser/rswireitems.cc b/libretroshare/src/serialiser/rswireitems.cc new file mode 100644 index 000000000..068499bf8 --- /dev/null +++ b/libretroshare/src/serialiser/rswireitems.cc @@ -0,0 +1,408 @@ +/* + * libretroshare/src/serialiser: rswikiitems.cc + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "rswireitems.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +#define WIRE_DEBUG 1 + + +uint32_t RsGxsWireSerialiser::size(RsItem *item) +{ + RsGxsWireGroupItem* grp_item = NULL; + RsGxsWirePulseItem* snap_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWireGroupItem(grp_item); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return sizeGxsWirePulseItem(snap_item); + } + return NULL; +} + +bool RsGxsWireSerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsGxsWireGroupItem* grp_item = NULL; + RsGxsWirePulseItem* snap_item = NULL; + + if((grp_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWireGroupItem(grp_item, data, size); + } + else if((snap_item = dynamic_cast(item)) != NULL) + { + return serialiseGxsWirePulseItem(snap_item, data, size); + } + return false; +} + +RsItem* RsGxsWireSerialiser::deserialise(void* data, uint32_t* size) +{ + +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIRE != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + + case RS_PKT_SUBTYPE_WIRE_GROUP_ITEM: + return deserialiseGxsWireGroupItem(data, size); + break; + case RS_PKT_SUBTYPE_WIRE_PULSE_ITEM: + return deserialiseGxsWirePulseItem(data, size); + break; + default: +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; +#endif + break; + } + return NULL; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWireGroupItem::clear() +{ + group.mDescription.clear(); +} + +std::ostream& RsGxsWireGroupItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWireGroupItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Description: " << group.mDescription << std::endl; + + printRsItemEnd(out ,"RsGxsWireGroupItem", indent); + return out; +} + + +uint32_t RsGxsWireSerialiser::sizeGxsWireGroupItem(RsGxsWireGroupItem *item) +{ + + const RsWireGroup& group = item->group; + uint32_t s = 8; // header + + s += GetTlvStringSize(group.mDescription); + + return s; +} + +bool RsGxsWireSerialiser::serialiseGxsWireGroupItem(RsGxsWireGroupItem *item, void *data, uint32_t *size) +{ + +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::serialiseGxsWireGroupItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWireGroupItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::serialiseGxsWireGroupItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWireGroupItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mDescription); + + if(offset != tlvsize) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::serialiseGxsWireGroupItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef WIRE_DEBUG + if (!ok) + { + std::cerr << "RsGxsWireSerialiser::serialiseGxsWireGroupItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWireGroupItem* RsGxsWireSerialiser::deserialiseGxsWireGroupItem(void *data, uint32_t *size) +{ + +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWireGroupItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIRE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIRE_GROUP_ITEM != getRsItemSubType(rstype))) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWireGroupItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWireGroupItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWireGroupItem* item = new RsGxsWireGroupItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->group.mDescription); + + if (offset != rssize) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWireGroupItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWireGroupItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + + +void RsGxsWirePulseItem::clear() +{ + pulse.mPulseText.clear(); + pulse.mHashTags.clear(); +} + +std::ostream& RsGxsWirePulseItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsWirePulseItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Page: " << pulse.mPulseText << std::endl; + + printIndent(out, int_Indent); + out << "HashTags: " << pulse.mHashTags << std::endl; + + printRsItemEnd(out ,"RsGxsWirePulseItem", indent); + return out; +} + + +uint32_t RsGxsWireSerialiser::sizeGxsWirePulseItem(RsGxsWirePulseItem *item) +{ + + const RsWirePulse& pulse = item->pulse; + uint32_t s = 8; // header + + s += GetTlvStringSize(pulse.mPulseText); + s += GetTlvStringSize(pulse.mHashTags); + + return s; +} + +bool RsGxsWireSerialiser::serialiseGxsWirePulseItem(RsGxsWirePulseItem *item, void *data, uint32_t *size) +{ + +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::serialiseGxsWirePulseItem()" << std::endl; +#endif + + uint32_t tlvsize = sizeGxsWirePulseItem(item); + uint32_t offset = 0; + + if(*size < tlvsize) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::serialiseGxsWirePulseItem()" << std::endl; +#endif + return false; + } + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* GxsWirePulseItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->pulse.mPulseText); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->pulse.mHashTags); + + if(offset != tlvsize) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::serialiseGxsWirePulseItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef WIRE_DEBUG + if (!ok) + { + std::cerr << "RsGxsWireSerialiser::serialiseGxsWirePulseItem() NOK" << std::endl; + } +#endif + + return ok; + } + +RsGxsWirePulseItem* RsGxsWireSerialiser::deserialiseGxsWirePulseItem(void *data, uint32_t *size) +{ + +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWirePulseItem()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_WIRE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_WIRE_PULSE_ITEM != getRsItemSubType(rstype))) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWirePulseItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWirePulseItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsWirePulseItem* item = new RsGxsWirePulseItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->pulse.mPulseText); + ok &= GetTlvString(data, rssize, &offset, 1, item->pulse.mHashTags); + + if (offset != rssize) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWirePulseItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef WIRE_DEBUG + std::cerr << "RsGxsWireSerialiser::deserialiseGxsWirePulseItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + diff --git a/libretroshare/src/serialiser/rswireitems.h b/libretroshare/src/serialiser/rswireitems.h new file mode 100644 index 000000000..c7dfc4f03 --- /dev/null +++ b/libretroshare/src/serialiser/rswireitems.h @@ -0,0 +1,93 @@ +/* + * libretroshare/src/serialiser: rswireitems.h + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RS_WIRE_ITEMS_H +#define RS_WIRE_ITEMS_H + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "rsgxsitems.h" +#include "retroshare/rswire.h" + +const uint8_t RS_PKT_SUBTYPE_WIRE_GROUP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_WIRE_PULSE_ITEM = 0x03; + +class RsGxsWireGroupItem : public RsGxsGrpItem +{ + +public: + + RsGxsWireGroupItem(): RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_WIRE, + RS_PKT_SUBTYPE_WIRE_GROUP_ITEM) { return;} + virtual ~RsGxsWireGroupItem() { return;} + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + + RsWireGroup group; +}; + +class RsGxsWirePulseItem : public RsGxsMsgItem +{ +public: + + RsGxsWirePulseItem(): RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_WIRE, + RS_PKT_SUBTYPE_WIRE_PULSE_ITEM) {return; } + virtual ~RsGxsWirePulseItem() { return;} + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + RsWirePulse pulse; +}; + +class RsGxsWireSerialiser : public RsSerialType +{ +public: + + RsGxsWireSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_WIRE) + { return; } + virtual ~RsGxsWireSerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + private: + + uint32_t sizeGxsWireGroupItem(RsGxsWireGroupItem *item); + bool serialiseGxsWireGroupItem (RsGxsWireGroupItem *item, void *data, uint32_t *size); + RsGxsWireGroupItem * deserialiseGxsWireGroupItem(void *data, uint32_t *size); + + uint32_t sizeGxsWirePulseItem(RsGxsWirePulseItem *item); + bool serialiseGxsWirePulseItem (RsGxsWirePulseItem *item, void *data, uint32_t *size); + RsGxsWirePulseItem * deserialiseGxsWirePulseItem(void *data, uint32_t *size); +}; + +#endif /* RS_WIKI_ITEMS_H */ diff --git a/libretroshare/src/services/p3forumsv2.cc b/libretroshare/src/services/p3forumsv2.cc deleted file mode 100644 index 837e21709..000000000 --- a/libretroshare/src/services/p3forumsv2.cc +++ /dev/null @@ -1,805 +0,0 @@ -/* - * libretroshare/src/services p3forumsv2.cc - * - * ForumsV2 interface for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/p3forumsv2.h" - -#include "util/rsrandom.h" -#include - -/**** - * #define FORUMV2_DEBUG 1 - ****/ - -RsForumsV2 *rsForumsV2 = NULL; - - - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3ForumsV2::p3ForumsV2(uint16_t type) - :p3GxsDataService(type, new ForumDataProxy()), mForumMtx("p3ForumsV2"), mUpdated(true) -{ - { - RsStackMutex stack(mForumMtx); /********** STACK LOCKED MTX ******/ - - mForumProxy = (ForumDataProxy *) mProxy; - } - - generateDummyData(); - - return; -} - - -int p3ForumsV2::tick() -{ - std::cerr << "p3ForumsV2::tick()"; - std::cerr << std::endl; - - fakeprocessrequests(); - - return 0; -} - -bool p3ForumsV2::updated() -{ - RsStackMutex stack(mForumMtx); /********** STACK LOCKED MTX ******/ - - if (mUpdated) - { - mUpdated = false; - return true; - } - return false; -} - - - - /* Data Requests */ -bool p3ForumsV2::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3ForumsV2::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3ForumsV2::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3ForumsV2::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3ForumsV2::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3ForumsV2::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3ForumsV2::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3ForumsV2::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3ForumsV2::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3ForumsV2::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3ForumsV2::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3ForumsV2::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3ForumsV2::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3ForumsV2::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3ForumsV2::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3ForumsV2::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3ForumsV2::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3ForumsV2::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3ForumsV2::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3ForumsV2::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3ForumsV2::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3ForumsV2::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - - /* Specific Service Data */ -bool p3ForumsV2::getGroupData(const uint32_t &token, RsForumV2Group &group) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3ForumsV2::getGroupData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3ForumsV2::getGroupData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3ForumsV2::getGroupData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsForumAlbum */ - bool ans = mForumProxy->getForumGroup(id, group); - return ans; -} - - -bool p3ForumsV2::getMsgData(const uint32_t &token, RsForumV2Msg &msg) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3ForumsV2::getMsgData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3ForumsV2::getMsgData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3ForumsV2::getMsgData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsForumAlbum */ - bool ans = mForumProxy->getForumMsg(id, msg); - return ans; -} - - - - /* Poll */ -uint32_t p3ForumsV2::requestStatus(const uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - return status; -} - - - /* Cancel Request */ -bool p3ForumsV2::cancelRequest(const uint32_t &token) -{ - return clearRequest(token); -} - - ////////////////////////////////////////////////////////////////////////////// - -bool p3ForumsV2::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) -{ - return mForumProxy->setMessageStatus(msgId, status, statusMask); -} - -bool p3ForumsV2::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mForumProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3ForumsV2::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mForumProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3ForumsV2::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mForumProxy->setMessageServiceString(msgId, str); -} - -bool p3ForumsV2::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mForumProxy->setGroupServiceString(grpId, str); -} - - - -bool p3ForumsV2::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3ForumsV2::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - - - -/********************************************************************************************/ - - -std::string p3ForumsV2::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3ForumsV2::createGroup(uint32_t &token, RsForumV2Group &group, bool isNew) -{ - if (group.mMeta.mGroupId.empty()) - { - /* new photo */ - - /* generate a temp id */ - group.mMeta.mGroupId = genRandomId(); - } - else - { - std::cerr << "p3ForumsV2::createGroup() Group with existing Id... dropping"; - std::cerr << std::endl; - return false; - } - - { - RsStackMutex stack(mForumMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mForumProxy->addForumGroup(group); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3ForumsV2::createGroup() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - - - - -bool p3ForumsV2::createMsg(uint32_t &token, RsForumV2Msg &msg, bool isNew) -{ - if (msg.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3ForumsV2::createForumMsg() Missing MsgID"; - std::cerr << std::endl; - return false; - } - - /* check if its a mod or new msg */ - if (msg.mMeta.mOrigMsgId.empty()) - { - std::cerr << "p3ForumsV2::createForumMsg() New Msg"; - std::cerr << std::endl; - - /* new msg, generate a new OrigMsgId */ - msg.mMeta.mOrigMsgId = genRandomId(); - msg.mMeta.mMsgId = msg.mMeta.mOrigMsgId; - } - else - { - std::cerr << "p3ForumsV2::createForumMsg() Modified Msg"; - std::cerr << std::endl; - - /* mod msg, keep orig msg id, generate a new MsgId */ - msg.mMeta.mMsgId = genRandomId(); - } - - std::cerr << "p3ForumsV2::createForumMsg() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - std::cerr << "p3ForumsV2::createForumMsg() MsgId: " << msg.mMeta.mMsgId; - std::cerr << std::endl; - std::cerr << "p3ForumsV2::createForumMsg() OrigMsgId: " << msg.mMeta.mOrigMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mForumMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mForumProxy->addForumMsg(msg); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(msg.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3ForumsV2::createMsg() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - - -bool ForumDataProxy::getForumGroup(const std::string &id, RsForumV2Group &group) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsForumV2Group *pG = (RsForumV2Group *) groupData; - group = *pG; - - // update definitive version of the metadata. - group.mMeta = meta; - - std::cerr << "ForumDataProxy::getForumGroup() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; - return true; - } - - std::cerr << "ForumDataProxy::getForumGroup() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool ForumDataProxy::getForumMsg(const std::string &id, RsForumV2Msg &page) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsForumV2Msg *pP = (RsForumV2Msg *) msgData; - // Shallow copy of thumbnail. - page = *pP; - - // update definitive version of the metadata. - page.mMeta = meta; - - std::cerr << "ForumDataProxy::getForumMsg() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - - std::cerr << "ForumDataProxy::getForumMsg() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool ForumDataProxy::addForumGroup(const RsForumV2Group &group) -{ - // Make duplicate. - RsForumV2Group *pG = new RsForumV2Group(); - *pG = group; - - std::cerr << "ForumDataProxy::addForumGroup()"; - std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; - std::cerr << std::endl; - - return createGroup(pG); -} - - -bool ForumDataProxy::addForumMsg(const RsForumV2Msg &msg) -{ - // Make duplicate. - RsForumV2Msg *pM = new RsForumV2Msg(); - *pM = msg; - - std::cerr << "ForumDataProxy::addForumMsg()"; - std::cerr << " MetaData: " << pM->mMeta << " DataPointer: " << pM; - std::cerr << std::endl; - - return createMsg(pM); -} - - - - /* These Functions must be overloaded to complete the service */ -bool ForumDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsForumV2Group *group = (RsForumV2Group *) groupData; - meta = group->mMeta; - - return true; -} - -bool ForumDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsForumV2Msg *page = (RsForumV2Msg *) msgData; - meta = page->mMeta; - - return true; -} - - -/********************************************************************************************/ - - - -bool p3ForumsV2::generateDummyData() -{ - /* so we want to generate 100's of forums */ -#define MAX_FORUMS 10 //100 -#define MAX_THREADS 10 //1000 -#define MAX_MSGS 100 //10000 - - std::list mGroups; - std::list::iterator git; - - std::list mMsgs; - std::list::iterator mit; - -#define DUMMY_NAME_MAX_LEN 10000 - char name[DUMMY_NAME_MAX_LEN]; - int i, j; - time_t now = time(NULL); - - for(i = 0; i < MAX_FORUMS; i++) - { - /* generate a new forum */ - RsForumV2Group forum; - - /* generate a temp id */ - forum.mMeta.mGroupId = genRandomId(); - - snprintf(name, DUMMY_NAME_MAX_LEN, "TestForum_%d", i+1); - - forum.mMeta.mGroupId = genRandomId(); - forum.mMeta.mGroupName = name; - - forum.mMeta.mPublishTs = now - (RSRandom::random_f32() * 100000); - /* key fields to fill in: - * GroupId. - * Name. - * Flags. - * Pop. - */ - - - - /* use probability to decide which are subscribed / own / popularity. - */ - - float rnd = RSRandom::random_f32(); - if (rnd < 0.1) - { - forum.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_ADMIN; - - } - else if (rnd < 0.3) - { - forum.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - } - else - { - forum.mMeta.mSubscribeFlags = 0; - } - - forum.mMeta.mPop = (int) (RSRandom::random_f32() * 10.0); - - mGroups.push_back(forum); - - - //std::cerr << "p3ForumsV2::generateDummyData() Generated Forum: " << forum.mMeta; - //std::cerr << std::endl; - } - - - for(i = 0; i < MAX_THREADS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsForumV2Group head = mGroups.front(); - mGroups.pop_front(); - mGroups.push_back(head); - } - - RsForumV2Group forum = mGroups.front(); - - /* now create a new thread */ - - RsForumV2Msg msg; - - /* fill in key data - * GroupId - * MsgId - * OrigMsgId - * ThreadId - * ParentId - * PublishTS (take Forum TS + a bit ). - * - * ChildTS ???? - */ - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => ThreadMsg_%d", forum.mMeta.mGroupName.c_str(), i+1); - msg.mMeta.mMsgName = name; - - msg.mMeta.mGroupId = forum.mMeta.mGroupId; - msg.mMeta.mMsgId = genRandomId(); - msg.mMeta.mOrigMsgId = msg.mMeta.mMsgId; - msg.mMeta.mThreadId = msg.mMeta.mMsgId; - msg.mMeta.mParentId = ""; - - msg.mMeta.mPublishTs = forum.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (msg.mMeta.mPublishTs > now) - msg.mMeta.mPublishTs = now - 1; - - mMsgs.push_back(msg); - - //std::cerr << "p3ForumsV2::generateDummyData() Generated Thread: " << msg.mMeta; - //std::cerr << std::endl; - - } - - for(i = 0; i < MAX_MSGS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsForumV2Msg head = mMsgs.front(); - mMsgs.pop_front(); - mMsgs.push_back(head); - } - - RsForumV2Msg parent = mMsgs.front(); - - /* now create a new child msg */ - - RsForumV2Msg msg; - - /* fill in key data - * GroupId - * MsgId - * OrigMsgId - * ThreadId - * ParentId - * PublishTS (take Forum TS + a bit ). - * - * ChildTS ???? - */ - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Msg_%d", parent.mMeta.mMsgName.c_str(), i+1); - msg.mMeta.mMsgName = name; - msg.mMsg = name; - - msg.mMeta.mGroupId = parent.mMeta.mGroupId; - msg.mMeta.mMsgId = genRandomId(); - msg.mMeta.mOrigMsgId = msg.mMeta.mMsgId; - msg.mMeta.mThreadId = parent.mMeta.mThreadId; - msg.mMeta.mParentId = parent.mMeta.mOrigMsgId; - - msg.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (msg.mMeta.mPublishTs > now) - msg.mMeta.mPublishTs = now - 1; - - mMsgs.push_back(msg); - - //std::cerr << "p3ForumsV2::generateDummyData() Generated Child Msg: " << msg.mMeta; - //std::cerr << std::endl; - - } - - - mUpdated = true; - - /* Then - at the end, we push them all into the Proxy */ - for(git = mGroups.begin(); git != mGroups.end(); git++) - { - /* pushback */ - mForumProxy->addForumGroup(*git); - - } - - for(mit = mMsgs.begin(); mit != mMsgs.end(); mit++) - { - /* pushback */ - mForumProxy->addForumMsg(*mit); - } - - return true; -} - diff --git a/libretroshare/src/services/p3forumsv2.h b/libretroshare/src/services/p3forumsv2.h deleted file mode 100644 index f6c8d627f..000000000 --- a/libretroshare/src/services/p3forumsv2.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * libretroshare/src/services: p3forumsv2.h - * - * Wiki interface for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef P3_FORUMSV2_SERVICE_HEADER -#define P3_FORUMSV2_SERVICE_HEADER - -#include "services/p3gxsservice.h" - -#include "retroshare/rsforumsv2.h" - -#include -#include - -/* - * - */ - -class ForumDataProxy: public GxsDataProxy -{ - public: - - bool getForumGroup(const std::string &id, RsForumV2Group &group); - bool getForumMsg(const std::string &id, RsForumV2Msg &msg); - - bool addForumGroup(const RsForumV2Group &group); - bool addForumMsg(const RsForumV2Msg &msg); - - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *msgData, RsMsgMetaData &meta); - -}; - - - - - -class p3ForumsV2: public p3GxsDataService, public RsForumsV2 -{ - public: - - p3ForumsV2(uint16_t type); - -virtual int tick(); - - public: - - -virtual bool updated(); - - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds); - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); - - /* Actual Data -> specific to Interface */ - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsForumV2Group &group); -virtual bool getMsgData(const uint32_t &token, RsForumV2Msg &msg); - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); - - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - -virtual bool createGroup(uint32_t &token, RsForumV2Group &group, bool isNew); -virtual bool createMsg(uint32_t &token, RsForumV2Msg &msg, bool isNew); - - private: - -std::string genRandomId(); -bool generateDummyData(); - - ForumDataProxy *mForumProxy; - - RsMutex mForumMtx; - - /***** below here is locked *****/ - - bool mUpdated; - -}; - -#endif diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc new file mode 100644 index 000000000..7f60f1ee9 --- /dev/null +++ b/libretroshare/src/services/p3gxscircles.cc @@ -0,0 +1,1376 @@ +/* + * libretroshare/src/services p3gxscircles.cc + * + * Circles Interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3gxscircles.h" +#include "serialiser/rsgxscircleitems.h" +#include "gxs/rsgxsflags.h" +#include "util/rsrandom.h" +#include "util/rsstring.h" + +#include "pqi/authgpg.h" + +#include + +#include +#include + +/**** + * #define ID_DEBUG 1 + ****/ + +RsGxsCircles *rsGxsCircles = NULL; + +/****** + * + * GxsCircles are used to limit the spread of Gxs Groups and Messages. + * + * This is done via GxsCircle parameters in GroupMetaData: + * mCircleType (ALL, External, Internal). + * mCircleId. + * + * The Circle Group contains the definition of who is allowed access to the Group. + * and GXS asks this service before forwarding any data. + * + * The CircleGroup contains: + * list of GxsId's + * list of GxsCircleId's (subcircles also allowed). + * + * This service runs a background task to transform the CircleGroups + * into a list of friends/peers who are allowed access. + * These results are cached to provide GXS with quick access to the information. + * This involves: + * - fetching the GroupData via GXS. + * - querying the list of GxsId to see if they are known. + * (NB: this will cause caching of GxsId in p3IdService. + * - recursively loading subcircles to complete Circle definition. + * - saving the result into Cache. + * + * For Phase 1, we will only use the list of GxsIds. No subcircles will be allowed. + * Recursively determining membership via sub-circles is complex and needs more thought. + * The data-types for the full system, however, will be in-place. + */ + + +#define CIRCLEREQ_CACHELOAD 0x0001 +#define CIRCLEREQ_CIRCLE_LIST 0x0002 + +//#define CIRCLEREQ_PGPHASH 0x0010 +//#define CIRCLEREQ_REPUTATION 0x0020 + +//#define CIRCLEREQ_CACHETEST 0x1000 + +// Events. +#define CIRCLE_EVENT_LOADIDS 0x0001 +#define CIRCLE_EVENT_CACHELOAD 0x0002 +#define CIRCLE_EVENT_RELOADIDS 0x0003 +#define CIRCLE_EVENT_DUMMYSTART 0x0004 +#define CIRCLE_EVENT_DUMMYLOAD 0x0005 +#define CIRCLE_EVENT_DUMMYGEN 0x0006 + +#define CIRCLE_DUMMY_STARTPERIOD 300 // MUST BE LONG ENOUGH FOR IDS TO HAVE BEEN MADE. +#define CIRCLE_DUMMY_GENPERIOD 10 + +//#define CIRCLE_EVENT_CACHETEST 0x1000 +//#define CACHETEST_PERIOD 60 +//#define OWNID_RELOAD_DELAY 10 + +#define GXSID_LOAD_CYCLE 10 // GXSID completes a load in this period. + +#define MIN_CIRCLE_LOAD_GAP 5 + +/********************************************************************************/ +/******************* Startup / Tick ******************************************/ +/********************************************************************************/ + +p3GxsCircles::p3GxsCircles(RsGeneralDataService *gds, RsNetworkExchangeService *nes, p3IdService *identities) + : RsGxsCircleExchange(gds, nes, new RsGxsCircleSerialiser(), + RS_SERVICE_GXSV1_TYPE_GXSCIRCLE, identities, circleAuthenPolicy()), + RsGxsCircles(this), GxsTokenQueue(this), RsTickEvent(), mIdentities(identities), + mCircleMtx("p3GxsCircles"), + mCircleCache(DEFAULT_MEM_CACHE_SIZE, "GxsCircleCache") + +{ + // Kick off Cache Testing, + Others. + //RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD); + + RsTickEvent::schedule_now(CIRCLE_EVENT_LOADIDS); + + // Dummy Circles. + RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYSTART, CIRCLE_DUMMY_STARTPERIOD); +} + + +uint32_t p3GxsCircles::circleAuthenPolicy() +{ + return 0; +} + +void p3GxsCircles::service_tick() +{ + RsTickEvent::tick_events(); + GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. + return; +} + +void p3GxsCircles::notifyChanges(std::vector &changes) +{ + std::cerr << "p3GxsCircles::notifyChanges()"; + std::cerr << std::endl; + + receiveChanges(changes); + + // for new circles we need to add them to the list. + // TODO. +#if 0 + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + mCircleIdList.push_back(grpItem->meta.mGroupId); + } +#endif + +} + +/********************************************************************************/ +/******************* RsCircles Interface ***************************************/ +/********************************************************************************/ + +void p3GxsCircles::createLocalCircle() +{ + return; +} + +void p3GxsCircles::addToLocalCircle() +{ + return; +} + +void p3GxsCircles::removeFromLocalCircle() +{ + return; +} + +void p3GxsCircles::getLocalCirclePeers() +{ + return; +} + +void p3GxsCircles::getListOfLocalCircles() +{ + return; +} + + +#if 0 +bool p3GxsCircles:: getNickname(const RsGxsId &id, std::string &nickname) +{ + return false; +} + +#endif + +bool p3GxsCircles:: getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &details) +{ + std::cerr << "p3GxsCircles::getCircleDetails(" << id << ")"; + std::cerr << std::endl; + + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + if (mCircleCache.is_cached(id)) + { + RsGxsCircleCache &data = mCircleCache.ref(id); + + // should also have meta data.... + details.mCircleId = id; + details.mCircleName = data.mCircleName; + details.mUnknownPeers = data.mUnknownPeers; + details.mAllowedPeers = data.mAllowedPeers; + return true; + } + } + + /* it isn't there - add to public requests */ + cache_request_load(id); + + return false; +} + + +bool p3GxsCircles:: getCircleIdList(std::list &circleIds) +{ + std::cerr << "p3GxsCircles::getCircleIdList()"; + std::cerr << std::endl; + + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + circleIds = mCircleIdList; + + return true; +} + + +/********************************************************************************/ +/******************* RsGixs Interface ***************************************/ +/********************************************************************************/ + +bool p3GxsCircles::isLoaded(const RsGxsCircleId &circleId) +{ + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + return mCircleCache.is_cached(circleId); +} + +bool p3GxsCircles::loadCircle(const RsGxsCircleId &circleId) +{ + return cache_request_load(circleId); +} + +int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id) +{ + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + if (mCircleCache.is_cached(circleId)) + { + RsGxsCircleCache &data = mCircleCache.ref(circleId); + if (data.isAllowedPeer(id)) + { + return 1; + } + return 0; + } + return -1; +} + +bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list &friendlist) +{ + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + if (mCircleCache.is_cached(circleId)) + { + RsGxsCircleCache &data = mCircleCache.ref(circleId); + data.getAllowedPeersList(friendlist); + return true; + } + return false; +} + +/********************************************************************************/ +/******************* Get/Set Data ******************************************/ +/********************************************************************************/ + +bool p3GxsCircles::getGroupData(const uint32_t &token, std::vector &groups) +{ + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsCircleGroupItem* item = dynamic_cast(*vit); + RsGxsCircleGroup group; + item->convertTo(group); + + // If its cached - add that info (TODO). + groups.push_back(group); + } + } + + return ok; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +bool p3GxsCircles::createGroup(uint32_t& token, RsGxsCircleGroup &group) +{ + std::cerr << "p3GxsCircles::createGroup()"; + std::cerr << std::endl; + + RsGxsCircleGroupItem* item = new RsGxsCircleGroupItem(); + item->convertFrom(group); + RsGenExchange::publishGroup(token, item); + return true; +} + +void p3GxsCircles::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /*keySet*/) +{ + std::cerr << "p3GxsCircles::service_CreateGroup()"; + std::cerr << std::endl; + + RsGxsCircleGroupItem *item = dynamic_cast(grpItem); + if (!item) + { + std::cerr << "p3GxsCircles::service_CreateGroup() ERROR invalid cast"; + std::cerr << std::endl; + return; + } + + // Now copy the GroupId into the mCircleId, and set the mode. + // TODO. +#ifdef HAVE_CIRCLE_META_DATA + grpItem->meta.mCircleType = EXTERNAL; + grpItem->meta.mCircleId = grpItem->meta.mGroupId; + + grpItem->group.mMeta.mCircleType = grpItem->meta.mCircleType; + grpItem->group.mMeta.mCircleId = grpItem->meta.mCircleId; +#endif + + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + mCircleIdList.push_back(grpItem->meta.mGroupId); + } +} + + + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* + * Cache of recently used circles. + */ + +RsGxsCircleCache::RsGxsCircleCache() +{ + return; +} + + +bool RsGxsCircleCache::loadBaseCircle(const RsGxsCircleGroup &circle) +{ + + mCircleId = circle.mMeta.mGroupId; + mCircleName = circle.mMeta.mGroupName; + mUpdateTime = time(NULL); + mProcessedCircles.insert(mCircleId); + + std::cerr << "RsGxsCircleCache::loadBaseCircle(" << mCircleId << ")"; + std::cerr << std::endl; + + return true; +} + +bool RsGxsCircleCache::loadSubCircle(const RsGxsCircleCache &subcircle) +{ + /* copy across all the lists */ + + /* should not be any unprocessed circles or peers */ + std::cerr << "RsGxsCircleCache::loadSubCircle(" << subcircle.mCircleId << ") TODO"; + std::cerr << std::endl; + + return true; +} + +bool RsGxsCircleCache::getAllowedPeersList(std::list &friendlist) +{ + std::map >::iterator it; + for(mAllowedPeers.begin(); it != mAllowedPeers.end(); it++) + { + friendlist.push_back(it->first); + } + return true; +} + +bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) +{ + std::map >::iterator it = mAllowedPeers.find(id); + if (it != mAllowedPeers.end()) + { + return true; + } + return false; +} + +bool RsGxsCircleCache::addAllowedPeer(const RsPgpId &pgpId, const RsGxsId &gxsId) +{ + /* created if doesn't exist */ + std::list &gxsList = mAllowedPeers[pgpId]; + gxsList.push_back(gxsId); + return true; +} + + + +/************************************************************************************/ +/************************************************************************************/ + +bool p3GxsCircles::request_CircleIdList() +{ + /* trigger request to load missing ids into cache */ + std::list groupIds; + std::cerr << "p3GxsCircles::request_CircleIdList()"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, CIRCLEREQ_CIRCLE_LIST); + return 1; +} + + +bool p3GxsCircles::load_CircleIdList(uint32_t token) +{ + std::cerr << "p3GxsCircles::load_CircleIdList() : " << token; + std::cerr << std::endl; + + std::list groupIds; + bool ok = RsGenExchange::getGroupList(token, groupIds); + + if(ok) + { + // Save List + std::list::iterator vit; + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + + mCircleIdList.clear(); + + for(vit = groupIds.begin(); vit != groupIds.end(); vit++) + { + mCircleIdList.push_back(*vit); + } + } + else + { + std::cerr << "p3GxsCircles::load_CircleIdList() ERROR no data"; + std::cerr << std::endl; + + return false; + } + return true; +} + + + +/****************************************************************************/ +// ID STUFF. \/ \/ \/ \/ \/ \/ \/ :) +/****************************************************************************/ +#if 0 + +/************************************************************************************/ +/************************************************************************************/ + +bool p3GxsCircles::cachetest_getlist() +{ + std::cerr << "p3GxsCircles::cachetest_getlist() making request"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, CIRCLEREQ_CACHETEST); + + // Schedule Next Event. + RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD); + return true; +} + +bool p3GxsCircles::cachetest_handlerequest(uint32_t token) +{ + std::cerr << "p3GxsCircles::cachetest_handlerequest() token: " << token; + std::cerr << std::endl; + + std::list grpIds; + bool ok = RsGenExchange::getGroupList(token, grpIds); + + if(ok) + { + std::list::iterator vit = grpIds.begin(); + for(; vit != grpIds.end(); vit++) + { + /* 5% chance of checking it! */ + if (RSRandom::random_f32() < 0.25) + { + std::cerr << "p3GxsCircles::cachetest_request() Testing Id: " << *vit; + std::cerr << std::endl; + + /* try the cache! */ + if (!haveKey(*vit)) + { + std::list nullpeers; + requestKey(*vit, nullpeers); + + std::cerr << "p3GxsCircles::cachetest_request() Requested Key Id: " << *vit; + std::cerr << std::endl; + } + else + { + RsTlvSecurityKey seckey; + if (getKey(*vit, seckey)) + { + std::cerr << "p3GxsCircles::cachetest_request() Got Key OK Id: " << *vit; + std::cerr << std::endl; + + // success! + seckey.print(std::cerr, 10); + std::cerr << std::endl; + + + } + else + { + std::cerr << "p3GxsCircles::cachetest_request() ERROR no Key for Id: " << *vit; + std::cerr << std::endl; + } + } + + /* try private key too! */ + if (!havePrivateKey(*vit)) + { + requestPrivateKey(*vit); + std::cerr << "p3GxsCircles::cachetest_request() Requested PrivateKey Id: " << *vit; + std::cerr << std::endl; + } + else + { + RsTlvSecurityKey seckey; + if (getPrivateKey(*vit, seckey)) + { + // success! + std::cerr << "p3GxsCircles::cachetest_request() Got PrivateKey OK Id: " << *vit; + std::cerr << std::endl; + } + else + { + std::cerr << "p3GxsCircles::cachetest_request() ERROR no PrivateKey for Id: " << *vit; + std::cerr << std::endl; + } + } + } + } + } + else + { + std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; + std::cerr << std::endl; + + return false; + } + return true; +} + +/****************************************************************************/ +// ID STUFF. /\ /\ /\ /\ /\ /\ /\ /\ :) +/****************************************************************************/ +#endif + + + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ +// Complicated deal of loading Circles. + + +bool p3GxsCircles::cache_request_load(const RsGxsCircleId &id) +{ + std::cerr << "p3GxsCircles::cache_request_load(" << id << ")"; + std::cerr << std::endl; + + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + + /* check its not loaded */ + if (mCircleCache.is_cached(id)) + return true; + + /* check it is not already being loaded */ + std::map::iterator it; + it = mLoadingCache.find(id); + if (it != mLoadingCache.end()) + { + // Already loading. + return true; + } + // Put it into the Loading Cache - so we will detect it later. + mLoadingCache[id] = RsGxsCircleCache(); + mCacheLoad_ToCache.push_back(id); + } + + if (RsTickEvent::event_count(CIRCLE_EVENT_CACHELOAD) > 0) + { + /* its already scheduled */ + return true; + } + + int32_t age = 0; + if (RsTickEvent::prev_event_ago(CIRCLE_EVENT_CACHELOAD, age)) + { + if (age < MIN_CIRCLE_LOAD_GAP) + { + RsTickEvent::schedule_in(CIRCLE_EVENT_CACHELOAD, + MIN_CIRCLE_LOAD_GAP - age); + return true; + } + } + + RsTickEvent::schedule_now(CIRCLE_EVENT_CACHELOAD); + return true; +} + + +bool p3GxsCircles::cache_start_load() +{ + std::cerr << "p3GxsCircles::cache_start_load()"; + std::cerr << std::endl; + + /* trigger request to load missing ids into cache */ + std::list groupIds; + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + + /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ + std::list::iterator it; + for(it = mCacheLoad_ToCache.begin(); it != mCacheLoad_ToCache.end(); it++) + { + std::cerr << "p3GxsCircles::cache_start_load() GroupId: " << *it; + std::cerr << std::endl; + groupIds.push_back(*it); // might need conversion? + } + + mCacheLoad_ToCache.clear(); + } + + if (groupIds.size() > 0) + { + std::cerr << "p3GxsCircles::cache_start_load() #Groups: " << groupIds.size(); + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); + GxsTokenQueue::queueRequest(token, CIRCLEREQ_CACHELOAD); + } + return 1; +} + + +bool p3GxsCircles::cache_load_for_token(uint32_t token) +{ + std::cerr << "p3GxsCircles::cache_load_for_token() : " << token; + std::cerr << std::endl; + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsCircleGroupItem *item = dynamic_cast(*vit); + RsGxsCircleGroup group; + item->convertTo(group); + + std::cerr << "p3GxsCircles::cache_load_for_token() Loaded Id with Meta: "; + std::cerr << item->meta; + std::cerr << std::endl; + + + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + + /* should already have a LoadingCache entry */ + RsGxsCircleId id = item->meta.mGroupId; + std::map::iterator it; + it = mLoadingCache.find(id); + if (it == mLoadingCache.end()) + { + // ERROR. + continue; + } + + RsGxsCircleCache &cache = it->second; + cache.loadBaseCircle(group); + delete item; + + bool isComplete = true; + bool isUnprocessedPeers = false; + + std::list &peers = group.mInvitedMembers; + std::list::const_iterator pit; + + // need to trigger the searches. + for(pit = peers.begin(); pit != peers.end(); pit++) + { + /* check cache */ + if (mIdentities->haveKey(*pit)) + { + /* we can process now! */ + RsIdentityDetails details; + if (mIdentities->getIdDetails(*pit, details)) + { + if (details.mPgpLinked && details.mPgpKnown) + { + cache.addAllowedPeer(details.mPgpId, *pit); + } + else + { + cache.mUnknownPeers.insert(*pit); + } + } + else + { + // ERROR. + } + } + else + { + /* store in to_process queue. */ + cache.mUnprocessedPeers.insert(*pit); + + isComplete = false; + isUnprocessedPeers = true; + } + } + +#ifdef HANDLE_SUBCIRCLES +#if 0 + std::list &circles = group.mSubCircles; + std::list::const_iterator cit; + for(cit = circles.begin(); cit != circles.end(); cit++) + { + /* if its cached already -> then its complete. */ + if (mCircleCache.is_loaded(*cit)) + { + RsGxsCircleCache cachedCircle; + if (mCircleCache.fetch(&cit, cachedCircle)) + { + /* copy cached circle into circle */ + cache.loadSubCircle(cachedCircle); + } + else + { + /* error */ + continue; + } + } + else + { + /* push into secondary processing queues */ + std::list &proc_circles = mCacheLoad_SubCircle[*cit]; + proc_circles.push_back(id); + + subCirclesToLoad.push_back(*cit); + + isComplete = false; + isUnprocessedCircles = true; + } + } +#endif +#endif + + if (isComplete) + { + /* move straight into the cache */ + mCircleCache.store(id, cache); + mCircleCache.resize(); + + /* remove from loading queue */ + mLoadingCache.erase(it); + } + + if (isUnprocessedPeers) + { + /* schedule event to try reload gxsIds */ + RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, id); + } + } + } + else + { + std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; + std::cerr << std::endl; + + return false; + } + +#ifdef HANDLE_SUBCIRCLES +#if 0 + if (!subCirclesToLoad.empty()) + { + /* request load of subcircles */ + + + } +#endif +#endif + return true; +} + + +bool p3GxsCircles::cache_reloadids(const std::string &circleId) +{ + std::cerr << "p3GxsCircles::cache_reloadids()"; + std::cerr << std::endl; + + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + + /* fetch from loadMap */ + std::map::iterator it; + it = mLoadingCache.find(circleId); + if (it == mLoadingCache.end()) + { + std::cerr << "p3GxsCircles::cache_reloadids() ERROR Id: " << circleId; + std::cerr << " Not in mLoadingCache Map"; + std::cerr << std::endl; + + // ERROR + return false; + } + + RsGxsCircleCache &cache = it->second; + + /* try reload Ids */ + std::set::const_iterator pit; + for(pit = cache.mUnprocessedPeers.begin(); + pit != cache.mUnprocessedPeers.end(); pit++) + { + /* check cache */ + if (mIdentities->haveKey(*pit)) + { + /* we can process now! */ + RsIdentityDetails details; + if (mIdentities->getIdDetails(*pit, details)) + { + if (details.mPgpLinked && details.mPgpKnown) + { + cache.addAllowedPeer(details.mPgpId, *pit); + + std::cerr << "p3GxsCircles::cache_reloadids() AllowedPeer: "; + std::cerr << *pit; + std::cerr << std::endl; + } + else + { + cache.mUnknownPeers.insert(*pit); + + std::cerr << "p3GxsCircles::cache_reloadids() UnknownPeer: "; + std::cerr << *pit; + std::cerr << std::endl; + } + } + else + { + // ERROR. + std::cerr << "p3GxsCircles::cache_reloadids() ERROR "; + std::cerr << " Should haveKey for Id: " << *pit; + std::cerr << std::endl; + } + } + else + { + // UNKNOWN ID. + std::cerr << "p3GxsCircles::cache_reloadids() UNKNOWN Id: "; + std::cerr << *pit; + std::cerr << std::endl; + } + } + + // clear unprocessed List. + cache.mUnprocessedPeers.clear(); + + // If sub-circles are complete too. + if (cache.mUnprocessedCircles.empty()) + { + std::cerr << "p3GxsCircles::cache_reloadids() Adding to cache Id: "; + std::cerr << circleId; + std::cerr << std::endl; + + // Push to Cache. + mCircleCache.store(circleId, cache); + mCircleCache.resize(); + + /* remove from loading queue */ + mLoadingCache.erase(it); + } + else + { + std::cerr << "p3GxsCircles::cache_reloadids() WARNING Incomplete Cache Loading: "; + std::cerr << circleId; + std::cerr << std::endl; + } + + return true; +} + + + +#ifdef HANDLE_SUBCIRCLES +#if 0 +/**** TODO BELOW ****/ + +bool p3GxsCircles::cache_load_subcircles(uint32_t token) +{ + std::cerr << "p3GxsCircles::cache_load_subcircles() : " << token; + std::cerr << std::endl; + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsIdGroupItem* item = dynamic_cast(*vit); + + RsGxsCircleId id = item->meta.mGroupId; + RsGxsCircleGroup group = item->group; + group.mMeta = item->meta; + delete item; + + std::cerr << "p3GxsCircles::cache_load_subcircles() Loaded Id with Meta: "; + std::cerr << item->meta; + std::cerr << std::endl; + + + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + + /* stage 2 of loading, load subcircles */ + std::map >::iterator sit; + sit = mCacheLoad_SubCircle.find(id) + if (sit == mCacheLoad_SubCircle.end()) + { + /* ERROR */ + continue; + } + + std::list updateCaches = sit->second; + // cleanup while we're here. + mCacheLoad_SubCircle.erase(sit); + + /* Now iterate through peers / subcircles, and apply + * - similarly to base load function + */ + + + RsGxsCircleCache &cache = it->second; + cache.loadBaseCircle(group); + + bool isComplete = true; + + std::list &peers = group.peers; + std::list::const_iterator pit; + + // need to trigger the searches. + for(pit = peers.begin(); pit != peers.end(); pit++) + { + /* check cache */ + if (mIdentities->is_cached(*pit)) + { + /* we can process now! */ + RsIdentityDetails details; + if (mIdentities->getDetails(*pit, details)) + { + if (details.isPgpKnown) + { + // Problem - could have multiple GxsIds here! + // TODO. + //cache.mAllowedPeers[details.mPgpId] = *pit; + + for(uit = updateCaches.begin(); uit != updateCaches.end(); uit++) + { + /* fetch the cache - and update */ + mLoadingCache[id] = RsGxsCircleCache(); + std::map::iterator it; + it = mLoadingCache.find(id); + } + + } + else + { + //cache.mUnknownPeers.push_back(*pit); + } + } + else + { + // ERROR. + } + } + else + { + /* store in to_process queue. */ + cache.mUnprocessedPeers.push_back(*pit); + + if (isComplete) + { + /* store reference to update */ + isComplete = false; + mCacheLoad_KeyWait.push_back(id); + } + } + } + + std::list &circles = group.circles; + std::list::const_iterator cit; + for(cit = circles.begin(); cit != circles.end(); cit++) + { + /* if its cached already -> then its complete. */ + if (mCircleCache.is_loaded(*cit)) + { + RsGxsCircleCache cachedCircle; + if (mCircleCache.fetch(&cit, cachedCircle)) + { + /* copy cached circle into circle */ + cache.loadSubCircle(cachedCircle); + } + else + { + /* error */ + continue; + } + } + else + { + /* push into secondary processing queues */ + std::list &proc_circles = mCacheLoad_SubCircle[id]; + proc_circles.push_back(id); + + subCirclesToLoad.push_back(id); + + isComplete = false; + } + } + + if (isComplete) + { + /* move straight into the cache */ + mCircleCache.store(id, cache); + + /* remove from loading queue */ + mLoadingCache.erase(it); + } + } + } + else + { + std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; + std::cerr << std::endl; + + return false; + } + + if (!keysToLoad.empty()) + { + /* schedule event to try reload gxsIds */ + + } + + if (!subCirclesToLoad.empty()) + { + /* request load of subcircles */ + + + } + return true; +} + +#endif +#endif + + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +std::string p3GxsCircles::genRandomId() +{ + std::string randomId; + for(int i = 0; i < 20; i++) + { + randomId += (char) ('a' + (RSRandom::random_u32() % 26)); + } + + return randomId; +} + +void p3GxsCircles::generateDummyData() +{ + // request Id Data... + std::cerr << "p3GxsCircles::generateDummyData() getting Id List"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + uint32_t token; + rsIdentity->getTokenService()->requestGroupInfo(token, ansType, opts); + + { + RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ + mDummyIdToken = token; + } + + RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYLOAD, CIRCLE_DUMMY_GENPERIOD); +} + + +void p3GxsCircles::checkDummyIdData() +{ + std::cerr << "p3GxsCircles::checkDummyIdData()"; + std::cerr << std::endl; + // check the token. + uint32_t status = rsIdentity->getTokenService()->requestStatus(mDummyIdToken); + if ( (RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == status) || + (RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == status) ) + { + std::vector ids; + if (!rsIdentity->getGroupData(mDummyIdToken, ids)) + { + std::cerr << "p3GxsCircles::checkDummyIdData() ERROR getting data"; + std::cerr << std::endl; + /* error */ + return; + } + + std::vector::iterator it; + for(it = ids.begin(); it != ids.end(); it++) + { + if (it->mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + std::cerr << "p3GxsCircles::checkDummyIdData() PgpLinkedId: " << it->mMeta.mGroupId; + std::cerr << std::endl; + mDummyPgpLinkedIds.push_back(it->mMeta.mGroupId); + + if (it->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + { + std::cerr << "p3GxsCircles::checkDummyIdData() OwnId: " << it->mMeta.mGroupId; + std::cerr << std::endl; + mDummyOwnIds.push_back(it->mMeta.mGroupId); + } + } + else + { + std::cerr << "p3GxsCircles::checkDummyIdData() Other Id: " << it->mMeta.mGroupId; + std::cerr << std::endl; + } + } + + /* schedule the generate events */ +#define MAX_CIRCLES 10 + for(int i = 0; i < MAX_CIRCLES; i++) + { + RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYGEN, i * CIRCLE_DUMMY_GENPERIOD); + } + return; + } + + // Otherwise - reschedule to come back here. + RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYLOAD, CIRCLE_DUMMY_GENPERIOD); + return; +} + + +void p3GxsCircles::generateDummyCircle() +{ + std::cerr << "p3GxsCircles::generateDummyCircle()"; + std::cerr << std::endl; + + int npgps = mDummyPgpLinkedIds.size(); + RsGxsCircleGroup group; + + std::set idset; + // select a random number of them. +#define MAX_PEERS_PER_CIRCLE_GROUP 20 + int nIds = 1 + (RSRandom::random_u32() % MAX_PEERS_PER_CIRCLE_GROUP); + for(int i = 0; i < nIds; i++) + { + + int selection = (RSRandom::random_u32() % npgps); + std::list::iterator it = mDummyPgpLinkedIds.begin(); + for(int j = 0; (it != mDummyPgpLinkedIds.end()) && (j < selection); j++, it++); + if (it != mDummyPgpLinkedIds.end()) + { + idset.insert(*it); + } + } + + /* be sure to add one of our IDs too (otherwise we wouldn't get the group) + */ + { + + int selection = (RSRandom::random_u32() % mDummyOwnIds.size()); + std::list::iterator it = mDummyOwnIds.begin(); + mDummyOwnIds.push_back(*it); + for(int j = 0; (it != mDummyOwnIds.end()) && (j < selection); j++, it++); + if (it != mDummyOwnIds.end()) + { + idset.insert(*it); + } + } + + group.mMeta.mGroupName = genRandomId(); + std::cerr << "p3GxsCircles::generateDummyCircle() Name: " << group.mMeta.mGroupName; + std::cerr << std::endl; + + std::set::iterator it; + for(it = idset.begin(); it != idset.end(); it++) + { + group.mInvitedMembers.push_back(*it); + std::cerr << "p3GxsCircles::generateDummyCircle() Adding: " << *it; + std::cerr << std::endl; + } + + uint32_t dummyToken; + createGroup(dummyToken, group); +} + + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + + +std::ostream &operator<<(std::ostream &out, const RsGxsCircleGroup &grp) +{ + out << "RsGxsCircleGroup: Meta: " << grp.mMeta; + out << "InvitedMembers: "; + out << std::endl; + + std::list::const_iterator it; + std::list::const_iterator sit; + for(it = grp.mInvitedMembers.begin(); + it != grp.mInvitedMembers.begin(); it++) + { + out << "\t" << *it; + out << std::endl; + } + + for(sit = grp.mSubCircles.begin(); + sit != grp.mSubCircles.begin(); sit++) + { + out << "\t" << *it; + out << std::endl; + } + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsGxsCircleMsg &msg) +{ + out << "RsGxsCircleMsg: Meta: " << msg.mMeta; + out << std::endl; + + return out; +} + + + + // Overloaded from GxsTokenQueue for Request callbacks. +void p3GxsCircles::handleResponse(uint32_t token, uint32_t req_type) +{ + std::cerr << "p3GxsCircles::handleResponse(" << token << "," << req_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(req_type) + { + case CIRCLEREQ_CIRCLE_LIST: + load_CircleIdList(token); + break; + + case CIRCLEREQ_CACHELOAD: + cache_load_for_token(token); + break; + +#if 0 + case CIRCLEREQ_CACHETEST: + cachetest_handlerequest(token); + break; +#endif + + default: + /* error */ + std::cerr << "p3GxsCircles::handleResponse() Unknown Request Type: " << req_type; + std::cerr << std::endl; + break; + } +} + + + // Overloaded from RsTickEvent for Event callbacks. +void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel) +{ + std::cerr << "p3GxsCircles::handle_event(" << event_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(event_type) + { + case CIRCLE_EVENT_LOADIDS: + request_CircleIdList(); + break; + + case CIRCLE_EVENT_CACHELOAD: + cache_start_load(); + break; + + case CIRCLE_EVENT_RELOADIDS: + cache_reloadids(elabel); + break; + +#if 0 + case CIRCLE_EVENT_CACHETEST: + cachetest_getlist(); + break; +#endif + + + case CIRCLE_EVENT_DUMMYSTART: + generateDummyData(); + break; + + case CIRCLE_EVENT_DUMMYLOAD: + checkDummyIdData(); + break; + + case CIRCLE_EVENT_DUMMYGEN: + generateDummyCircle(); + break; + + default: + /* error */ + std::cerr << "p3GxsCircles::handle_event() Unknown Event Type: " << event_type; + std::cerr << std::endl; + break; + } +} + + + diff --git a/libretroshare/src/services/p3gxscircles.h b/libretroshare/src/services/p3gxscircles.h new file mode 100644 index 000000000..0ad2aab14 --- /dev/null +++ b/libretroshare/src/services/p3gxscircles.h @@ -0,0 +1,246 @@ +/* + * libretroshare/src/services: p3circles.h + * + * Identity interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_CIRCLES_SERVICE_HEADER +#define P3_CIRCLES_SERVICE_HEADER + + +#include "retroshare/rsgxscircles.h" // External Interfaces. +#include "gxs/rsgenexchange.h" // GXS service. +#include "gxs/rsgixs.h" // Internal Interfaces. + +#include "services/p3idservice.h" // For constructing Caches + +#include "gxs/gxstokenqueue.h" +#include "util/rstickevent.h" +#include "util/rsmemcache.h" + +#include +#include + +/* + * Circles Identity Service + * + * A collection of notes: + * + * We want to be able to express the following types of Circles. + * + * - Public + * - Groups & Messages can be passed onto anyone. ( No Restrictions. ) + * - GXS Notes: + * - This is what we have currently. + * + * - External Circle + * - List of Identities that can receive the Group / Messages. + * - This list will be defined via a set of RsIdentities - which have PGPHashes set. + * - We need the PGPHashes to be able to identify which peers can receive msgs. + * - Messages are passed to the Intersection of (Identified PGPHashes & Friends) + * - Distribution of Circle Definitions can be also be restricted via circles. + * - You can have Public External Groups, or Groups that only the Members know about. + * - Control of these External Groups is determined by Admin / Publish Keys. + * - The Danger with External Groups, is your ID wll be associated with other people... + * - Leaking information!!! + * - GXS Notes: + * - p3Circles will provide a distrib list for a given Circle Group. + * + * - Personal Circle or "Your Eyes Only". + * - Same as an Internal Circle Definition. (What will be used for File Sharing initially) + * - Each peer will have a bunch of these, Friends, Family, etc. + * + * - The list is not publically shared, only the originator of the message will distribute. + * - You can communicate back to the originator, who will share with the other members. + * but you mustn't discuss / share content with anyone else. + * - This is quite a Weak / Fragile Group, as there is only one distributor. + * - GXS NOTES: + * - TO make this work, we need GXS or RsCircles to maintain extra info: + * - GXS stores the original source, so communications can go back there. + * - If Originator, GXS store a REFERENCE, Circles turn this into a distrib list of peers. + * + * + * + * Like RsIdentities are used to validation messages, + * RsCircles will be used to determine if a peer can receive a group / messages. + * + * bool RsCircles::canSend(RsGxsCircleId, RsPeerId) + * bool RsCircles::canSend(RsCircleInternalId, RsPeerId) + * + * or maybe just: + * + * bool RsCircles::recipients(GxsPermission &perms, std::list friendlist); + * + */ + +/* Permissions is part of GroupMetaData + */ + +class RsGxsCircleCache +{ + public: + + RsGxsCircleCache(); + bool loadBaseCircle(const RsGxsCircleGroup &circle); + bool loadSubCircle(const RsGxsCircleCache &subcircle); + + bool getAllowedPeersList(std::list &friendlist); + bool isAllowedPeer(const RsPgpId &id); + bool addAllowedPeer(const RsPgpId &pgpid, const RsGxsId &gxsId); + + RsGxsCircleId mCircleId; + std::string mCircleName; + + time_t mUpdateTime; + std::set mUnprocessedCircles; + std::set mUnprocessedPeers; + + std::set mProcessedCircles; + std::set mUnknownPeers; + std::map > mAllowedPeers; +}; + + + +class RsCircles +{ + /* Functions to handle Local / Internal Circles == Same as for file permissions. */ +public: + virtual void createLocalCircle() = 0; + virtual void addToLocalCircle() = 0; + virtual void removeFromLocalCircle() = 0; + virtual void getLocalCirclePeers() = 0; + virtual void getListOfLocalCircles() = 0; + + /* similar functions for External Groups */ + virtual bool createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0; + virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; + +}; + + +class p3GxsCircles: public RsGxsCircleExchange, public RsGxsCircles, + public GxsTokenQueue, public RsTickEvent +{ + public: + p3GxsCircles(RsGeneralDataService* gds, RsNetworkExchangeService* nes, + p3IdService *identities); + + /*********** External Interface ***************/ + + virtual bool getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &details); + virtual bool getCircleIdList(std::list &circleIds); + + virtual bool isLoaded(const RsGxsCircleId &circleId); + virtual bool loadCircle(const RsGxsCircleId &circleId); + + virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id); + virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist); + + /*******/ + + virtual void createLocalCircle(); + virtual void addToLocalCircle(); + virtual void removeFromLocalCircle(); + virtual void getLocalCirclePeers(); + virtual void getListOfLocalCircles(); + + /*******/ + + virtual bool getGroupData(const uint32_t &token, std::vector &groups); + virtual bool createGroup(uint32_t& token, RsGxsCircleGroup &group); + + /**********************************************/ + + // needed for background processing. + virtual void service_tick(); + + protected: + + static uint32_t circleAuthenPolicy(); + + /** Notifications **/ + virtual void notifyChanges(std::vector& changes); + + /** Overloaded to add PgpIdHash to Group Definition **/ + virtual void service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); + + // Overloaded from GxsTokenQueue for Request callbacks. + virtual void handleResponse(uint32_t token, uint32_t req_type); + + // Overloaded from RsTickEvent. + virtual void handle_event(uint32_t event_type, const std::string &elabel); + + private: + + // Load data. + bool request_CircleIdList(); + bool load_CircleIdList(uint32_t token); + + // Need some crazy arsed cache to store the circle info. + // so we don't have to keep loading groups. + + int cache_tick(); + + bool cache_request_load(const RsGxsCircleId &id); + bool cache_start_load(); + bool cache_load_for_token(uint32_t token); + bool cache_reloadids(const std::string &circleId); + + + p3IdService *mIdentities; // Needed for constructing Circle Info, + + RsMutex mCircleMtx; /* Locked Below Here */ + + std::list mCircleIdList; + + /***** Caching Circle Info, *****/ + // initial load queue + std::list mCacheLoad_ToCache; + + // waiting for subcircle to load. (first is part of each of the second list) + // TODO. + //std::map > mCacheLoad_SubCircle; + + // Circles that are being loaded. + std::map mLoadingCache; + + // actual cache. + RsMemCache mCircleCache; + + private: + + std::string genRandomId(); + + void generateDummyData(); + void checkDummyIdData(); + void generateDummyCircle(); + + + uint32_t mDummyIdToken; + std::list mDummyPgpLinkedIds; + std::list mDummyOwnIds; + + +}; + +#endif // P3_CIRCLES_SERVICE_HEADER diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc new file mode 100644 index 000000000..bbfcdc628 --- /dev/null +++ b/libretroshare/src/services/p3gxsforums.cc @@ -0,0 +1,471 @@ +/* + * libretroshare/src/services p3gxsforums.cc + * + * GxsForums interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3gxsforums.h" +#include "serialiser/rsgxsforumitems.h" + +#include + + +#include "gxs/rsgxsflags.h" +#include + +// For Dummy Msgs. +#include "util/rsrandom.h" +#include "util/rsstring.h" + +/**** + * #define GXSFORUM_DEBUG 1 + ****/ + +RsGxsForums *rsGxsForums = NULL; + + +#define FORUM_TESTEVENT_DUMMYDATA 0x0001 +#define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated. + +/********************************************************************************/ +/******************* Startup / Tick ******************************************/ +/********************************************************************************/ + +p3GxsForums::p3GxsForums(RsGeneralDataService *gds, RsNetworkExchangeService *nes) + : RsGenExchange(gds, nes, new RsGxsForumSerialiser(), RS_SERVICE_GXSV1_TYPE_FORUMS), RsGxsForums(this) +{ + // For Dummy Msgs. + mGenActive = false; + RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); +} + +void p3GxsForums::notifyChanges(std::vector &changes) +{ + receiveChanges(changes); +} + +void p3GxsForums::service_tick() +{ + dummy_tick(); + RsTickEvent::tick_events(); + return; +} + +bool p3GxsForums::getGroupData(const uint32_t &token, std::vector &groups) +{ + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsForumGroupItem* item = dynamic_cast(*vit); + RsGxsForumGroup grp = item->mGroup; + item->mGroup.mMeta = item->meta; + grp.mMeta = item->mGroup.mMeta; + delete item; + groups.push_back(grp); + } + } + return ok; +} + +/* Okay - chris is not going to be happy with this... + * but I can't be bothered with crazy data structures + * at the moment - fix it up later + */ + +bool p3GxsForums::getMsgData(const uint32_t &token, std::vector &msgs) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsForumMsgItem* item = dynamic_cast(*vit); + + if(item) + { + RsGxsForumMsg msg = item->mMsg; + msg.mMeta = item->meta; + msgs.push_back(msg); + delete item; + } + else + { + std::cerr << "Not a GxsForumMsgItem, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + + +bool p3GxsForums::getRelatedMessages(const uint32_t &token, std::vector &msgs) +{ + GxsMsgRelatedDataMap msgData; + bool ok = RsGenExchange::getMsgRelatedData(token, msgData); + + if(ok) + { + GxsMsgRelatedDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsForumMsgItem* item = dynamic_cast(*vit); + + if(item) + { + /* HACK UNTIL CHRIS FIXES RELATED MSGS in GXS */ + if (item->meta.mMsgId == (mit->first).second) + { + std::cerr << "p3GxsForums::getRelatedMessages()"; + std::cerr << " ERROR Found Original - discarding"; + std::cerr << " Id: " << item->meta.mMsgId; + std::cerr << std::endl; + delete item; + continue; + } + + if (item->meta.mParentId != (mit->first).second) + { + std::cerr << "p3GxsForums::getRelatedMessages()"; + std::cerr << " ERROR Found !CHILD - discarding"; + std::cerr << " Id: " << item->meta.mMsgId; + std::cerr << std::endl; + delete item; + continue; + } + + RsGxsForumMsg msg = item->mMsg; + msg.mMeta = item->meta; + msgs.push_back(msg); + delete item; + } + else + { + std::cerr << "Not a GxsForumMsgItem, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + +/********************************************************************************************/ + +bool p3GxsForums::createGroup(uint32_t &token, RsGxsForumGroup &group) +{ + std::cerr << "p3GxsForums::createGroup()" << std::endl; + + RsGxsForumGroupItem* grpItem = new RsGxsForumGroupItem(); + grpItem->mGroup = group; + grpItem->meta = group.mMeta; + + RsGenExchange::publishGroup(token, grpItem); + return true; +} + + +bool p3GxsForums::createMsg(uint32_t &token, RsGxsForumMsg &msg) +{ + std::cerr << "p3GxsForums::createForumMsg() GroupId: " << msg.mMeta.mGroupId; + std::cerr << std::endl; + + RsGxsForumMsgItem* msgItem = new RsGxsForumMsgItem(); + msgItem->mMsg = msg; + msgItem->meta = msg.mMeta; + + RsGenExchange::publishMsg(token, msgItem); + return true; +} + + +/********************************************************************************************/ +/********************************************************************************************/ + +void p3GxsForums::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) +{ + uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; + if (read) + { + status = 0; + } + + setMsgStatusFlags(token, msgId, status, mask); + +} + +/********************************************************************************************/ +/********************************************************************************************/ + +/* so we need the same tick idea as wiki for generating dummy forums + */ + +#define MAX_GEN_GROUPS 5 +#define MAX_GEN_MESSAGES 100 + +std::string p3GxsForums::genRandomId() +{ + std::string randomId; + for(int i = 0; i < 20; i++) + { + randomId += (char) ('a' + (RSRandom::random_u32() % 26)); + } + + return randomId; +} + +bool p3GxsForums::generateDummyData() +{ + mGenCount = 0; + mGenRefs.resize(MAX_GEN_MESSAGES); + + std::string groupName; + rs_sprintf(groupName, "TestForum_%d", mGenCount); + + std::cerr << "p3GxsForums::generateDummyData() Starting off with Group: " << groupName; + std::cerr << std::endl; + + /* create a new group */ + generateGroup(mGenToken, groupName); + + mGenActive = true; + + return true; +} + + +void p3GxsForums::dummy_tick() +{ + /* check for a new callback */ + + if (mGenActive) + { + std::cerr << "p3GxsForums::dummyTick() AboutActive"; + std::cerr << std::endl; + + uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); + if (status != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::cerr << "p3GxsForums::dummy_tick() Status: " << status; + std::cerr << std::endl; + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + std::cerr << "p3GxsForums::dummy_tick() generateDummyMsgs() FAILED"; + std::cerr << std::endl; + mGenActive = false; + } + return; + } + + if (mGenCount < MAX_GEN_GROUPS) + { + /* get the group Id */ + RsGxsGroupId groupId; + RsGxsMessageId emptyId; + if (!acknowledgeTokenGrp(mGenToken, groupId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mGenActive = false; + return; + } + + std::cerr << "p3GxsForums::dummy_tick() Acknowledged GroupId: " << groupId; + std::cerr << std::endl; + + ForumDummyRef ref(groupId, emptyId, emptyId); + mGenRefs[mGenCount] = ref; + } + else if (mGenCount < MAX_GEN_MESSAGES) + { + /* get the msg Id, and generate next snapshot */ + RsGxsGrpMsgIdPair msgId; + if (!acknowledgeTokenMsg(mGenToken, msgId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mGenActive = false; + return; + } + + std::cerr << "p3GxsForums::dummy_tick() Acknowledged "; + std::cerr << std::endl; + + /* store results for later selection */ + + ForumDummyRef ref(msgId.first, mGenThreadId, msgId.second); + mGenRefs[mGenCount] = ref; + } + else + { + std::cerr << "p3GxsForums::dummy_tick() Finished"; + std::cerr << std::endl; + + /* done */ + mGenActive = false; + return; + } + + mGenCount++; + + if (mGenCount < MAX_GEN_GROUPS) + { + std::string groupName; + rs_sprintf(groupName, "TestForum_%d", mGenCount); + + std::cerr << "p3GxsForums::dummy_tick() Generating Group: " << groupName; + std::cerr << std::endl; + + /* create a new group */ + generateGroup(mGenToken, groupName); + } + else + { + /* create a new message */ + uint32_t idx = (uint32_t) (mGenCount * RSRandom::random_f32()); + ForumDummyRef &ref = mGenRefs[idx]; + + RsGxsGroupId grpId = ref.mGroupId; + RsGxsMessageId parentId = ref.mMsgId; + mGenThreadId = ref.mThreadId; + if (mGenThreadId.empty()) + { + mGenThreadId = parentId; + } + + std::cerr << "p3GxsForums::dummy_tick() Generating Msg ... "; + std::cerr << " GroupId: " << grpId; + std::cerr << " ThreadId: " << mGenThreadId; + std::cerr << " ParentId: " << parentId; + std::cerr << std::endl; + + generateMessage(mGenToken, grpId, parentId, mGenThreadId); + } + } +} + + +bool p3GxsForums::generateMessage(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) +{ + RsGxsForumMsg msg; + + std::string rndId = genRandomId(); + + rs_sprintf(msg.mMsg, "Forum Msg: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", + grpId.c_str(), threadId.c_str(), parentId.c_str(), rndId.c_str()); + + msg.mMeta.mMsgName = msg.mMsg; + + msg.mMeta.mGroupId = grpId; + msg.mMeta.mThreadId = threadId; + msg.mMeta.mParentId = parentId; + + msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; + + /* chose a random Id to sign with */ + std::list ownIds; + std::list::iterator it; + + rsIdentity->getOwnIds(ownIds); + + uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); + int i = 0; + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + + if (it != ownIds.end()) + { + std::cerr << "p3GxsForums::generateMessage() Author: " << *it; + std::cerr << std::endl; + msg.mMeta.mAuthorId = *it; + } + else + { + std::cerr << "p3GxsForums::generateMessage() No Author!"; + std::cerr << std::endl; + } + + createMsg(token, msg); + + return true; +} + + +bool p3GxsForums::generateGroup(uint32_t &token, std::string groupName) +{ + /* generate a new forum */ + RsGxsForumGroup forum; + forum.mMeta.mGroupName = groupName; + + createGroup(token, forum); + + return true; +} + + + // Overloaded from RsTickEvent for Event callbacks. +void p3GxsForums::handle_event(uint32_t event_type, const std::string &elabel) +{ + std::cerr << "p3GxsForums::handle_event(" << event_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(event_type) + { + case FORUM_TESTEVENT_DUMMYDATA: + generateDummyData(); + break; + + default: + /* error */ + std::cerr << "p3GxsForums::handle_event() Unknown Event Type: " << event_type; + std::cerr << std::endl; + break; + } +} + diff --git a/libretroshare/src/services/p3gxsforums.h b/libretroshare/src/services/p3gxsforums.h new file mode 100644 index 000000000..6205a229d --- /dev/null +++ b/libretroshare/src/services/p3gxsforums.h @@ -0,0 +1,111 @@ +/* + * libretroshare/src/services: p3gxsforums.h + * + * GxsForum interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_GXSFORUMS_SERVICE_HEADER +#define P3_GXSFORUMS_SERVICE_HEADER + + +#include "retroshare/rsgxsforums.h" +#include "gxs/rsgenexchange.h" + +#include "util/rstickevent.h" + +#include +#include + +/* + * + */ + +class p3GxsForums: public RsGenExchange, public RsGxsForums, + public RsTickEvent /* only needed for testing - remove after */ +{ + public: + + p3GxsForums(RsGeneralDataService* gds, RsNetworkExchangeService* nes); + +virtual void service_tick(); + + protected: + + +virtual void notifyChanges(std::vector& changes); + + // Overloaded from RsTickEvent. +virtual void handle_event(uint32_t event_type, const std::string &elabel); + + public: + +virtual bool getGroupData(const uint32_t &token, std::vector &groups); +virtual bool getMsgData(const uint32_t &token, std::vector &msgs); +virtual bool getRelatedMessages(const uint32_t &token, std::vector &msgs); + + ////////////////////////////////////////////////////////////////////////////// +virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); + +//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); +//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); + +//virtual bool groupRestoreKeys(const std::string &groupId); +//virtual bool groupShareKeys(const std::string &groupId, std::list& peers); + +virtual bool createGroup(uint32_t &token, RsGxsForumGroup &group); +virtual bool createMsg(uint32_t &token, RsGxsForumMsg &msg); + + + + private: + +virtual bool generateDummyData(); + +std::string genRandomId(); + +void dummy_tick(); + +bool generateMessage(uint32_t &token, const RsGxsGroupId &grpId, + const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); +bool generateGroup(uint32_t &token, std::string groupName); + + class ForumDummyRef + { + public: + ForumDummyRef() { return; } + ForumDummyRef(const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, const RsGxsMessageId &msgId) + :mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) { return; } + + RsGxsGroupId mGroupId; + RsGxsMessageId mThreadId; + RsGxsMessageId mMsgId; + }; + + uint32_t mGenToken; + bool mGenActive; + int mGenCount; + std::vector mGenRefs; + RsGxsMessageId mGenThreadId; + +}; + +#endif diff --git a/libretroshare/src/services/p3gxsservice.cc b/libretroshare/src/services/p3gxsserviceVEG.cc similarity index 69% rename from libretroshare/src/services/p3gxsservice.cc rename to libretroshare/src/services/p3gxsserviceVEG.cc index f2b316011..11ab6e013 100644 --- a/libretroshare/src/services/p3gxsservice.cc +++ b/libretroshare/src/services/p3gxsserviceVEG.cc @@ -23,16 +23,16 @@ * */ -#include "services/p3gxsservice.h" +#include "services/p3gxsserviceVEG.h" -p3GxsService::p3GxsService(uint16_t type) +p3GxsServiceVEG::p3GxsServiceVEG(uint16_t type) :p3Service(type), mReqMtx("p3GxsService") { mNextToken = 0; return; } -bool p3GxsService::generateToken(uint32_t &token) +bool p3GxsServiceVEG::generateToken(uint32_t &token) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -41,7 +41,7 @@ bool p3GxsService::generateToken(uint32_t &token) return true; } -bool p3GxsService::storeRequest(const uint32_t &token, const uint32_t &ansType, const RsTokReqOptions &opts, const uint32_t &type, const std::list &ids) +bool p3GxsServiceVEG::storeRequest(const uint32_t &token, const uint32_t &ansType, const RsTokReqOptionsVEG &opts, const uint32_t &type, const std::list &ids) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -60,7 +60,7 @@ bool p3GxsService::storeRequest(const uint32_t &token, const uint32_t &ansTyp } -bool p3GxsService::clearRequest(const uint32_t &token) +bool p3GxsServiceVEG::clearRequest(const uint32_t &token) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -77,7 +77,7 @@ bool p3GxsService::clearRequest(const uint32_t &token) return true; } -bool p3GxsService::updateRequestStatus(const uint32_t &token, const uint32_t &status) +bool p3GxsServiceVEG::updateRequestStatus(const uint32_t &token, const uint32_t &status) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -94,7 +94,7 @@ bool p3GxsService::updateRequestStatus(const uint32_t &token, const uint32_t &st return true; } -bool p3GxsService::updateRequestInList(const uint32_t &token, std::list ids) +bool p3GxsServiceVEG::updateRequestInList(const uint32_t &token, std::list ids) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -116,7 +116,7 @@ bool p3GxsService::updateRequestInList(const uint32_t &token, std::list ids) +bool p3GxsServiceVEG::updateRequestOutList(const uint32_t &token, std::list ids) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -138,7 +138,7 @@ bool p3GxsService::updateRequestOutList(const uint32_t &token, std::list data) +bool p3GxsServiceVEG::updateRequestData(const uint32_t &token, std::map data) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -160,7 +160,7 @@ bool p3GxsService::updateRequestData(const uint32_t &token, std::map &tokens) +bool p3GxsServiceVEG::tokenList(std::list &tokens) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -196,7 +196,7 @@ bool p3GxsService::tokenList(std::list &tokens) return true; } -bool p3GxsService::popRequestInList(const uint32_t &token, std::string &id) +bool p3GxsServiceVEG::popRequestInList(const uint32_t &token, std::string &id) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -220,7 +220,7 @@ bool p3GxsService::popRequestInList(const uint32_t &token, std::string &id) } -bool p3GxsService::popRequestOutList(const uint32_t &token, std::string &id) +bool p3GxsServiceVEG::popRequestOutList(const uint32_t &token, std::string &id) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -244,7 +244,7 @@ bool p3GxsService::popRequestOutList(const uint32_t &token, std::string &id) } -bool p3GxsService::loadRequestOutList(const uint32_t &token, std::list &ids) +bool p3GxsServiceVEG::loadRequestOutList(const uint32_t &token, std::list &ids) { RsStackMutex stack(mReqMtx); /****** LOCKED *****/ @@ -270,7 +270,7 @@ bool p3GxsService::loadRequestOutList(const uint32_t &token, std::list::iterator it; std::list tokens; @@ -287,7 +287,7 @@ bool p3GxsService::fakeprocessrequests() time_t ts; checkRequestStatus(token, status, reqtype, anstype, ts); - std::cerr << "p3GxsService::fakeprocessrequests() Token: " << token << " Status: " << status << " ReqType: " << reqtype << "Age: " << now - ts << std::endl; + std::cerr << "p3GxsServiceVEG::fakeprocessrequests() Token: " << token << " Status: " << status << " ReqType: " << reqtype << "Age: " << now - ts << std::endl; if (status == GXS_REQUEST_STATUS_PENDING) { @@ -299,13 +299,13 @@ bool p3GxsService::fakeprocessrequests() } else if (status == GXS_REQUEST_STATUS_DONE) { - std::cerr << "p3GxsService::fakeprocessrequests() Clearing Done Request Token: " << token; + std::cerr << "p3GxsServiceVEG::fakeprocessrequests() Clearing Done Request Token: " << token; std::cerr << std::endl; clearRequest(token); } else if (now - ts > MAX_REQUEST_AGE) { - std::cerr << "p3GxsService::fakeprocessrequests() Clearing Old Request Token: " << token; + std::cerr << "p3GxsServiceVEG::fakeprocessrequests() Clearing Old Request Token: " << token; std::cerr << std::endl; clearRequest(token); } @@ -334,14 +334,14 @@ bool p3GxsService::fakeprocessrequests() * ****/ -GxsDataProxy::GxsDataProxy() +GxsDataProxyVEG::GxsDataProxyVEG() :mDataMtx("GxsDataProxyMtx") { return; } -static bool checkGroupFilter(const RsTokReqOptions &opts, const RsGroupMetaData &group) +static bool checkGroupFilter(const RsTokReqOptionsVEG &opts, const RsGroupMetaData &group) { bool statusMatch = false; if (opts.mStatusMask) @@ -370,6 +370,33 @@ static bool checkGroupFilter(const RsTokReqOptions &opts, const RsGroupMetaData statusMatch = true; } + bool flagsMatch = false; + if (opts.mFlagsMask) + { + // Exact Flags match required. + if ((opts.mFlagsMask & opts.mFlagsFilter) == (opts.mFlagsMask & group.mGroupFlags)) + { + std::cerr << "checkGroupFilter() Accepting Group as Flags Match: "; + std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; + std::cerr << " GroupFlags: " << group.mGroupFlags << " GroupId: " << group.mGroupId; + std::cerr << std::endl; + + flagsMatch = true; + } + else + { + std::cerr << "checkGroupFilter() Dropping Group due to !Flags Match "; + std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; + std::cerr << " GroupFlags: " << group.mGroupFlags << " GroupId: " << group.mGroupId; + std::cerr << std::endl; + } + } + else + { + // no status comparision, + flagsMatch = true; + } + bool subMatch = false; if (opts.mSubscribeFilter) { @@ -397,11 +424,11 @@ static bool checkGroupFilter(const RsTokReqOptions &opts, const RsGroupMetaData subMatch = true; } - return (statusMatch && subMatch); + return (statusMatch && flagsMatch && subMatch); } -static bool checkMsgFilter(const RsTokReqOptions &opts, const RsMsgMetaData &msg) +static bool checkMsgFilter(const RsTokReqOptionsVEG &opts, const RsMsgMetaData &msg) { bool statusMatch = false; if (opts.mStatusMask) @@ -429,11 +456,39 @@ static bool checkMsgFilter(const RsTokReqOptions &opts, const RsMsgMetaData &msg // no status comparision, statusMatch = true; } - return statusMatch; + + bool flagsMatch = false; + if (opts.mFlagsMask) + { + // Exact Flags match required. + if ((opts.mFlagsMask & opts.mFlagsFilter) == (opts.mFlagsMask & msg.mMsgFlags)) + { + std::cerr << "checkMsgFilter() Accepting Msg as Flags Match: "; + std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; + std::cerr << " MsgFlags: " << msg.mMsgFlags << " MsgId: " << msg.mMsgId; + std::cerr << std::endl; + + flagsMatch = true; + } + else + { + std::cerr << "checkMsgFilter() Dropping Msg due to !Flags Match "; + std::cerr << " Mask: " << opts.mFlagsMask << " FlagsFilter: " << opts.mFlagsFilter; + std::cerr << " MsgFlags: " << msg.mMsgFlags << " MsgId: " << msg.mMsgId; + std::cerr << std::endl; + } + } + else + { + // no status comparision, + flagsMatch = true; + } + + return (statusMatch && flagsMatch); } -bool GxsDataProxy::filterGroupList(const RsTokReqOptions &opts, std::list &groupIds) +bool GxsDataProxyVEG::filterGroupList(const RsTokReqOptionsVEG &opts, std::list &groupIds) { std::list::iterator it; for(it = groupIds.begin(); it != groupIds.end(); ) @@ -462,7 +517,7 @@ bool GxsDataProxy::filterGroupList(const RsTokReqOptions &opts, std::list &msgIds) +bool GxsDataProxyVEG::filterMsgList(const RsTokReqOptionsVEG &opts, std::list &msgIds) { std::list::iterator it; for(it = msgIds.begin(); it != msgIds.end(); ) @@ -492,14 +547,14 @@ bool GxsDataProxy::filterMsgList(const RsTokReqOptions &opts, std::list &groupIds, std::list &outGroupIds) +bool GxsDataProxyVEG::getGroupList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outGroupIds) { /* CASEs that this handles ... * 1) if groupIds is Empty... return all groupIds. * 2) else copy list. * */ - std::cerr << "GxsDataProxy::getGroupList()"; + std::cerr << "GxsDataProxyVEG::getGroupList()"; std::cerr << std::endl; if (groupIds.size() == 0) @@ -524,14 +579,14 @@ bool GxsDataProxy::getGroupList( uint32_t &token, const RsTokReqOptions &opt } -bool GxsDataProxy::getMsgList( uint32_t &token, const RsTokReqOptions &opts, const std::list &groupIds, std::list &outMsgIds) +bool GxsDataProxyVEG::getMsgList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outMsgIds) { /* CASEs this handles. * Input is groupList + Flags. * 1) No Flags => All Messages in those Groups. * */ - std::cerr << "GxsDataProxy::getMsgList()"; + std::cerr << "GxsDataProxyVEG::getMsgList()"; std::cerr << std::endl; @@ -542,20 +597,20 @@ bool GxsDataProxy::getMsgList( uint32_t &token, const RsTokReqOptions &opt // Can only choose one of these two. if (opts.mOptions & RS_TOKREQOPT_MSG_ORIGMSG) { - std::cerr << "GxsDataProxy::getMsgList() MSG_ORIGMSG"; + std::cerr << "GxsDataProxyVEG::getMsgList() MSG_ORIGMSG"; std::cerr << std::endl; onlyOrigMsgs = true; } else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) { - std::cerr << "GxsDataProxy::getMsgList() MSG_LATEST"; + std::cerr << "GxsDataProxyVEG::getMsgList() MSG_LATEST"; std::cerr << std::endl; onlyLatestMsgs = true; } if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) { - std::cerr << "GxsDataProxy::getMsgList() MSG_THREAD"; + std::cerr << "GxsDataProxyVEG::getMsgList() MSG_THREAD"; std::cerr << std::endl; onlyThreadHeadMsgs = true; } @@ -593,7 +648,7 @@ bool GxsDataProxy::getMsgList( uint32_t &token, const RsTokReqOptions &opt bool addMsg = false; if (oit == origMsgTs.end()) { - std::cerr << "GxsDataProxy::getMsgList() Found New OrigMsgId: "; + std::cerr << "GxsDataProxyVEG::getMsgList() Found New OrigMsgId: "; std::cerr << mit->second.mOrigMsgId; std::cerr << " MsgId: " << mit->second.mMsgId; std::cerr << " TS: " << mit->second.mPublishTs; @@ -604,7 +659,7 @@ bool GxsDataProxy::getMsgList( uint32_t &token, const RsTokReqOptions &opt // check timestamps. else if (oit->second.second < mit->second.mPublishTs) { - std::cerr << "GxsDataProxy::getMsgList() Found Later Msg. OrigMsgId: "; + std::cerr << "GxsDataProxyVEG::getMsgList() Found Later Msg. OrigMsgId: "; std::cerr << mit->second.mOrigMsgId; std::cerr << " MsgId: " << mit->second.mMsgId; std::cerr << " TS: " << mit->second.mPublishTs; @@ -673,7 +728,7 @@ bool GxsDataProxy::getMsgList( uint32_t &token, const RsTokReqOptions &opt } -bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opts, const std::list &msgIds, std::list &outMsgIds) +bool GxsDataProxyVEG::getMsgRelatedList(uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &msgIds, std::list &outMsgIds) { /* CASEs this handles. * Input is msgList + Flags. @@ -681,36 +736,52 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt * */ - std::cerr << "GxsDataProxy::getMsgRelatedList()"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList()"; std::cerr << std::endl; bool onlyLatestMsgs = false; bool onlyAllVersions = false; bool onlyChildMsgs = false; + bool onlyThreadMsgs = false; if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) { - std::cerr << "GxsDataProxy::getMsgRelatedList() MSG_LATEST"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_LATEST"; std::cerr << std::endl; onlyLatestMsgs = true; } else if (opts.mOptions & RS_TOKREQOPT_MSG_VERSIONS) { - std::cerr << "GxsDataProxy::getMsgRelatedList() MSG_VERSIONS"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_VERSIONS"; std::cerr << std::endl; onlyAllVersions = true; } if (opts.mOptions & RS_TOKREQOPT_MSG_PARENT) { - std::cerr << "GxsDataProxy::getMsgRelatedList() MSG_PARENTS"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_PARENTS"; std::cerr << std::endl; onlyChildMsgs = true; } + if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) + { + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() MSG_THREAD"; + std::cerr << std::endl; + onlyThreadMsgs = true; + } + if (onlyAllVersions && onlyChildMsgs) { - std::cerr << "GxsDataProxy::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & PARENT)"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & PARENT)"; + std::cerr << std::endl; + + return false; + } + + if (onlyAllVersions && onlyThreadMsgs) + { + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (VERSIONS & THREAD)"; std::cerr << std::endl; return false; @@ -718,7 +789,23 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt if ((!onlyLatestMsgs) && onlyChildMsgs) { - std::cerr << "GxsDataProxy::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & PARENT)"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & PARENT)"; + std::cerr << std::endl; + + return false; + } + + if ((!onlyLatestMsgs) && onlyThreadMsgs) + { + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (!LATEST & THREAD)"; + std::cerr << std::endl; + + return false; + } + + if (onlyChildMsgs && onlyThreadMsgs) + { + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() ERROR Incompatible FLAGS (PARENT & THREAD)"; std::cerr << std::endl; return false; @@ -726,9 +813,9 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt /* FALL BACK OPTION */ - if ((!onlyLatestMsgs) && (!onlyAllVersions) && (!onlyChildMsgs)) + if ((!onlyLatestMsgs) && (!onlyAllVersions) && (!onlyChildMsgs) && (!onlyThreadMsgs)) { - std::cerr << "GxsDataProxy::getMsgRelatedList() FALLBACK -> NO FLAGS -> JUST COPY"; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() FALLBACK -> NO FLAGS -> JUST COPY"; std::cerr << std::endl; /* just copy */ outMsgIds = msgIds; @@ -755,7 +842,7 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt if (onlyLatestMsgs) { - if (onlyChildMsgs) + if (onlyChildMsgs || onlyThreadMsgs) { // RUN THROUGH ALL MSGS... in map origId -> TS. std::map > origMsgTs; @@ -763,16 +850,27 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt for(mit = mMsgMetaData.begin(); mit != mMsgMetaData.end(); mit++) { // skip msgs that aren't children. - if (mit->second.mParentId != origMsgId) + if (onlyChildMsgs) { - continue; + if (mit->second.mParentId != origMsgId) + { + continue; + } + } + else /* onlyThreadMsgs */ + { + if (mit->second.mThreadId != (*it)) + { + continue; + } } + oit = origMsgTs.find(mit->second.mOrigMsgId); bool addMsg = false; if (oit == origMsgTs.end()) { - std::cerr << "GxsDataProxy::getMsgList() Found New OrigMsgId: "; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() Found New OrigMsgId: "; std::cerr << mit->second.mOrigMsgId; std::cerr << " MsgId: " << mit->second.mMsgId; std::cerr << " TS: " << mit->second.mPublishTs; @@ -783,7 +881,7 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt // check timestamps. else if (oit->second.second < mit->second.mPublishTs) { - std::cerr << "GxsDataProxy::getMsgList() Found Later Msg. OrigMsgId: "; + std::cerr << "GxsDataProxyVEG::getMsgRelatedList() Found Later Msg. OrigMsgId: "; std::cerr << mit->second.mOrigMsgId; std::cerr << " MsgId: " << mit->second.mMsgId; std::cerr << " TS: " << mit->second.mPublishTs; @@ -843,14 +941,14 @@ bool GxsDataProxy::getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opt } -bool GxsDataProxy::createGroup(void *groupData) +bool GxsDataProxyVEG::createGroup(void *groupData) { RsGroupMetaData meta; if (convertGroupToMetaData(groupData, meta)) { if (!isUniqueGroup(meta.mGroupId)) { - std::cerr << "GxsDataProxy::createGroup() ERROR GroupId Clashes, discarding"; + std::cerr << "GxsDataProxyVEG::createGroup() ERROR GroupId Clashes, discarding"; std::cerr << std::endl; return false; } @@ -869,20 +967,20 @@ bool GxsDataProxy::createGroup(void *groupData) return true; } - std::cerr << "GxsDataProxy::createGroup() ERROR Failed to convert Data"; + std::cerr << "GxsDataProxyVEG::createGroup() ERROR Failed to convert Data"; std::cerr << std::endl; return false; } -bool GxsDataProxy::createMsg(void *msgData) +bool GxsDataProxyVEG::createMsg(void *msgData) { RsMsgMetaData meta; if (convertMsgToMetaData(msgData, meta)) { if (!isUniqueMsg(meta.mMsgId)) { - std::cerr << "GxsDataProxy::createMsg() ERROR MsgId Clashes, discarding"; + std::cerr << "GxsDataProxyVEG::createMsg() ERROR MsgId Clashes, discarding"; std::cerr << std::endl; return false; } @@ -895,7 +993,7 @@ bool GxsDataProxy::createMsg(void *msgData) git = mGroupMetaData.find(meta.mGroupId); if (git == mGroupMetaData.end()) { - std::cerr << "GxsDataProxy::createMsg() ERROR GroupId Doesn't exist, discarding"; + std::cerr << "GxsDataProxyVEG::createMsg() ERROR GroupId Doesn't exist, discarding"; std::cerr << std::endl; return false; } @@ -915,14 +1013,14 @@ bool GxsDataProxy::createMsg(void *msgData) return true; } - std::cerr << "GxsDataProxy::createMsg() ERROR Failed to convert Data"; + std::cerr << "GxsDataProxyVEG::createMsg() ERROR Failed to convert Data"; std::cerr << std::endl; return false; } // Get Message Status - is retrived via MessageSummary. -bool GxsDataProxy::setMessageStatus(const std::string &msgId,const uint32_t status, const uint32_t statusMask) +bool GxsDataProxyVEG::setMessageStatus(const std::string &msgId,const uint32_t status, const uint32_t statusMask) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -932,7 +1030,7 @@ bool GxsDataProxy::setMessageStatus(const std::string &msgId,const uint32_t stat if (mit == mMsgMetaData.end()) { // error. - std::cerr << "GxsDataProxy::getMsgSummary() Error Finding MsgId: " << msgId; + std::cerr << "GxsDataProxyVEG::getMsgSummary() Error Finding MsgId: " << msgId; std::cerr << std::endl; } else @@ -946,7 +1044,7 @@ bool GxsDataProxy::setMessageStatus(const std::string &msgId,const uint32_t stat return true; } -bool GxsDataProxy::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) +bool GxsDataProxyVEG::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -956,7 +1054,7 @@ bool GxsDataProxy::setGroupStatus(const std::string &groupId, const uint32_t sta if (git == mGroupMetaData.end()) { // error. - std::cerr << "GxsDataProxy::setGroupStatus() Error Finding GroupId: " << groupId; + std::cerr << "GxsDataProxyVEG::setGroupStatus() Error Finding GroupId: " << groupId; std::cerr << std::endl; } else @@ -971,7 +1069,7 @@ bool GxsDataProxy::setGroupStatus(const std::string &groupId, const uint32_t sta } -bool GxsDataProxy::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) +bool GxsDataProxyVEG::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -981,7 +1079,7 @@ bool GxsDataProxy::setGroupSubscribeFlags(const std::string &groupId, uint32_t s if (git == mGroupMetaData.end()) { // error. - std::cerr << "GxsDataProxy::setGroupSubscribeFlags() Error Finding GroupId: " << groupId; + std::cerr << "GxsDataProxyVEG::setGroupSubscribeFlags() Error Finding GroupId: " << groupId; std::cerr << std::endl; } else @@ -995,7 +1093,7 @@ bool GxsDataProxy::setGroupSubscribeFlags(const std::string &groupId, uint32_t s return true; } -bool GxsDataProxy::setMessageServiceString(const std::string &msgId, const std::string &str) +bool GxsDataProxyVEG::setMessageServiceString(const std::string &msgId, const std::string &str) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -1005,7 +1103,7 @@ bool GxsDataProxy::setMessageServiceString(const std::string &msgId, const std:: if (mit == mMsgMetaData.end()) { // error. - std::cerr << "GxsDataProxy::setMessageServiceString() Error Finding MsgId: " << msgId; + std::cerr << "GxsDataProxyVEG::setMessageServiceString() Error Finding MsgId: " << msgId; std::cerr << std::endl; } else @@ -1017,7 +1115,7 @@ bool GxsDataProxy::setMessageServiceString(const std::string &msgId, const std:: return true; } -bool GxsDataProxy::setGroupServiceString(const std::string &groupId, const std::string &str) +bool GxsDataProxyVEG::setGroupServiceString(const std::string &groupId, const std::string &str) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -1027,7 +1125,7 @@ bool GxsDataProxy::setGroupServiceString(const std::string &groupId, const std:: if (git == mGroupMetaData.end()) { // error. - std::cerr << "GxsDataProxy::setGroupServiceString() Error Finding GroupId: " << groupId; + std::cerr << "GxsDataProxyVEG::setGroupServiceString() Error Finding GroupId: " << groupId; std::cerr << std::endl; } else @@ -1041,22 +1139,22 @@ bool GxsDataProxy::setGroupServiceString(const std::string &groupId, const std:: /* These Functions must be overloaded to complete the service */ -bool GxsDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) +bool GxsDataProxyVEG::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) { - std::cerr << "GxsDataProxy::convert fn ... please implement!"; + std::cerr << "GxsDataProxyVEG::convert fn ... please implement!"; std::cerr << std::endl; return false; } -bool GxsDataProxy::convertMsgToMetaData(void *groupData, RsMsgMetaData &meta) +bool GxsDataProxyVEG::convertMsgToMetaData(void *groupData, RsMsgMetaData &meta) { - std::cerr << "GxsDataProxy::convert fn ... please implement!"; + std::cerr << "GxsDataProxyVEG::convert fn ... please implement!"; std::cerr << std::endl; return false; } /* extract Data */ -bool GxsDataProxy::getGroupSummary(const std::string &groupId, RsGroupMetaData &groupSummary) +bool GxsDataProxyVEG::getGroupSummary(const std::string &groupId, RsGroupMetaData &groupSummary) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -1066,7 +1164,7 @@ bool GxsDataProxy::getGroupSummary(const std::string &groupId, RsGroupMetaData & if (mit == mGroupMetaData.end()) { // error. - std::cerr << "GxsDataProxy::getGroupMetaData() Error Finding GroupId: " << groupId; + std::cerr << "GxsDataProxyVEG::getGroupMetaData() Error Finding GroupId: " << groupId; std::cerr << std::endl; return false; } @@ -1078,7 +1176,7 @@ bool GxsDataProxy::getGroupSummary(const std::string &groupId, RsGroupMetaData & } -bool GxsDataProxy::getMsgSummary(const std::string &msgId, RsMsgMetaData &msgSummary) +bool GxsDataProxyVEG::getMsgSummary(const std::string &msgId, RsMsgMetaData &msgSummary) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -1088,7 +1186,7 @@ bool GxsDataProxy::getMsgSummary(const std::string &msgId, RsMsgMetaData &msgSum if (mit == mMsgMetaData.end()) { // error. - std::cerr << "GxsDataProxy::getMsgSummary() Error Finding MsgId: " << msgId; + std::cerr << "GxsDataProxyVEG::getMsgSummary() Error Finding MsgId: " << msgId; std::cerr << std::endl; } else @@ -1100,7 +1198,7 @@ bool GxsDataProxy::getMsgSummary(const std::string &msgId, RsMsgMetaData &msgSum /* extract Data */ -bool GxsDataProxy::getGroupSummary(const std::list &groupIds, std::list &groupSummary) +bool GxsDataProxyVEG::getGroupSummary(const std::list &groupIds, std::list &groupSummary) { std::list::const_iterator it; for(it = groupIds.begin(); it != groupIds.end(); it++) @@ -1113,7 +1211,7 @@ bool GxsDataProxy::getGroupSummary(const std::list &groupIds, std:: if (mit == mGroupMetaData.end()) { // error. - std::cerr << "GxsDataProxy::getGroupMetaData() Error Finding GroupId: " << *it; + std::cerr << "GxsDataProxyVEG::getGroupMetaData() Error Finding GroupId: " << *it; std::cerr << std::endl; } else @@ -1125,7 +1223,7 @@ bool GxsDataProxy::getGroupSummary(const std::list &groupIds, std:: } -bool GxsDataProxy::getMsgSummary(const std::list &msgIds, std::list &msgSummary) +bool GxsDataProxyVEG::getMsgSummary(const std::list &msgIds, std::list &msgSummary) { std::list::const_iterator it; for(it = msgIds.begin(); it != msgIds.end(); it++) @@ -1138,7 +1236,7 @@ bool GxsDataProxy::getMsgSummary(const std::list &msgIds, std::list if (mit == mMsgMetaData.end()) { // error. - std::cerr << "GxsDataProxy::getMsgSummary() Error Finding MsgId: " << *it; + std::cerr << "GxsDataProxyVEG::getMsgSummary() Error Finding MsgId: " << *it; std::cerr << std::endl; } else @@ -1150,7 +1248,7 @@ bool GxsDataProxy::getMsgSummary(const std::list &msgIds, std::list } -bool GxsDataProxy::getGroupData(const std::string &groupId, void * &groupData) +bool GxsDataProxyVEG::getGroupData(const std::string &groupId, void * &groupData) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -1160,7 +1258,7 @@ bool GxsDataProxy::getGroupData(const std::string &groupId, void * &groupData) if (mit == mGroupData.end()) { // error. - std::cerr << "GxsDataProxy::getGroupData() Error Finding GroupId: " << groupId; + std::cerr << "GxsDataProxyVEG::getGroupData() Error Finding GroupId: " << groupId; std::cerr << std::endl; return false; } @@ -1171,7 +1269,7 @@ bool GxsDataProxy::getGroupData(const std::string &groupId, void * &groupData) return true; } -bool GxsDataProxy::getMsgData(const std::string &msgId, void * &msgData) +bool GxsDataProxyVEG::getMsgData(const std::string &msgId, void * &msgData) { RsStackMutex stack(mDataMtx); /***** LOCKED *****/ @@ -1181,7 +1279,7 @@ bool GxsDataProxy::getMsgData(const std::string &msgId, void * &msgData) if (mit == mMsgData.end()) { // error. - std::cerr << "GxsDataProxy::getMsgData() Error Finding MsgId: " << msgId; + std::cerr << "GxsDataProxyVEG::getMsgData() Error Finding MsgId: " << msgId; std::cerr << std::endl; return false; } @@ -1193,7 +1291,7 @@ bool GxsDataProxy::getMsgData(const std::string &msgId, void * &msgData) } #if 0 -bool GxsDataProxy::getGroupData(const std::list &groupIds, std::list &groupData) +bool GxsDataProxyVEG::getGroupData(const std::list &groupIds, std::list &groupData) { std::list::const_iterator it; for(it = groupIds.begin(); it != groupIds.end(); it++) @@ -1206,7 +1304,7 @@ bool GxsDataProxy::getGroupData(const std::list &groupIds, std::lis if (mit == mGroupData.end()) { // error. - std::cerr << "GxsDataProxy::getGroupData() Error Finding GroupId: " << *it; + std::cerr << "GxsDataProxyVEG::getGroupData() Error Finding GroupId: " << *it; std::cerr << std::endl; } else @@ -1217,7 +1315,7 @@ bool GxsDataProxy::getGroupData(const std::list &groupIds, std::lis return true; } -bool GxsDataProxy::getMsgData(const std::list &msgIds, std::list &msgData) +bool GxsDataProxyVEG::getMsgData(const std::list &msgIds, std::list &msgData) { std::list::const_iterator it; for(it = msgIds.begin(); it != msgIds.end(); it++) @@ -1230,7 +1328,7 @@ bool GxsDataProxy::getMsgData(const std::list &msgIds, std::list &msgIds, std::list toClear; std::list::iterator cit; @@ -1294,11 +1392,11 @@ bool p3GxsDataService::fakeprocessrequests() for(it = mRequests.begin(); it != mRequests.end(); it++) { - //std::cerr << "p3GxsDataService::fakeprocessrequests() Token: " << it->second.token << " Status: " << it->second.status << " ReqType: " << it->second.reqType << " Age: " << now - it->second.reqTime << std::endl; + //std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Token: " << it->second.token << " Status: " << it->second.status << " ReqType: " << it->second.reqType << " Age: " << now - it->second.reqTime << std::endl; if (it->second.status == GXS_REQUEST_STATUS_PENDING) { - std::cerr << "p3GxsDataService::fakeprocessrequests() Processing Token: " << it->second.token << " Status: " << it->second.status << " ReqType: " << it->second.reqType << " Age: " << now - it->second.reqTime << std::endl; + std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Processing Token: " << it->second.token << " Status: " << it->second.status << " ReqType: " << it->second.reqType << " Age: " << now - it->second.reqTime << std::endl; it->second.status = GXS_REQUEST_STATUS_PARTIAL; /* PROCESS REQUEST! */ switch(it->second.reqType) @@ -1323,13 +1421,13 @@ bool p3GxsDataService::fakeprocessrequests() } else if (it->second.status == GXS_REQUEST_STATUS_DONE) { - std::cerr << "p3GxsDataService::fakeprocessrequests() Clearing Done Request Token: " << it->second.token; + std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Clearing Done Request Token: " << it->second.token; std::cerr << std::endl; toClear.push_back(it->second.token); } else if (now - it->second.reqTime > MAX_REQUEST_AGE) { - std::cerr << "p3GxsDataService::fakeprocessrequests() Clearing Old Request Token: " << it->second.token; + std::cerr << "p3GxsDataServiceVEG::fakeprocessrequests() Clearing Old Request Token: " << it->second.token; std::cerr << std::endl; toClear.push_back(it->second.token); } @@ -1345,23 +1443,25 @@ bool p3GxsDataService::fakeprocessrequests() return true; } +#if 0 // DISABLED AND MOVED TO GXS CODE. -std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta) -{ - out << "[ GroupId: " << meta.mGroupId << " Name: " << meta.mGroupName << " ]"; - return out; -} +//std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta) +//{ +// out << "[ GroupId: " << meta.mGroupId << " Name: " << meta.mGroupName << " ]"; +// return out; +//} -std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta) -{ - out << "[ GroupId: " << meta.mGroupId << " MsgId: " << meta.mMsgId; - out << " Name: " << meta.mMsgName; - out << " OrigMsgId: " << meta.mOrigMsgId; - out << " ThreadId: " << meta.mThreadId; - out << " ParentId: " << meta.mParentId; - out << " AuthorId: " << meta.mAuthorId; - out << " Name: " << meta.mMsgName << " ]"; - return out; -} +//std::ostream &operator<<(std::ostream &out, const RsMsgMetaData &meta) +//{ +// out << "[ GroupId: " << meta.mGroupId << " MsgId: " << meta.mMsgId; +// out << " Name: " << meta.mMsgName; +// out << " OrigMsgId: " << meta.mOrigMsgId; +// out << " ThreadId: " << meta.mThreadId; +// out << " ParentId: " << meta.mParentId; +// out << " AuthorId: " << meta.mAuthorId; +// out << " Name: " << meta.mMsgName << " ]"; +// return out; +//} +#endif diff --git a/libretroshare/src/services/p3gxsservice.h b/libretroshare/src/services/p3gxsserviceVEG.h similarity index 86% rename from libretroshare/src/services/p3gxsservice.h rename to libretroshare/src/services/p3gxsserviceVEG.h index e1580aeef..096ebdfb0 100644 --- a/libretroshare/src/services/p3gxsservice.h +++ b/libretroshare/src/services/p3gxsserviceVEG.h @@ -27,7 +27,7 @@ #define P3_GXS_SERVICE_HEADER #include "services/p3service.h" -#include "retroshare/rsidentity.h" +#include "retroshare/rsidentityVEG.h" /* * This class provides useful generic support for GXS style services. @@ -54,7 +54,7 @@ class gxsRequest uint32_t ansType; uint32_t reqType; - RsTokReqOptions Options; + RsTokReqOptionsVEG Options; uint32_t status; @@ -64,18 +64,18 @@ class gxsRequest }; -class p3GxsService: public p3Service +class p3GxsServiceVEG: public p3Service { protected: - p3GxsService(uint16_t type); + p3GxsServiceVEG(uint16_t type); public: //virtual ~p3Service() { p3Service::~p3Service(); return; } bool generateToken(uint32_t &token); -bool storeRequest(const uint32_t &token, const uint32_t &ansType, const RsTokReqOptions &opts, const uint32_t &type, const std::list &ids); +bool storeRequest(const uint32_t &token, const uint32_t &ansType, const RsTokReqOptionsVEG &opts, const uint32_t &type, const std::list &ids); bool clearRequest(const uint32_t &token); bool updateRequestStatus(const uint32_t &token, const uint32_t &status); @@ -103,15 +103,15 @@ virtual bool fakeprocessrequests(); }; -class GxsDataProxy +class GxsDataProxyVEG { public: - GxsDataProxy(); + GxsDataProxyVEG(); -virtual bool getGroupList( uint32_t &token, const RsTokReqOptions &opts, const std::list &groupIds, std::list &outGroupIds); -virtual bool getMsgList( uint32_t &token, const RsTokReqOptions &opts, const std::list &groupIds, std::list &outMsgIds); -virtual bool getMsgRelatedList(uint32_t &token, const RsTokReqOptions &opts, const std::list &msgIds, std::list &outMsgIds); +virtual bool getGroupList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outGroupIds); +virtual bool getMsgList( uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &groupIds, std::list &outMsgIds); +virtual bool getMsgRelatedList(uint32_t &token, const RsTokReqOptionsVEG &opts, const std::list &msgIds, std::list &outMsgIds); /* This functions return a token - which can be used to retrieve the RsGroupMetaData, later @@ -157,8 +157,8 @@ virtual bool setGroupServiceString(const std::string &grpId, const std::string & protected: - bool filterGroupList(const RsTokReqOptions &opts, std::list &groupIds); - bool filterMsgList(const RsTokReqOptions &opts, std::list &msgIds); + bool filterGroupList(const RsTokReqOptionsVEG &opts, std::list &groupIds); + bool filterMsgList(const RsTokReqOptionsVEG &opts, std::list &msgIds); RsMutex mDataMtx; @@ -172,17 +172,17 @@ virtual bool setGroupServiceString(const std::string &grpId, const std::string & }; -class p3GxsDataService: public p3GxsService +class p3GxsDataServiceVEG: public p3GxsServiceVEG { public: - p3GxsDataService(uint16_t type, GxsDataProxy *proxy); + p3GxsDataServiceVEG(uint16_t type, GxsDataProxyVEG *proxy); virtual bool fakeprocessrequests(); protected: - GxsDataProxy *mProxy; + GxsDataProxyVEG *mProxy; }; diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 1dc8bc3c0..147d15d10 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -24,15 +24,24 @@ */ #include "services/p3idservice.h" - +#include "serialiser/rsgxsiditems.h" +#include "gxs/rsgxsflags.h" #include "util/rsrandom.h" +#include "util/rsstring.h" + +#include "pqi/authgpg.h" + #include + #include #include /**** * #define ID_DEBUG 1 ****/ +#define GXSID_GEN_DUMMY_DATA 1 + + #define ID_REQUEST_LIST 0x0001 #define ID_REQUEST_IDENTITY 0x0002 @@ -42,700 +51,1427 @@ RsIdentity *rsIdentity = NULL; +/****** + * Some notes: + * Identity tasks: + * - Provide keys for signing / validating author signatures. + * - Reputations + * - Identify Known Friend's IDs. + * - Provide details to other services (nicknames, reputations, gpg ids, etc) + * + * Background services: + * - Lookup and cache keys / details of identities. + * - Check GPGHashes. + * - Calculate Reputations. + * + * We have a lot of information to store in Service Strings. + * - GPGId or last check ts. + * - Reputation stuff. + */ + +#define RSGXSID_MAX_SERVICE_STRING 1024 + +#define BG_PGPHASH 1 +#define BG_REPUTATION 2 + + +#define GXSIDREQ_CACHELOAD 0x0001 +#define GXSIDREQ_CACHEOWNIDS 0x0002 + +#define GXSIDREQ_PGPHASH 0x0010 +#define GXSIDREQ_REPUTATION 0x0020 + +#define GXSIDREQ_CACHETEST 0x1000 + +// Events. +#define GXSID_EVENT_CACHEOWNIDS 0x0001 +#define GXSID_EVENT_CACHELOAD 0x0002 + +#define GXSID_EVENT_PGPHASH 0x0010 +#define GXSID_EVENT_PGPHASH_PROC 0x0011 + +#define GXSID_EVENT_REPUTATION 0x0020 + +#define GXSID_EVENT_CACHETEST 0x1000 + +#define GXSID_EVENT_DUMMYDATA 0x2000 +#define GXSID_EVENT_DUMMY_OWNIDS 0x2001 +#define GXSID_EVENT_DUMMY_PGPID 0x2002 +#define GXSID_EVENT_DUMMY_UNKNOWN_PGPID 0x2003 +#define GXSID_EVENT_DUMMY_PSEUDOID 0x2004 + + +/* delays */ + +#define CACHETEST_PERIOD 60 + +#define OWNID_RELOAD_DELAY 10 + +#define PGPHASH_PERIOD 60 +#define PGPHASH_RETRY_PERIOD 11 +#define PGPHASH_PROC_PERIOD 1 + +#define REPUTATION_PERIOD 60 +#define REPUTATION_RETRY_PERIOD 13 +#define REPUTATION_PROC_PERIOD 1 + /********************************************************************************/ /******************* Startup / Tick ******************************************/ /********************************************************************************/ -p3IdService::p3IdService(uint16_t type) - :p3GxsDataService(type, new IdDataProxy()), mIdMtx("p3IdService"), mUpdated(true) +p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *nes) + : RsGxsIdExchange(gds, nes, new RsGxsIdSerialiser(), RS_SERVICE_GXSV1_TYPE_GXSID), + RsIdentity(this), GxsTokenQueue(this), RsTickEvent(), mIdMtx("p3IdService"), + mPublicKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPublicKeyCache"), + mPrivateKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPrivateKeyCache") { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mBgSchedule_Mode = 0; + mBgSchedule_Active = false; - mIdProxy = (IdDataProxy *) mProxy; + // Kick off Cache Testing, + Others. + RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); + RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); + RsTickEvent::schedule_in(GXSID_EVENT_REPUTATION, REPUTATION_PERIOD); + RsTickEvent::schedule_now(GXSID_EVENT_CACHEOWNIDS); + +#ifdef GXSID_GEN_DUMMY_DATA + RsTickEvent::schedule_now(GXSID_EVENT_DUMMYDATA); +#endif + +} + + + +void p3IdService::service_tick() +{ + RsTickEvent::tick_events(); + GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. return; } - -int p3IdService::tick() +void p3IdService::notifyChanges(std::vector &changes) { - std::cerr << "p3IdService::tick()"; + std::cerr << "p3IdService::notifyChanges()"; std::cerr << std::endl; - fakeprocessrequests(); - // Disable for now. - // background_tick(); - - return 0; + receiveChanges(changes); } -bool p3IdService::updated() +/********************************************************************************/ +/******************* RsIdentity Interface ***************************************/ +/********************************************************************************/ + +#if 0 +bool p3IdService:: getNickname(const RsGxsId &id, std::string &nickname) +{ + return false; +} +#endif + +bool p3IdService:: getIdDetails(const RsGxsId &id, RsIdentityDetails &details) +{ + std::cerr << "p3IdService::getIdDetails(" << id << ")"; + std::cerr << std::endl; + + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + RsGxsIdCache data; + if (mPublicKeyCache.fetch(id, data)) + { + details = data.details; + return true; + } + + /* try private cache too */ + if (mPrivateKeyCache.fetch(id, data)) + { + details = data.details; + return true; + } + } + + /* it isn't there - add to public requests */ + cache_request_load(id); + + return false; +} + + +bool p3IdService:: getOwnIds(std::list &ownIds) +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + ownIds = mOwnIds; + + return true; +} + + +// +bool p3IdService::submitOpinion(uint32_t& token, RsIdOpinion &opinion) +{ + return false; +} + +bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms) +{ + + RsGxsIdGroup id; + + id.mMeta.mGroupName = params.nickname; + if (params.isPgpLinked) + { + id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; + } + else + { + id.mMeta.mGroupFlags = 0; + } + + createGroup(token, id); + + return true; +} + + +/********************************************************************************/ +/******************* RsGixs Interface ***************************************/ +/********************************************************************************/ + +bool p3IdService::haveKey(const RsGxsId &id) +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + return mPublicKeyCache.is_cached(id); +} + +bool p3IdService::havePrivateKey(const RsGxsId &id) +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + return mPrivateKeyCache.is_cached(id); +} + +bool p3IdService::requestKey(const RsGxsId &id, const std::list &peers) +{ + if (haveKey(id)) + return true; + return cache_request_load(id); +} + +int p3IdService::getKey(const RsGxsId &id, RsTlvSecurityKey &key) +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + RsGxsIdCache data; + if (mPublicKeyCache.fetch(id, data)) + { + key = data.pubkey; + return 1; + } + return -1; +} + +bool p3IdService::requestPrivateKey(const RsGxsId &id) +{ + if (havePrivateKey(id)) + return true; + return cache_request_load(id); +} + +int p3IdService::getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + RsGxsIdCache data; + if (mPrivateKeyCache.fetch(id, data)) + { + key = data.pubkey; + return 1; + } + return -1; +} + + +/********************************************************************************/ +/******************* RsGixsReputation ***************************************/ +/********************************************************************************/ + +bool p3IdService::getReputation(const RsGxsId &id, const GixsReputation &rep) +{ + return false; +} + + +/********************************************************************************/ +/******************* Get/Set Data ******************************************/ +/********************************************************************************/ + +bool p3IdService::getGroupData(const uint32_t &token, std::vector &groups) +{ + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsIdGroupItem* item = dynamic_cast(*vit); + RsGxsIdGroup group = item->group; + group.mMeta = item->meta; + + // Decode information from serviceString. + SSGxsIdGroup ssdata; + if (ssdata.load(group.mMeta.mServiceString)) + { + group.mPgpKnown = ssdata.pgp.idKnown; + group.mPgpId = ssdata.pgp.pgpId; + + std::cerr << "p3IdService::getGroupData() Success decoding ServiceString"; + std::cerr << std::endl; + std::cerr << "\t mGpgKnown: " << group.mPgpKnown; + std::cerr << std::endl; + std::cerr << "\t mGpgId: " << group.mPgpId; + std::cerr << std::endl; + } + else + { + group.mPgpKnown = false; + group.mPgpId = ""; + + std::cerr << "p3IdService::getGroupData() Failed to decode ServiceString"; + std::cerr << std::endl; + } + + groups.push_back(group); + } + } + + return ok; +} + + +bool p3IdService::getMsgData(const uint32_t &token, std::vector &opinions) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsIdOpinionItem* item = dynamic_cast(*vit); + + if (item) + { + RsGxsIdOpinion opinion = item->opinion; + opinion.mMeta = item->meta; + opinions.push_back(opinion); + delete item; + } + else + { + std::cerr << "Not a IdOpinion Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + return ok; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +bool p3IdService::createGroup(uint32_t& token, RsGxsIdGroup &group) +{ + RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); + item->group = group; + item->meta = group.mMeta; + RsGenExchange::publishGroup(token, item); + return true; +} + +bool p3IdService::createMsg(uint32_t& token, RsGxsIdOpinion &opinion) +{ + RsGxsIdOpinionItem* item = new RsGxsIdOpinionItem(); + item->opinion = opinion; + item->meta = opinion.mMeta; + RsGenExchange::publishMsg(token, item); + return true; +} + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* Encoding / Decoding Group Service String stuff + * + * Pgp stuff. + * + * If flagged as pgp id.... + * then we need to know if its been matched, or when we last tried to match. + * + */ + +bool SSGxsIdPgp::load(const std::string &input) +{ + char pgpline[RSGXSID_MAX_SERVICE_STRING]; + int timestamp = 0; + if (1 == sscanf(input.c_str(), "K:1 I:%[^)]", pgpline)) + { + idKnown = true; + pgpId = pgpline; + } + else if (1 == sscanf(input.c_str(), "K:0 T:%d", ×tamp)) + { + lastCheckTs = timestamp; + idKnown = false; + } + else + { + return false; + } + return true; +} + +std::string SSGxsIdPgp::save() const +{ + std::string output; + if (idKnown) + { + output += "K:1 I:"; + output += pgpId; + } + else + { + rs_sprintf(output, "K:0 T:%d", lastCheckTs); + } + return output; +} + +bool SSGxsIdScore::load(const std::string &input) +{ + return (1 == sscanf(input.c_str(), "%d", &score)); +} + +std::string SSGxsIdScore::save() const +{ + std::string output; + rs_sprintf(output, "%d", score); + return output; +} + +bool SSGxsIdCumulator::load(const std::string &input) +{ + return (4 == sscanf(input.c_str(), "%d %d %lf %lf", &count, &nullcount, &sum, &sumsq)); +} + +std::string SSGxsIdCumulator::save() const +{ + std::string output; + rs_sprintf(output, "%d %d %lf %lf", count, nullcount, sum, sumsq); + return output; +} + +bool SSGxsIdGroup::load(const std::string &input) +{ + char pgpstr[RSGXSID_MAX_SERVICE_STRING]; + char scorestr[RSGXSID_MAX_SERVICE_STRING]; + char opinionstr[RSGXSID_MAX_SERVICE_STRING]; + char repstr[RSGXSID_MAX_SERVICE_STRING]; + + // split into two parts. + if (4 != sscanf(input.c_str(), "v1 {P:%[^}]} {Y:%[^}]} {O:%[^}]} {R:%[^}]}", pgpstr, scorestr, opinionstr, repstr)) + { + std::cerr << "SSGxsIdGroup::load() Failed to extract 4 Parts"; + std::cerr << std::endl; + return false; + } + + bool ok = true; + if (pgp.load(pgpstr)) + { + std::cerr << "SSGxsIdGroup::load() pgpstr: " << pgpstr; + std::cerr << std::endl; + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid pgpstr: " << pgpstr; + std::cerr << std::endl; + ok = false; + } + + if (score.load(scorestr)) + { + std::cerr << "SSGxsIdGroup::load() scorestr: " << scorestr; + std::cerr << std::endl; + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid scorestr: " << scorestr; + std::cerr << std::endl; + ok = false; + } + + if (opinion.load(opinionstr)) + { + std::cerr << "SSGxsIdGroup::load() opinionstr: " << opinionstr; + std::cerr << std::endl; + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid opinionstr: " << opinionstr; + std::cerr << std::endl; + ok = false; + } + + if (reputation.load(repstr)) + { + std::cerr << "SSGxsIdGroup::load() repstr: " << repstr; + std::cerr << std::endl; + } + else + { + std::cerr << "SSGxsIdGroup::load() Invalid repstr: " << repstr; + std::cerr << std::endl; + ok = false; + } + + std::cerr << "SSGxsIdGroup::load() regurgitated: " << save(); + std::cerr << std::endl; + + std::cerr << "SSGxsIdGroup::load() isOkay?: " << ok; + std::cerr << std::endl; + return ok; +} + +std::string SSGxsIdGroup::save() const +{ + std::string output = "v1 "; + + output += "{P:"; + output += pgp.save(); + output += "}"; + + output += "{Y:"; + output += score.save(); + output += "}"; + + output += "{O:"; + output += opinion.save(); + output += "}"; + + output += "{R:"; + output += reputation.save(); + output += "}"; + + //std::cerr << "SSGxsIdGroup::save() output: " << output; + //std::cerr << std::endl; + + return output; +} + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* Cache of recently used keys + * + * It is expensive to fetch the keys, so we want to keep them around if possible. + * It only stores the immutable stuff. + * + * This is probably crude and crap to start with. + * Want Least Recently Used (LRU) discard policy, without having to search whole cache. + * Use two maps: + * - CacheMap[key] => data. + * - LRUMultiMap[AccessTS] => key + * + * NOTE: This could be moved to a seperate class and templated to make generic + * as it might be generally useful. + * + */ + +RsGxsIdCache::RsGxsIdCache() +{ + return; +} + +RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey) +{ + // Save Keys. + pubkey = in_pkey; + + // Fill in Details. + details.mNickname = item->meta.mGroupName; + details.mId = item->meta.mGroupId; + + std::cerr << "RsGxsIdCache::RsGxsIdCache() for: " << details.mId; + std::cerr << std::endl; + + details.mIsOwnId = (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); + + details.mPgpLinked = (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID); + + /* rest must be retrived from ServiceString */ + updateServiceString(item->meta.mServiceString); +} + +void RsGxsIdCache::updateServiceString(std::string serviceString) +{ + SSGxsIdGroup ssdata; + if (ssdata.load(serviceString)) + { + if (details.mPgpLinked) + { + details.mPgpKnown = ssdata.pgp.idKnown; + if (details.mPgpKnown) + { + details.mPgpId = ssdata.pgp.pgpId; + } + else + { + details.mPgpId = ""; + } + } + + details.mOpinion = 0; + details.mReputation = ssdata.score.score; + } + else + { + details.mPgpKnown = false; + details.mPgpId = ""; + + details.mOpinion = 0; + details.mReputation = 0; + } +} + + + + + + + +bool p3IdService::cache_store(const RsGxsIdGroupItem *item) +{ + std::cerr << "p3IdService::cache_store() Item: " << item->meta.mGroupId; + std::cerr << std::endl; + //item->print(std::cerr, 0); NEEDS CONST!!!! TODO + //std::cerr << std::endl; + + /* extract key from keys */ + RsTlvSecurityKeySet keySet; + RsTlvSecurityKey pubkey; + RsTlvSecurityKey fullkey; + bool pub_key_ok = false; + bool full_key_ok = false; + + RsGxsId id = item->meta.mGroupId; + if (!getGroupKeys(id, keySet)) + { + std::cerr << "p3IdService::cache_store() ERROR getting GroupKeys for: "; + std::cerr << item->meta.mGroupId; + std::cerr << std::endl; + return false; + } + + std::map::iterator kit; + + //std::cerr << "p3IdService::cache_store() KeySet is:"; + //keySet.print(std::cerr, 10); + + for (kit = keySet.keys.begin(); kit != keySet.keys.end(); kit++) + { + if (kit->second.keyFlags | RSTLV_KEY_DISTRIB_ADMIN) + { + std::cerr << "p3IdService::cache_store() Found Admin Key"; + std::cerr << std::endl; + + /* save full key - if we have it */ + if (kit->second.keyFlags | RSTLV_KEY_TYPE_FULL) + { + fullkey = kit->second; + full_key_ok = true; + } + + /* cache public key always */ + pubkey = kit->second; + pub_key_ok = true; + } + } + + if (!pub_key_ok) + { + std::cerr << "p3IdService::cache_store() ERROR No Public Key Found"; + std::cerr << std::endl; + return false; + } + + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + // Create Cache Data. + RsGxsIdCache pubcache(item, pubkey); + mPublicKeyCache.store(id, pubcache); + mPublicKeyCache.resize(); + + if (full_key_ok) + { + RsGxsIdCache fullcache(item, fullkey); + mPrivateKeyCache.store(id, fullcache); + mPrivateKeyCache.resize(); + } + + return true; +} + + + +/***** BELOW LOADS THE CACHE FROM GXS DATASTORE *****/ + +#define MIN_CYCLE_GAP 2 + +bool p3IdService::cache_request_load(const RsGxsId &id) +{ + std::cerr << "p3IdService::cache_request_load(" << id << ")"; + std::cerr << std::endl; + + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mCacheLoad_ToCache.push_back(id); + } + + if (RsTickEvent::event_count(GXSID_EVENT_CACHELOAD) > 0) + { + /* its already scheduled */ + return true; + } + + int32_t age = 0; + if (RsTickEvent::prev_event_ago(GXSID_EVENT_CACHELOAD, age)) + { + if (age < MIN_CYCLE_GAP) + { + RsTickEvent::schedule_in(GXSID_EVENT_CACHELOAD, MIN_CYCLE_GAP - age); + return true; + } + } + + RsTickEvent::schedule_now(GXSID_EVENT_CACHELOAD); + return true; +} + + +bool p3IdService::cache_start_load() +{ + /* trigger request to load missing ids into cache */ + std::list groupIds; + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ + std::list::iterator it; + for(it = mCacheLoad_ToCache.begin(); it != mCacheLoad_ToCache.end(); it++) + { + std::cerr << "p3IdService::cache_start_load() GroupId: " << *it; + std::cerr << std::endl; + groupIds.push_back(*it); // might need conversion? + } + + mCacheLoad_ToCache.clear(); + } + + if (groupIds.size() > 0) + { + std::cerr << "p3IdService::cache_start_load() #Groups: " << groupIds.size(); + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); + GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHELOAD); + } + return 1; +} + + +bool p3IdService::cache_load_for_token(uint32_t token) +{ + std::cerr << "p3IdService::cache_load_for_token() : " << token; + std::cerr << std::endl; + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsIdGroupItem* item = dynamic_cast(*vit); + + std::cerr << "p3IdService::cache_load_for_token() Loaded Id with Meta: "; + std::cerr << item->meta; + std::cerr << std::endl; + + /* cache the data */ + cache_store(item); + delete item; + } + } + else + { + std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; + std::cerr << std::endl; + + return false; + } + return true; +} + + + +bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceString) +{ + /* if these entries are cached - update with new info */ + std::cerr << "p3IdService::cache_update_if_cached(" << id << ")"; + std::cerr << std::endl; + + /* retrieve - update, save */ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + RsGxsIdCache pub_data; + if (mPublicKeyCache.fetch(id, pub_data)) + { + std::cerr << "p3IdService::cache_update_if_cached() Updating Public Cache"; + std::cerr << std::endl; + + pub_data.updateServiceString(serviceString); + mPublicKeyCache.store(id, pub_data); + } + + + RsGxsIdCache priv_data; + if (mPrivateKeyCache.fetch(id, priv_data)) + { + std::cerr << "p3IdService::cache_update_if_cached() Updating Private Cache"; + std::cerr << std::endl; + + priv_data.updateServiceString(serviceString); + mPrivateKeyCache.store(id, priv_data); + } + + return true; +} + +/************************************************************************************/ +/************************************************************************************/ + +bool p3IdService::cache_request_ownids() +{ + /* trigger request to load missing ids into cache */ + std::list groupIds; + std::cerr << "p3IdService::cache_request_ownids()"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + //opts.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; + + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHEOWNIDS); + return 1; +} + + +bool p3IdService::cache_load_ownids(uint32_t token) +{ + std::cerr << "p3IdService::cache_load_ownids() : " << token; + std::cerr << std::endl; + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + // Save List + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + mOwnIds.clear(); + for(vit = grpData.begin(); vit != grpData.end(); vit++) + { + RsGxsIdGroupItem* item = dynamic_cast(*vit); + + + if (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + { + mOwnIds.push_back(item->meta.mGroupId); + } + } + } + +// No need to cache these items... +// as it just causes the cache to be flushed. +#if 0 + // Cache Items too. + for(vit = grpData.begin(); vit != grpData.end(); vit++) + { + RsGxsIdGroupItem* item = dynamic_cast(*vit); + if (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) + { + + std::cerr << "p3IdService::cache_load_ownids() Loaded Id with Meta: "; + std::cerr << item->meta; + std::cerr << std::endl; + + /* cache the data */ + cache_store(item); + } + delete item; + } +#endif + + } + else + { + std::cerr << "p3IdService::cache_load_ownids() ERROR no data"; + std::cerr << std::endl; + + return false; + } + return true; +} + + +/************************************************************************************/ +/************************************************************************************/ + +bool p3IdService::cachetest_getlist() +{ + std::cerr << "p3IdService::cachetest_getlist() making request"; + std::cerr << std::endl; + + uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHETEST); + + // Schedule Next Event. + RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); + return true; +} + +bool p3IdService::cachetest_handlerequest(uint32_t token) +{ + std::cerr << "p3IdService::cachetest_handlerequest() token: " << token; + std::cerr << std::endl; + + std::list grpIds; + bool ok = RsGenExchange::getGroupList(token, grpIds); + + if(ok) + { + std::list::iterator vit = grpIds.begin(); + for(; vit != grpIds.end(); vit++) + { + /* 5% chance of checking it! */ + if (RSRandom::random_f32() < 0.25) + { + std::cerr << "p3IdService::cachetest_request() Testing Id: " << *vit; + std::cerr << std::endl; + + /* try the cache! */ + if (!haveKey(*vit)) + { + std::list nullpeers; + requestKey(*vit, nullpeers); + + std::cerr << "p3IdService::cachetest_request() Requested Key Id: " << *vit; + std::cerr << std::endl; + } + else + { + RsTlvSecurityKey seckey; + if (getKey(*vit, seckey)) + { + std::cerr << "p3IdService::cachetest_request() Got Key OK Id: " << *vit; + std::cerr << std::endl; + + // success! + seckey.print(std::cerr, 10); + std::cerr << std::endl; + + + } + else + { + std::cerr << "p3IdService::cachetest_request() ERROR no Key for Id: " << *vit; + std::cerr << std::endl; + } + } + + /* try private key too! */ + if (!havePrivateKey(*vit)) + { + requestPrivateKey(*vit); + std::cerr << "p3IdService::cachetest_request() Requested PrivateKey Id: " << *vit; + std::cerr << std::endl; + } + else + { + RsTlvSecurityKey seckey; + if (getPrivateKey(*vit, seckey)) + { + // success! + std::cerr << "p3IdService::cachetest_request() Got PrivateKey OK Id: " << *vit; + std::cerr << std::endl; + } + else + { + std::cerr << "p3IdService::cachetest_request() ERROR no PrivateKey for Id: " << *vit; + std::cerr << std::endl; + } + } + } + } + } + else + { + std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; + std::cerr << std::endl; + + return false; + } + return true; +} + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* + * We have two background tasks that use the ServiceString: PGPHash & Reputation. + * + * Only one task can be run at a time - otherwise potential overwrite issues. + * So this part coordinates that part of the code. + * + * + * + * + */ + + +bool p3IdService::CacheArbitration(uint32_t mode) { RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (mUpdated) + if (!mBgSchedule_Active) { - mUpdated = false; - return true; - } - return false; -} - - - - /* Data Requests */ -bool p3IdService::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3IdService::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3IdService::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3IdService::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3IdService::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3IdService::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3IdService::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3IdService::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3IdService::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3IdService::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3IdService::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3IdService::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3IdService::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3IdService::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3IdService::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3IdService::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3IdService::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3IdService::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3IdService::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3IdService::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3IdService::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3IdService::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - - /* Specific Service Data */ -bool p3IdService::getGroupData(const uint32_t &token, RsIdGroup &group) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3IdService::getGroupData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3IdService::getGroupData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3IdService::getGroupData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsIdGroup */ - bool ans = mIdProxy->getGroup(id, group); - return ans; -} - - -bool p3IdService::getMsgData(const uint32_t &token, RsIdMsg &msg) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3IdService::getMsgData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3IdService::getMsgData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3IdService::getMsgData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsIdMsg */ - bool ans = mIdProxy->getMsg(id, msg); - return ans; -} - - - - /* Poll */ -uint32_t p3IdService::requestStatus(const uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - return status; -} - - - /* Cancel Request */ -bool p3IdService::cancelRequest(const uint32_t &token) -{ - return clearRequest(token); -} - - ////////////////////////////////////////////////////////////////////////////// -bool p3IdService::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) -{ - return mIdProxy->setMessageStatus(msgId, status, statusMask); -} - -bool p3IdService::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mIdProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3IdService::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mIdProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3IdService::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mIdProxy->setMessageServiceString(msgId, str); -} - -bool p3IdService::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mIdProxy->setGroupServiceString(grpId, str); -} - - -bool p3IdService::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3IdService::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - -/********************************************************************************************/ - - -std::string p3IdService::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3IdService::createGroup(uint32_t &token, RsIdGroup &group, bool isNew) -{ - if (group.mMeta.mGroupId.empty()) - { - /* new photo */ - - /* generate a temp id */ - group.mMeta.mGroupId = genRandomId(); - } - else - { - std::cerr << "p3IdService::createGroup() Group with existing Id... dropping"; - std::cerr << std::endl; - return false; - } - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mIdProxy->addGroup(group); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3IdService::createGroup() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - - return true; -} - - - - -bool p3IdService::createMsg(uint32_t &token, RsIdMsg &msg, bool isNew) -{ - if (msg.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3IdService::createMsg() Missing MsgID"; - std::cerr << std::endl; - return false; - } - - /* check if its a mod or new msg */ - if (msg.mMeta.mOrigMsgId.empty()) - { - std::cerr << "p3IdService::createMsg() New Msg"; + std::cerr << "p3IdService::CacheArbitration() Okay"; std::cerr << std::endl; - /* new msg, generate a new OrigMsgId */ - msg.mMeta.mOrigMsgId = genRandomId(); - msg.mMeta.mMsgId = msg.mMeta.mOrigMsgId; - } - else - { - std::cerr << "p3IdService::createMsg() Modified Msg"; - std::cerr << std::endl; - - /* mod msg, keep orig msg id, generate a new MsgId */ - msg.mMeta.mMsgId = genRandomId(); - } - - std::cerr << "p3IdService::createMsg() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - std::cerr << "p3IdService::createMsg() MsgId: " << msg.mMeta.mMsgId; - std::cerr << std::endl; - std::cerr << "p3IdService::createMsg() OrigMsgId: " << msg.mMeta.mOrigMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mIdProxy->addMsg(msg); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(msg.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3IdService::createMsg() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - - - -bool IdDataProxy::getGroup(const std::string &id, RsIdGroup &group) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsIdGroup *pG = (RsIdGroup *) groupData; - group = *pG; - - // update definitive version of the metadata. - group.mMeta = meta; - - std::cerr << "IdDataProxy::getGroup() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; + mBgSchedule_Active = true; + mBgSchedule_Mode = mode; return true; } - std::cerr << "IdDataProxy::getGroup() FAILED Id: " << id; + std::cerr << "p3IdService::CacheArbitration() Is busy..."; std::cerr << std::endl; return false; } -bool IdDataProxy::getMsg(const std::string &id, RsIdMsg &msg) +void p3IdService::CacheArbitrationDone(uint32_t mode) { - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsIdMsg *pM = (RsIdMsg *) msgData; - // Shallow copy of thumbnail. - msg = *pM; - - // update definitive version of the metadata. - msg.mMeta = meta; + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - std::cerr << "IdDataProxy::getMsg() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + if (mBgSchedule_Mode != mode) + { + /* issues */ + std::cerr << "p3IdService::CacheArbitrationDone() ERROR Wrong Current Mode"; std::cerr << std::endl; - return true; + return; } - std::cerr << "IdDataProxy::getMsg() FAILED Id: " << id; + std::cerr << "p3IdService::CacheArbitrationDone()"; std::cerr << std::endl; - return false; + mBgSchedule_Active = false; } -bool IdDataProxy::addGroup(const RsIdGroup &group) -{ - // Make duplicate. - RsIdGroup *pG = new RsIdGroup(); - *pG = group; - - std::cerr << "IdDataProxy::addGroup()"; - std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; - std::cerr << std::endl; - - return createGroup(pG); -} - - -bool IdDataProxy::addMsg(const RsIdMsg &msg) -{ - // Make duplicate. - RsIdMsg *pM = new RsIdMsg(); - *pM = msg; - - std::cerr << "IdDataProxy::addMsg()"; - std::cerr << " MetaData: " << pM->mMeta << " DataPointer: " << pM; - std::cerr << std::endl; - - return createMsg(pM); -} - - - - /* These Functions must be overloaded to complete the service */ -bool IdDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsIdGroup *group = (RsIdGroup *) groupData; - meta = group->mMeta; - - return true; -} - -bool IdDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsIdMsg *page = (RsIdMsg *) msgData; - meta = page->mMeta; - - return true; -} - - - - -/************************************************************************************/ -/************************************************************************************/ /************************************************************************************/ /************************************************************************************/ /************************************************************************************/ -#if 0 +/* Task to determine GPGHash matches + * + * Info to be stored in GroupServiceString + Cache. + * + * Actually - it must be a Signature here - otherwise, you could + * put in a hash from someone else! + * + * Don't think that we need to match very often - maybe once a day? + * Actually - we should scale the matching based on number of keys we have. + * + * imagine - 10^6 rsa keys + 10^3 gpg keys => 10^9 combinations. + * -- far too many to check all quickly. + * + * Need to grab and cache data we need... then check over slowly. + * + * maybe grab a list of all gpgids - that we know of: store id list. + * then big GroupRequest, and iterate through these. + **/ -/* details are updated */ -bool p3IdService::updateIdentity(RsIdData &data) +//const int SHA_DIGEST_LENGTH = 20; + +typedef t_RsGenericIdType GxsIdPgpHash; + +static void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdPgpHash &hash); + + +// Must Use meta. +void p3IdService::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) { - if (data.mKeyId.empty()) + RsGxsIdGroupItem *item = dynamic_cast(grpItem); + if (!item) { - /* new photo */ + std::cerr << "p3IdService::service_CreateGroup() ERROR invalid cast"; + std::cerr << std::endl; + return; + } - /* generate a temp id */ - data.mKeyId = genRandomId(); - - if (data.mIdType & RSID_TYPE_REALID) + /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ + // find private admin key + std::map::iterator mit = keySet.keys.begin(); + for(; mit != keySet.keys.end(); mit++) + { + RsTlvSecurityKey& pk = mit->second; + + if(pk.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) { - data.mGpgIdHash = genRandomId(); + item->group.mMeta.mGroupId = pk.keyId; + break; + } + } + + if(mit == keySet.keys.end()) + { + std::cerr << "p3IdService::service_CreateGroup() ERROR no admin key"; + std::cerr << std::endl; + return; + } + + + /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ + + // SANITY CHECK. + if (item->group.mMeta.mAuthorId != item->meta.mAuthorId) + { + std::cerr << "p3IdService::service_CreateGroup() AuthorId mismatch("; + std::cerr << item->group.mMeta.mAuthorId; + std::cerr << " vs "; + std::cerr << item->meta.mAuthorId; + std::cerr << std::endl; + } + + if (item->group.mMeta.mGroupId != item->meta.mGroupId) + { + std::cerr << "p3IdService::service_CreateGroup() GroupId mismatch("; + std::cerr << item->group.mMeta.mGroupId; + std::cerr << " vs "; + std::cerr << item->meta.mGroupId; + std::cerr << std::endl; + } + + + if (item->group.mMeta.mGroupFlags != item->meta.mGroupFlags) + { + std::cerr << "p3IdService::service_CreateGroup() GroupFlags mismatch("; + std::cerr << item->group.mMeta.mGroupFlags; + std::cerr << " vs "; + std::cerr << item->meta.mGroupFlags; + std::cerr << std::endl; + } + + + + + + + std::cerr << "p3IdService::service_CreateGroup() for : " << item->group.mMeta.mGroupId; + std::cerr << std::endl; + std::cerr << "p3IdService::service_CreateGroup() Alt GroupId : " << item->meta.mGroupId; + std::cerr << std::endl; + +#ifdef GXSID_GEN_DUMMY_DATA + if ((item->group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) && (item->group.mMeta.mAuthorId != "")) +#else + if (item->group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) +#endif + { + /* create the hash */ + GxsIdPgpHash hash; + + /* */ + PGPFingerprintType ownFinger; +#ifdef GXSID_GEN_DUMMY_DATA + PGPIdType ownId(item->group.mMeta.mAuthorId); +#else + PGPIdType ownId(AuthGPG::getAuthGPG()->getGPGOwnId()); +#endif + + if (!AuthGPG::getAuthGPG()->getKeyFingerprint(ownId,ownFinger)) + { + std::cerr << "p3IdService::service_CreateGroup() ERROR Own Finger is stuck"; + std::cerr << std::endl; + return; // abandon attempt! + } + + calcPGPHash(item->group.mMeta.mGroupId, ownFinger, hash); + item->group.mPgpIdHash = hash.toStdString(); + + /* do signature */ + +#if ENABLE_PGP_SIGNATURES +#define MAX_SIGN_SIZE 2048 + uint8_t signarray[MAX_SIGN_SIZE]; + unsigned int sign_size = MAX_SIGN_SIZE; + if (!AuthGPG::getAuthGPG()->SignDataBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, signarray, &sign_size)) + { + /* error */ + std::cerr << "p3IdService::service_CreateGroup() ERROR Signing stuff"; + std::cerr << std::endl; } else { - data.mGpgIdHash = ""; + /* push binary into string -> really bad! */ + item->group.mPgpIdSign = ""; + for(unsigned int i = 0; i < sign_size; i++) + { + item->group.mPgpIdSign += signarray[i]; + } } - - } - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - - /* add / modify */ - mIds[data.mKeyId] = data; - - return true; -} - - - - -bool p3IdService::updateOpinion(RsIdOpinion &opinion) -{ - if (opinion.mKeyId.empty()) - { - /* new photo */ - std::cerr << "p3IdService::updateOpinion() Missing KeyId"; - std::cerr << std::endl; - return false; - } - - /* check if its a mod or new page */ - if (opinion.mPeerId.empty()) - { - std::cerr << "p3IdService::updateOpinion() Missing PeerId"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3IdService::updateOpinion() KeyId: " << opinion.mKeyId; - std::cerr << std::endl; - std::cerr << "p3IdService::updateOpinion() PeerId: " << opinion.mPeerId; - std::cerr << std::endl; - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - - std::map >::iterator it; - std::map::iterator oit; - - it = mOpinions.find(opinion.mKeyId); - if (it == mOpinions.end()) - { - std::map emptyMap; - mOpinions[opinion.mKeyId] = emptyMap; - - it = mOpinions.find(opinion.mKeyId); - } - - (it->second)[opinion.mPeerId] = opinion; - return true; -} - - + /* done! */ +#else + item->group.mPgpIdSign = ""; #endif - + } -void p3IdService::generateDummyData() + // Enforce no AuthorId. + item->meta.mAuthorId = ""; + item->group.mMeta.mAuthorId = ""; + // copy meta data to be sure its all the same. + //item->group.mMeta = item->meta; + + // Reload in a little bit. + // HACK to get it to work. + RsTickEvent::schedule_in(GXSID_EVENT_CACHEOWNIDS, OWNID_RELOAD_DELAY); +} + + +#define HASHPGP_PERIOD 180 + + +bool p3IdService::pgphash_start() { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* grab all the gpg ids... and make some ids */ - - std::list gpgids; - std::list::iterator it; - - rsPeers->getGPGAllList(gpgids); - - std::string ownId = rsPeers->getGPGOwnId(); - gpgids.push_back(ownId); - - int i; - for(it = gpgids.begin(); it != gpgids.end(); it++) + if (!CacheArbitration(BG_PGPHASH)) { - /* create one or two for each one */ - int nIds = 1 + (RSRandom::random_u32() % 2); - for(i = 0; i < nIds; i++) - { - RsIdGroup id; + std::cerr << "p3IdService::pgphash_start() Other Events running... Rescheduling"; + std::cerr << std::endl; - RsPeerDetails details; + /* reschedule in a bit */ + RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_RETRY_PERIOD); + return false; + } - //id.mKeyId = genRandomId(); - id.mMeta.mGroupId = genRandomId(); - id.mIdType = RSID_TYPE_REALID; - id.mGpgIdHash = genRandomId(); + // SCHEDULE NEXT ONE. + RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); - if (rsPeers->getPeerDetails(*it, details)) + std::cerr << "p3IdService::pgphash_start() making request"; + std::cerr << std::endl; + + getPgpIdList(); + + // ACTUALLY only need summary - but have written code for data. + // Also need to use opts.groupFlags to filter stuff properly to REALID's only. + // TODO + + //uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + //opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, GXSIDREQ_PGPHASH); + return true; +} + + +bool p3IdService::pgphash_handlerequest(uint32_t token) +{ + std::cerr << "p3IdService::pgphash_handlerequest(" << token << ")"; + std::cerr << std::endl; + + // We need full data - for access to Hash & Signature. + // Perhaps we will change this to an initial pass through Meta, + // and use this to discard lots of things. + + // Even better - we can set flags in the Meta Data, (IdType), + // And use GXS to filter out all the AnonIds, and only have to process + // Proper Ids. + + // We Will do this later! + + std::vector groups; + std::vector groupsToProcess; + bool ok = getGroupData(token, groups); + + if(ok) + { + std::cerr << "p3IdService::pgphash_request() Have " << groups.size() << " Groups"; + std::cerr << std::endl; + + std::vector::iterator vit; + for(vit = groups.begin(); vit != groups.end(); vit++) + { + std::cerr << "p3IdService::pgphash_request() Group Id: " << vit->mMeta.mGroupId; + std::cerr << std::endl; + + /* Filter based on IdType */ + if (!(vit->mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID)) { - std::ostringstream out; - out << details.name << "_" << i + 1; + std::cerr << "p3IdService::pgphash_request() discarding AnonID"; + std::cerr << std::endl; + continue; + } - //id.mNickname = out.str(); - id.mMeta.mGroupName = out.str(); - + /* now we need to decode the Service String - see what is saved there */ + SSGxsIdGroup ssdata; + if (ssdata.load(vit->mMeta.mServiceString)) + { + if (ssdata.pgp.idKnown) + { + std::cerr << "p3IdService::pgphash_request() discarding Already Known"; + std::cerr << std::endl; + continue; + } + + /* Have a linear attempt policy - + * if zero checks - try now. + * if 1 check, at least a day. + * if 2 checks: 2days, etc. + */ + +#define SECS_PER_DAY (3600 * 24) + time_t age = time(NULL) - ssdata.pgp.lastCheckTs; + time_t wait_period = ssdata.pgp.checkAttempts * SECS_PER_DAY; + if (wait_period > 30 * SECS_PER_DAY) + { + wait_period = 30 * SECS_PER_DAY; + } + + if (age < wait_period) + { + std::cerr << "p3IdService::pgphash_request() discarding Recent Check"; + std::cerr << std::endl; + continue; + } + } + + /* if we get here -> then its to be processed */ + std::cerr << "p3IdService::pgphash_request() ToProcess Group: " << vit->mMeta.mGroupId; + std::cerr << std::endl; + + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mGroupsToProcess.push_back(*vit); + } + } + else + { + std::cerr << "p3IdService::pgphash_request() getGroupData ERROR"; + std::cerr << std::endl; + } + + // Schedule Processing. + RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH_PROC, PGPHASH_PROC_PERIOD); + return true; +} + +bool p3IdService::pgphash_process() +{ + /* each time this is called - process one Id from mGroupsToProcess */ + RsGxsIdGroup pg; + bool isDone = false; + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + if (!mGroupsToProcess.empty()) + { + pg = mGroupsToProcess.front(); + mGroupsToProcess.pop_front(); + + std::cerr << "p3IdService::pgphash_process() Popped Group: " << pg.mMeta.mGroupId; + std::cerr << std::endl; + } + else + { + isDone = true; + } + } + + if (isDone) + { + std::cerr << "p3IdService::pgphash_process() List Empty... Done"; + std::cerr << std::endl; + // FINISHED. + CacheArbitrationDone(BG_PGPHASH); + return true; + } + + + SSGxsIdGroup ssdata; + ssdata.load(pg.mMeta.mServiceString); // attempt load - okay if fails. + + PGPIdType pgpId; + + if (checkId(pg, pgpId)) + { + /* found a match - update everything */ + /* Consistency issues here - what if Reputation was recently updated? */ + + std::cerr << "p3IdService::pgphash_process() CheckId Success for Group: " << pg.mMeta.mGroupId; + std::cerr << " PgpId: " << pgpId.toStdString(); + std::cerr << std::endl; + + /* update */ + ssdata.pgp.idKnown = true; + ssdata.pgp.pgpId = pgpId.toStdString(); + +// SHOULD BE PUSHED TO CACHE! +#if 0 id.mGpgIdKnown = true; id.mGpgId = *it; @@ -755,82 +1491,313 @@ void p3IdService::generateDummyData() id.mIdType |= RSID_RELATION_OTHER; } - } - else +#endif + + } + else + { + std::cerr << "p3IdService::pgphash_process() No Match for Group: " << pg.mMeta.mGroupId; + std::cerr << std::endl; + + ssdata.pgp.lastCheckTs = time(NULL); + ssdata.pgp.checkAttempts++; + } + + /* set new Group ServiceString */ + uint32_t dummyToken = 0; + std::string serviceString = ssdata.save(); + setGroupServiceString(dummyToken, pg.mMeta.mGroupId, serviceString); + + cache_update_if_cached(pg.mMeta.mGroupId, serviceString); + + // Schedule Next Processing. + RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH_PROC, PGPHASH_PROC_PERIOD); + return false; // as there are more items on the queue to process. +} + + + +bool p3IdService::checkId(const RsGxsIdGroup &grp, PGPIdType &pgpId) +{ + std::cerr << "p3IdService::checkId() Starting Match Check for RsGxsId: "; + std::cerr << grp.mMeta.mGroupId; + std::cerr << std::endl; + + /* iterate through and check hash */ + GxsIdPgpHash ans(grp.mPgpIdHash); + + std::cerr << "\tExpected Answer: " << ans.toStdString(); + std::cerr << std::endl; + + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + for(mit = mPgpFingerprintMap.begin(); mit != mPgpFingerprintMap.end(); mit++) + { + GxsIdPgpHash hash; + calcPGPHash(grp.mMeta.mGroupId, mit->second, hash); + if (ans == hash) + { + std::cerr << "p3IdService::checkId() HASH MATCH!"; + std::cerr << std::endl; + +#if ENABLE_PGP_SIGNATURES + /* miracle match! */ + /* check signature too */ + if (AuthGPG::getAuthGPG()->VerifySignBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, + (unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(), + mit->second.toStdString())) { - std::cerr << "p3IdService::generateDummyData() missing" << std::endl; + std::cerr << "p3IdService::checkId() Signature Okay too!"; std::cerr << std::endl; - id.mIdType |= RSID_RELATION_OTHER; - //id.mNickname = genRandomId(); - id.mMeta.mGroupName = genRandomId(); - id.mGpgIdKnown = false; + pgpId = mit->first; + return true; } - //mIds[id.mKeyId] = id; - mIdProxy->addGroup(id); + /* error */ + std::cerr << "p3IdService::checkId() ERROR Signature Failed"; + std::cerr << std::endl; +#else + pgpId = mit->first; + std::cerr << "p3IdService::checkId() Skipping Signature check for now... Hash Okay"; + std::cerr << std::endl; + return true; +#endif + } } -#define MAX_RANDOM_GPGIDS 10 //1000 -#define MAX_RANDOM_PSEUDOIDS 50 //5000 + std::cerr << "p3IdService::checkId() Checked " << mPgpFingerprintMap.size() << " Hashes without Match"; + std::cerr << std::endl; - int nFakeGPGs = (RSRandom::random_u32() % MAX_RANDOM_GPGIDS); - int nFakePseudoIds = (RSRandom::random_u32() % MAX_RANDOM_PSEUDOIDS); - - /* make some fake gpg ids */ - for(i = 0; i < nFakeGPGs; i++) - { - RsIdGroup id; - - RsPeerDetails details; - - //id.mKeyId = genRandomId(); - id.mMeta.mGroupId = genRandomId(); - id.mIdType = RSID_TYPE_REALID; - id.mGpgIdHash = genRandomId(); - - id.mIdType |= RSID_RELATION_OTHER; - //id.mNickname = genRandomId(); - id.mMeta.mGroupName = genRandomId(); - id.mGpgIdKnown = false; - id.mGpgId = ""; - id.mGpgName = ""; - id.mGpgEmail = ""; - - //mIds[id.mKeyId] = id; - mIdProxy->addGroup(id); - } - - /* make lots of pseudo ids */ - for(i = 0; i < nFakePseudoIds; i++) - { - RsIdGroup id; - - RsPeerDetails details; - - //id.mKeyId = genRandomId(); - id.mMeta.mGroupId = genRandomId(); - id.mIdType = RSID_TYPE_PSEUDONYM; - id.mGpgIdHash = ""; - - //id.mNickname = genRandomId(); - id.mMeta.mGroupName = genRandomId(); - id.mGpgIdKnown = false; - id.mGpgId = ""; - id.mGpgName = ""; - id.mGpgEmail = ""; - - //mIds[id.mKeyId] = id; - mIdProxy->addGroup(id); - } - - mUpdated = true; - - return; + return false; } +/* worker functions */ +void p3IdService::getPgpIdList() +{ + std::cerr << "p3IdService::getPgpIdList() Starting...."; + std::cerr << std::endl; + + std::list list; + AuthGPG::getAuthGPG()->getGPGFilteredList(list); + + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + mPgpFingerprintMap.clear(); + + std::list::iterator it; + for(it = list.begin(); it != list.end(); it++) + { + PGPIdType pgpId(*it); + PGPFingerprintType fp; + AuthGPG::getAuthGPG()->getKeyFingerprint(pgpId, fp); + + std::cerr << "p3IdService::getPgpIdList() Id: " << pgpId.toStdString() << " => " << fp.toStdString(); + std::cerr << std::endl; + + mPgpFingerprintMap[pgpId] = fp; + } + + std::cerr << "p3IdService::getPgpIdList() Items: " << mPgpFingerprintMap.size(); + std::cerr << std::endl; +} + + +void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdPgpHash &hash) +{ + unsigned char signature[SHA_DIGEST_LENGTH]; + /* hash id + pubkey => pgphash */ + SHA_CTX *sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + + SHA1_Update(sha_ctx, id.c_str(), id.length()); // TO FIX ONE DAY. + SHA1_Update(sha_ctx, pgp.toByteArray(), pgp.SIZE_IN_BYTES); + SHA1_Final(signature, sha_ctx); + hash = GxsIdPgpHash(signature); + + std::cerr << "calcPGPHash():"; + std::cerr << std::endl; + std::cerr << "\tRsGxsId: " << id; + std::cerr << std::endl; + std::cerr << "\tFingerprint: " << pgp.toStdString(); + std::cerr << std::endl; + std::cerr << "\tFinal Hash: " << hash.toStdString(); + std::cerr << std::endl; + + delete sha_ctx; +} + + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + + +std::string p3IdService::genRandomId(int len) +{ + std::string randomId; + for(int i = 0; i < len; i++) + { + int val = RSRandom::random_u32() % 16; + if (val < 10) + { + randomId += (char) ('0' + val); + } + else + { + randomId += (char) ('a' + (val - 10)); + } + } + + return randomId; +} + +#define MAX_KNOWN_PGPIDS 20 +#define MAX_UNKNOWN_PGPIDS 20 +#define MAX_PSEUDOIDS 20 + +#define DUMMY_GXSID_DELAY 5 + +void p3IdService::generateDummyData() +{ + + generateDummy_OwnIds(); + + time_t age = 0; + for(int i = 0; i < MAX_KNOWN_PGPIDS; i++) + { + age += DUMMY_GXSID_DELAY; + RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_PGPID, age); + } + + for(int i = 0; i < MAX_PSEUDOIDS; i++) + { + age += DUMMY_GXSID_DELAY; + RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_PSEUDOID, age); + } + + for(int i = 0; i < MAX_UNKNOWN_PGPIDS; i++) + { + age += DUMMY_GXSID_DELAY; + RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_UNKNOWN_PGPID, age); + } +} + + + + + +void p3IdService::generateDummy_OwnIds() +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + /* grab all the gpg ids... and make some ids */ + + std::string ownId = rsPeers->getGPGOwnId(); + + // generate some ownIds. + int genCount = 0; + int i; + + int nIds = 2 + (RSRandom::random_u32() % 2); + for(i = 0; i < nIds; i++) + { + RsGxsIdGroup id; + RsPeerDetails details; + + id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; + + // HACK FOR DUMMY GENERATION. + id.mMeta.mAuthorId = ownId; + if (rsPeers->getPeerDetails(ownId, details)) + { + std::ostringstream out; + out << details.name << "_" << i + 1; + + id.mMeta.mGroupName = out.str(); + } + + uint32_t dummyToken = 0; + createGroup(dummyToken, id); + } +} + + +void p3IdService::generateDummy_FriendPGP() +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + // Now Generate for friends. + std::list gpgids; + std::list::iterator it; + rsPeers->getGPGAllList(gpgids); + + RsGxsIdGroup id; + + id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; + + int idx = RSRandom::random_f32() * (gpgids.size() - 1); + it = gpgids.begin(); + for(int j = 0; j < idx; j++, it++); + + // HACK FOR DUMMY GENERATION. + id.mMeta.mAuthorId = *it; + + RsPeerDetails details; + if (rsPeers->getPeerDetails(*it, details)) + { + std::ostringstream out; + out << details.name << "_" << RSRandom::random_u32() % 1000; + id.mMeta.mGroupName = out.str(); + } + else + { + std::cerr << "p3IdService::generateDummy_FriendPGP() missing" << std::endl; + std::cerr << std::endl; + id.mMeta.mGroupName = genRandomId(); + } + + uint32_t dummyToken = 0; + createGroup(dummyToken, id); +} + + +void p3IdService::generateDummy_UnknownPGP() +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + RsGxsIdGroup id; + + // FAKE DATA. + id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; + id.mPgpIdHash = genRandomId(40); + id.mPgpIdSign = genRandomId(40); + id.mMeta.mGroupName = genRandomId(); + + uint32_t dummyToken = 0; + createGroup(dummyToken, id); +} + + +void p3IdService::generateDummy_UnknownPseudo() +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + RsGxsIdGroup id; + + // FAKE DATA. + id.mMeta.mGroupFlags = 0; + id.mMeta.mGroupName = genRandomId(); + + uint32_t dummyToken = 0; + createGroup(dummyToken, id); +} + std::string rsIdTypeToString(uint32_t idtype) { @@ -936,6 +1903,25 @@ std::string rsIdTypeToString(uint32_t idtype) * */ +bool p3IdService::reputation_start() +{ + if (!CacheArbitration(BG_REPUTATION)) + { + std::cerr << "p3IdService::reputation_start() Other Events running... Rescheduling"; + std::cerr << std::endl; + + /* reschedule in a bit */ + RsTickEvent::schedule_in(GXSID_EVENT_REPUTATION, REPUTATION_RETRY_PERIOD); + return false; + } + + CacheArbitrationDone(BG_REPUTATION); + // SCHEDULE NEXT ONE. + RsTickEvent::schedule_in(GXSID_EVENT_REPUTATION, REPUTATION_PERIOD); + return true; +} + + #define ID_BACKGROUND_PERIOD 60 @@ -1006,9 +1992,12 @@ bool p3IdService::background_checkTokenRequest() uint32_t reqtype; uint32_t anstype; time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); + + + status = RsGenExchange::getTokenService()->requestStatus(token); + //checkRequestStatus(token, status, reqtype, anstype, ts); - if (status == GXS_REQUEST_STATUS_COMPLETE) + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) { switch(phase) { @@ -1053,13 +2042,16 @@ bool p3IdService::background_requestGroups() } uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; + RsTokReqOptions opts; std::list groupIds; +/** + TODO opts.mStatusFilter = RSGXS_GROUP_STATUS_NEWMSG; opts.mStatusMask = RSGXS_GROUP_STATUS_NEWMSG; +**/ - requestGroupInfo(token, ansType, opts, groupIds); + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); { RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ mBgToken = token; @@ -1102,7 +2094,10 @@ bool p3IdService::background_requestNewMessages() /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ for(it = modGroupList.begin(); it != modGroupList.end(); it++) { - setGroupStatus(it->mGroupId, 0, RSGXS_GROUP_STATUS_NEWMSG); + /*** TODO + uint32_t dummyToken = 0; + setGroupStatusFlags(dummyToken, it->mGroupId, 0, RSGXS_GROUP_STATUS_NEWMSG); + ***/ mBgGroupMap[it->mGroupId] = *it; groupIds.push_back(it->mGroupId); @@ -1110,13 +2105,15 @@ bool p3IdService::background_requestNewMessages() } uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; + RsTokReqOptions opts; token = 0; + /* TODO opts.mStatusFilter = RSGXS_MSG_STATUS_UNPROCESSED; opts.mStatusMask = RSGXS_MSG_STATUS_UNPROCESSED; + */ - requestMsgInfo(token, ansType, opts, groupIds); + RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, groupIds); { RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ @@ -1131,8 +2128,8 @@ bool p3IdService::background_processNewMessages() std::cerr << "p3IdService::background_processNewMessages()"; std::cerr << std::endl; - std::list newMsgList; - std::list::iterator it; + GxsMsgMetaMap newMsgMap; + GxsMsgMetaMap::iterator it; uint32_t token = 0; { @@ -1140,7 +2137,7 @@ bool p3IdService::background_processNewMessages() token = mBgToken; } - if (!getMsgSummary(token, newMsgList)) + if (!getMsgSummary(token, newMsgMap)) { std::cerr << "p3IdService::background_processNewMessages() ERROR No New Msgs"; std::cerr << std::endl; @@ -1148,7 +2145,6 @@ bool p3IdService::background_processNewMessages() return false; } - /* iterate through the msgs.. update the mBgGroupMap with new data, * and flag these items as modified - so we rewrite them to the db later. * @@ -1156,84 +2152,92 @@ bool p3IdService::background_processNewMessages() */ std::map::iterator mit; - for(it = newMsgList.begin(); it != newMsgList.end(); it++) + + for (it = newMsgMap.begin(); it != newMsgMap.end(); it++) { - std::cerr << "p3IdService::background_processNewMessages() new MsgId: " << it->mMsgId; - std::cerr << std::endl; - - /* flag each new vote as processed */ - setMessageStatus(it->mMsgId, 0, RSGXS_MSG_STATUS_UNPROCESSED); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mit = mBgGroupMap.find(it->mGroupId); - if (mit == mBgGroupMap.end()) + std::vector::iterator vit; + for(vit = it->second.begin(); vit != it->second.end(); vit++) { - std::cerr << "p3IdService::background_processNewMessages() ERROR missing GroupId: "; - std::cerr << it->mGroupId; + std::cerr << "p3IdService::background_processNewMessages() new MsgId: " << vit->mMsgId; std::cerr << std::endl; - - /* error */ - continue; - } - - if (mit->second.mGroupStatus & ID_LOCAL_STATUS_FULL_CALC_FLAG) - { - std::cerr << "p3IdService::background_processNewMessages() Group Already marked FULL_CALC"; - std::cerr << std::endl; - - /* already marked */ - continue; - } - - if (it->mMsgId != it->mOrigMsgId) - { - /* - * not original -> hard, redo calc (alt: could substract previous score) - */ - - std::cerr << "p3IdService::background_processNewMessages() Update, mark for FULL_CALC"; - std::cerr << std::endl; - - mit->second.mGroupStatus |= ID_LOCAL_STATUS_FULL_CALC_FLAG; - } - else - { - /* - * Try incremental calculation. - * - extract parameters from group. - * - increment, & save back. - * - flag group as modified. - */ - - std::cerr << "p3IdService::background_processNewMessages() NewOpt, Try Inc Calc"; - std::cerr << std::endl; - - mit->second.mGroupStatus |= ID_LOCAL_STATUS_INC_CALC_FLAG; - - std::string serviceString; - IdGroupServiceStrData ssData; - - if (!extractIdGroupCache(serviceString, ssData)) + + /* flag each new vote as processed */ + /** + TODO + uint32_t dummyToken = 0; + setMsgStatusFlags(dummyToken, it->mMsgId, 0, RSGXS_MSG_STATUS_UNPROCESSED); + **/ + + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + mit = mBgGroupMap.find(it->first); + if (mit == mBgGroupMap.end()) { - /* error */ - std::cerr << "p3IdService::background_processNewMessages() ERROR Extracting"; + std::cerr << "p3IdService::background_processNewMessages() ERROR missing GroupId: "; + std::cerr << vit->mGroupId; std::cerr << std::endl; + + /* error */ + continue; } - - /* do calcs */ - std::cerr << "p3IdService::background_processNewMessages() Extracted: "; - std::cerr << std::endl; - - /* store it back in */ - std::cerr << "p3IdService::background_processNewMessages() Stored: "; - std::cerr << std::endl; - - if (!encodeIdGroupCache(serviceString, ssData)) + + if (mit->second.mGroupStatus & ID_LOCAL_STATUS_FULL_CALC_FLAG) { - /* error */ - std::cerr << "p3IdService::background_processNewMessages() ERROR Storing"; + std::cerr << "p3IdService::background_processNewMessages() Group Already marked FULL_CALC"; std::cerr << std::endl; + + /* already marked */ + continue; + } + + if (vit->mMsgId != vit->mOrigMsgId) + { + /* + * not original -> hard, redo calc (alt: could substract previous score) + */ + + std::cerr << "p3IdService::background_processNewMessages() Update, mark for FULL_CALC"; + std::cerr << std::endl; + + mit->second.mGroupStatus |= ID_LOCAL_STATUS_FULL_CALC_FLAG; + } + else + { + /* + * Try incremental calculation. + * - extract parameters from group. + * - increment, & save back. + * - flag group as modified. + */ + + std::cerr << "p3IdService::background_processNewMessages() NewOpt, Try Inc Calc"; + std::cerr << std::endl; + + mit->second.mGroupStatus |= ID_LOCAL_STATUS_INC_CALC_FLAG; + + SSGxsIdGroup ssdata; + if (!ssdata.load(mit->second.mServiceString)) + { + /* error */ + std::cerr << "p3IdService::background_processNewMessages() ERROR Extracting"; + std::cerr << std::endl; + } + + /* do calcs */ + std::cerr << "p3IdService::background_processNewMessages() Extracted: "; + std::cerr << std::endl; + + /* store it back in */ + std::cerr << "p3IdService::background_processNewMessages() Stored: "; + std::cerr << std::endl; + + std::string serviceString = ssdata.save(); + if (0) + { + /* error */ + std::cerr << "p3IdService::background_processNewMessages() ERROR Storing"; + std::cerr << std::endl; + } } } } @@ -1267,7 +2271,8 @@ bool p3IdService::background_processNewMessages() std::cerr << std::endl; /* set Cache */ - setGroupServiceString(mit->second.mGroupId, mit->second.mServiceString); + uint32_t dummyToken = 0; + setGroupServiceString(dummyToken, mit->second.mGroupId, mit->second.mServiceString); } else { @@ -1283,75 +2288,6 @@ bool p3IdService::background_processNewMessages() } -bool p3IdService::encodeIdGroupCache(std::string &str, const IdGroupServiceStrData &data) -{ - char line[RSGXS_MAX_SERVICE_STRING]; - - snprintf(line, RSGXS_MAX_SERVICE_STRING, "v1 {%s} {Y:%d O:%d %d %f %f R:%d %d %f %f}", - data.pgpId.c_str(), data.ownScore, - data.opinion.count, data.opinion.nullcount, data.opinion.sum, data.opinion.sumsq, - data.reputation.count, data.reputation.nullcount, data.reputation.sum, data.reputation.sumsq); - - str = line; - return true; -} - - -bool p3IdService::extractIdGroupCache(std::string &str, IdGroupServiceStrData &data) -{ - char pgpline[RSGXS_MAX_SERVICE_STRING]; - char scoreline[RSGXS_MAX_SERVICE_STRING]; - - uint32_t iOwnScore; - IdRepCumulScore iOpin; - IdRepCumulScore iRep; - - // split into two parts. - if (2 != sscanf(str.c_str(), "v1 {%[^}]} {%[^}]", pgpline, scoreline)) - { - std::cerr << "p3IdService::extractIdGroupCache() Failed to extract Two Parts"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3IdService::extractIdGroupCache() pgpline: " << pgpline; - std::cerr << std::endl; - std::cerr << "p3IdService::extractIdGroupCache() scoreline: " << scoreline; - std::cerr << std::endl; - - std::string pgptmp = pgpline; - if (pgptmp.length() > 5) - { - std::cerr << "p3IdService::extractIdGroupCache() Believe to have pgpId: " << pgptmp; - std::cerr << std::endl; - data.pgpIdKnown = true; - data.pgpId = pgptmp; - } - else - { - std::cerr << "p3IdService::extractIdGroupCache() Think pgpId Invalid"; - std::cerr << std::endl; - data.pgpIdKnown = false; - } - - - if (9 == sscanf(scoreline, " Y:%d O:%d %d %lf %lf R:%d %d %lf %lf", &iOwnScore, - &(iOpin.count), &(iOpin.nullcount), &(iOpin.sum), &(iOpin.sumsq), - &(iRep.count), &(iRep.nullcount), &(iRep.sum), &(iRep.sumsq))) - { - data.ownScore = iOwnScore; - data.opinion = iOpin; - data.reputation = iRep; - return true; - } - - std::cerr << "p3IdService::extractIdGroupCache() Failed to extract scores"; - std::cerr << std::endl; - - return false; -} - - bool p3IdService::background_FullCalcRequest() { @@ -1384,10 +2320,10 @@ bool p3IdService::background_FullCalcRequest() /* request the summary info from the parents */ uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; uint32_t token = 0; - RsTokReqOptions opts; + RsTokReqOptions opts; opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - requestMsgInfo(token, ansType, opts, groupIds); + RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, groupIds); { RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ @@ -1407,7 +2343,6 @@ bool p3IdService::background_processFullCalc() std::list msgList; std::list::iterator it; - RsIdMsg msg; bool validmsgs = false; @@ -1422,20 +2357,40 @@ bool p3IdService::background_processFullCalc() double rep_sum = 0; double rep_sumsq = 0; - while(getMsgData(mBgToken, msg)) + std::vector opinions; + std::vector::iterator vit; + + if (!getMsgData(mBgToken, opinions)) { + std::cerr << "p3IdService::background_processFullCalc() ERROR Failed to get Opinions"; + std::cerr << std::endl; + + return false; + } + + std::string groupId; + for(vit = opinions.begin(); vit != opinions.end(); vit++) + { + RsGxsIdOpinion &opinion = *vit; + + /* These should all be same group - should check for sanity! */ + if (groupId == "") + { + groupId = opinion.mMeta.mGroupId; + } + std::cerr << "p3IdService::background_processFullCalc() Msg:"; - std::cerr << msg; + std::cerr << opinion; std::cerr << std::endl; validmsgs = true; - /* for each msg ... extract score, and reputation */ - if (msg.mOpinion != 0) + /* for each opinion.... extract score, and reputation */ + if (opinion.mOpinion != 0) { opinion_count++; - opinion_sum += msg.mOpinion; - opinion_sum += (msg.mOpinion * msg.mOpinion); + opinion_sum += opinion.mOpinion; + opinion_sum += (opinion.mOpinion * opinion.mOpinion); } else { @@ -1443,12 +2398,12 @@ bool p3IdService::background_processFullCalc() } - /* for each msg ... extract score, and reputation */ - if (msg.mReputation != 0) + /* for each opinion.... extract score, and reputation */ + if (opinion.mReputation != 0) { rep_nullcount++; - rep_sum += msg.mReputation; - rep_sum += (msg.mReputation * msg.mReputation); + rep_sum += opinion.mReputation; + rep_sum += (opinion.mReputation * opinion.mReputation); } else { @@ -1482,24 +2437,14 @@ bool p3IdService::background_processFullCalc() if (validmsgs) { - std::string groupId = msg.mMeta.mGroupId; + SSGxsIdGroup ssdata; + std::string serviceString = ssdata.save(); - std::string serviceString; - IdGroupServiceStrData ssData; - - - if (!encodeIdGroupCache(serviceString, ssData)) - { - std::cerr << "p3IdService::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3IdService::background_updateVoteCounts() Encoded String: " << serviceString; - std::cerr << std::endl; - /* store new result */ - setGroupServiceString(it->mMsgId, serviceString); - } + std::cerr << "p3IdService::background_updateVoteCounts() Encoded String: " << serviceString; + std::cerr << std::endl; + /* store new result */ + uint32_t dummyToken = 0; + setGroupServiceString(dummyToken, groupId, serviceString); } { @@ -1530,23 +2475,127 @@ bool p3IdService::background_cleanup() } -std::ostream &operator<<(std::ostream &out, const RsIdGroup &grp) +std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &grp) { - out << "RsIdGroup: Meta: " << grp.mMeta; - out << " IdType: " << grp.mIdType << " GpgIdHash: " << grp.mGpgIdHash; - out << "(((Unusable: ( GpgIdKnown: " << grp.mGpgIdKnown << " GpgId: " << grp.mGpgId; - out << " GpgName: " << grp.mGpgName << " GpgEmail: " << grp.mGpgEmail << ") )))"; + out << "RsGxsIdGroup: Meta: " << grp.mMeta; + out << " PgpIdHash: " << grp.mPgpIdHash; + out << " PgpIdSign: [binary]"; // << grp.mPgpIdSign; out << std::endl; return out; } -std::ostream &operator<<(std::ostream &out, const RsIdMsg &msg) +std::ostream &operator<<(std::ostream &out, const RsGxsIdOpinion &opinion) { - out << "RsIdMsg: Meta: " << msg.mMeta; - //out << " IdType: " << grp.mIdType << " GpgIdHash: " << grp.mGpgIdHash; + out << "RsGxsIdOpinion: Meta: " << opinion.mMeta; out << std::endl; return out; } + + + + + + + + + + // Overloaded from GxsTokenQueue for Request callbacks. +void p3IdService::handleResponse(uint32_t token, uint32_t req_type) +{ + std::cerr << "p3IdService::handleResponse(" << token << "," << req_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(req_type) + { + case GXSIDREQ_CACHEOWNIDS: + cache_load_ownids(token); + break; + case GXSIDREQ_CACHELOAD: + cache_load_for_token(token); + break; + case GXSIDREQ_PGPHASH: + pgphash_handlerequest(token); + break; + case GXSIDREQ_CACHETEST: + cachetest_handlerequest(token); + break; + + case GXSIDREQ_REPUTATION: + + break; + default: + /* error */ + std::cerr << "p3IdService::handleResponse() Unknown Request Type: " << req_type; + std::cerr << std::endl; + break; + } +} + + + // Overloaded from RsTickEvent for Event callbacks. +void p3IdService::handle_event(uint32_t event_type, const std::string &elabel) +{ + std::cerr << "p3IdService::handle_event(" << event_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(event_type) + { + case GXSID_EVENT_CACHEOWNIDS: + cache_request_ownids(); + break; + + case GXSID_EVENT_CACHELOAD: + cache_start_load(); + break; + + case GXSID_EVENT_CACHETEST: + cachetest_getlist(); + break; + + case GXSID_EVENT_REPUTATION: + reputation_start(); + break; + + case GXSID_EVENT_PGPHASH: + pgphash_start(); + break; + + case GXSID_EVENT_PGPHASH_PROC: + pgphash_process(); + break; + + case GXSID_EVENT_DUMMYDATA: + generateDummyData(); + break; + + case GXSID_EVENT_DUMMY_OWNIDS: + generateDummy_OwnIds(); + break; + + case GXSID_EVENT_DUMMY_PGPID: + generateDummy_FriendPGP(); + break; + + case GXSID_EVENT_DUMMY_UNKNOWN_PGPID: + generateDummy_UnknownPGP(); + break; + + case GXSID_EVENT_DUMMY_PSEUDOID: + generateDummy_UnknownPseudo(); + break; + + default: + /* error */ + std::cerr << "p3IdService::handle_event() Unknown Event Type: " << event_type; + std::cerr << std::endl; + break; + } +} + + + diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index c995c844b..85118556a 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -7,7 +7,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. + * License Version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,41 +26,74 @@ #ifndef P3_IDENTITY_SERVICE_HEADER #define P3_IDENTITY_SERVICE_HEADER -#include "services/p3service.h" -#include "services/p3gxsservice.h" -#include "retroshare/rsidentity.h" +#include "retroshare/rsidentity.h" // External Interfaces. +#include "gxs/rsgenexchange.h" // GXS service. +#include "gxs/rsgixs.h" // Internal Interfaces. + +#include "gxs/gxstokenqueue.h" #include #include +#include "util/rsmemcache.h" +#include "util/rstickevent.h" + +#include "pqi/authgpg.h" + /* * Identity Service * */ -class IdDataProxy: public GxsDataProxy +// INTERNAL DATA TYPES. +// Describes data stored in GroupServiceString. + +class SSBit { - public: - - bool getGroup(const std::string &id, RsIdGroup &group); - bool getMsg(const std::string &id, RsIdMsg &msg); - - bool addGroup(const RsIdGroup &group); - bool addMsg(const RsIdMsg &msg); - - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *msgData, RsMsgMetaData &meta); + public: +virtual bool load(const std::string &input) = 0; +virtual std::string save() const = 0; }; -// INTERNAL DATA TYPES... -// Describes data stored in GroupServiceString. -class IdRepCumulScore +class SSGxsIdPgp: public SSBit +{ + public: + SSGxsIdPgp() + :idKnown(false), lastCheckTs(0), checkAttempts(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + bool idKnown; + time_t lastCheckTs; + uint32_t checkAttempts; + std::string pgpId; +}; + +class SSGxsIdScore: public SSBit +{ + public: + SSGxsIdScore() + :score(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + int score; +}; + +class SSGxsIdCumulator: public SSBit { public: + SSGxsIdCumulator() + :count(0), nullcount(0), sum(0), sumsq(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + uint32_t count; uint32_t nullcount; double sum; @@ -69,80 +102,220 @@ public: // derived parameters: }; - -class IdGroupServiceStrData +class SSGxsIdGroup: public SSBit { public: - IdGroupServiceStrData() { pgpIdKnown = false; } - bool pgpIdKnown; - std::string pgpId; - - uint32_t ownScore; - IdRepCumulScore opinion; - IdRepCumulScore reputation; + SSGxsIdGroup() { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + // pgphash status + SSGxsIdPgp pgp; + + // reputation score. + SSGxsIdScore score; + SSGxsIdCumulator opinion; + SSGxsIdCumulator reputation; }; #define ID_LOCAL_STATUS_FULL_CALC_FLAG 0x00010000 #define ID_LOCAL_STATUS_INC_CALC_FLAG 0x00020000 -class p3IdService: public p3GxsDataService, public RsIdentity + +#define MAX_CACHE_SIZE 100 // Small for testing.. +//#define MAX_CACHE_SIZE 10000 // More useful size + +class RsGxsIdGroupItem; + +class RsGxsIdCache { public: + RsGxsIdCache(); + RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey); - p3IdService(uint16_t type); +void updateServiceString(std::string serviceString); -virtual int tick(); + RsIdentityDetails details; + RsTlvSecurityKey pubkey; +}; + +#if 0 +class LruData +{ public: + RsGxsId key; +}; +#endif + + + +// Not sure exactly what should be inherited here? +// Chris - please correct as necessary. + +class p3IdService: public RsGxsIdExchange, public RsIdentity, + public GxsTokenQueue, public RsTickEvent +{ + public: + p3IdService(RsGeneralDataService* gds, RsNetworkExchangeService* nes); - /* changed? */ -virtual bool updated(); + virtual void service_tick(); // needed for background processing. - /* From RsTokenService */ - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds); - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); + /* General Interface is provided by RsIdentity / RsGxsIfaceImpl. */ - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); + /* Data Specific Interface */ - /* Actual Data -> specific to Interface */ -virtual bool getGroupData(const uint32_t &token, RsIdGroup &group); -virtual bool getMsgData(const uint32_t &token, RsIdMsg &msg); + // These are exposed via RsIdentity. +virtual bool getGroupData(const uint32_t &token, std::vector &groups); - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); + // These are local - and not exposed via RsIdentity. +virtual bool getMsgData(const uint32_t &token, std::vector &opinions); +virtual bool createGroup(uint32_t& token, RsGxsIdGroup &group); +virtual bool createMsg(uint32_t& token, RsGxsIdOpinion &opinion); - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); + /**************** RsIdentity External Interface. + * Notes: + * + * All the data is cached together for the moment - We should probably + * seperate and sort this out. + * + * Also need to handle Cache updates / invalidation from internal changes. + * + */ - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); +//virtual bool getNickname(const RsGxsId &id, std::string &nickname); +virtual bool getIdDetails(const RsGxsId &id, RsIdentityDetails &details); +virtual bool getOwnIds(std::list &ownIds); -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); -virtual bool createGroup(uint32_t &token, RsIdGroup &group, bool isNew); -virtual bool createMsg(uint32_t &token, RsIdMsg &msg, bool isNew); + // +virtual bool submitOpinion(uint32_t& token, RsIdOpinion &opinion); +virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms); + + + /**************** RsGixs Implementation + * Notes: + * Interface is only suggestion at the moment, will be changed as necessary. + * Results should be cached / preloaded for maximum speed. + * + */ +virtual bool haveKey(const RsGxsId &id); +virtual bool requestKey(const RsGxsId &id, const std::list &peers); +virtual int getKey(const RsGxsId &id, RsTlvSecurityKey &key); + +virtual bool havePrivateKey(const RsGxsId &id); +virtual bool requestPrivateKey(const RsGxsId &id); +virtual int getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key); + + /**************** RsGixsReputation Implementation + * Notes: + * Again should be cached if possible. + */ + + // get Reputation. +virtual bool getReputation(const RsGxsId &id, const GixsReputation &rep); + + + protected: + + /** Notifications **/ +virtual void notifyChanges(std::vector& changes); + + /** Overloaded to add PgpIdHash to Group Definition **/ +virtual void service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); + + // Overloaded from GxsTokenQueue for Request callbacks. +virtual void handleResponse(uint32_t token, uint32_t req_type); + + // Overloaded from RsTickEvent. +virtual void handle_event(uint32_t event_type, const std::string &elabel); private: -virtual void generateDummyData(); +/************************************************************************ + * This is the Cache for minimising calls to the DataStore. + * + */ + int cache_tick(); -std::string genRandomId(); + bool cache_request_load(const RsGxsId &id); + bool cache_start_load(); + bool cache_load_for_token(uint32_t token); + + bool cache_store(const RsGxsIdGroupItem *item); + bool cache_update_if_cached(const RsGxsId &id, std::string serviceString); + + // Mutex protected. + + std::list mCacheLoad_ToCache; + + // Switching to RsMemCache for Key Caching. + RsMemCache mPublicKeyCache; + RsMemCache mPrivateKeyCache; + +/************************************************************************ + * Refreshing own Ids. + * + */ + bool cache_request_ownids(); + bool cache_load_ownids(uint32_t token); + + std::list mOwnIds; + +/************************************************************************ + * Test fns for Caching. + * + */ + bool cachetest_tick(); + bool cachetest_getlist(); + bool cachetest_handlerequest(uint32_t token); + +/************************************************************************ + * for processing background tasks that use the serviceString. + * - must be mutually exclusive to avoid clashes. + */ + bool CacheArbitration(uint32_t mode); + void CacheArbitrationDone(uint32_t mode); + + bool mBgSchedule_Active; + uint32_t mBgSchedule_Mode; + +/************************************************************************ + * pgphash processing. + * + */ + bool pgphash_start(); + bool pgphash_handlerequest(uint32_t token); + bool pgphash_process(); + + bool checkId(const RsGxsIdGroup &grp, PGPIdType &pgp_id); + void getPgpIdList(); + + /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ + + std::map mPgpFingerprintMap; + std::list mGroupsToProcess; + +/************************************************************************ + * Below is the background task for processing opinions => reputations + * + */ + +virtual void generateDummyData(); + void generateDummy_OwnIds(); + void generateDummy_FriendPGP(); + void generateDummy_UnknownPGP(); + void generateDummy_UnknownPseudo(); + +std::string genRandomId(int len = 20); + + bool reputation_start(); + bool reputation_continue(); int background_tick(); bool background_checkTokenRequest(); @@ -154,11 +327,6 @@ std::string genRandomId(); bool background_cleanup(); - bool encodeIdGroupCache(std::string &str, const IdGroupServiceStrData &data); - bool extractIdGroupCache(std::string &str, IdGroupServiceStrData &data); - - IdDataProxy *mIdProxy; - RsMutex mIdMtx; /***** below here is locked *****/ @@ -170,17 +338,17 @@ std::string genRandomId(); std::map mBgGroupMap; std::list mBgFullCalcGroups; - - - bool mUpdated; -#if 0 - std::map mIds; - std::map > mOpinions; +/************************************************************************ + * Other Data that is protected by the Mutex. + */ - std::map mReputations; // this is created locally. -#endif + std::vector mGroupChange; + std::vector mMsgChange; }; -#endif +#endif // P3_IDENTITY_SERVICE_HEADER + + + diff --git a/libretroshare/src/services/p3photoservice.cc b/libretroshare/src/services/p3photoservice.cc index e1dd0a50d..e704f6e66 100644 --- a/libretroshare/src/services/p3photoservice.cc +++ b/libretroshare/src/services/p3photoservice.cc @@ -1,679 +1,388 @@ -/* - * libretroshare/src/services p3photoservice.cc - * - * Photo Service for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/p3photoservice.h" -#include "util/rsrandom.h" - -/**** - * #define PHOTO_DEBUG 1 - ****/ +#include "p3photoservice.h" +#include "serialiser/rsphotoitems.h" +#include "gxs/rsgxsflags.h" RsPhoto *rsPhoto = NULL; -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ +const uint32_t RsPhoto::FLAG_MSG_TYPE_MASK = 0x000f; +const uint32_t RsPhoto::FLAG_MSG_TYPE_PHOTO_POST = 0x0001; +const uint32_t RsPhoto::FLAG_MSG_TYPE_PHOTO_COMMENT = 0x0002; -p3PhotoService::p3PhotoService(uint16_t type) - :p3GxsDataService(type, new PhotoDataProxy()), mPhotoMtx("p3PhotoService"), mUpdated(true) -{ - RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ - mPhotoProxy = (PhotoDataProxy *) mProxy; - return; -} -int p3PhotoService::tick() -{ - //std::cerr << "p3PhotoService::tick()"; - //std::cerr << std::endl; - - fakeprocessrequests(); - - return 0; -} - -bool p3PhotoService::updated() -{ - RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ - - if (mUpdated) - { - mUpdated = false; - return true; - } - return false; -} - - - /* Data Requests */ -bool p3PhotoService::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3PhotoService::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3PhotoService::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3PhotoService::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3PhotoService::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3PhotoService::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3PhotoService::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3PhotoService::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PhotoService::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PhotoService::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3PhotoService::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3PhotoService::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PhotoService::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PhotoService::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3PhotoService::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3PhotoService::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PhotoService::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PhotoService::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3PhotoService::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3PhotoService::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PhotoService::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PhotoService::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - - /* Specific Service Data */ -bool p3PhotoService::getAlbum(const uint32_t &token, RsPhotoAlbum &album) -{ - std::cerr << "p3PhotoService::getAlbum() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PhotoService::getAlbum() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PhotoService::getAlbum() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PhotoService::getAlbum() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPhotoAlbum */ - bool ans = mPhotoProxy->getAlbum(id, album); - return ans; -} - - -bool p3PhotoService::getPhoto(const uint32_t &token, RsPhotoPhoto &photo) -{ - std::cerr << "p3PhotoService::getPhoto() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PhotoService::getPhoto() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PhotoService::getPhoto() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PhotoService::getPhoto() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPhotoAlbum */ - bool ans = mPhotoProxy->getPhoto(id, photo); - return ans; -} - - - - /* Poll */ -uint32_t p3PhotoService::requestStatus(const uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - return status; -} - - - /* Cancel Request */ -bool p3PhotoService::cancelRequest(const uint32_t &token) -{ - return clearRequest(token); -} - - -bool p3PhotoService::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) -{ - return mPhotoProxy->setMessageStatus(msgId, status, statusMask); -} - -bool p3PhotoService::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mPhotoProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3PhotoService::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mPhotoProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3PhotoService::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mPhotoProxy->setMessageServiceString(msgId, str); -} - -bool p3PhotoService::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mPhotoProxy->setGroupServiceString(grpId, str); -} - - -bool p3PhotoService::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3PhotoService::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - -/* details are updated in album - to choose Album ID, and storage path */ - -bool p3PhotoService::submitAlbumDetails(uint32_t &token, RsPhotoAlbum &album, bool isNew) -{ - /* check if its a modification or a new album */ - - /* add to database */ - - /* check if its a mod or new photo */ - if (album.mMeta.mGroupId.empty()) - { - /* new photo */ - - /* generate a temp id */ - album.mMeta.mGroupId = genRandomId(); - // TODO. - //album.mMeta.mPublishTs = time(NULL); - - std::cerr << "p3PhotoService::submitAlbumDetails() Generated New GroupID: " << album.mMeta.mGroupId; - std::cerr << std::endl; - } - - album.mModFlags = 0; // These are always cleared. - - { - RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - - /* add / modify */ - mPhotoProxy->addAlbum(album); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list groupIds; - groupIds.push_back(album.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3PhotoService::submitAlbumDetails() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3PhotoService::submitPhoto(uint32_t &token, RsPhotoPhoto &photo, bool isNew) -{ - if (photo.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PhotoService::submitPhoto() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - photo.mMeta.mMsgId = genRandomId(); - photo.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - photo.mMeta.mOrigMsgId = photo.mMeta.mMsgId; - std::cerr << "p3PhotoService::submitPhoto() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PhotoService::submitPhoto() Updated Msg"; - std::cerr << std::endl; - } - - photo.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PhotoService::submitPhoto() OrigMsgId: " << photo.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPhotoProxy->addPhoto(photo); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(photo.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PhotoService::submitPhoto() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - -bool PhotoDataProxy::getAlbum(const std::string &id, RsPhotoAlbum &album) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsPhotoAlbum *pA = (RsPhotoAlbum *) groupData; - // Shallow copy of thumbnail. - album = *pA; - - // update definitive version of the metadata. - album.mMeta = meta; - - std::cerr << "PhotoDataProxy::getAlbum() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; - return true; - } - - std::cerr << "PhotoDataProxy::getAlbum() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool PhotoDataProxy::getPhoto(const std::string &id, RsPhotoPhoto &photo) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPhotoPhoto *pP = (RsPhotoPhoto *) msgData; - // Shallow copy of thumbnail. - photo = *pP; - - // update definitive version of the metadata. - photo.mMeta = meta; - - std::cerr << "PhotoDataProxy::getPhoto() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - - std::cerr << "PhotoDataProxy::getPhoto() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - -bool PhotoDataProxy::addAlbum(const RsPhotoAlbum &album) -{ - // Make duplicate. - RsPhotoAlbum *pA = new RsPhotoAlbum(); - *pA = album; - - std::cerr << "PhotoDataProxy::addAlbum()"; - std::cerr << " MetaData: " << pA->mMeta << " DataPointer: " << pA; - std::cerr << std::endl; - - // deep copy thumbnail. - pA->mThumbnail.data = NULL; - pA->mThumbnail.copyFrom(album.mThumbnail); - - return createGroup(pA); -} - - -bool PhotoDataProxy::addPhoto(const RsPhotoPhoto &photo) -{ - // Make duplicate. - RsPhotoPhoto *pP = new RsPhotoPhoto(); - *pP = photo; - - std::cerr << "PhotoDataProxy::addPhoto()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - // deep copy thumbnail. - pP->mThumbnail.data = NULL; - pP->mThumbnail.copyFrom(photo.mThumbnail); - - return createMsg(pP); -} - - - - /* These Functions must be overloaded to complete the service */ -bool PhotoDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsPhotoAlbum *album = (RsPhotoAlbum *) groupData; - meta = album->mMeta; - - return true; -} - -bool PhotoDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsPhotoPhoto *photo = (RsPhotoPhoto *) msgData; - meta = photo->mMeta; - - return true; -} - - -/********************************************************************************************/ - -std::string p3PhotoService::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - - bool RsPhotoThumbnail::copyFrom(const RsPhotoThumbnail &nail) { - if (data) - { - deleteImage(); - } + if (data) + { + deleteImage(); + } - if ((!nail.data) || (nail.size == 0)) - { - return false; - } + if ((!nail.data) || (nail.size == 0)) + { + return false; + } - size = nail.size; - type = nail.type; - data = (uint8_t *) malloc(size); - memcpy(data, nail.data, size); + size = nail.size; + type = nail.type; + data = (uint8_t *) malloc(size); + memcpy(data, nail.data, size); - return true; + return true; } bool RsPhotoThumbnail::deleteImage() { - if (data) - { - free(data); - data = NULL; - size = 0; - } - return true; + if (data) + { + free(data); + data = NULL; + size = 0; + type.clear(); + } + return true; } - -/********************************************************************************************/ - RsPhotoPhoto::RsPhotoPhoto() - :mSetFlags(0), mOrder(0), mMode(0), mModFlags(0) + :mSetFlags(0), mOrder(0), mMode(0), mModFlags(0) { - return; + return; } RsPhotoAlbum::RsPhotoAlbum() - :mMode(0), mSetFlags(0), mModFlags(0) + :mMode(0), mSetFlags(0), mModFlags(0) { - return; + return; } +RsPhotoComment::RsPhotoComment() + : mComment(""), mCommentFlag(0) { + +} + +RsPhotoComment::RsPhotoComment(const RsGxsPhotoCommentItem &comment) + : mComment(""), mCommentFlag(0) { + + *this = comment.comment; + (*this).mMeta = comment.meta; + +} std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo) { - out << "RsPhotoPhoto [ "; - out << "Title: " << photo.mMeta.mMsgName; - out << "]"; - return out; + out << "RsPhotoPhoto [ "; + out << "Title: " << photo.mMeta.mMsgName; + out << "]"; + return out; } std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album) { - out << "RsPhotoAlbum [ "; - out << "Title: " << album.mMeta.mGroupName; - out << "]"; - return out; + out << "RsPhotoAlbum [ "; + out << "Title: " << album.mMeta.mGroupName; + out << "]"; + return out; +} + +p3PhotoService::p3PhotoService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs, + uint32_t authenPolicy) + : RsGenExchange(gds, nes, new RsGxsPhotoSerialiser(), RS_SERVICE_GXSV1_TYPE_PHOTO, gixs, authenPolicy), + mPhotoMutex(std::string("Photo Mutex")) +{ + + // create dummy grps + + RsGxsPhotoAlbumItem* item1 = new RsGxsPhotoAlbumItem(), *item2 = new RsGxsPhotoAlbumItem(); + + item1->meta.mGroupName = "Dummy Album 1"; + item1->meta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_RESTRICTED; + item1->album.mCaption = "Dummy 1"; + item2->meta.mGroupName = "Dummy Album 2"; + item2->meta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_RESTRICTED; + item2->album.mCaption = "Dummy 2"; + + createDummyGroup(item1); + createDummyGroup(item2); +} + +bool p3PhotoService::updated() +{ + RsStackMutex stack(mPhotoMutex); + + bool changed = (!mGroupChange.empty() || !mMsgChange.empty()); + + return changed; +} + +void p3PhotoService::service_tick() +{ + +} + + + +void p3PhotoService::groupsChanged(std::list& grpIds) +{ + RsStackMutex stack(mPhotoMutex); + + while(!mGroupChange.empty()) + { + RsGxsGroupChange* gc = mGroupChange.back(); + std::list& gList = gc->grpIdList; + std::list::iterator lit = gList.begin(); + for(; lit != gList.end(); lit++) + grpIds.push_back(*lit); + + mGroupChange.pop_back(); + delete gc; + } +} + + +void p3PhotoService::msgsChanged( + std::map >& msgs) +{ + RsStackMutex stack(mPhotoMutex); + + while(!mMsgChange.empty()) + { + RsGxsMsgChange* mc = mMsgChange.back(); + msgs = mc->msgChangeMap; + mMsgChange.pop_back(); + delete mc; + } +} + + +RsTokenService* p3PhotoService::getTokenService() { + + return RsGenExchange::getTokenService(); +} + + +bool p3PhotoService::getGroupList(const uint32_t& token, + std::list& groupIds) +{ + return RsGenExchange::getGroupList(token, groupIds); +} + + +bool p3PhotoService::getMsgList(const uint32_t& token, + GxsMsgIdResult& msgIds) +{ + + return RsGenExchange::getMsgList(token, msgIds); +} + + +bool p3PhotoService::getGroupSummary(const uint32_t& token, + std::list& groupInfo) +{ + return RsGenExchange::getGroupMeta(token, groupInfo); +} + + +bool p3PhotoService::getMsgSummary(const uint32_t& token, + MsgMetaResult& msgInfo) +{ + return RsGenExchange::getMsgMeta(token, msgInfo); +} + + +bool p3PhotoService::getAlbum(const uint32_t& token, std::vector& albums) +{ + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsPhotoAlbumItem* item = dynamic_cast(*vit); + RsPhotoAlbum album = item->album; + item->album.mMeta = item->meta; + album.mMeta = item->album.mMeta; + delete item; + albums.push_back(album); + } + } + + return ok; +} + + +bool p3PhotoService::getPhoto(const uint32_t& token, PhotoResult& photos) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsPhotoPhotoItem* item = dynamic_cast(*vit); + + if(item) + { + RsPhotoPhoto photo = item->photo; + photo.mMeta = item->meta; + photos[grpId].push_back(photo); + delete item; + }else + { + std::cerr << "Not a photo Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + +bool p3PhotoService::getPhotoComment(const uint32_t &token, PhotoCommentResult &comments) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsPhotoCommentItem* item = dynamic_cast(*vit); + + if(item) + { + RsPhotoComment comment = item->comment; + comment.mMeta = item->meta; + comments[grpId].push_back(comment); + delete item; + }else + { + std::cerr << "Not a comment Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + +RsPhotoComment& RsPhotoComment::operator=(const RsGxsPhotoCommentItem& comment) +{ + *this = comment.comment; + return *this; +} + +bool p3PhotoService::getPhotoRelatedComment(const uint32_t &token, PhotoRelatedCommentResult &comments) +{ + + return RsGenExchange::getMsgRelatedDataT(token, comments); + +} + +bool p3PhotoService::submitAlbumDetails(uint32_t& token, RsPhotoAlbum& album) +{ + RsGxsPhotoAlbumItem* albumItem = new RsGxsPhotoAlbumItem(); + albumItem->album = album; + albumItem->meta = album.mMeta; + RsGenExchange::publishGroup(token, albumItem); + return true; +} + + + +void p3PhotoService::notifyChanges(std::vector& changes) +{ + + RsStackMutex stack(mPhotoMutex); + + std::vector::iterator vit = changes.begin(); + + for(; vit != changes.end(); vit++) + { + RsGxsNotify* n = *vit; + RsGxsGroupChange* gc; + RsGxsMsgChange* mc; + if((mc = dynamic_cast(n)) != NULL) + { + mMsgChange.push_back(mc); + } + else if((gc = dynamic_cast(n)) != NULL) + { + mGroupChange.push_back(gc); + } + else + { + delete n; + } + } +} + +bool p3PhotoService::submitPhoto(uint32_t& token, RsPhotoPhoto& photo) +{ + RsGxsPhotoPhotoItem* photoItem = new RsGxsPhotoPhotoItem(); + photoItem->photo = photo; + photoItem->meta = photo.mMeta; + photoItem->meta.mMsgFlags = FLAG_MSG_TYPE_PHOTO_POST; + + RsGenExchange::publishMsg(token, photoItem); + return true; +} + +bool p3PhotoService::submitComment(uint32_t &token, RsPhotoComment &comment) +{ + RsGxsPhotoCommentItem* commentItem = new RsGxsPhotoCommentItem(); + commentItem->comment = comment; + commentItem->meta = comment.mMeta; + commentItem->meta.mMsgFlags = FLAG_MSG_TYPE_PHOTO_COMMENT; + + RsGenExchange::publishMsg(token, commentItem); + return true; +} + +bool p3PhotoService::acknowledgeMsg(const uint32_t& token, + std::pair& msgId) +{ + return RsGenExchange::acknowledgeTokenMsg(token, msgId); +} + + +bool p3PhotoService::acknowledgeGrp(const uint32_t& token, + RsGxsGroupId& grpId) +{ + return RsGenExchange::acknowledgeTokenGrp(token, grpId); +} + +bool p3PhotoService::subscribeToAlbum(uint32_t &token, const RsGxsGroupId &grpId, bool subscribe) +{ + if(subscribe) + RsGenExchange::setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED, GXS_SERV::GROUP_SUBSCRIBE_MASK); + else + RsGenExchange::setGroupSubscribeFlags(token, grpId, 0, GXS_SERV::GROUP_SUBSCRIBE_MASK); + + return true; } diff --git a/libretroshare/src/services/p3photoservice.h b/libretroshare/src/services/p3photoservice.h index 16e4f2cc5..728fc7402 100644 --- a/libretroshare/src/services/p3photoservice.h +++ b/libretroshare/src/services/p3photoservice.h @@ -1,9 +1,12 @@ +#ifndef P3PHOTOSERVICEV2_H +#define P3PHOTOSERVICEV2_H + /* - * libretroshare/src/services: p3photoservice.h + * libretroshare/src/retroshare: rsphoto.h * - * 3P/PQI network interface for RetroShare. + * RetroShare C++ Interface. * - * Copyright 2012-2012 by Robert Fernie. + * Copyright 2008-2012 by Robert Fernie, Christopher Evi-Parker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,116 +26,123 @@ * */ -#ifndef P3_PHOTO_SERVICE_HEADER -#define P3_PHOTO_SERVICE_HEADER - -#include "services/p3gxsservice.h" +#include "gxs/rsgenexchange.h" #include "retroshare/rsphoto.h" -#include -#include - -/* - * Photo Service - * - * This is an example service for the new cache system. - * For the moment, it will only hold data passed to it from the GUI. - * and spew that back when asked.... - * - * We are doing it like this - so we can check the required interface functionality. - * - * Expect it won't take long before it'll be properly linked into the backend! - * - * This will be transformed into a Plugin Service, once the basics have been worked out. - * - */ - - -class PhotoDataProxy: public GxsDataProxy +class p3PhotoService : public RsPhoto, public RsGenExchange { - public: +public: - bool addAlbum(const RsPhotoAlbum &album); - bool addPhoto(const RsPhotoPhoto &photo); + p3PhotoService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs, + uint32_t authenPolicy); - bool getAlbum(const std::string &id, RsPhotoAlbum &album); - bool getPhoto(const std::string &id, RsPhotoPhoto &photo); +public: - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *groupData, RsMsgMetaData &meta); + /*! + * @return true if a change has occured + */ + bool updated(); + /*! + * + */ + void service_tick(); + +protected: + + void notifyChanges(std::vector& changes); +public: + + /** Requests **/ + + void groupsChanged(std::list& grpIds); + + + void msgsChanged(std::map >& msgs); + + RsTokenService* getTokenService(); + + bool getGroupList(const uint32_t &token, + std::list &groupIds); + bool getMsgList(const uint32_t &token, + GxsMsgIdResult& msgIds); + + /* Generic Summary */ + bool getGroupSummary(const uint32_t &token, + std::list &groupInfo); + + bool getMsgSummary(const uint32_t &token, + MsgMetaResult &msgInfo); + + /* Specific Service Data */ + bool getAlbum(const uint32_t &token, std::vector &albums); + bool getPhoto(const uint32_t &token, PhotoResult &photos); + bool getPhotoComment(const uint32_t &token, PhotoCommentResult &comments); + bool getPhotoRelatedComment(const uint32_t &token, PhotoRelatedCommentResult &comments); + +public: + + /** Modifications **/ + + /*! + * submits album, which returns a token that needs + * to be acknowledge to get album grp id + * @param token token to redeem for acknowledgement + * @param album album to be submitted + */ + bool submitAlbumDetails(uint32_t& token, RsPhotoAlbum &album); + + /*! + * submits photo, which returns a token that needs + * to be acknowledge to get photo msg-grp id pair + * @param token token to redeem for acknowledgement + * @param photo photo to be submitted + */ + bool submitPhoto(uint32_t& token, RsPhotoPhoto &photo); + + /*! + * submits photo comment, which returns a token that needs + * to be acknowledged to get photo msg-grp id pair + * The mParentId needs to be set to an existing msg for which + * commenting is enabled + * @param token token to redeem for acknowledgement + * @param comment comment to be submitted + */ + bool submitComment(uint32_t& token, RsPhotoComment &photo); + + /*! + * subscribes to group, and returns token which can be used + * to be acknowledged to get group Id + * @param token token to redeem for acknowledgement + * @param grpId the id of the group to subscribe to + */ + bool subscribeToAlbum(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe); + + /*! + * This allows the client service to acknowledge that their msgs has + * been created/modified and retrieve the create/modified msg ids + * @param token the token related to modification/create request + * @param msgIds map of grpid->msgIds of message created/modified + * @return true if token exists false otherwise + */ + bool acknowledgeMsg(const uint32_t& token, std::pair& msgId); + + /*! + * This allows the client service to acknowledge that their grps has + * been created/modified and retrieve the create/modified grp ids + * @param token the token related to modification/create request + * @param msgIds vector of ids of groups created/modified + * @return true if token exists false otherwise + */ + bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId); + +private: + + std::vector mGroupChange; + std::vector mMsgChange; + + RsMutex mPhotoMutex; }; - - -class p3PhotoService: public p3GxsDataService, public RsPhoto -{ - public: - - p3PhotoService(uint16_t type); - -virtual int tick(); - - public: - -// NEW INTERFACE. -/************* Extern Interface *******/ - - /* changed? */ -virtual bool updated(); - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds); - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); - - /* Actual Data -> specific to Interface */ - /* Specific Service Data */ -virtual bool getAlbum(const uint32_t &token, RsPhotoAlbum &album); -virtual bool getPhoto(const uint32_t &token, RsPhotoPhoto &photo); - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); - - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - - -/* details are updated in album - to choose Album ID, and storage path */ -virtual bool submitAlbumDetails(uint32_t &token, RsPhotoAlbum &album, bool isNew); -virtual bool submitPhoto(uint32_t &token, RsPhotoPhoto &photo, bool isNew); - - - - private: - -std::string genRandomId(); - - PhotoDataProxy *mPhotoProxy; - - RsMutex mPhotoMtx; - bool mUpdated; - - -}; - -#endif +#endif // P3PHOTOSERVICEV2_H diff --git a/libretroshare/src/services/p3photoserviceV2.cc b/libretroshare/src/services/p3photoserviceV2.cc deleted file mode 100644 index f961452e4..000000000 --- a/libretroshare/src/services/p3photoserviceV2.cc +++ /dev/null @@ -1,132 +0,0 @@ -#include "p3photoserviceV2.h" -#include "serialiser/rsphotov2items.h" - -p3PhotoServiceV2::p3PhotoServiceV2(RsGeneralDataService* gds, RsNetworkExchangeService* nes) - : RsGenExchange(gds, nes, new RsGxsPhotoSerialiser(), RS_SERVICE_TYPE_PHOTO) -{ - -} - -bool p3PhotoServiceV2::updated() -{ - return false; -} - - -void p3PhotoServiceV2::groupsChanged(std::list& grpIds) { -} - - -void p3PhotoServiceV2::msgsChanged( - std::map >& msgs) -{ - -} - - -RsTokenServiceV2* p3PhotoServiceV2::getTokenService() { - - return RsGenExchange::getTokenService(); -} - - -bool p3PhotoServiceV2::getGroupList(const uint32_t& token, - std::list& groupIds) -{ - return RsGenExchange::getGroupList(token, groupIds); -} - - -bool p3PhotoServiceV2::getMsgList(const uint32_t& token, - GxsMsgIdResult& msgIds) -{ - - return RsGenExchange::getMsgList(token, msgIds); -} - - -bool p3PhotoServiceV2::getGroupSummary(const uint32_t& token, - std::list& groupInfo) -{ - return RsGenExchange::getGroupMeta(token, groupInfo); -} - - -bool p3PhotoServiceV2::getMsgSummary(const uint32_t& token, - MsgMetaResult& msgInfo) -{ - return RsGenExchange::getMsgMeta(token, msgInfo); -} - - -bool p3PhotoServiceV2::getAlbum(const uint32_t& token, std::vector& albums) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); vit++) - { - RsGxsPhotoAlbumItem* item = dynamic_cast(*vit); - RsPhotoAlbum album = item->album; - delete item; - albums.push_back(album); - } - } - - return ok; -} - - -bool p3PhotoServiceV2::getPhoto(const uint32_t& token, PhotoResult& photos) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); mit++) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); vit++) - { - RsGxsPhotoPhotoItem* item = dynamic_cast(*vit); - - if(item) - { - RsPhotoPhoto photo = item->photo; - photos[grpId].push_back(photo); - delete item; - }else - { - delete *vit; - } - } - } - } - - return ok; -} - - -bool p3PhotoServiceV2::submitAlbumDetails(RsPhotoAlbum& album) -{ - return false; -} - - - -bool p3PhotoServiceV2::submitPhoto(RsPhotoPhoto& photo) -{ - return false; -} - - diff --git a/libretroshare/src/services/p3photoserviceV2.h b/libretroshare/src/services/p3photoserviceV2.h deleted file mode 100644 index d92317c91..000000000 --- a/libretroshare/src/services/p3photoserviceV2.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef P3PHOTOSERVICEV2_H -#define P3PHOTOSERVICEV2_H - -/* - * libretroshare/src/retroshare: rsphoto.h - * - * RetroShare C++ Interface. - * - * Copyright 2008-2012 by Robert Fernie, Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsphotoV2.h" - - -class p3PhotoServiceV2 : public RsPhotoV2, public RsGenExchange -{ -public: - - p3PhotoServiceV2(RsGeneralDataService* gds, RsNetworkExchangeService* nes); - -public: - - /*! - * @return - */ - bool updated(); - -public: - - /** Requests **/ - - void groupsChanged(std::list& grpIds); - - - void msgsChanged(std::map >& msgs); - - RsTokenServiceV2* getTokenService(); - - bool getGroupList(const uint32_t &token, - std::list &groupIds); - bool getMsgList(const uint32_t &token, - GxsMsgIdResult& msgIds); - - /* Generic Summary */ - bool getGroupSummary(const uint32_t &token, - std::list &groupInfo); - - bool getMsgSummary(const uint32_t &token, - MsgMetaResult &msgInfo); - - /* Specific Service Data */ - bool getAlbum(const uint32_t &token, std::vector &albums); - bool getPhoto(const uint32_t &token, PhotoResult &photos); - -public: - - /** Modifications **/ - - bool submitAlbumDetails(RsPhotoAlbum &album); - bool submitPhoto(RsPhotoPhoto &photo); -}; - -#endif // P3PHOTOSERVICEV2_H diff --git a/libretroshare/src/services/p3posted.cc b/libretroshare/src/services/p3posted.cc index 5e3776ee7..a207fac04 100644 --- a/libretroshare/src/services/p3posted.cc +++ b/libretroshare/src/services/p3posted.cc @@ -1,2032 +1,1203 @@ -/* - * libretroshare/src/services p3photoservice.cc - * - * Photo Service for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/p3posted.h" -#include "util/rsrandom.h" -#include -#include -#include - -/**** - * #define POSTED_DEBUG 1 - ****/ - -RsPosted *rsPosted = NULL; - - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3PostedService::p3PostedService(uint16_t type) - :p3GxsDataService(type, new PostedDataProxy()), mPostedMtx("p3PostedService"), mUpdated(true) -{ - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mPostedProxy = (PostedDataProxy *) mProxy; - - mViewMode = RSPOSTED_VIEWMODE_HOT; - mViewPeriod = RSPOSTED_PERIOD_WEEK; - mViewStart = 0; - mViewCount = 50; - - mProcessingRanking = false; - mRankingState = 0; - mRankingExternalToken = 0; - mRankingInternalToken = 0; - - mLastBgCheck = 0; - mBgProcessing = 0; - mBgPhase = 0; - mBgToken = 0; - - } - - generateDummyData(); - return; -} - -#define POSTED_BACKGROUND_PERIOD 60 - -int p3PostedService::tick() -{ - //std::cerr << "p3PostedService::tick()"; - //std::cerr << std::endl; - - fakeprocessrequests(); - - - // Contine Ranking Request. - checkRankingRequest(); - - // Run Background Stuff. - background_checkTokenRequest(); - - /* every minute - run a background check */ - time_t now = time(NULL); - bool doCheck = false; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (now - mLastBgCheck > POSTED_BACKGROUND_PERIOD) - { - doCheck = true; - mLastBgCheck = now; - } - } - - if (doCheck) - { - addExtraDummyData(); - background_requestGroups(); - } - - - - // Add in new votes + comments. - return 0; -} - -bool p3PostedService::updated() -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - if (mUpdated) - { - mUpdated = false; - return true; - } - return false; -} - - - - /* Data Requests */ -bool p3PostedService::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3PostedService::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3PostedService::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3PostedService::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3PostedService::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3PostedService::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3PostedService::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3PostedService::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PostedService::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3PostedService::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3PostedService::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedService::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3PostedService::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3PostedService::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PostedService::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3PostedService::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3PostedService::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedService::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - - /* Specific Service Data */ -bool p3PostedService::getGroup(const uint32_t &token, RsPostedGroup &group) -{ - std::cerr << "p3PostedService::getGroup() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PostedService::getGroup() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3PostedService::getGroup() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getGroup() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPostedGroup */ - bool ans = mPostedProxy->getGroup(id, group); - return ans; -} - - -bool p3PostedService::getPost(const uint32_t &token, RsPostedPost &post) -{ - std::cerr << "p3PostedService::getPost() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PostedService::getPost() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedService::getPost() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getPost() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPhotoAlbum */ - bool ans = mPostedProxy->getPost(id, post); - return ans; -} - - -bool p3PostedService::getComment(const uint32_t &token, RsPostedComment &comment) -{ - std::cerr << "p3PostedService::getComment() Token: " << token; - std::cerr << std::endl; - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3PostedService::getComment() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3PostedService::getComment() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3PostedService::getComment() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsPhotoAlbum */ - bool ans = mPostedProxy->getComment(id, comment); - return ans; -} - - - - - - /* Poll */ -/*** - * THE STANDARD ONE IS REPLACED - SO WE CAN HANDLE RANKING REQUESTS - * Its defined lower - next to the ranking code. - ***/ - -#if 0 -uint32_t p3PostedService::requestStatus(const uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - - checkRequestStatus(token, status, reqtype, anstype, ts); - - return status; -} - -#endif - - - /* Cancel Request */ -bool p3PostedService::cancelRequest(const uint32_t &token) -{ - return clearRequest(token); -} - - ////////////////////////////////////////////////////////////////////////////// - - - -bool p3PostedService::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) -{ - return mPostedProxy->setMessageStatus(msgId, status, statusMask); -} - -bool p3PostedService::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mPostedProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3PostedService::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mPostedProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3PostedService::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mPostedProxy->setMessageServiceString(msgId, str); -} - -bool p3PostedService::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mPostedProxy->setGroupServiceString(grpId, str); -} - - -bool p3PostedService::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3PostedService::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - -bool p3PostedService::submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew) -{ - /* check if its a modification or a new album */ - - /* add to database */ - - /* check if its a mod or new photo */ - if (group.mMeta.mGroupId.empty()) - { - /* new photo */ - - /* generate a temp id */ - group.mMeta.mGroupId = genRandomId(); - group.mMeta.mPublishTs = time(NULL); - - std::cerr << "p3PostedService::submitGroup() Generated New GroupID: " << group.mMeta.mGroupId; - std::cerr << std::endl; - } - - //group.mModFlags = 0; // These are always cleared. - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addGroup(group); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3PostedService::submitGroup() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - - -bool p3PostedService::submitPost(uint32_t &token, RsPostedPost &post, bool isNew) -{ - if (post.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PostedService::submitPost() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - post.mMeta.mMsgId = genRandomId(); - post.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - post.mMeta.mOrigMsgId = post.mMeta.mMsgId; - std::cerr << "p3PostedService::submitPost() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedService::submitPost() Updated Msg"; - std::cerr << std::endl; - } - - //post.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PostedService::submitPost() OrigMsgId: " << post.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << post.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addPost(post); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(post.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PostedService::submitPost() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -bool p3PostedService::submitVote(uint32_t &token, RsPostedVote &vote, bool isNew) -{ - if (vote.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PostedService::submitVote() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - vote.mMeta.mMsgId = genRandomId(); - vote.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - vote.mMeta.mOrigMsgId = vote.mMeta.mMsgId; - std::cerr << "p3PostedService::submitVote() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedService::submitVote() Updated Msg"; - std::cerr << std::endl; - } - - //vote.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PostedService::submitVote() OrigMsgId: " << vote.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << vote.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addVote(vote); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(vote.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PostedService::submitVote() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - - return true; -} - - -bool p3PostedService::submitComment(uint32_t &token, RsPostedComment &comment, bool isNew) -{ - if (comment.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3PostedService::submitPost() Missing GroupID: ERROR"; - std::cerr << std::endl; - return false; - } - - /* generate a new id */ - comment.mMeta.mMsgId = genRandomId(); - comment.mMeta.mPublishTs = time(NULL); - - if (isNew) - { - /* new (Original Msg) photo */ - comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; - std::cerr << "p3PostedService::submitComment() New Msg"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedService::submitComment() Updated Msg"; - std::cerr << std::endl; - } - - //comment.mModFlags = 0; // These are always cleared. - - std::cerr << "p3PostedService::submitComment() OrigMsgId: " << comment.mMeta.mOrigMsgId; - std::cerr << " MsgId: " << comment.mMeta.mMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mPostedProxy->addComment(comment); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(comment.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3PostedService::submitComment() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - -bool PostedDataProxy::getGroup(const std::string &id, RsPostedGroup &group) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsPostedGroup *pG = (RsPostedGroup *) groupData; - group = *pG; - - group.mMeta = meta; - - std::cerr << "PostedDataProxy::getGroup() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; - return true; - } - - std::cerr << "PostedDataProxy::getGroup() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - -bool PostedDataProxy::getPost(const std::string &id, RsPostedPost &post) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPostedMsg *pM = (RsPostedMsg *) msgData; - - if (pM->postedType == RSPOSTED_MSGTYPE_POST) - { - RsPostedPost *pP = (RsPostedPost *) pM; - post = *pP; - - // update definitive version of the metadata. - post.mMeta = meta; - - std::cerr << "PostedDataProxy::getPost() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - else - { - std::cerr << "PostedDataProxy::getPost() ERROR NOT POST Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return false; - } - } - - std::cerr << "PostedDataProxy::getPost() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - - -bool PostedDataProxy::getVote(const std::string &id, RsPostedVote &vote) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPostedMsg *pM = (RsPostedMsg *) msgData; - - if (pM->postedType == RSPOSTED_MSGTYPE_VOTE) - { - RsPostedVote *pP = (RsPostedVote *) pM; - vote = *pP; - - // update definitive version of the metadata. - vote.mMeta = meta; - - std::cerr << "PostedDataProxy::getVote() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - else - { - std::cerr << "PostedDataProxy::getVote() ERROR NOT VOTE Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return false; - } - } - - std::cerr << "PostedDataProxy::getVote() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - - -bool PostedDataProxy::getComment(const std::string &id, RsPostedComment &comment) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsPostedMsg *pM = (RsPostedMsg *) msgData; - - if (pM->postedType == RSPOSTED_MSGTYPE_COMMENT) - { - RsPostedComment *pP = (RsPostedComment *) pM; - comment = *pP; - - // update definitive version of the metadata. - comment.mMeta = meta; - - std::cerr << "PostedDataProxy::getComment() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - else - { - std::cerr << "PostedDataProxy::getComment() ERROR NOT POST Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return false; - } - } - - std::cerr << "PostedDataProxy::getComment() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - - - - -bool PostedDataProxy::addGroup(const RsPostedGroup &group) -{ - // Make duplicate. - RsPostedGroup *pG = new RsPostedGroup(); - *pG = group; - - std::cerr << "PostedDataProxy::addGroup()"; - std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; - std::cerr << std::endl; - - return createGroup(pG); -} - - -bool PostedDataProxy::addPost(const RsPostedPost &post) -{ - // Make duplicate. - RsPostedPost *pP = new RsPostedPost(); - *pP = post; - - std::cerr << "PostedDataProxy::addPost()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - -bool PostedDataProxy::addVote(const RsPostedVote &vote) -{ - // Make duplicate. - RsPostedVote *pP = new RsPostedVote(); - *pP = vote; - - std::cerr << "PostedDataProxy::addVote()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - -bool PostedDataProxy::addComment(const RsPostedComment &comment) -{ - // Make duplicate. - RsPostedComment *pP = new RsPostedComment(); - *pP = comment; - - std::cerr << "PostedDataProxy::addComment()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - - /* These Functions must be overloaded to complete the service */ -bool PostedDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsPostedGroup *group = (RsPostedGroup *) groupData; - meta = group->mMeta; - - return true; -} - -bool PostedDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsPostedMsg *msg = (RsPostedMsg *) msgData; - meta = msg->mMeta; - - return true; -} - - -/********************************************************************************************/ - -std::string p3PostedService::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - - -/********************************************************************************************/ - -std::ostream &operator<<(std::ostream &out, const RsPostedPost &post) -{ - out << "RsPostedPost [ "; - out << "Title: " << post.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote) -{ - out << "RsPostedVote [ "; - out << "Title: " << vote.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment) -{ - out << "RsPostedComment [ "; - out << "Title: " << comment.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group) -{ - out << "RsPostedGroup [ "; - out << "Title: " << group.mMeta.mGroupName; - out << "]"; - return out; -} - - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3PostedService::generateDummyData() -{ -#define MAX_GROUPS 10 //100 -#define MAX_POSTS 100 //1000 -#define MAX_COMMENTS 5000 //10000 -#define MAX_VOTES 10000 //10000 - - std::list mGroups; - std::list::iterator git; - - std::list mPosts; - std::list::iterator pit; - - std::list mVotes; - std::list::iterator vit; - - std::list mComments; - std::list::iterator cit; - -#define DUMMY_NAME_MAX_LEN 10000 - char name[DUMMY_NAME_MAX_LEN]; - int i, j; - time_t now = time(NULL); - - for(i = 0; i < MAX_GROUPS; i++) - { - /* generate a new forum */ - RsPostedGroup group; - - snprintf(name, DUMMY_NAME_MAX_LEN, "TestTopic_%d", i+1); - - group.mMeta.mGroupId = genRandomId(); - group.mMeta.mGroupName = name; - - group.mMeta.mPublishTs = now - (RSRandom::random_f32() * 100000); - /* key fields to fill in: - * GroupId. - * Name. - * Flags. - * Pop. - */ - - - - /* use probability to decide which are subscribed / own / popularity. - */ - - float rnd = RSRandom::random_f32(); - if (rnd < 0.1) - { - group.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_ADMIN | RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - - } - else if (rnd < 0.3) - { - group.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - } - else - { - group.mMeta.mSubscribeFlags = 0; - } - - group.mMeta.mPop = (int) (RSRandom::random_f32() * 10.0); - mGroups.push_back(group); - - } - - for(i = 0; i < MAX_POSTS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedGroup head = mGroups.front(); - mGroups.pop_front(); - mGroups.push_back(head); - } - - RsPostedGroup group = mGroups.front(); - - /* now create a new thread */ - - RsPostedPost post; - - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Post_%d", group.mMeta.mGroupName.c_str(), i+1); - post.mMeta.mMsgName = name; - - post.mMeta.mGroupId = group.mMeta.mGroupId; - post.mMeta.mMsgId = genRandomId(); - post.mMeta.mOrigMsgId = post.mMeta.mMsgId; - post.mMeta.mThreadId = post.mMeta.mMsgId; - post.mMeta.mParentId = ""; - - post.mMeta.mPublishTs = group.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (post.mMeta.mPublishTs > now) - post.mMeta.mPublishTs = now - 1; - - mPosts.push_back(post); - - } - - for(i = 0; i < MAX_COMMENTS; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedPost head = mPosts.front(); - mPosts.pop_front(); - mPosts.push_back(head); - } - - RsPostedPost parent = mPosts.front(); - - /* now create a new child msg */ - - RsPostedComment comment; - - /* fill in key data - * GroupId - * MsgId - * OrigMsgId - * ThreadId - * ParentId - * PublishTS (take Forum TS + a bit ). - * - * ChildTS ???? - */ - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Comment_%d", parent.mMeta.mMsgName.c_str(), i+1); - comment.mMeta.mMsgName = name; - //comment.mMsg = name; - - comment.mMeta.mGroupId = parent.mMeta.mGroupId; - comment.mMeta.mMsgId = genRandomId(); - comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; - comment.mMeta.mThreadId = parent.mMeta.mThreadId; - comment.mMeta.mParentId = parent.mMeta.mOrigMsgId; - - comment.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (comment.mMeta.mPublishTs > now) - comment.mMeta.mPublishTs = now - 1; - - mComments.push_back(comment); - } - - - for(i = 0; i < MAX_VOTES; i++) - { - /* generate a base thread */ - - /* rotate the Forum Groups Around, then pick one. - */ - - int rnd = (int) (RSRandom::random_f32() * 10.0); - - for(j = 0; j < rnd; j++) - { - RsPostedPost head = mPosts.front(); - mPosts.pop_front(); - mPosts.push_back(head); - } - - RsPostedPost parent = mPosts.front(); - - /* now create a new child msg */ - - RsPostedVote vote; - - snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Vote_%d", parent.mMeta.mMsgName.c_str(), i+1); - vote.mMeta.mMsgName = name; - //vote.mMsg = name; - - vote.mMeta.mGroupId = parent.mMeta.mGroupId; - vote.mMeta.mMsgId = genRandomId(); - vote.mMeta.mOrigMsgId = vote.mMeta.mMsgId; - vote.mMeta.mThreadId = parent.mMeta.mThreadId; - vote.mMeta.mParentId = parent.mMeta.mOrigMsgId; - - vote.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); - if (vote.mMeta.mPublishTs > now) - vote.mMeta.mPublishTs = now - 1; - - mVotes.push_back(vote); - } - - - mUpdated = true; - - /* Then - at the end, we push them all into the Proxy */ - for(git = mGroups.begin(); git != mGroups.end(); git++) - { - /* pushback */ - mPostedProxy->addGroup(*git); - - } - - for(pit = mPosts.begin(); pit != mPosts.end(); pit++) - { - /* pushback */ - mPostedProxy->addPost(*pit); - } - - for(cit = mComments.begin(); cit != mComments.end(); cit++) - { - /* pushback */ -#define COMMENT_FRAC_FOR_LATER (0.70) - if (RSRandom::random_f32() > COMMENT_FRAC_FOR_LATER) - { - mPostedProxy->addComment(*cit); - } - else - { - mDummyLaterComments.push_back(*cit); - } - } - - - for(vit = mVotes.begin(); vit != mVotes.end(); vit++) - { - /* pushback */ - -#define VOTE_FRAC_FOR_LATER (0.70) - if (RSRandom::random_f32() > VOTE_FRAC_FOR_LATER) - { - mPostedProxy->addVote(*vit); - } - else - { - mDummyLaterVotes.push_back(*vit); - } - } - - return true; -} - -#define EXTRA_COMMENT_ADD (20) -#define EXTRA_VOTE_ADD (50) - -bool p3PostedService::addExtraDummyData() -{ - std::cerr << "p3PostedService::addExtraDummyData()"; - std::cerr << std::endl; - - int i = 0; - - std::list::iterator vit; - std::list::iterator cit; - - for(cit = mDummyLaterComments.begin(); (cit != mDummyLaterComments.end()) && (i < EXTRA_COMMENT_ADD); i++) - { - mPostedProxy->addComment(*cit); - cit = mDummyLaterComments.erase(cit); - } - - i = 0; - for(vit = mDummyLaterVotes.begin(); (vit != mDummyLaterVotes.end()) && (i < EXTRA_VOTE_ADD); i++) - { - mPostedProxy->addVote(*vit); - vit = mDummyLaterVotes.erase(vit); - } - - return true; -} - - - - -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ - - -/* This is the part that will be kept for the final Version. - * we provide a processed view of the data... - * - * start off crude -> then make it efficient. - */ - - -bool p3PostedService::setViewMode(uint32_t mode) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mViewMode = mode; - - return true; -} - -bool p3PostedService::setViewPeriod(uint32_t period) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mViewPeriod = period; - - return true; -} - -bool p3PostedService::setViewRange(uint32_t first, uint32_t count) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mViewStart = first; - mViewCount = count; - - return true; -} - -float p3PostedService::calcPostScore(const RsMsgMetaData &meta) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - float score = 0; - uint32_t votes = 0; - uint32_t comments = 0; - time_t now = time(NULL); - time_t age_secs = now - meta.mPublishTs; - // This is a potential problem for gaming the system... post into the future. - // Should fix this by discarding/hiding until ts valid XXX. - if (age_secs < 0) - { - age_secs = 0; - } - - if (!extractPostedCache(meta.mServiceString, votes, comments)) - { - /* no votes/comments yet */ - } - - /* this is dependent on View Mode */ - switch(mViewMode) - { - default: - case RSPOSTED_VIEWMODE_LATEST: - { - score = -age_secs; // - - break; - } - case RSPOSTED_VIEWMODE_TOP: - { - score = votes; - break; - } -// Potentially only -// This is effectively HackerNews Algorithm: which is (p-1)/(t+2)^1.5, where p is votes and t is age in hours. - case RSPOSTED_VIEWMODE_HOT: - { -#define POSTED_AGESHIFT (2.0) -#define POSTED_AGEFACTOR (3600.0) - score = votes / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - break; - } -// Like HOT, but using number of Comments. - case RSPOSTED_VIEWMODE_COMMENTS: - { - score = comments / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - break; - } - } - - return score; -} - -static uint32_t convertPeriodFlagToSeconds(uint32_t periodMode) -{ - float secs = 1; - switch(periodMode) - { - // Fallthrough all of them. - case RSPOSTED_PERIOD_YEAR: - secs *= 12; - case RSPOSTED_PERIOD_MONTH: - secs *= 4.3; // average ~30.4 days = 4.3 weeks. - case RSPOSTED_PERIOD_WEEK: - secs *= 7; - case RSPOSTED_PERIOD_DAY: - secs *= 24; - case RSPOSTED_PERIOD_HOUR: - secs *= 3600; - } - - return (uint32_t) secs; -} - -#define POSTED_RANKINGS_INITIAL_CHECK 1 -#define POSTED_RANKINGS_DATA_REQUEST 2 -#define POSTED_RANKINGS_DATA_DONE 3 - - /* Poll */ -uint32_t p3PostedService::requestStatus(const uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - - uint32_t int_token = token; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if ((mProcessingRanking) && (token == mRankingExternalToken)) - { - { - switch(mRankingState) - { - case POSTED_RANKINGS_INITIAL_CHECK: - status = GXS_REQUEST_STATUS_PENDING; - return status; - break; - case POSTED_RANKINGS_DATA_REQUEST: - // Switch to real token. - int_token = mRankingInternalToken; - break; - } - } - } - } - - checkRequestStatus(int_token, status, reqtype, anstype, ts); - - return status; -} - -bool p3PostedService::getRankedPost(const uint32_t &token, RsPostedPost &post) -{ - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mProcessingRanking) - { - - return false; - } - - if (token != mRankingExternalToken) - { - - - return false; - } - - if (mRankingState != POSTED_RANKINGS_DATA_REQUEST) - { - - return false; - - } - - - if (!getPost(mRankingInternalToken, post)) - { - /* clean up */ - mProcessingRanking = false; - mRankingExternalToken = 0; - mRankingInternalToken = 0; - mRankingState = POSTED_RANKINGS_DATA_DONE; - - return false; - } - - return true; -} - - -bool p3PostedService::requestRanking(uint32_t &token, std::string groupId) -{ - std::cerr << "p3PostedService::requestRanking()"; - std::cerr << std::endl; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (mProcessingRanking) - { - std::cerr << "p3PostedService::requestRanking() ERROR Request already running - ignoring"; - std::cerr << std::endl; - - return false; - } - } - - generateToken(token); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mProcessingRanking = true; - mRankingState = POSTED_RANKINGS_INITIAL_CHECK; - mRankingExternalToken = token; - } - - /* now we request all the posts within the timeframe */ - - uint32_t posttoken; - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; - //uint32_t age = convertPeriodFlagToSeconds(mViewPeriod); - - std::list groupIds; - groupIds.push_back(groupId); - - requestMsgInfo(posttoken, ansType, opts, groupIds); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mRankingInternalToken = posttoken; - } - return true; -} - -bool p3PostedService::checkRankingRequest() -{ - uint32_t token = 0; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mProcessingRanking) - { - return false; - } - - if (mRankingState != POSTED_RANKINGS_INITIAL_CHECK) - { - return false; - } - - /* here it actually running! */ - token = mRankingInternalToken; - } - - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (status == GXS_REQUEST_STATUS_COMPLETE) - { - processPosts(); - } - return true; -} - - -bool p3PostedService::processPosts() -{ - std::cerr << "p3PostedService::processPosts()"; - std::cerr << std::endl; - - uint32_t token = 0; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mProcessingRanking) - { - std::cerr << "p3PostedService::processPosts() ERROR Ranking Request not running"; - std::cerr << std::endl; - - return false; - } - - if (mRankingState != POSTED_RANKINGS_INITIAL_CHECK) - { - std::cerr << "p3PostedService::processPosts() ERROR Ranking Request not running"; - std::cerr << std::endl; - - return false; - } - token = mRankingInternalToken; - } - - /* extract the info -> and sort */ - std::list postList; - std::list::const_iterator it; - - if (!getMsgSummary(token, postList)) - { - std::cerr << "p3PostedService::processPosts() ERROR getting postList"; - std::cerr << std::endl; - return false; - } - - std::multimap postMap; - std::multimap::reverse_iterator mit; - - for(it = postList.begin(); it != postList.end(); it++) - { - float score = calcPostScore(*it); - postMap.insert(std::make_pair(score, it->mMsgId)); - } - - /* now grab the N required, and request the data again... - * -> this is what will be passed back to GUI - */ - - std::list msgList; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - unsigned int i = 0; - for(mit = postMap.rbegin(); (mit != postMap.rend()) && (i < mViewStart); mit++, i++) - { - std::cerr << "p3PostedService::processPosts() Skipping PostId: " << mit->second; - std::cerr << " with score: " << mit->first; - std::cerr << std::endl; - } - - - for(i = 0; (mit != postMap.rend()) && (i < mViewCount); mit++, i++) - { - std::cerr << "p3PostedService::processPosts() Adding PostId: " << mit->second; - std::cerr << " with score: " << mit->first; - std::cerr << std::endl; - msgList.push_back(mit->second); - } - } - - token = 0; - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - - requestMsgRelatedInfo(token, ansType, opts, msgList); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mRankingState = POSTED_RANKINGS_DATA_REQUEST; - mRankingInternalToken = token; - } - return true; -} - - - -/***** Background Processing **** - * - * Process Each Message - as it arrives. - * - * Update - * - */ - -#define POSTED_BG_REQUEST_GROUPS 1 -#define POSTED_BG_REQUEST_UNPROCESSED 2 -#define POSTED_BG_REQUEST_PARENTS 3 -#define POSTED_BG_PROCESS_VOTES 4 - -bool p3PostedService::background_checkTokenRequest() -{ - uint32_t token = 0; - uint32_t phase = 0; - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - if (!mBgProcessing) - { - return false; - } - - token = mBgToken; - phase = mBgPhase; - } - - - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (status == GXS_REQUEST_STATUS_COMPLETE) - { - switch(phase) - { - case POSTED_BG_REQUEST_GROUPS: - background_requestNewMessages(); - break; - case POSTED_BG_REQUEST_UNPROCESSED: - background_processNewMessages(); - break; - case POSTED_BG_REQUEST_PARENTS: - background_updateVoteCounts(); - break; - default: - break; - } - } - return true; -} - - -bool p3PostedService::background_requestGroups() -{ - std::cerr << "p3PostedService::background_requestGroups()"; - std::cerr << std::endl; - - // grab all the subscribed groups. - uint32_t token = 0; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - mBgProcessing = true; - mBgPhase = POSTED_BG_REQUEST_GROUPS; - mBgToken = 0; - } - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - std::list groupIds; - - opts.mSubscribeFilter = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - - requestGroupInfo(token, ansType, opts, groupIds); - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgToken = token; - } - - return true; -} - - -bool p3PostedService::background_requestNewMessages() -{ - std::cerr << "p3PostedService::background_requestNewMessages()"; - std::cerr << std::endl; - - std::list groupIds; - uint32_t token = 0; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - token = mBgToken; - } - - if (!getGroupList(token, groupIds)) - { - std::cerr << "p3PostedService::background_requestNewMessages() ERROR No Group List"; - std::cerr << std::endl; - background_cleanup(); - return false; - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgPhase = POSTED_BG_REQUEST_UNPROCESSED; - mBgToken = 0; - } - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - token = 0; - - opts.mStatusFilter = RSGXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = RSGXS_MSG_STATUS_UNPROCESSED; - - requestMsgInfo(token, ansType, opts, groupIds); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgToken = token; - } - return true; -} - - -bool p3PostedService::background_processNewMessages() -{ - std::cerr << "p3PostedService::background_processNewMessages()"; - std::cerr << std::endl; - - std::list newMsgList; - std::list::iterator it; - uint32_t token = 0; - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - token = mBgToken; - } - - if (!getMsgSummary(token, newMsgList)) - { - std::cerr << "p3PostedService::background_processNewMessages() ERROR No New Msgs"; - std::cerr << std::endl; - background_cleanup(); - return false; - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgPhase = POSTED_BG_REQUEST_PARENTS; - mBgToken = 0; - mBgVoteMap.clear(); - mBgCommentMap.clear(); - } - - /* loop through and sort by parents. - * - grab - */ - - std::list parentList; - - std::map::iterator vit; - - for(it = newMsgList.begin(); it != newMsgList.end(); it++) - { - std::cerr << "Found New MsgId: " << it->mMsgId; - std::cerr << std::endl; - - /* discard threadheads */ - if (it->mParentId.empty()) - { - std::cerr << "\tIgnoring ThreadHead: " << *it; - std::cerr << std::endl; - } - else if (it->mMsgFlags & RSPOSTED_MSGTYPE_COMMENT) - { - /* Comments are counted by Thread Id */ - std::cerr << "\tProcessing Comment: " << *it; - std::cerr << std::endl; - - vit = mBgCommentMap.find(it->mThreadId); - if (vit == mBgCommentMap.end()) - { - mBgCommentMap[it->mThreadId] = 1; - - /* check VoteMap too before adding to parentList */ - if (mBgVoteMap.end() == mBgVoteMap.find(it->mThreadId)) - { - parentList.push_back(it->mThreadId); - } - - std::cerr << "\tThreadId: " << it->mThreadId; - std::cerr << " Comment Total: " << mBgCommentMap[it->mThreadId]; - std::cerr << std::endl; - } - else - { - mBgVoteMap[it->mThreadId]++; - std::cerr << "\tThreadId: " << it->mThreadId; - std::cerr << " Comment Total: " << mBgCommentMap[it->mThreadId]; - std::cerr << std::endl; - } - } - else if (it->mMsgFlags & RSPOSTED_MSGTYPE_VOTE) - { - /* Votes are organised by Parent Id, - * ie. you can vote for both Posts and Comments - */ - std::cerr << "\tProcessing Vote: " << *it; - std::cerr << std::endl; - - vit = mBgVoteMap.find(it->mParentId); - if (vit == mBgVoteMap.end()) - { - mBgVoteMap[it->mParentId] = 1; - - /* check CommentMap too before adding to parentList */ - if (mBgCommentMap.end() == mBgCommentMap.find(it->mParentId)) - { - parentList.push_back(it->mParentId); - } - - std::cerr << "\tParentId: " << it->mParentId; - std::cerr << " Vote Total: " << mBgVoteMap[it->mParentId]; - std::cerr << std::endl; - } - else - { - mBgVoteMap[it->mParentId]++; - std::cerr << "\tParentId: " << it->mParentId; - std::cerr << " Vote Total: " << mBgVoteMap[it->mParentId]; - std::cerr << std::endl; - } - } - else - { - /* unknown! */ - std::cerr << "p3PostedService::background_processNewMessages() ERROR Strange NEW Message:"; - std::cerr << std::endl; - std::cerr << "\t" << *it; - std::cerr << std::endl; - - } - - /* flag each new vote as processed */ - setMessageStatus(it->mMsgId, 0, RSGXS_MSG_STATUS_UNPROCESSED); - } - - - /* request the summary info from the parents */ - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - token = 0; - RsTokReqOptions opts; - requestMsgRelatedInfo(token, ansType, opts, parentList); - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgToken = token; - } - return true; -} - - -bool p3PostedService::encodePostedCache(std::string &str, uint32_t votes, uint32_t comments) -{ - char line[RSGXS_MAX_SERVICE_STRING]; - - snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d", votes, comments); - - str = line; - return true; -} - -bool p3PostedService::extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments) -{ - - uint32_t ivotes, icomments; - if (2 == sscanf(str.c_str(), "%d %d", &ivotes, &icomments)) - { - votes = ivotes; - comments = icomments; - return true; - } - - return false; -} - - -bool p3PostedService::background_updateVoteCounts() -{ - std::cerr << "p3PostedService::background_updateVoteCounts()"; - std::cerr << std::endl; - - std::list parentMsgList; - std::list::iterator it; - - if (!getMsgSummary(mBgToken, parentMsgList)) - { - std::cerr << "p3PostedService::background_updateVoteCounts() ERROR"; - std::cerr << std::endl; - background_cleanup(); - return false; - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - mBgPhase = POSTED_BG_PROCESS_VOTES; - mBgToken = 0; - } - - for(it = parentMsgList.begin(); it != parentMsgList.end(); it++) - { - /* extract current vote count */ - uint32_t votes = 0; - uint32_t comments = 0; - - if (!extractPostedCache(it->mServiceString, votes, comments)) - { - if (!(it->mServiceString.empty())) - { - std::cerr << "p3PostedService::background_updateVoteCounts() Failed to extract Votes"; - std::cerr << std::endl; - std::cerr << "\tFrom String: " << it->mServiceString; - std::cerr << std::endl; - } - } - - /* find increment in votemap */ - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator vit; - vit = mBgVoteMap.find(it->mMsgId); - if (vit != mBgVoteMap.end()) - { - votes += vit->second; - } - else - { - // warning. - std::cerr << "p3PostedService::background_updateVoteCounts() Warning No New Votes found."; - std::cerr << " For MsgId: " << it->mMsgId; - std::cerr << std::endl; - } - - } - - { - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator cit; - cit = mBgCommentMap.find(it->mMsgId); - if (cit != mBgCommentMap.end()) - { - comments += cit->second; - } - else - { - // warning. - std::cerr << "p3PostedService::background_updateVoteCounts() Warning No New Comments found."; - std::cerr << " For MsgId: " << it->mMsgId; - std::cerr << std::endl; - } - - } - - std::string str; - if (!encodePostedCache(str, votes, comments)) - { - std::cerr << "p3PostedService::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { - std::cerr << "p3PostedService::background_updateVoteCounts() Encoded String: " << str; - std::cerr << std::endl; - /* store new result */ - setMessageServiceString(it->mMsgId, str); - } - } - - // DONE!. - background_cleanup(); - return true; - -} - - -bool p3PostedService::background_cleanup() -{ - std::cerr << "p3PostedService::background_cleanup()"; - std::cerr << std::endl; - - RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ - - // Cleanup. - mBgVoteMap.clear(); - mBgCommentMap.clear(); - mBgProcessing = false; - mBgToken = 0; - - return true; -} - - + +#include +#include +#include +#include + +#include "p3posted.h" +#include "gxs/rsgxsflags.h" +#include "serialiser/rsposteditems.h" + +#define UPDATE_PHASE_GRP_REQUEST 1 +#define UPDATE_PHASE_MSG_REQUEST 2 +#define UPDATE_PHASE_VOTE_COMMENT_REQUEST 3 +#define UPDATE_PHASE_VOTE_COUNT 4 +#define UPDATE_PHASE_COMMENT_COUNT 5 +#define UPDATE_PHASE_COMPLETE 6 + +#define NUM_TOPICS_TO_GENERATE 5 +#define NUM_POSTS_TO_GENERATE 7 +#define NUM_VOTES_TO_GENERATE 11 +#define NUM_COMMENTS_TO_GENERATE 3 + +#define VOTE_UPDATE_PERIOD 5 // 20 seconds +#define HOT_PERIOD 4 // 4 secs for testing prob 1 to 2 days in practice + +const uint32_t RsPosted::FLAG_MSGTYPE_COMMENT = 0x0001; +const uint32_t RsPosted::FLAG_MSGTYPE_POST = 0x0002; +const uint32_t RsPosted::FLAG_MSGTYPE_VOTE = 0x0004; +const uint32_t RsPosted::FLAG_MSGTYPE_MASK = 0x000f; + +#define POSTED_MAX_SERVICE_STRING 50 + +RsPosted *rsPosted = NULL; + +RsPostedComment::RsPostedComment(const RsGxsPostedCommentItem & item) +{ + mComment = item.mComment.mComment; + mMeta = item.meta; +} + +RsPostedVote::RsPostedVote(const RsGxsPostedVoteItem& item) +{ + mDirection = item.mVote.mDirection; + mMeta = item.meta; +} + +p3Posted::p3Posted(RsGeneralDataService *gds, RsNetworkExchangeService *nes) + : RsGenExchange(gds, nes, new RsGxsPostedSerialiser(), RS_SERVICE_GXSV1_TYPE_POSTED), RsPosted(this), mPostedMutex("Posted"), + mTokenService(NULL), mGeneratingTopics(true), mGeneratingPosts(false), mRequestPhase1(true), mRequestPhase2(false), + mRequestPhase3(false), mGenerateVotesAndComments(false) +{ + mPostUpdate = false; + mLastUpdate = time(NULL); + mUpdatePhase = UPDATE_PHASE_GRP_REQUEST; + + mTokenService = RsGenExchange::getTokenService(); +} + +void p3Posted::notifyChanges(std::vector &changes) +{ + receiveChanges(changes); +} + +void p3Posted::service_tick() +{ + + generateTopics(); + generatePosts(); + generateVotesAndComments(); + + time_t now = time(NULL); + + if((now > (time_t) (VOTE_UPDATE_PERIOD + mLastUpdate)) && + (mUpdatePhase == UPDATE_PHASE_GRP_REQUEST)) + { + mPostUpdate = true; + mLastUpdate = time(NULL); + } + + updateVotes(); + + processRankings(); +} + +void p3Posted::generateVotesAndComments() +{ + if(mGenerateVotesAndComments) + { + + if(mRequestPhase1) + { + // request topics then chose at random which one to use to generate a post about + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_POST; + opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; + + mTokenService->requestMsgInfo(mToken, 0, opts, mGrpIds); + mRequestPhase1 = false; + mRequestPhase2 = true; + return; + } + + if(mRequestPhase2) + { + + if(mTokenService->requestStatus(mToken) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + GxsMsgIdResult msgIds; + RsGenExchange::getMsgList(mToken, msgIds); + + // for each msg generate a random number of votes and comments + + + GxsMsgIdResult::iterator mit = msgIds.begin(); + + for(; mit != msgIds.end(); mit++) + { + const RsGxsGroupId& grpId = mit->first; + std::vector& msgIdsV = mit->second; + std::vector::iterator vit = msgIdsV.begin(); + + for(; vit != msgIdsV.end(); vit++) + { + const RsGxsMessageId& msgId = *vit; + + int nVotes = rand()%NUM_VOTES_TO_GENERATE; + uint32_t token; + + for(int i=1; i < nVotes; i++) + { + RsPostedVote v; + + v.mDirection = (rand()%10 > 3) ? 0 : 1; + v.mMeta.mParentId = msgId; + v.mMeta.mGroupId = grpId; + + std::ostringstream ostrm; + ostrm << i; + + v.mMeta.mMsgName = "Vote " + ostrm.str(); + + + + submitVote(token, v); + mTokens.push_back(token); + + } + + int nComments = rand()%NUM_COMMENTS_TO_GENERATE; + + // single level comments for now + for(int i=1; i < nComments; i++) + { + RsPostedComment c; + + std::ostringstream ostrm; + ostrm << i; + + c.mComment = "Comment " + ostrm.str(); + c.mMeta.mParentId = msgId; + c.mMeta.mGroupId = grpId; + c.mMeta.mThreadId = msgId; + + submitComment(token, c); + mTokens.push_back(token); + + } + + } + } + mRequestPhase2 = false; + mRequestPhase3 = true; + } + } + + if(mRequestPhase3) + { + if(!mTokens.empty()) + { + std::vector::iterator vit = mTokens.begin(); + + for(; vit != mTokens.end(); ) + { + if(mTokenService->requestStatus(*vit) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + vit = mTokens.erase(vit); + else + vit++; + } + }else + { + // stop generating posts after acknowledging all the ones you created + mGeneratingPosts = false; + mRequestPhase3 = false; + } + } + + } +} + +void p3Posted::generatePosts() +{ + if(mGeneratingPosts) + { + + + if(mRequestPhase1) + { + // request topics then chose at random which one to use to generate a post about + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + mTokenService->requestGroupInfo(mToken, 0, opts); + mRequestPhase1 = false; + return; + } + else if(!mRequestPhase2) + { + if(mTokenService->requestStatus(mToken) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + RsGenExchange::getGroupList(mToken, mGrpIds); + + mRequestPhase2 = true; + } + } + + if(mRequestPhase2) + { + // for each group generate NUM_POSTS_TO_GENERATE posts + std::list::iterator lit = mGrpIds.begin(); + + for(; lit != mGrpIds.end(); lit++) + { + RsGxsGroupId& grpId = *lit; + + for(int i=0; i < NUM_POSTS_TO_GENERATE; i++) + { + std::ostringstream ostrm; + ostrm << i; + std::string link = "link " + ostrm.str(); + + RsPostedPost post; + post.mLink = link; + post.mNotes = link; + post.mMeta.mMsgName = link; + post.mMeta.mGroupId = grpId; + + uint32_t token; + submitPost(token, post); + mTokens.push_back(token); + } + } + + mRequestPhase2 = false; + mRequestPhase3 = true; + + } + else if(mRequestPhase3) + { + + if(!mTokens.empty()) + { + std::vector::iterator vit = mTokens.begin(); + + for(; vit != mTokens.end(); ) + { + if(mTokenService->requestStatus(*vit) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + vit = mTokens.erase(vit); + else + vit++; + } + }else + { + // stop generating posts after acknowledging all the ones you created + mGeneratingPosts = false; + mRequestPhase3 = false; + mGenerateVotesAndComments = true; + mRequestPhase1 = true; + } + + } + } +} + +void p3Posted::generateTopics() +{ + if(mGeneratingTopics) + { + if(mRequestPhase1) + { + + + for(int i=0; i < NUM_TOPICS_TO_GENERATE; i++) + { + std::ostringstream strm; + strm << i; + std::string topicName = "Topic " + strm.str(); + + RsPostedGroup topic; + topic.mMeta.mGroupName = topicName; + + uint32_t token; + submitGroup(token, topic); + mTokens.push_back(token); + } + + mRequestPhase1 = false; + } + else + { + + if(!mTokens.empty()) + { + std::vector::iterator vit = mTokens.begin(); + + for(; vit != mTokens.end(); ) + { + if(mTokenService->requestStatus(*vit) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + RsGxsGroupId grpId; + RsGenExchange::acknowledgeTokenGrp(*vit, grpId); + vit = mTokens.erase(vit); + } + else + vit++; + } + } + else + { + mGeneratingPosts = true; + mGeneratingTopics = false; + mRequestPhase1 = true; + } + } + } +} + +bool p3Posted::getGroup(const uint32_t &token, std::vector &groups) +{ + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsPostedGroupItem* item = dynamic_cast(*vit); + RsPostedGroup grp = item->mGroup; + item->mGroup.mMeta = item->meta; + grp.mMeta = item->mGroup.mMeta; + delete item; + groups.push_back(grp); + } + } + return ok; +} + +bool p3Posted::getPost(const uint32_t &token, PostedPostResult &posts) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsPostedPostItem* item = dynamic_cast(*vit); + + if(item) + { + RsPostedPost post = item->mPost; + post.mMeta = item->meta; + posts[grpId].push_back(post); + delete item; + }else + { + std::cerr << "Not a post Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + +bool p3Posted::getComment(const uint32_t &token, PostedCommentResult &comments) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsPostedCommentItem* item = dynamic_cast(*vit); + + if(item) + { + RsPostedComment comment = item->mComment; + comment.mMeta = item->meta; + comments[grpId].push_back(comment); + delete item; + }else + { + std::cerr << "Not a comment Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + +bool p3Posted::getRelatedComment(const uint32_t& token, PostedRelatedCommentResult &comments) +{ + return RsGenExchange::getMsgRelatedDataT(token, comments); +} + +bool p3Posted::submitGroup(uint32_t &token, RsPostedGroup &group) +{ + RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); + grpItem->mGroup = group; + grpItem->meta = group.mMeta; + RsGenExchange::publishGroup(token, grpItem); + return true; +} + +bool p3Posted::submitPost(uint32_t &token, RsPostedPost &post) +{ + RsGxsPostedPostItem* postItem = new RsGxsPostedPostItem(); + postItem->mPost = post; + postItem->meta = post.mMeta; + postItem->meta.mMsgFlags |= FLAG_MSGTYPE_POST; + + RsGenExchange::publishMsg(token, postItem); + return true; +} + +bool p3Posted::submitVote(uint32_t &token, RsPostedVote &vote) +{ + RsGxsPostedVoteItem* voteItem = new RsGxsPostedVoteItem(); + voteItem->mVote = vote; + voteItem->meta = vote.mMeta; + voteItem->meta.mMsgFlags |= FLAG_MSGTYPE_VOTE; + + RsGenExchange::publishMsg(token, voteItem); + return true; +} + +bool p3Posted::submitComment(uint32_t &token, RsPostedComment &comment) +{ + RsGxsPostedCommentItem* commentItem = new RsGxsPostedCommentItem(); + commentItem->mComment = comment; + commentItem->meta = comment.mMeta; + commentItem->meta.mMsgFlags |= FLAG_MSGTYPE_COMMENT; + + RsGenExchange::publishMsg(token, commentItem); + return true; +} + + // Special Ranking Request. +bool p3Posted::requestCommentRankings(uint32_t &token, const RankType &rType, const RsGxsGrpMsgIdPair &msgId) +{ + token = RsGenExchange::generatePublicToken(); + + RsStackMutex stack(mPostedMutex); + + GxsPostedCommentRanking* gpc = new GxsPostedCommentRanking(); + gpc->msgId = msgId; + gpc->rType = rType; + gpc->pubToken = token; + + mPendingCommentRanks.insert(std::make_pair(token, gpc)); + + return true; +} + +bool p3Posted::requestPostRankings(uint32_t &token, const RankType &rType, const RsGxsGroupId &groupId) +{ + token = RsGenExchange::generatePublicToken(); + + RsStackMutex stack(mPostedMutex); + GxsPostedPostRanking* gp = new GxsPostedPostRanking(); + gp->grpId = groupId; + gp->rType = rType; + gp->pubToken = token; + gp->rankingResult.rType = gp->rType; + gp->rankingResult.grpId = gp->grpId; + gp->grpId = gp->grpId; + + mPendingPostRanks.push_back(gp); + + return true; +} + +bool p3Posted::getPostRanking(const uint32_t &token, RsPostedPostRanking &ranking) +{ + RsStackMutex stack(mPostedMutex); + + if( mCompletePostRanks.find(token) == mCompletePostRanks.end()) return false; + + ranking = mCompletePostRanks[token]; + mCompletePostRanks.erase(token); + + // put this in service tick as it's blocking + // and likely costly + disposeOfPublicToken(token); + + return true; +} + +void p3Posted::processRankings() +{ + processPostRanks(); + + //processCommentRanks(); +} + +void p3Posted::processPostRanks() +{ + + RsStackMutex stack(mPostedMutex); + + std::vector::iterator vit = mPendingPostRanks.begin(); + + // go through all pending posts + for(; vit !=mPendingPostRanks.end(); ) + { + GxsPostedPostRanking* gp = *vit; + uint32_t token; + std::list grpL; + grpL.push_back(gp->grpId); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_META; + opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_POST; + opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; + + RsGenExchange::getTokenService()->requestMsgInfo(token, GXS_REQUEST_TYPE_GROUP_DATA, opts, grpL); + + + gp->reqToken = token; + + vit = mPendingPostRanks.erase(vit); + mCompletionPostRanks.push_back(gp); + } + + mPendingPostRanks.clear(); + + vit = mCompletionPostRanks.begin(); + + for(; vit != mCompletionPostRanks.end(); ) + { + bool ok = false; + GxsPostedPostRanking *gp = *vit; + uint32_t status = mTokenService->requestStatus(gp->reqToken); + + if(RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE + == status) + { + ok = completePostedPostCalc(gp); + + if(ok) + { + mCompletePostRanks.insert( + std::make_pair(gp->pubToken, gp->rankingResult)); + } + } + else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED + == status) + { + discardCalc(gp->reqToken); + ok = false; + }else + { + vit++; + continue; + } + + if(ok) + { + updatePublicRequestStatus(gp->pubToken, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); + } + else + { + updatePublicRequestStatus(gp->pubToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); + } + + vit = mCompletionPostRanks.erase(vit); + delete gp; + } + +} + +void p3Posted::discardCalc(const uint32_t &token) +{ + mTokenService->cancelRequest(token); +} + +bool PostedTopScoreComp(const PostedScore& i, const PostedScore& j) +{ + int32_t i_score = (int32_t)i.upVotes - (int32_t)i.downVotes; + int32_t j_score = (int32_t)j.upVotes - (int32_t)j.downVotes; + + if(i_score == j_score){ + return i.date > j.date; + }else + { + return i_score > j_score; + } +} + + +bool PostedHotScoreComp(const PostedScore& i, const PostedScore& j) +{ + int32_t i_score = (int32_t)i.upVotes - (int32_t)i.downVotes; + int32_t j_score = (int32_t)j.upVotes - (int32_t)j.downVotes; + + time_t now = time(NULL); + long long td = now - i.date; + + if(td == 0) + { + return i.date > j.date; + } + + int y; + if(i_score > 0) + { + y = 1; + }else if(i_score == 0) + { + y = 0; + }else + { + y = -1; + } + + double z; + if(abs(i_score) >= 1) + { + z = abs(i_score); + } + else + { + z = 1; + } + + double i_hot_score = log10(z) + ( ((double)(y*td)) + / HOT_PERIOD ); + + if(j_score > 0) + { + y = 1; + }else if(j_score == 0) + { + y = 0; + }else + { + y = -1; + } + + + if(abs(j_score) >= 1) + { + z = abs(j_score); + } + else + { + z = 1; + } + + td = now - j.date; + + double j_hot_score = log10(z) + ( ((double)(y*td)) + / HOT_PERIOD ); + if(i_hot_score == j_hot_score) + { + return i.date > j.date; + }else + { + return i_hot_score > j_hot_score; + } + +} + +bool PostedNewScoreComp(const PostedScore& i, const PostedScore& j) +{ + return i.date > j.date; +} + +bool PostedBestScoreComp(const PostedScore& i, const PostedScore& j) +{ + +// n = ups + downs if n == 0: return 0 z = 1.0 +// #1.0 = 85%, 1.6 = 95% phat = float(ups) +// / n return sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n) +// def confidence(ups, downs): if ups + downs == 0: return 0 else: +// return _confidence(ups, downs) + // very expensive!! + + static float z = 1.0; + float phat; + + float i_score; + int n = i.upVotes + (-i.downVotes); + if(n==0) + i_score = 0.; + else + { + phat = float(i.upVotes); + i_score = sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n); + } + + float j_score; + n = j.upVotes + (-j.downVotes); + if(n==0) + j_score = 0.; + else + { + phat = float(j.upVotes); + j_score = sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n); + } + + if(j_score == i_score) + return i.date < j.date; + else + return i_score < j_score; +} + +bool p3Posted::completePostedPostCalc(GxsPostedPostRanking *gpp) +{ + GxsMsgMetaMap msgMetas; + + if(getMsgMeta(gpp->reqToken, msgMetas)) + { + std::vector& msgMetaV = msgMetas[gpp->grpId]; + switch(gpp->rType) + { + case NewRankType: + calcPostedPostRank(msgMetaV, gpp->rankingResult.ranking, PostedNewScoreComp); + break; + case HotRankType: + calcPostedPostRank(msgMetaV, gpp->rankingResult.ranking, PostedHotScoreComp); + break; + case TopRankType: + calcPostedPostRank(msgMetaV, gpp->rankingResult.ranking, PostedTopScoreComp); + break; + default: + std::cerr << "Unknown ranking tpye: " << gpp->rType << std::endl; + } + return true; + }else + return false; +} + + +void p3Posted::calcPostedPostRank(const std::vector msgMeta, PostedRanking &ranking, + bool comp(const PostedScore &, const PostedScore &)) const +{ + + std::vector::const_iterator cit = msgMeta.begin(); + std::vector scores; + + for(; cit != msgMeta.end(); cit++) + { + const RsMsgMetaData& m = *cit; + uint32_t upVotes, downVotes, nComments; + retrieveScores(m.mServiceString, upVotes, downVotes, nComments); + + PostedScore c; + c.upVotes = upVotes; + c.downVotes = downVotes; + c.date = m.mPublishTs; + c.msgId = m.mMsgId; + scores.push_back(c); + } + + std::sort(scores.begin(), scores.end(), comp); + + + for(int i = 0; i < scores.size(); i++) + { + const PostedScore& p = scores[i]; + ranking.insert(std::make_pair(i+1, p.msgId)); + } +} + +void p3Posted::calcPostedCommentsRank(const std::map > &msgBranches, + std::map& msgMetas, PostedRanking &ranking, bool comp(const PostedScore &, const PostedScore &)) const +{ + + std::map >::const_iterator cit = msgBranches.begin(); + + for(; cit != msgBranches.end(); cit++) + { + const std::vector& branch = cit->second; + std::vector scores; + + std::vector::const_iterator vit = branch.begin(); + + for(; vit != branch.end(); vit++) + { + + std::map::iterator mit = + msgMetas.find(*vit); + + if(mit != msgMetas.end()) + { + uint32_t upVotes, downVotes, nComments; + + const RsMsgMetaData& m = mit->second; + retrieveScores(m.mServiceString, upVotes, downVotes, nComments); + + PostedScore c; + c.upVotes = upVotes; + c.downVotes = downVotes; + c.date = m.mPublishTs; + scores.push_back(c); + } + } + + std::sort(scores.begin(), scores.end(), comp); + + std::vector::iterator cvit = scores.begin(); + + int i = 1; + for(; cvit != scores.end(); cvit) + { + const PostedScore& p = *cvit; + ranking.insert(std::make_pair(i++, p.msgId)); + } + } + +} + +void p3Posted::completePostedCommentRanking(GxsPostedCommentRanking *gpc) +{ + GxsMsgRelatedMetaMap msgMetas; + + if(getMsgRelatedMeta(gpc->reqToken, msgMetas)) + { + + // create map of msgs + std::vector& msgV = msgMetas[gpc->msgId]; + std::map > msgBranches; + std::map remappedMsgMeta; + + std::vector::iterator vit = msgV.begin(); + + for(; vit != msgV.end(); vit++) + { + const RsMsgMetaData& m = *vit; + + if(!m.mParentId.empty()) + { + msgBranches[m.mParentId].push_back(m.mMsgId); + } + + remappedMsgMeta.insert(std::make_pair(m.mMsgId, m)); + } + + switch(gpc->rType) + { + case HotRankType: + calcPostedCommentsRank(msgBranches, remappedMsgMeta, gpc->result, PostedBestScoreComp); + break; + case TopRankType: + calcPostedCommentsRank(msgBranches, remappedMsgMeta, gpc->result, PostedTopScoreComp); + break; + case NewRankType: + calcPostedCommentsRank(msgBranches, remappedMsgMeta, gpc->result, PostedNewScoreComp); + break; + default: + std::cerr << "Unknown Rank type" << gpc->rType << std::endl; + break; + } + } +} + +bool p3Posted::retrieveScores(const std::string &serviceString, uint32_t &upVotes, uint32_t& downVotes, uint32_t& nComments) const +{ + if (3 == sscanf(serviceString.c_str(), "%d %d %d", &upVotes, &downVotes, &nComments)) + { + return true; + } + + return false; +} + +bool p3Posted::storeScores(std::string &serviceString, uint32_t &upVotes, uint32_t downVotes, uint32_t nComments) const +{ + char line[POSTED_MAX_SERVICE_STRING]; + + bool ok = snprintf(line, POSTED_MAX_SERVICE_STRING, "%d %d %d", upVotes, downVotes, nComments) > -1; + + serviceString = line; + return ok; +} +void p3Posted::processCommentRanks() +{ + +} + + + +void p3Posted::updateVotes() +{ + // any request failure stops update process + + if(mPostUpdate) + { + switch(mUpdatePhase) + { + case UPDATE_PHASE_GRP_REQUEST: + { + mPostUpdate = updateRequestGroups(); + break; + } + case UPDATE_PHASE_MSG_REQUEST: + { + mPostUpdate = updateRequestMessages(); + break; + } + case UPDATE_PHASE_VOTE_COMMENT_REQUEST: + { + mPostUpdate = updateRequestVotesComments(); + break; + } + case UPDATE_PHASE_VOTE_COUNT: + { + mPostUpdate = updateCompleteVotes(); + break; + } + case UPDATE_PHASE_COMMENT_COUNT: + { + mPostUpdate = updateCompleteComments(); + break; + } + case UPDATE_PHASE_COMPLETE: + { + updateComplete(); + break; + } + default: + { + std::cerr << "Unknown update phase, we should not be here!" << std::endl; + break; + } + } + } +} + +bool p3Posted::updateRequestGroups() +{ + + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + // opts.mSubscribeMask = GXS_SERV::GROUP_SUBSCRIBE_MASK; +// opts.mSubscribeFilter = GXS_SERV::GROUP_SUBSCRIBE_ADMIN | +// GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED; + mTokenService->requestGroupInfo(mUpdateRequestGroup, 0, opts); + + mUpdatePhase = UPDATE_PHASE_MSG_REQUEST; +} + +bool p3Posted::updateRequestMessages() +{ + + uint32_t status = mTokenService->requestStatus(mUpdateRequestGroup); + + if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::list grpIds; + RsGenExchange::getGroupList(mUpdateRequestGroup, grpIds); + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_META; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; + mTokenService->requestMsgInfo(mUpdateRequestMessages, 0, opts, grpIds); + mUpdatePhase = UPDATE_PHASE_VOTE_COMMENT_REQUEST; + return true; + } + else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + mTokenService->cancelRequest(mUpdateRequestGroup); + return false; + } + + return true; +} + +bool p3Posted::updateRequestVotesComments() +{ + + uint32_t status = mTokenService->requestStatus(mUpdateRequestMessages); + + if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + + RsGenExchange::getMsgMeta(mUpdateRequestMessages, mMsgMetaUpdate); + + std::vector msgIds; + + GxsMsgMetaMap::iterator mit = mMsgMetaUpdate.begin(); + + for(; mit != mMsgMetaUpdate.end(); mit++) + { + std::vector& msgIdV = mit->second; + std::vector::const_iterator cit = msgIdV.begin(); + + for(; cit != msgIdV.end(); cit++) + msgIds.push_back(std::make_pair(mit->first, cit->mMsgId)); + } + + RsTokReqOptions opts; + // only need ids for comments + + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_IDS; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_PARENT; + opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; + opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_COMMENT; + mTokenService->requestMsgRelatedInfo(mUpdateRequestComments, 0, opts, msgIds); + + // need actual data for votes + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_PARENT; + opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; + opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_VOTE; + mTokenService->requestMsgRelatedInfo(mUpdateRequestVotes, 0, opts, msgIds); + + mUpdatePhase = UPDATE_PHASE_VOTE_COUNT; + + return true; + } + else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + mTokenService->cancelRequest(mUpdateRequestMessages); + return false; + } + + return true; +} + + +bool p3Posted::updateCompleteVotes() +{ + uint32_t status = mTokenService->requestStatus(mUpdateRequestVotes); + + if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::map > votes; + getMsgRelatedDataT(mUpdateRequestVotes, + votes); + + // now for each msg count the number of votes and thats it + + std::map >::iterator mit = votes.begin(); + + for(; mit != votes.end(); mit++) + { + const std::vector& v = mit->second; + std::vector::const_iterator cit = v.begin(); + + for(; cit != v.end(); cit++) + { + const RsPostedVote& vote = *cit; + + if(vote.mDirection) + { + mMsgCounts[mit->first].upVotes++; + }else + { + mMsgCounts[mit->first].downVotes++; + } + } + } + mUpdatePhase = UPDATE_PHASE_COMMENT_COUNT; + } + else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + mTokenService->cancelRequest(mUpdateRequestVotes); + return false; + } + return true; +} + +bool p3Posted::updateCompleteComments() +{ + uint32_t status = mTokenService->requestStatus(mUpdateRequestComments); + + if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + MsgRelatedIdResult commentIds; + RsGenExchange::getMsgRelatedList(mUpdateRequestComments, commentIds); + + // now for each msg count the number of votes and thats it + + MsgRelatedIdResult::iterator mit = commentIds.begin(); + + for(; mit != commentIds.end(); mit++) + { + const std::vector& v = mit->second; + std::vector::const_iterator cit = v.begin(); + + for(; cit != v.end(); cit++) + { + mMsgCounts[mit->first].commentCount++; + } + } + mUpdatePhase = UPDATE_PHASE_COMPLETE; + } + else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + mTokenService->cancelRequest(mUpdateRequestComments); + return false; + } + return true; +} + +bool p3Posted::updateComplete() +{ + // now compare with msg meta to see what currently store there + + GxsMsgMetaMap::iterator mit = mMsgMetaUpdate.begin(); + + for(; mit != mMsgMetaUpdate.end(); mit++) + { + const std::vector& msgMetaV = mit->second; + std::vector::const_iterator cit = msgMetaV.begin(); + + for(; cit != msgMetaV.end(); cit++) + { + const RsMsgMetaData& msgMeta = *cit; + uint32_t upVotes, downVotes, nComments; + retrieveScores(msgMeta.mServiceString, upVotes, downVotes, nComments); + + RsGxsGrpMsgIdPair msgId; + msgId.first = mit->first; + msgId.second = msgMeta.mMsgId; + PostedScore& sc = mMsgCounts[msgId]; + + bool changed = (sc.upVotes != upVotes) || (sc.downVotes != downVotes) + || (sc.commentCount != nComments); + + if(changed) + { + std::string servStr; + storeScores(servStr, sc.upVotes, sc.downVotes, sc.commentCount); + uint32_t token; + setMsgServiceString(token, msgId, servStr); + mChangeTokens.push_back(token); + } + else + { + mMsgCounts.erase(msgId); + } + } + } + + mPostUpdate = false; + mUpdatePhase = UPDATE_PHASE_GRP_REQUEST; + + if(!mMsgCounts.empty()) + { + RsGxsMsgChange* msgChange = new RsGxsMsgChange(); + + std::map::iterator mit_c = mMsgCounts.begin(); + + for(; mit_c != mMsgCounts.end(); mit_c++) + { + const RsGxsGrpMsgIdPair& msgId = mit_c->first; + msgChange->msgChangeMap[msgId.first].push_back(msgId.second); + } + + std::vector n; + n.push_back(msgChange); + notifyChanges(n); + + mMsgCounts.clear(); + } + +} diff --git a/libretroshare/src/services/p3posted.h b/libretroshare/src/services/p3posted.h index 3466be7c4..0996208e5 100644 --- a/libretroshare/src/services/p3posted.h +++ b/libretroshare/src/services/p3posted.h @@ -1,190 +1,175 @@ -/* - * libretroshare/src/services: p3posted.h - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef P3_POSTED_SERVICE_HEADER -#define P3_POSTED_SERVICE_HEADER - -#include "services/p3gxsservice.h" -#include "retroshare/rsposted.h" - -#include -#include - -/* - * Posted Service - * - */ - - -class PostedDataProxy: public GxsDataProxy -{ - public: - - bool addGroup(const RsPostedGroup &group); - bool addPost(const RsPostedPost &post); - bool addVote(const RsPostedVote &vote); - bool addComment(const RsPostedComment &comment); - - bool getGroup(const std::string &id, RsPostedGroup &group); - bool getPost(const std::string &id, RsPostedPost &post); - bool getVote(const std::string &id, RsPostedVote &vote); - bool getComment(const std::string &id, RsPostedComment &comment); - - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *groupData, RsMsgMetaData &meta); - -}; - - - -class p3PostedService: public p3GxsDataService, public RsPosted -{ - public: - - p3PostedService(uint16_t type); - -virtual int tick(); - - public: - -// NEW INTERFACE. -/************* Extern Interface *******/ - -virtual bool updated(); - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds); - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); - - /* Actual Data -> specific to Interface */ - /* Specific Service Data */ -virtual bool getGroup(const uint32_t &token, RsPostedGroup &group); -virtual bool getPost(const uint32_t &token, RsPostedPost &post); -virtual bool getComment(const uint32_t &token, RsPostedComment &comment); - - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); - - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - -virtual bool submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew); -virtual bool submitPost(uint32_t &token, RsPostedPost &post, bool isNew); -virtual bool submitVote(uint32_t &token, RsPostedVote &vote, bool isNew); -virtual bool submitComment(uint32_t &token, RsPostedComment &comment, bool isNew); - - // Extended Interface for Collated Data View. -virtual bool setViewMode(uint32_t mode); -virtual bool setViewPeriod(uint32_t period); -virtual bool setViewRange(uint32_t first, uint32_t count); - -virtual bool requestRanking(uint32_t &token, std::string groupId); -virtual bool getRankedPost(const uint32_t &token, RsPostedPost &post); - - - // These are exposed for GUI usage. -virtual bool encodePostedCache(std::string &str, uint32_t votes, uint32_t comments); -virtual bool extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments); -virtual float calcPostScore(const RsMsgMetaData &meta); - - private: - - // -bool checkRankingRequest(); -bool processPosts(); - - // background processing of Votes. - // NB: These should probably be handled by a background thread. - // At the moment they are run from the tick() thread. - -bool background_checkTokenRequest(); -bool background_requestGroups(); -bool background_requestNewMessages(); -bool background_processNewMessages(); - -bool background_updateVoteCounts(); -bool background_cleanup(); - - - -std::string genRandomId(); -bool generateDummyData(); -bool addExtraDummyData(); - - PostedDataProxy *mPostedProxy; - - RsMutex mPostedMtx; - bool mUpdated; - - // Ranking view mode, stored here. - uint32_t mViewMode; - uint32_t mViewPeriod; - uint32_t mViewStart; - uint32_t mViewCount; - - // Processing Ranking stuff. - bool mProcessingRanking; - uint32_t mRankingState; - uint32_t mRankingExternalToken; - uint32_t mRankingInternalToken; - - // background processing - Mutex protected. - time_t mLastBgCheck; - bool mBgProcessing; - uint32_t mBgPhase; - uint32_t mBgToken; - - std::map mBgVoteMap; // ParentId -> Vote Count. - std::map mBgCommentMap; // ThreadId -> Comment Count. - - // extra dummy data. - std::list mDummyLaterVotes; - std::list mDummyLaterComments; - - -}; - -#endif +#ifndef P3POSTED_H +#define P3POSTED_H + +#include + +#include "retroshare/rsposted.h" +#include "gxs/rsgenexchange.h" + + +class GxsPostedPostRanking +{ +public: + + uint32_t pubToken; + uint32_t reqToken; + RsPosted::RankType rType; + RsGxsGroupId grpId; + RsPostedPostRanking rankingResult; +}; + +class GxsPostedCommentRanking +{ +public: + + uint32_t pubToken; + uint32_t reqToken; + RsPosted::RankType rType; + RsGxsGrpMsgIdPair msgId; + PostedRanking result; +}; + +class PostedScore { +public: + + PostedScore() : upVotes(0), downVotes(0), commentCount(0), date(0) {} + uint32_t upVotes, downVotes; + uint32_t commentCount; + time_t date; + RsGxsMessageId msgId; +}; + + + +class p3Posted : public RsGenExchange, public RsPosted +{ +public: + p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes); + +protected: + + /*! + * This confirms this class as an abstract one that \n + * should not be instantiated \n + * The deriving class should implement this function \n + * as it is called by the backend GXS system to \n + * update client of changes which should \n + * instigate client to retrieve new content from the system + * @param changes the changes that have occured to data held by this service + */ + void notifyChanges(std::vector& changes) ; + + void service_tick(); + +public: + + void generateTopics(); + /*! + * Exists solely for testing + */ + void generatePosts(); + + /*! + * Exists solely for testing + * Generates random votes to existing posts + * in the system + */ + void generateVotesAndComments(); + +public: + + bool getGroup(const uint32_t &token, std::vector &group); + bool getPost(const uint32_t &token, PostedPostResult& posts) ; + bool getComment(const uint32_t &token, PostedCommentResult& comments) ; + bool getRelatedComment(const uint32_t& token, PostedRelatedCommentResult &comments); + bool getPostRanking(const uint32_t &token, RsPostedPostRanking &ranking); + + bool submitGroup(uint32_t &token, RsPostedGroup &group); + bool submitPost(uint32_t &token, RsPostedPost &post); + bool submitVote(uint32_t &token, RsPostedVote &vote); + bool submitComment(uint32_t &token, RsPostedComment &comment) ; + // Special Ranking Request. + bool requestPostRankings(uint32_t &token, const RankType &rType, const RsGxsGroupId &groupId); + bool requestCommentRankings(uint32_t &token, const RankType &rType, const RsGxsGrpMsgIdPair &msgId); + + bool retrieveScores(const std::string& serviceString, uint32_t& upVotes, uint32_t& downVotes, uint32_t& nComments) const; + +private: + + /* Functions for processing rankings */ + + void processRankings(); + void processPostRanks(); + void processCommentRanks(); + void discardCalc(const uint32_t& token); + bool completePostedPostCalc(GxsPostedPostRanking* gpp); + void completePostedCommentRanking(GxsPostedCommentRanking* gpc); + + bool storeScores(std::string& serviceString, uint32_t& upVotes, uint32_t downVotes, uint32_t nComments) const; + + // for posts + void calcPostedPostRank(const std::vector, PostedRanking& ranking, bool com(const PostedScore& i, const PostedScore &j)) const; + + // for comments + void calcPostedCommentsRank(const std::map >& msgBranches, std::map& msgMetas, + PostedRanking& ranking, bool com(const PostedScore& i, const PostedScore &j)) const; + + /* Functions for maintaing vote counts in meta data */ + + /*! + * Update votes should only be called when a vote comes in + * Several phases to calculating votes. + * First get all messages for groups which you are subscribed + * Then for these messages get all the votes accorded to them + * Then do the calculation and update messages + * Also stores updates for messages which have new scores + */ + void updateVotes(); + bool updateRequestGroups(); + bool updateRequestMessages(); + bool updateRequestVotesComments(); + bool updateCompleteVotes(); + bool updateCompleteComments(); + + /*! + * The aim of this is create notifications + * for the UI of changes to a post if their vote + * or comment count has changed + */ + bool updateComplete(); + + +private: + + // for calculating ranks + std::vector mPendingPostRanks; + std::vector mCompletionPostRanks; + std::map mCompletePostRanks; + std::map mPendingCommentRanks; + std::map mPendingCalculationCommentRanks; + + // for maintaining vote counts in msg meta + uint32_t mUpdateRequestGroup, mUpdateRequestMessages, mUpdateRequestComments, mUpdateRequestVotes; + bool mPostUpdate; + uint32_t mUpdatePhase; + std::vector mMsgsPendingUpdate; + time_t mLastUpdate; + GxsMsgMetaMap mMsgMetaUpdate; + std::map mMsgCounts; + std::vector mChangeTokens; + + RsTokenService* mTokenService; + RsMutex mPostedMutex; + + + // for data generation + + bool mGeneratingPosts, mGeneratingTopics, + mRequestPhase1, mRequestPhase2, mRequestPhase3, mGenerateVotesAndComments; + std::vector mTokens; + uint32_t mToken; + std::list mGrpIds; + +}; + +#endif // P3POSTED_H diff --git a/libretroshare/src/services/p3postedVEG.cc b/libretroshare/src/services/p3postedVEG.cc new file mode 100644 index 000000000..63acd3cba --- /dev/null +++ b/libretroshare/src/services/p3postedVEG.cc @@ -0,0 +1,2148 @@ +/* + * libretroshare/src/services p3photoservice.cc + * + * Photo Service for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3postedVEG.h" +#include "util/rsrandom.h" +#include +#include +#include + +/**** + * #define POSTED_DEBUG 1 + ****/ + +RsPostedVEG *rsPostedVEG = NULL; + + +/********************************************************************************/ +/******************* Startup / Tick ******************************************/ +/********************************************************************************/ + +p3PostedServiceVEG::p3PostedServiceVEG(uint16_t type) + :p3GxsDataServiceVEG(type, new PostedDataProxy()), mPostedMtx("p3PostedService"), mUpdated(true) +{ + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mPostedProxy = (PostedDataProxy *) mProxy; + + mViewMode = RSPOSTED_VIEWMODE_HOT; + mViewPeriod = RSPOSTED_PERIOD_WEEK; + mViewStart = 0; + mViewCount = 50; + + mProcessingRanking = false; + mRankingState = 0; + mRankingExternalToken = 0; + mRankingInternalToken = 0; + + mLastBgCheck = 0; + mBgProcessing = 0; + mBgPhase = 0; + mBgToken = 0; + + } + + generateDummyData(); + return; +} + +#define POSTED_BACKGROUND_PERIOD 60 + +int p3PostedServiceVEG::tick() +{ + //std::cerr << "p3PostedServiceVEG::tick()"; + //std::cerr << std::endl; + + fakeprocessrequests(); + + + // Contine Ranking Request. + checkRankingRequest(); + + // Run Background Stuff. + background_checkTokenRequest(); + + /* every minute - run a background check */ + time_t now = time(NULL); + bool doCheck = false; + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if (now - mLastBgCheck > POSTED_BACKGROUND_PERIOD) + { + doCheck = true; + mLastBgCheck = now; + } + } + + if (doCheck) + { + addExtraDummyData(); + background_requestGroups(); + } + + + + // Add in new votes + comments. + return 0; +} + +bool p3PostedServiceVEG::updated() +{ + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + if (mUpdated) + { + mUpdated = false; + return true; + } + return false; +} + + + + /* Data Requests */ +bool p3PostedServiceVEG::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds) +{ + generateToken(token); + std::cerr << "p3PostedServiceVEG::requestGroupInfo() gets Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); + + return true; +} + +bool p3PostedServiceVEG::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds) +{ + generateToken(token); + std::cerr << "p3PostedServiceVEG::requestMsgInfo() gets Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); + + return true; +} + +bool p3PostedServiceVEG::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &msgIds) +{ + generateToken(token); + std::cerr << "p3PostedServiceVEG::requestMsgRelatedInfo() gets Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); + + return true; +} + + /* Generic Lists */ +bool p3PostedServiceVEG::getGroupList( const uint32_t &token, std::list &groupIds) +{ + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + if (anstype != RS_TOKREQ_ANSTYPE_LIST) + { + std::cerr << "p3PostedServiceVEG::getGroupList() ERROR AnsType Wrong" << std::endl; + return false; + } + + if (reqtype != GXS_REQUEST_TYPE_GROUPS) + { + std::cerr << "p3PostedServiceVEG::getGroupList() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getGroupList() ERROR Status Incomplete" << std::endl; + return false; + } + + bool ans = loadRequestOutList(token, groupIds); + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + + return ans; +} + + + + +bool p3PostedServiceVEG::getMsgList( const uint32_t &token, std::list &msgIds) +{ + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + if (anstype != RS_TOKREQ_ANSTYPE_LIST) + { + std::cerr << "p3PostedServiceVEG::getMsgList() ERROR AnsType Wrong" << std::endl; + return false; + } + + if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) + { + std::cerr << "p3PostedServiceVEG::getMsgList() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getMsgList() ERROR Status Incomplete" << std::endl; + return false; + } + + bool ans = loadRequestOutList(token, msgIds); + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + + return ans; +} + + + /* Generic Summary */ +bool p3PostedServiceVEG::getGroupSummary( const uint32_t &token, std::list &groupInfo) +{ + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) + { + std::cerr << "p3PostedServiceVEG::getGroupSummary() ERROR AnsType Wrong" << std::endl; + return false; + } + + if (reqtype != GXS_REQUEST_TYPE_GROUPS) + { + std::cerr << "p3PostedServiceVEG::getGroupSummary() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getGroupSummary() ERROR Status Incomplete" << std::endl; + return false; + } + + std::list groupIds; + bool ans = loadRequestOutList(token, groupIds); + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + + /* convert to RsGroupMetaData */ + mProxy->getGroupSummary(groupIds, groupInfo); + + return ans; +} + +bool p3PostedServiceVEG::getMsgSummary( const uint32_t &token, std::list &msgInfo) +{ + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) + { + std::cerr << "p3PostedServiceVEG::getMsgSummary() ERROR AnsType Wrong" << std::endl; + return false; + } + + if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) + { + std::cerr << "p3PostedServiceVEG::getMsgSummary() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getMsgSummary() ERROR Status Incomplete" << std::endl; + return false; + } + + std::list msgIds; + bool ans = loadRequestOutList(token, msgIds); + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + + /* convert to RsMsgMetaData */ + mProxy->getMsgSummary(msgIds, msgInfo); + + return ans; +} + + + /* Specific Service Data */ +bool p3PostedServiceVEG::getGroup(const uint32_t &token, RsPostedGroup &group) +{ + std::cerr << "p3PostedServiceVEG::getGroup() Token: " << token; + std::cerr << std::endl; + + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + + if (anstype != RS_TOKREQ_ANSTYPE_DATA) + { + std::cerr << "p3PostedServiceVEG::getGroup() ERROR AnsType Wrong" << std::endl; + return false; + } + + if (reqtype != GXS_REQUEST_TYPE_GROUPS) + { + std::cerr << "p3PostedServiceVEG::getGroup() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getGroup() ERROR Status Incomplete" << std::endl; + return false; + } + + std::string id; + if (!popRequestOutList(token, id)) + { + /* finished */ + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + return false; + } + + /* convert to RsPostedGroup */ + bool ans = mPostedProxy->getGroup(id, group); + return ans; +} + + +bool p3PostedServiceVEG::getPost(const uint32_t &token, RsPostedPost &post) +{ + std::cerr << "p3PostedServiceVEG::getPost() Token: " << token; + std::cerr << std::endl; + + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + + if (anstype != RS_TOKREQ_ANSTYPE_DATA) + { + std::cerr << "p3PostedServiceVEG::getPost() ERROR AnsType Wrong" << std::endl; + return false; + } + + if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) + { + std::cerr << "p3PostedServiceVEG::getPost() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getPost() ERROR Status Incomplete" << std::endl; + return false; + } + + std::string id; + if (!popRequestOutList(token, id)) + { + /* finished */ + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + return false; + } + + /* convert to RsPhotoAlbum */ + bool ans = mPostedProxy->getPost(id, post); + return ans; +} + + +bool p3PostedServiceVEG::getComment(const uint32_t &token, RsPostedComment &comment) +{ + std::cerr << "p3PostedServiceVEG::getComment() Token: " << token; + std::cerr << std::endl; + + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + + if (anstype != RS_TOKREQ_ANSTYPE_DATA) + { + std::cerr << "p3PostedServiceVEG::getComment() ERROR AnsType Wrong" << std::endl; + return false; + } + + if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) + { + std::cerr << "p3PostedServiceVEG::getComment() ERROR ReqType Wrong" << std::endl; + return false; + } + + if (status != GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::getComment() ERROR Status Incomplete" << std::endl; + return false; + } + + std::string id; + if (!popRequestOutList(token, id)) + { + /* finished */ + updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); + return false; + } + + /* convert to RsPhotoAlbum */ + bool ans = mPostedProxy->getComment(id, comment); + return ans; +} + + /* Cancel Request */ +bool p3PostedServiceVEG::cancelRequest(const uint32_t &token) +{ + return clearRequest(token); +} + + ////////////////////////////////////////////////////////////////////////////// + + + +bool p3PostedServiceVEG::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) +{ + return mPostedProxy->setMessageStatus(msgId, status, statusMask); +} + +bool p3PostedServiceVEG::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) +{ + return mPostedProxy->setGroupStatus(groupId, status, statusMask); +} + +bool p3PostedServiceVEG::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) +{ + return mPostedProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); +} + +bool p3PostedServiceVEG::setMessageServiceString(const std::string &msgId, const std::string &str) +{ + return mPostedProxy->setMessageServiceString(msgId, str); +} + +bool p3PostedServiceVEG::setGroupServiceString(const std::string &grpId, const std::string &str) +{ + return mPostedProxy->setGroupServiceString(grpId, str); +} + + +bool p3PostedServiceVEG::groupRestoreKeys(const std::string &groupId) +{ + return false; +} + +bool p3PostedServiceVEG::groupShareKeys(const std::string &groupId, std::list& peers) +{ + return false; +} + + +bool p3PostedServiceVEG::submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew) +{ + /* check if its a modification or a new album */ + + /* add to database */ + + /* check if its a mod or new photo */ + if (group.mMeta.mGroupId.empty()) + { + /* new photo */ + + /* generate a temp id */ + group.mMeta.mGroupId = genRandomId(); + group.mMeta.mPublishTs = time(NULL); + + std::cerr << "p3PostedServiceVEG::submitGroup() Generated New GroupID: " << group.mMeta.mGroupId; + std::cerr << std::endl; + } + + //group.mModFlags = 0; // These are always cleared. + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mUpdated = true; + mPostedProxy->addGroup(group); + } + + // Fake a request to return the GroupMetaData. + generateToken(token); + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptionsVEG opts; // NULL is good. + std::list groupIds; + groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. + + std::cerr << "p3PostedServiceVEG::submitGroup() Generating Request Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); + + return true; +} + + +bool p3PostedServiceVEG::submitPost(uint32_t &token, RsPostedPost &post, bool isNew) +{ + if (post.mMeta.mGroupId.empty()) + { + /* new photo */ + std::cerr << "p3PostedServiceVEG::submitPost() Missing GroupID: ERROR"; + std::cerr << std::endl; + return false; + } + + /* generate a new id */ + post.mMeta.mMsgId = genRandomId(); + post.mMeta.mPublishTs = time(NULL); + + if (isNew) + { + /* new (Original Msg) photo */ + post.mMeta.mOrigMsgId = post.mMeta.mMsgId; + std::cerr << "p3PostedServiceVEG::submitPost() New Msg"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3PostedServiceVEG::submitPost() Updated Msg"; + std::cerr << std::endl; + } + + //post.mModFlags = 0; // These are always cleared. + + std::cerr << "p3PostedServiceVEG::submitPost() OrigMsgId: " << post.mMeta.mOrigMsgId; + std::cerr << " MsgId: " << post.mMeta.mMsgId; + std::cerr << std::endl; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mUpdated = true; + mPostedProxy->addPost(post); + } + + // Fake a request to return the MsgMetaData. + generateToken(token); + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptionsVEG opts; // NULL is good. + std::list msgIds; + msgIds.push_back(post.mMeta.mMsgId); // It will just return this one. + + std::cerr << "p3PostedServiceVEG::submitPost() Generating Request Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); + + return true; +} + + + +bool p3PostedServiceVEG::submitVote(uint32_t &token, RsPostedVote &vote, bool isNew) +{ + if (vote.mMeta.mGroupId.empty()) + { + /* new photo */ + std::cerr << "p3PostedServiceVEG::submitVote() Missing GroupID: ERROR"; + std::cerr << std::endl; + return false; + } + + /* generate a new id */ + vote.mMeta.mMsgId = genRandomId(); + vote.mMeta.mPublishTs = time(NULL); + + if (isNew) + { + /* new (Original Msg) photo */ + vote.mMeta.mOrigMsgId = vote.mMeta.mMsgId; + std::cerr << "p3PostedServiceVEG::submitVote() New Msg"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3PostedServiceVEG::submitVote() Updated Msg"; + std::cerr << std::endl; + } + + //vote.mModFlags = 0; // These are always cleared. + + std::cerr << "p3PostedServiceVEG::submitVote() OrigMsgId: " << vote.mMeta.mOrigMsgId; + std::cerr << " MsgId: " << vote.mMeta.mMsgId; + std::cerr << std::endl; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mUpdated = true; + mPostedProxy->addVote(vote); + } + + // Fake a request to return the MsgMetaData. + generateToken(token); + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptionsVEG opts; // NULL is good. + std::list msgIds; + msgIds.push_back(vote.mMeta.mMsgId); // It will just return this one. + + std::cerr << "p3PostedServiceVEG::submitVote() Generating Request Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); + + + return true; +} + + +bool p3PostedServiceVEG::submitComment(uint32_t &token, RsPostedComment &comment, bool isNew) +{ + if (comment.mMeta.mGroupId.empty()) + { + /* new photo */ + std::cerr << "p3PostedServiceVEG::submitPost() Missing GroupID: ERROR"; + std::cerr << std::endl; + return false; + } + + /* generate a new id */ + comment.mMeta.mMsgId = genRandomId(); + comment.mMeta.mPublishTs = time(NULL); + + if (isNew) + { + /* new (Original Msg) photo */ + comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; + std::cerr << "p3PostedServiceVEG::submitComment() New Msg"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3PostedServiceVEG::submitComment() Updated Msg"; + std::cerr << std::endl; + } + + //comment.mModFlags = 0; // These are always cleared. + + std::cerr << "p3PostedServiceVEG::submitComment() OrigMsgId: " << comment.mMeta.mOrigMsgId; + std::cerr << " MsgId: " << comment.mMeta.mMsgId; + std::cerr << std::endl; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mUpdated = true; + mPostedProxy->addComment(comment); + } + + // Fake a request to return the MsgMetaData. + generateToken(token); + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptionsVEG opts; // NULL is good. + std::list msgIds; + msgIds.push_back(comment.mMeta.mMsgId); // It will just return this one. + + std::cerr << "p3PostedServiceVEG::submitComment() Generating Request Token: " << token << std::endl; + storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); + + return true; +} + + + +/********************************************************************************************/ + +bool PostedDataProxy::getGroup(const std::string &id, RsPostedGroup &group) +{ + void *groupData = NULL; + RsGroupMetaData meta; + if (getGroupData(id, groupData) && getGroupSummary(id, meta)) + { + RsPostedGroup *pG = (RsPostedGroup *) groupData; + group = *pG; + + group.mMeta = meta; + + std::cerr << "PostedDataProxy::getGroup() Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; + std::cerr << std::endl; + return true; + } + + std::cerr << "PostedDataProxy::getGroup() FAILED Id: " << id; + std::cerr << std::endl; + + return false; +} + + + +bool PostedDataProxy::getPost(const std::string &id, RsPostedPost &post) +{ + void *msgData = NULL; + RsMsgMetaData meta; + if (getMsgData(id, msgData) && getMsgSummary(id, meta)) + { + RsPostedMsg *pM = (RsPostedMsg *) msgData; + + if (pM->postedType == RSPOSTED_MSGTYPE_POST) + { + RsPostedPost *pP = (RsPostedPost *) pM; + post = *pP; + + // update definitive version of the metadata. + post.mMeta = meta; + + std::cerr << "PostedDataProxy::getPost() Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + std::cerr << std::endl; + return true; + } + else + { + std::cerr << "PostedDataProxy::getPost() ERROR NOT POST Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + std::cerr << std::endl; + return false; + } + } + + std::cerr << "PostedDataProxy::getPost() FAILED Id: " << id; + std::cerr << std::endl; + + return false; +} + + + + +bool PostedDataProxy::getVote(const std::string &id, RsPostedVote &vote) +{ + void *msgData = NULL; + RsMsgMetaData meta; + if (getMsgData(id, msgData) && getMsgSummary(id, meta)) + { + RsPostedMsg *pM = (RsPostedMsg *) msgData; + + if (pM->postedType == RSPOSTED_MSGTYPE_VOTE) + { + RsPostedVote *pP = (RsPostedVote *) pM; + vote = *pP; + + // update definitive version of the metadata. + vote.mMeta = meta; + + std::cerr << "PostedDataProxy::getVote() Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + std::cerr << std::endl; + return true; + } + else + { + std::cerr << "PostedDataProxy::getVote() ERROR NOT VOTE Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + std::cerr << std::endl; + return false; + } + } + + std::cerr << "PostedDataProxy::getVote() FAILED Id: " << id; + std::cerr << std::endl; + + return false; +} + + + + +bool PostedDataProxy::getComment(const std::string &id, RsPostedComment &comment) +{ + void *msgData = NULL; + RsMsgMetaData meta; + if (getMsgData(id, msgData) && getMsgSummary(id, meta)) + { + RsPostedMsg *pM = (RsPostedMsg *) msgData; + + if (pM->postedType == RSPOSTED_MSGTYPE_COMMENT) + { + RsPostedComment *pP = (RsPostedComment *) pM; + comment = *pP; + + // update definitive version of the metadata. + comment.mMeta = meta; + + std::cerr << "PostedDataProxy::getComment() Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + std::cerr << std::endl; + return true; + } + else + { + std::cerr << "PostedDataProxy::getComment() ERROR NOT POST Id: " << id; + std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; + std::cerr << std::endl; + return false; + } + } + + std::cerr << "PostedDataProxy::getComment() FAILED Id: " << id; + std::cerr << std::endl; + + return false; +} + + + + +bool PostedDataProxy::addGroup(const RsPostedGroup &group) +{ + // Make duplicate. + RsPostedGroup *pG = new RsPostedGroup(); + *pG = group; + + std::cerr << "PostedDataProxy::addGroup()"; + std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; + std::cerr << std::endl; + + return createGroup(pG); +} + + +bool PostedDataProxy::addPost(const RsPostedPost &post) +{ + // Make duplicate. + RsPostedPost *pP = new RsPostedPost(); + *pP = post; + + std::cerr << "PostedDataProxy::addPost()"; + std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; + std::cerr << std::endl; + + return createMsg(pP); +} + + +bool PostedDataProxy::addVote(const RsPostedVote &vote) +{ + // Make duplicate. + RsPostedVote *pP = new RsPostedVote(); + *pP = vote; + + std::cerr << "PostedDataProxy::addVote()"; + std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; + std::cerr << std::endl; + + return createMsg(pP); +} + + +bool PostedDataProxy::addComment(const RsPostedComment &comment) +{ + // Make duplicate. + RsPostedComment *pP = new RsPostedComment(); + *pP = comment; + + std::cerr << "PostedDataProxy::addComment()"; + std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; + std::cerr << std::endl; + + return createMsg(pP); +} + + + /* These Functions must be overloaded to complete the service */ +bool PostedDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) +{ + RsPostedGroup *group = (RsPostedGroup *) groupData; + meta = group->mMeta; + + return true; +} + +bool PostedDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) +{ + RsPostedMsg *msg = (RsPostedMsg *) msgData; + meta = msg->mMeta; + + return true; +} + + +/********************************************************************************************/ + +std::string p3PostedServiceVEG::genRandomId() +{ + std::string randomId; + for(int i = 0; i < 20; i++) + { + randomId += (char) ('a' + (RSRandom::random_u32() % 26)); + } + + return randomId; +} + + +/********************************************************************************************/ + +std::ostream &operator<<(std::ostream &out, const RsPostedPost &post) +{ + out << "RsPostedPost [ "; + out << "Title: " << post.mMeta.mMsgName; + out << "]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote) +{ + out << "RsPostedVote [ "; + out << "Title: " << vote.mMeta.mMsgName; + out << "]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment) +{ + out << "RsPostedComment [ "; + out << "Title: " << comment.mMeta.mMsgName; + out << "]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group) +{ + out << "RsPostedGroup [ "; + out << "Title: " << group.mMeta.mGroupName; + out << "]"; + return out; +} + + +/********************************************************************************************/ +/********************************************************************************************/ + +bool p3PostedServiceVEG::generateDummyData() +{ +#define MAX_GROUPS 10 //100 +#define MAX_POSTS 50 //1000 + +#define MAX_BASE_COMMENTS 1000 //10000 +#define MAX_COMMENTS 4000 //10000 + +#define MAX_VOTES 10000 //10000 + + std::list mGroups; + std::list::iterator git; + + std::list mPosts; + std::list::iterator pit; + + std::list mVotes; + std::list::iterator vit; + + std::list mComments; + std::list::iterator cit; + +#define DUMMY_NAME_MAX_LEN 10000 + char name[DUMMY_NAME_MAX_LEN]; + int i, j; + time_t now = time(NULL); + + for(i = 0; i < MAX_GROUPS; i++) + { + /* generate a new forum */ + RsPostedGroup group; + + snprintf(name, DUMMY_NAME_MAX_LEN, "TestTopic_%d", i+1); + + group.mMeta.mGroupId = genRandomId(); + group.mMeta.mGroupName = name; + + group.mMeta.mPublishTs = now - (RSRandom::random_f32() * 100000); + /* key fields to fill in: + * GroupId. + * Name. + * Flags. + * Pop. + */ + + + + /* use probability to decide which are subscribed / own / popularity. + */ + + float rnd = RSRandom::random_f32(); + if (rnd < 0.1) + { + group.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_ADMIN | RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; + + } + else if (rnd < 0.3) + { + group.mMeta.mSubscribeFlags = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; + } + else + { + group.mMeta.mSubscribeFlags = 0; + } + + group.mMeta.mPop = (int) (RSRandom::random_f32() * 10.0); + mGroups.push_back(group); + + } + + for(i = 0; i < MAX_POSTS; i++) + { + /* generate a base thread */ + + /* rotate the Forum Groups Around, then pick one. + */ + + int rnd = (int) (RSRandom::random_f32() * 10.0); + + for(j = 0; j < rnd; j++) + { + RsPostedGroup head = mGroups.front(); + mGroups.pop_front(); + mGroups.push_back(head); + } + + RsPostedGroup group = mGroups.front(); + + /* now create a new thread */ + + RsPostedPost post; + + snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Post_%d", group.mMeta.mGroupName.c_str(), i+1); + post.mMeta.mMsgName = name; + + post.mMeta.mGroupId = group.mMeta.mGroupId; + post.mMeta.mMsgId = genRandomId(); + post.mMeta.mOrigMsgId = post.mMeta.mMsgId; + post.mMeta.mThreadId = post.mMeta.mMsgId; + post.mMeta.mParentId = ""; + + post.mMeta.mPublishTs = group.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); + if (post.mMeta.mPublishTs > now) + post.mMeta.mPublishTs = now - 1; + + mPosts.push_back(post); + + } + + for(i = 0; i < MAX_BASE_COMMENTS; i++) + { + /* generate a base thread */ + + /* rotate the Forum Groups Around, then pick one. + */ + + int rnd = (int) (RSRandom::random_f32() * 10.0); + + for(j = 0; j < rnd; j++) + { + RsPostedPost head = mPosts.front(); + mPosts.pop_front(); + mPosts.push_back(head); + } + + RsPostedPost parent = mPosts.front(); + + /* now create a new child msg */ + + RsPostedComment comment; + + /* fill in key data + * GroupId + * MsgId + * OrigMsgId + * ThreadId + * ParentId + * PublishTS (take Forum TS + a bit ). + * + * ChildTS ???? + */ + snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Comment_%d", parent.mMeta.mMsgName.c_str(), i+1); + comment.mMeta.mMsgName = name; + //comment.mMsg = name; + + comment.mMeta.mGroupId = parent.mMeta.mGroupId; + comment.mMeta.mMsgId = genRandomId(); + comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; + comment.mMeta.mThreadId = parent.mMeta.mThreadId; + comment.mMeta.mParentId = parent.mMeta.mOrigMsgId; + + comment.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); + if (comment.mMeta.mPublishTs > now) + comment.mMeta.mPublishTs = now - 1; + + mComments.push_back(comment); + } + + + for(i = 0; i < MAX_COMMENTS; i++) + { + /* generate a base thread */ + + /* rotate the Forum Groups Around, then pick one. + */ + + int rnd = (int) (RSRandom::random_f32() * 10.0); + + for(j = 0; j < rnd; j++) + { + RsPostedComment head = mComments.front(); + mComments.pop_front(); + mComments.push_back(head); + } + + RsPostedComment parent = mComments.front(); + + /* now create a new child msg */ + + RsPostedComment comment; + + /* fill in key data + * GroupId + * MsgId + * OrigMsgId + * ThreadId + * ParentId + * PublishTS (take Forum TS + a bit ). + * + * ChildTS ???? + */ + snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Comment_%d", parent.mMeta.mMsgName.c_str(), i+1); + comment.mMeta.mMsgName = name; + //comment.mMsg = name; + + comment.mMeta.mGroupId = parent.mMeta.mGroupId; + comment.mMeta.mMsgId = genRandomId(); + comment.mMeta.mOrigMsgId = comment.mMeta.mMsgId; + comment.mMeta.mThreadId = parent.mMeta.mThreadId; + comment.mMeta.mParentId = parent.mMeta.mOrigMsgId; + + comment.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); + if (comment.mMeta.mPublishTs > now) + comment.mMeta.mPublishTs = now - 1; + + mComments.push_back(comment); + } + + + for(i = 0; i < MAX_VOTES; i++) + { + /* generate a base thread */ + + /* rotate the Forum Groups Around, then pick one. + */ + + int rnd = (int) (RSRandom::random_f32() * 10.0); + + for(j = 0; j < rnd; j++) + { + RsPostedPost head = mPosts.front(); + mPosts.pop_front(); + mPosts.push_back(head); + } + + RsPostedPost parent = mPosts.front(); + + /* now create a new child msg */ + + RsPostedVote vote; + + snprintf(name, DUMMY_NAME_MAX_LEN, "%s => Vote_%d", parent.mMeta.mMsgName.c_str(), i+1); + vote.mMeta.mMsgName = name; + //vote.mMsg = name; + + vote.mMeta.mGroupId = parent.mMeta.mGroupId; + vote.mMeta.mMsgId = genRandomId(); + vote.mMeta.mOrigMsgId = vote.mMeta.mMsgId; + vote.mMeta.mThreadId = parent.mMeta.mThreadId; + vote.mMeta.mParentId = parent.mMeta.mOrigMsgId; + + vote.mMeta.mPublishTs = parent.mMeta.mPublishTs + (RSRandom::random_f32() * 10000); + if (vote.mMeta.mPublishTs > now) + vote.mMeta.mPublishTs = now - 1; + + mVotes.push_back(vote); + } + + + mUpdated = true; + + /* Then - at the end, we push them all into the Proxy */ + for(git = mGroups.begin(); git != mGroups.end(); git++) + { + /* pushback */ + mPostedProxy->addGroup(*git); + + } + + for(pit = mPosts.begin(); pit != mPosts.end(); pit++) + { + /* pushback */ + mPostedProxy->addPost(*pit); + } + + for(cit = mComments.begin(); cit != mComments.end(); cit++) + { + /* pushback */ +#define COMMENT_FRAC_FOR_LATER (0.70) + if (RSRandom::random_f32() > COMMENT_FRAC_FOR_LATER) + { + mPostedProxy->addComment(*cit); + } + else + { + mDummyLaterComments.push_back(*cit); + } + } + + + for(vit = mVotes.begin(); vit != mVotes.end(); vit++) + { + /* pushback */ + +#define VOTE_FRAC_FOR_LATER (0.70) + if (RSRandom::random_f32() > VOTE_FRAC_FOR_LATER) + { + mPostedProxy->addVote(*vit); + } + else + { + mDummyLaterVotes.push_back(*vit); + } + } + + return true; +} + +#define EXTRA_COMMENT_ADD (20) +#define EXTRA_VOTE_ADD (50) + +bool p3PostedServiceVEG::addExtraDummyData() +{ + std::cerr << "p3PostedServiceVEG::addExtraDummyData()"; + std::cerr << std::endl; + + int i = 0; + + std::list::iterator vit; + std::list::iterator cit; + + for(cit = mDummyLaterComments.begin(); (cit != mDummyLaterComments.end()) && (i < EXTRA_COMMENT_ADD); i++) + { + mPostedProxy->addComment(*cit); + cit = mDummyLaterComments.erase(cit); + } + + i = 0; + for(vit = mDummyLaterVotes.begin(); (vit != mDummyLaterVotes.end()) && (i < EXTRA_VOTE_ADD); i++) + { + mPostedProxy->addVote(*vit); + vit = mDummyLaterVotes.erase(vit); + } + + return true; +} + + + + +/********************************************************************************************/ +/********************************************************************************************/ +/********************************************************************************************/ +/********************************************************************************************/ +/********************************************************************************************/ + + +/* This is the part that will be kept for the final Version. + * we provide a processed view of the data... + * + * start off crude -> then make it efficient. + */ + + + +bool p3PostedServiceVEG::setViewMode(uint32_t mode) +{ + std::cerr << "p3PostedServiceVEG::setViewMode() : " << mode; + std::cerr << std::endl; + + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mViewMode = mode; + + return true; +} + +bool p3PostedServiceVEG::setViewPeriod(uint32_t period) +{ + std::cerr << "p3PostedServiceVEG::setViewPeriod() : " << period; + std::cerr << std::endl; + + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mViewPeriod = period; + + return true; +} + +bool p3PostedServiceVEG::setViewRange(uint32_t first, uint32_t count) +{ + std::cerr << "p3PostedServiceVEG::setViewRange() : " << first << " +" << count; + std::cerr << std::endl; + + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mViewStart = first; + mViewCount = count; + + return true; +} + +float p3PostedServiceVEG::calcPostScore(const RsMsgMetaData &meta) +{ + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + float score = 0; + uint32_t votes = 0; + uint32_t comments = 0; + time_t now = time(NULL); + time_t age_secs = now - meta.mPublishTs; + // This is a potential problem for gaming the system... post into the future. + // Should fix this by discarding/hiding until ts valid XXX. + if (age_secs < 0) + { + age_secs = 0; + } + + if (!extractPostedCache(meta.mServiceString, votes, comments)) + { + /* no votes/comments yet */ + } + + /* this is dependent on View Mode */ + switch(mViewMode) + { + default: + case RSPOSTED_VIEWMODE_LATEST: + { + score = -age_secs; // + + break; + } + case RSPOSTED_VIEWMODE_TOP: + { + score = votes; + break; + } +// Potentially only +// This is effectively HackerNews Algorithm: which is (p-1)/(t+2)^1.5, where p is votes and t is age in hours. + case RSPOSTED_VIEWMODE_HOT: + { +#define POSTED_AGESHIFT (2.0) +#define POSTED_AGEFACTOR (3600.0) + score = votes / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); + break; + } +// Like HOT, but using number of Comments. + case RSPOSTED_VIEWMODE_COMMENTS: + { + score = comments / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); + break; + } + } + + return score; +} + +static uint32_t convertPeriodFlagToSeconds(uint32_t periodMode) +{ + float secs = 1; + switch(periodMode) + { + // Fallthrough all of them. + case RSPOSTED_PERIOD_YEAR: + secs *= 12; + case RSPOSTED_PERIOD_MONTH: + secs *= 4.3; // average ~30.4 days = 4.3 weeks. + case RSPOSTED_PERIOD_WEEK: + secs *= 7; + case RSPOSTED_PERIOD_DAY: + secs *= 24; + case RSPOSTED_PERIOD_HOUR: + secs *= 3600; + } + + return (uint32_t) secs; +} + +#define POSTED_RANKINGS_INITIAL_CHECK 1 +#define POSTED_RANKINGS_DATA_REQUEST 2 +#define POSTED_RANKINGS_NODATA 3 +#define POSTED_RANKINGS_DATA_DONE 4 + + /* Poll */ +uint32_t p3PostedServiceVEG::requestStatus(const uint32_t token) +{ + std::cerr << "p3PostedServiceVEG::requestStatus() Token: " << token; + std::cerr << std::endl; + + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + + uint32_t int_token = token; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if ((mProcessingRanking) && (token == mRankingExternalToken)) + { + std::cerr << "p3PostedServiceVEG::requestStatus() is RankingToken"; + std::cerr << std::endl; + + { + switch(mRankingState) + { + case POSTED_RANKINGS_INITIAL_CHECK: + status = GXS_REQUEST_STATUS_PENDING; + std::cerr << "p3PostedServiceVEG::requestStatus() RANKING PENDING"; + std::cerr << std::endl; + return status; + break; + case POSTED_RANKINGS_NODATA: + status = GXS_REQUEST_STATUS_COMPLETE; + std::cerr << "p3PostedServiceVEG::requestStatus() RANKING RETURNED NO DATA"; + std::cerr << std::endl; + return status; + break; + case POSTED_RANKINGS_DATA_REQUEST: + // Switch to real token. + int_token = mRankingInternalToken; + std::cerr << "p3PostedServiceVEG::requestStatus() Flipping to Int Token: " << int_token; + std::cerr << std::endl; + break; + + } + } + } + } + + checkRequestStatus(int_token, status, reqtype, anstype, ts); + + return status; +} + +bool p3PostedServiceVEG::getRankedPost(const uint32_t &token, RsPostedPost &post) +{ + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if (!mProcessingRanking) + { + + std::cerr << "p3PostedServiceVEG::getRankedPost() ERROR not processing"; + std::cerr << std::endl; + return false; + } + + if (token != mRankingExternalToken) + { + std::cerr << "p3PostedServiceVEG::getRankedPost() ERROR wrong token"; + std::cerr << std::endl; + + return false; + } + + if (mRankingState == POSTED_RANKINGS_NODATA) + { + std::cerr << "p3PostedServiceVEG::getRankedPost() No Data for this request - sorry"; + std::cerr << std::endl; + + /* clean up */ + mProcessingRanking = false; + mRankingExternalToken = 0; + mRankingInternalToken = 0; + mRankingState = POSTED_RANKINGS_DATA_DONE; + + return false; + } + + if (mRankingState != POSTED_RANKINGS_DATA_REQUEST) + { + + std::cerr << "p3PostedServiceVEG::getRankedPost() ERROR wrong state"; + std::cerr << std::endl; + + return false; + + } + + + if (!getPost(mRankingInternalToken, post)) + { + std::cerr << "p3PostedServiceVEG::getRankedPost() End of Posts for this token"; + std::cerr << std::endl; + + /* clean up */ + mProcessingRanking = false; + mRankingExternalToken = 0; + mRankingInternalToken = 0; + mRankingState = POSTED_RANKINGS_DATA_DONE; + + return false; + } + + std::cerr << "p3PostedServiceVEG::getRankedPost() Got Post"; + std::cerr << std::endl; + + return true; +} + + +bool p3PostedServiceVEG::requestRanking(uint32_t &token, std::string groupId) +{ + std::cerr << "p3PostedServiceVEG::requestRanking()"; + std::cerr << std::endl; + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if (mProcessingRanking) + { + std::cerr << "p3PostedServiceVEG::requestRanking() ERROR Request already running - ignoring"; + std::cerr << std::endl; + + return false; + } + } + + generateToken(token); + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mProcessingRanking = true; + mRankingState = POSTED_RANKINGS_INITIAL_CHECK; + mRankingExternalToken = token; + } + + /* now we request all the posts within the timeframe */ + + uint32_t posttoken; + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptionsVEG opts; + + opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; + //uint32_t age = convertPeriodFlagToSeconds(mViewPeriod); + + std::list groupIds; + groupIds.push_back(groupId); + + requestMsgInfo(posttoken, ansType, opts, groupIds); + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + std::cerr << "p3PostedServiceVEG::requestRanking() Saved Internal Token: " << posttoken; + std::cerr << std::endl; + mRankingInternalToken = posttoken; + } + return true; +} + +bool p3PostedServiceVEG::checkRankingRequest() +{ + uint32_t token = 0; + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if (!mProcessingRanking) + { + //std::cerr << "p3PostedServiceVEG::checkRankingRequest() Not Processing"; + //std::cerr << std::endl; + return false; + } + + if (mRankingState != POSTED_RANKINGS_INITIAL_CHECK) + { + std::cerr << "p3PostedServiceVEG::checkRankingRequest() Not in Initial Check"; + std::cerr << std::endl; + return false; + } + + /* here it actually running! */ + token = mRankingInternalToken; + + std::cerr << "p3PostedServiceVEG::checkRankingRequest() Running with token: " << token; + std::cerr << std::endl; + } + + + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + if (checkRequestStatus(token, status, reqtype, anstype, ts)) + { + std::cerr << "p3PostedServiceVEG::checkRankingRequest() checkRequestStatus => OK"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3PostedServiceVEG::checkRankingRequest() checkRequestStatus => ERROR"; + std::cerr << std::endl; + return false; + } + + if (status == GXS_REQUEST_STATUS_COMPLETE) + { + std::cerr << "p3PostedServiceVEG::checkRankingRequest() Init Complete => processPosts"; + std::cerr << std::endl; + + processPosts(); + } + return true; +} + + +bool p3PostedServiceVEG::processPosts() +{ + std::cerr << "p3PostedServiceVEG::processPosts()"; + std::cerr << std::endl; + + uint32_t token = 0; + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if (!mProcessingRanking) + { + std::cerr << "p3PostedServiceVEG::processPosts() ERROR Ranking Request not running"; + std::cerr << std::endl; + + return false; + } + + if (mRankingState != POSTED_RANKINGS_INITIAL_CHECK) + { + std::cerr << "p3PostedServiceVEG::processPosts() ERROR Ranking Request not running"; + std::cerr << std::endl; + + return false; + } + token = mRankingInternalToken; + } + + /* extract the info -> and sort */ + std::list postList; + std::list::const_iterator it; + + if (!getMsgSummary(token, postList)) + { + std::cerr << "p3PostedServiceVEG::processPosts() No Data for Request"; + std::cerr << std::endl; + + /* put it into a state, where the GUI will get to read an empty Queue */ + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mRankingState = POSTED_RANKINGS_NODATA; + + return false; + } + + std::multimap postMap; + std::multimap::reverse_iterator mit; + + for(it = postList.begin(); it != postList.end(); it++) + { + float score = calcPostScore(*it); + postMap.insert(std::make_pair(score, it->mMsgId)); + } + + /* now grab the N required, and request the data again... + * -> this is what will be passed back to GUI + */ + + std::list msgList; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + unsigned int i = 0; + for(mit = postMap.rbegin(); (mit != postMap.rend()) && (i < mViewStart); mit++, i++) + { + std::cerr << "p3PostedServiceVEG::processPosts() Skipping PostId: " << mit->second; + std::cerr << " with score: " << mit->first; + std::cerr << std::endl; + } + + + for(i = 0; (mit != postMap.rend()) && (i < mViewCount); mit++, i++) + { + std::cerr << "p3PostedServiceVEG::processPosts() Adding PostId: " << mit->second; + std::cerr << " with score: " << mit->first; + std::cerr << std::endl; + msgList.push_back(mit->second); + } + } + + token = 0; + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptionsVEG opts; + + requestMsgRelatedInfo(token, ansType, opts, msgList); + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mRankingState = POSTED_RANKINGS_DATA_REQUEST; + mRankingInternalToken = token; + + std::cerr << "p3PostedServiceVEG::processPosts() Second Stage: token: " << token; + std::cerr << std::endl; + } + return true; +} + + + + + + + + +/***** Background Processing **** + * + * Process Each Message - as it arrives. + * + * Update + * + */ + +#define POSTED_BG_REQUEST_GROUPS 1 +#define POSTED_BG_REQUEST_UNPROCESSED 2 +#define POSTED_BG_REQUEST_PARENTS 3 +#define POSTED_BG_PROCESS_VOTES 4 + +bool p3PostedServiceVEG::background_checkTokenRequest() +{ + uint32_t token = 0; + uint32_t phase = 0; + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + if (!mBgProcessing) + { + return false; + } + + token = mBgToken; + phase = mBgPhase; + } + + + uint32_t status; + uint32_t reqtype; + uint32_t anstype; + time_t ts; + checkRequestStatus(token, status, reqtype, anstype, ts); + + if (status == GXS_REQUEST_STATUS_COMPLETE) + { + switch(phase) + { + case POSTED_BG_REQUEST_GROUPS: + background_requestNewMessages(); + break; + case POSTED_BG_REQUEST_UNPROCESSED: + background_processNewMessages(); + break; + case POSTED_BG_REQUEST_PARENTS: + background_updateVoteCounts(); + break; + default: + break; + } + } + return true; +} + + +bool p3PostedServiceVEG::background_requestGroups() +{ + std::cerr << "p3PostedServiceVEG::background_requestGroups()"; + std::cerr << std::endl; + + // grab all the subscribed groups. + uint32_t token = 0; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + mBgProcessing = true; + mBgPhase = POSTED_BG_REQUEST_GROUPS; + mBgToken = 0; + } + + uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; + RsTokReqOptionsVEG opts; + std::list groupIds; + + opts.mSubscribeFilter = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; + + requestGroupInfo(token, ansType, opts, groupIds); + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mBgToken = token; + } + + return true; +} + + +bool p3PostedServiceVEG::background_requestNewMessages() +{ + std::cerr << "p3PostedServiceVEG::background_requestNewMessages()"; + std::cerr << std::endl; + + std::list groupIds; + uint32_t token = 0; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + token = mBgToken; + } + + if (!getGroupList(token, groupIds)) + { + std::cerr << "p3PostedServiceVEG::background_requestNewMessages() ERROR No Group List"; + std::cerr << std::endl; + background_cleanup(); + return false; + } + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mBgPhase = POSTED_BG_REQUEST_UNPROCESSED; + mBgToken = 0; + } + + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptionsVEG opts; + token = 0; + + opts.mStatusFilter = RSGXS_MSG_STATUS_UNPROCESSED; + opts.mStatusMask = RSGXS_MSG_STATUS_UNPROCESSED; + + requestMsgInfo(token, ansType, opts, groupIds); + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mBgToken = token; + } + return true; +} + + +bool p3PostedServiceVEG::background_processNewMessages() +{ + std::cerr << "p3PostedServiceVEG::background_processNewMessages()"; + std::cerr << std::endl; + + std::list newMsgList; + std::list::iterator it; + uint32_t token = 0; + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + token = mBgToken; + } + + if (!getMsgSummary(token, newMsgList)) + { + std::cerr << "p3PostedServiceVEG::background_processNewMessages() ERROR No New Msgs"; + std::cerr << std::endl; + background_cleanup(); + return false; + } + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mBgPhase = POSTED_BG_REQUEST_PARENTS; + mBgToken = 0; + mBgVoteMap.clear(); + mBgCommentMap.clear(); + } + + /* loop through and sort by parents. + * - grab + */ + + std::list parentList; + + std::map::iterator vit; + + for(it = newMsgList.begin(); it != newMsgList.end(); it++) + { + std::cerr << "Found New MsgId: " << it->mMsgId; + std::cerr << std::endl; + + /* discard threadheads */ + if (it->mParentId.empty()) + { + std::cerr << "\tIgnoring ThreadHead: " << *it; + std::cerr << std::endl; + } + else if (it->mMsgFlags & RSPOSTED_MSGTYPE_COMMENT) + { + /* Comments are counted by Thread Id */ + std::cerr << "\tProcessing Comment: " << *it; + std::cerr << std::endl; + + vit = mBgCommentMap.find(it->mThreadId); + if (vit == mBgCommentMap.end()) + { + mBgCommentMap[it->mThreadId] = 1; + + /* check VoteMap too before adding to parentList */ + if (mBgVoteMap.end() == mBgVoteMap.find(it->mThreadId)) + { + parentList.push_back(it->mThreadId); + } + + std::cerr << "\tThreadId: " << it->mThreadId; + std::cerr << " Comment Total: " << mBgCommentMap[it->mThreadId]; + std::cerr << std::endl; + } + else + { + mBgVoteMap[it->mThreadId]++; + std::cerr << "\tThreadId: " << it->mThreadId; + std::cerr << " Comment Total: " << mBgCommentMap[it->mThreadId]; + std::cerr << std::endl; + } + } + else if (it->mMsgFlags & RSPOSTED_MSGTYPE_VOTE) + { + /* Votes are organised by Parent Id, + * ie. you can vote for both Posts and Comments + */ + std::cerr << "\tProcessing Vote: " << *it; + std::cerr << std::endl; + + vit = mBgVoteMap.find(it->mParentId); + if (vit == mBgVoteMap.end()) + { + mBgVoteMap[it->mParentId] = 1; + + /* check CommentMap too before adding to parentList */ + if (mBgCommentMap.end() == mBgCommentMap.find(it->mParentId)) + { + parentList.push_back(it->mParentId); + } + + std::cerr << "\tParentId: " << it->mParentId; + std::cerr << " Vote Total: " << mBgVoteMap[it->mParentId]; + std::cerr << std::endl; + } + else + { + mBgVoteMap[it->mParentId]++; + std::cerr << "\tParentId: " << it->mParentId; + std::cerr << " Vote Total: " << mBgVoteMap[it->mParentId]; + std::cerr << std::endl; + } + } + else + { + /* unknown! */ + std::cerr << "p3PostedServiceVEG::background_processNewMessages() ERROR Strange NEW Message:"; + std::cerr << std::endl; + std::cerr << "\t" << *it; + std::cerr << std::endl; + + } + + /* flag each new vote as processed */ + setMessageStatus(it->mMsgId, 0, RSGXS_MSG_STATUS_UNPROCESSED); + } + + + /* request the summary info from the parents */ + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + token = 0; + RsTokReqOptionsVEG opts; + requestMsgRelatedInfo(token, ansType, opts, parentList); + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mBgToken = token; + } + return true; +} + + +bool p3PostedServiceVEG::encodePostedCache(std::string &str, uint32_t votes, uint32_t comments) +{ + char line[RSGXS_MAX_SERVICE_STRING]; + + snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d", votes, comments); + + str = line; + return true; +} + +bool p3PostedServiceVEG::extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments) +{ + + uint32_t ivotes, icomments; + if (2 == sscanf(str.c_str(), "%d %d", &ivotes, &icomments)) + { + votes = ivotes; + comments = icomments; + return true; + } + + return false; +} + + +bool p3PostedServiceVEG::background_updateVoteCounts() +{ + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts()"; + std::cerr << std::endl; + + std::list parentMsgList; + std::list::iterator it; + + if (!getMsgSummary(mBgToken, parentMsgList)) + { + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() ERROR"; + std::cerr << std::endl; + background_cleanup(); + return false; + } + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + mBgPhase = POSTED_BG_PROCESS_VOTES; + mBgToken = 0; + } + + for(it = parentMsgList.begin(); it != parentMsgList.end(); it++) + { + /* extract current vote count */ + uint32_t votes = 0; + uint32_t comments = 0; + + if (!extractPostedCache(it->mServiceString, votes, comments)) + { + if (!(it->mServiceString.empty())) + { + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Failed to extract Votes"; + std::cerr << std::endl; + std::cerr << "\tFrom String: " << it->mServiceString; + std::cerr << std::endl; + } + } + + /* find increment in votemap */ + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator vit; + vit = mBgVoteMap.find(it->mMsgId); + if (vit != mBgVoteMap.end()) + { + votes += vit->second; + } + else + { + // warning. + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Warning No New Votes found."; + std::cerr << " For MsgId: " << it->mMsgId; + std::cerr << std::endl; + } + + } + + { + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator cit; + cit = mBgCommentMap.find(it->mMsgId); + if (cit != mBgCommentMap.end()) + { + comments += cit->second; + } + else + { + // warning. + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Warning No New Comments found."; + std::cerr << " For MsgId: " << it->mMsgId; + std::cerr << std::endl; + } + + } + + std::string str; + if (!encodePostedCache(str, votes, comments)) + { + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Failed to encode Votes"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3PostedServiceVEG::background_updateVoteCounts() Encoded String: " << str; + std::cerr << std::endl; + /* store new result */ + setMessageServiceString(it->mMsgId, str); + } + } + + // DONE!. + background_cleanup(); + return true; + +} + + +bool p3PostedServiceVEG::background_cleanup() +{ + std::cerr << "p3PostedServiceVEG::background_cleanup()"; + std::cerr << std::endl; + + RsStackMutex stack(mPostedMtx); /********** STACK LOCKED MTX ******/ + + // Cleanup. + mBgVoteMap.clear(); + mBgCommentMap.clear(); + mBgProcessing = false; + mBgToken = 0; + + return true; +} + + diff --git a/libretroshare/src/services/p3postedVEG.h b/libretroshare/src/services/p3postedVEG.h new file mode 100644 index 000000000..f48bee9d0 --- /dev/null +++ b/libretroshare/src/services/p3postedVEG.h @@ -0,0 +1,190 @@ +/* + * libretroshare/src/services: p3posted.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_POSTED_SERVICE_VEG_HEADER +#define P3_POSTED_SERVICE_VEG_HEADER + +#include "services/p3gxsserviceVEG.h" +#include "retroshare/rspostedVEG.h" + +#include +#include + +/* + * Posted Service + * + */ + + +class PostedDataProxy: public GxsDataProxyVEG +{ + public: + + bool addGroup(const RsPostedGroup &group); + bool addPost(const RsPostedPost &post); + bool addVote(const RsPostedVote &vote); + bool addComment(const RsPostedComment &comment); + + bool getGroup(const std::string &id, RsPostedGroup &group); + bool getPost(const std::string &id, RsPostedPost &post); + bool getVote(const std::string &id, RsPostedVote &vote); + bool getComment(const std::string &id, RsPostedComment &comment); + + /* These Functions must be overloaded to complete the service */ +virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); +virtual bool convertMsgToMetaData(void *groupData, RsMsgMetaData &meta); + +}; + + + +class p3PostedServiceVEG: public p3GxsDataServiceVEG, public RsPostedVEG +{ + public: + + p3PostedServiceVEG(uint16_t type); + +virtual int tick(); + + public: + +// NEW INTERFACE. +/************* Extern Interface *******/ + +virtual bool updated(); + + /* Data Requests */ +virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds); +virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &groupIds); +virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptionsVEG &opts, const std::list &msgIds); + + /* Generic Lists */ +virtual bool getGroupList( const uint32_t &token, std::list &groupIds); +virtual bool getMsgList( const uint32_t &token, std::list &msgIds); + + /* Generic Summary */ +virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); +virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); + + /* Actual Data -> specific to Interface */ + /* Specific Service Data */ +virtual bool getGroup(const uint32_t &token, RsPostedGroup &group); +virtual bool getPost(const uint32_t &token, RsPostedPost &post); +virtual bool getComment(const uint32_t &token, RsPostedComment &comment); + + + /* Poll */ +virtual uint32_t requestStatus(const uint32_t token); + + /* Cancel Request */ +virtual bool cancelRequest(const uint32_t &token); + + ////////////////////////////////////////////////////////////////////////////// +virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); +virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); +virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); +virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); +virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); + +virtual bool groupRestoreKeys(const std::string &groupId); +virtual bool groupShareKeys(const std::string &groupId, std::list& peers); + +virtual bool submitGroup(uint32_t &token, RsPostedGroup &group, bool isNew); +virtual bool submitPost(uint32_t &token, RsPostedPost &post, bool isNew); +virtual bool submitVote(uint32_t &token, RsPostedVote &vote, bool isNew); +virtual bool submitComment(uint32_t &token, RsPostedComment &comment, bool isNew); + + // Extended Interface for Collated Data View. +virtual bool setViewMode(uint32_t mode); +virtual bool setViewPeriod(uint32_t period); +virtual bool setViewRange(uint32_t first, uint32_t count); + +virtual bool requestRanking(uint32_t &token, std::string groupId); +virtual bool getRankedPost(const uint32_t &token, RsPostedPost &post); + + + // These are exposed for GUI usage. +virtual bool encodePostedCache(std::string &str, uint32_t votes, uint32_t comments); +virtual bool extractPostedCache(const std::string &str, uint32_t &votes, uint32_t &comments); +virtual float calcPostScore(const RsMsgMetaData &meta); + + private: + + // +bool checkRankingRequest(); +bool processPosts(); + + // background processing of Votes. + // NB: These should probably be handled by a background thread. + // At the moment they are run from the tick() thread. + +bool background_checkTokenRequest(); +bool background_requestGroups(); +bool background_requestNewMessages(); +bool background_processNewMessages(); + +bool background_updateVoteCounts(); +bool background_cleanup(); + + + +std::string genRandomId(); +bool generateDummyData(); +bool addExtraDummyData(); + + PostedDataProxy *mPostedProxy; + + RsMutex mPostedMtx; + bool mUpdated; + + // Ranking view mode, stored here. + uint32_t mViewMode; + uint32_t mViewPeriod; + uint32_t mViewStart; + uint32_t mViewCount; + + // Processing Ranking stuff. + bool mProcessingRanking; + uint32_t mRankingState; + uint32_t mRankingExternalToken; + uint32_t mRankingInternalToken; + + // background processing - Mutex protected. + time_t mLastBgCheck; + bool mBgProcessing; + uint32_t mBgPhase; + uint32_t mBgToken; + + std::map mBgVoteMap; // ParentId -> Vote Count. + std::map mBgCommentMap; // ThreadId -> Comment Count. + + // extra dummy data. + std::list mDummyLaterVotes; + std::list mDummyLaterComments; + + +}; + +#endif diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc new file mode 100644 index 000000000..8f714fccf --- /dev/null +++ b/libretroshare/src/services/p3wiki.cc @@ -0,0 +1,739 @@ +/* + * libretroshare/src/services p3wiki.cc + * + * Wiki interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3wiki.h" +#include "serialiser/rswikiitems.h" + +#include "util/rsrandom.h" + +/**** + * #define WIKI_DEBUG 1 + ****/ + +RsWiki *rsWiki = NULL; + +/** + * #define WIKI_GEN_DUMMY_DATA 1 + **/ + +#define WIKI_GEN_DUMMY_DATA 1 + +#define WIKI_EVENT_DUMMYTICK 0x0001 +#define WIKI_EVENT_DUMMYSTART 0x0002 + +#define DUMMYSTART_PERIOD 60 // some time for dummyIds to be generated. +#define DUMMYTICK_PERIOD 3 + +p3Wiki::p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes) + :RsGenExchange(gds, nes, new RsGxsWikiSerialiser(), RS_SERVICE_GXSV1_TYPE_WIKI), RsWiki(this) +{ + // Setup of dummy Pages. + mAboutActive = false; + mImprovActive = false; + mMarkdownActive = false; + +#ifdef WIKI_GEN_DUMMY_DATA + RsTickEvent::schedule_in(WIKI_EVENT_DUMMYSTART, DUMMYSTART_PERIOD); +#endif + +} + +void p3Wiki::service_tick() +{ + RsTickEvent::tick_events(); + return; +} + + +void p3Wiki::notifyChanges(std::vector& changes) +{ + std::cerr << "p3Wiki::notifyChanges() New stuff"; + std::cerr << std::endl; + + receiveChanges(changes); +} + + /* Specific Service Data */ +bool p3Wiki::getCollections(const uint32_t &token, std::vector &collections) +{ + std::cerr << "p3Wiki::getCollections()"; + std::cerr << std::endl; + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsWikiCollectionItem* item = dynamic_cast(*vit); + + if (item) + { + RsWikiCollection collection = item->collection; + collection.mMeta = item->meta; + delete item; + collections.push_back(collection); + + std::cerr << "p3Wiki::getCollections() Adding Collection to Vector: "; + std::cerr << std::endl; + std::cerr << collection; + std::cerr << std::endl; + } + else + { + std::cerr << "Not a WikiCollectionItem, deleting!" << std::endl; + delete *vit; + } + + } + } + return ok; +} + + +bool p3Wiki::getSnapshots(const uint32_t &token, std::vector &snapshots) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsWikiSnapshotItem* item = dynamic_cast(*vit); + + if(item) + { + RsWikiSnapshot snapshot = item->snapshot; + snapshot.mMeta = item->meta; + snapshots.push_back(snapshot); + delete item; + } + else + { + std::cerr << "Not a WikiSnapshot Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + + +bool p3Wiki::getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) +{ + GxsMsgRelatedDataMap msgData; + bool ok = RsGenExchange::getMsgRelatedData(token, msgData); + + if(ok) + { + GxsMsgRelatedDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsWikiSnapshotItem* item = dynamic_cast(*vit); + + if(item) + { + RsWikiSnapshot snapshot = item->snapshot; + snapshot.mMeta = item->meta; + snapshots.push_back(snapshot); + delete item; + } + else + { + std::cerr << "Not a WikiSnapshot Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + + +bool p3Wiki::getComments(const uint32_t &token, std::vector &comments) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsWikiCommentItem* item = dynamic_cast(*vit); + + if(item) + { + RsWikiComment comment = item->comment; + comment.mMeta = item->meta; + comments.push_back(comment); + delete item; + } + else + { + std::cerr << "Not a WikiComment Item, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; + return false; +} + + + +bool p3Wiki::submitCollection(uint32_t &token, RsWikiCollection &collection) +{ + RsGxsWikiCollectionItem* collectionItem = new RsGxsWikiCollectionItem(); + collectionItem->collection = collection; + collectionItem->meta = collection.mMeta; + + std::cerr << "p3Wiki::submitCollection(): "; + std::cerr << std::endl; + std::cerr << collection; + std::cerr << std::endl; + + std::cerr << "p3Wiki::submitCollection() pushing to RsGenExchange"; + std::cerr << std::endl; + + RsGenExchange::publishGroup(token, collectionItem); + return true; +} + + +bool p3Wiki::submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) +{ + std::cerr << "p3Wiki::submitSnapshot(): " << snapshot; + std::cerr << std::endl; + + RsGxsWikiSnapshotItem* snapshotItem = new RsGxsWikiSnapshotItem(); + snapshotItem->snapshot = snapshot; + snapshotItem->meta = snapshot.mMeta; + snapshotItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_SNAPSHOT; + + RsGenExchange::publishMsg(token, snapshotItem); + return true; +} + + +bool p3Wiki::submitComment(uint32_t &token, RsWikiComment &comment) +{ + RsGxsWikiCommentItem* commentItem = new RsGxsWikiCommentItem(); + commentItem->comment = comment; + commentItem->meta = comment.mMeta; + commentItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_COMMENT; + + RsGenExchange::publishMsg(token, commentItem); + return true; +} + + + +std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group) +{ + out << "RsWikiCollection [ "; + out << " Name: " << group.mMeta.mGroupName; + out << " Desc: " << group.mDescription; + out << " Category: " << group.mCategory; + out << " ]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot) +{ + out << "RsWikiSnapshot [ "; + out << "Title: " << shot.mMeta.mMsgName; + out << "]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment) +{ + out << "RsWikiComment [ "; + out << "Title: " << comment.mMeta.mMsgName; + out << "]"; + return out; +} + + +/***** FOR TESTING *****/ + +std::string p3Wiki::genRandomId() +{ + std::string randomId; + for(int i = 0; i < 20; i++) + { + randomId += (char) ('a' + (RSRandom::random_u32() % 26)); + } + + return randomId; +} + +const int about_len = 10; +const std::string about_txt[] = + { "Welcome to RsWiki, a fully distributed Wiki system that anyone can edit.", + "Please read through these dummy Wiki pages to learn how it should work\n", + "Basic Functionality:", + " - New Group: creates a collection of Wiki Pages, the creator of group", + " and anyone they share the publish keys with) is the moderator\n", + " - New Page: Create a new Wiki Page, only Group Moderators can do this\n", + " - Edit: Anyone Can Edit the Wiki Page, and the changes form a tree under the original\n", + " - RePublish: This is used by the Moderators to accept and reject Edits.", + " the republished page becomes a new version of the Root Page, allowing more edits to be done\n", + "Please read the improvements section to see how we envision the wiki's working", + }; + + +const int improvements_len = 14; +const std::string improvements_txt[] = + { "As you can see, the current Wiki is a basic framework waiting to be expanded.", + "There are lots of potential improvements... some of my ideas are listed below\n", + "Ideas:", + " - Formatting: No HTML, lets use Markdown or something similar.\n", + " - Diffs, lots of edits will lead to complex merges - a robust merge tool is essential\n", + " - Read Mode... hide all the Edits, and only show the most recently published versions\n", + " - Easy Duplication - to take over an Abandoned or badly moderated Wiki. Copies All base versions to a new group\n", + " - WikiLinks. A generic Wiki Cross Linking system. This should be combined with Easy Duplication option,", + " to allow easy replacement of groups if necessary... A good design here is critical to a successful Wiki ecosystem\n", + " - work out how to include media (photos, audio, video, etc) without embedding in pages", + " this would leverage the turtle transfer system somehow - maybe like channels.\n", + " - Comments, reviews etc can be incorporated - ideas here are welcome.\n", + " - Any other suggestion???", + " - Come on more ideas!" + }; + + +const int markdown_len = 34; +const std::string markdown_txt[] = { + "# An Example of Markdown Editing.", + "", + "Markdown is quite simple to use, and allows simple HTML.", + "", + "## Some Blocks below an H2 heading.", + "", + " * Firstly, we can put a link [in here][]", + " * Secondly, as you can see we're in a list.", + " * Thirdly, I don't know.", + "", + "### A Sub (H3) heading.", + "", + "#### If we want to get into the very small details. (H6).", + "", + " A bit of code.", + " This is a lit", + " foreach(in loop)", + " a++", + " Double quoted stuff.", + "", + "Or it can be indented like this:", + "", + "> A block of indented stuff looks like this", + "> > With double indenting and ", + "> > > triple indenting possible too", + "", + "Images can be embedded, but thats somethinng to work on in the future.", + "", + "Sadly it doesn't support tables or div's or anything that complex.", + "", + "Keep it simple and help write good wiki pages, thx.", + "", + "[in here]: http://example.com/ \"Optional Title Here\"", + "" + }; + + +void p3Wiki::generateDummyData() +{ + std::cerr << "p3Wiki::generateDummyData()"; + std::cerr << std::endl; + +#define GEN_COLLECTIONS 0 + + int i; + for(i = 0; i < GEN_COLLECTIONS; i++) + { + RsWikiCollection wiki; + wiki.mMeta.mGroupId = genRandomId(); + wiki.mMeta.mGroupFlags = 0; + wiki.mMeta.mGroupName = genRandomId(); + + uint32_t dummyToken = 0; + submitCollection(dummyToken, wiki); + } + + + RsWikiCollection wiki; + wiki.mMeta.mGroupFlags = 0; + wiki.mMeta.mGroupName = "About RsWiki"; + + submitCollection(mAboutToken, wiki); + + wiki.mMeta.mGroupFlags = 0; + wiki.mMeta.mGroupName = "RsWiki Improvements"; + + submitCollection(mImprovToken, wiki); + + wiki.mMeta.mGroupFlags = 0; + wiki.mMeta.mGroupName = "RsWiki Markdown"; + + submitCollection(mMarkdownToken, wiki); + + mAboutLines = 0; + mImprovLines = 0; + mMarkdownLines = 0; + + mAboutActive = true; + mImprovActive = true; + mMarkdownActive = true; + + RsTickEvent::schedule_in(WIKI_EVENT_DUMMYTICK, DUMMYTICK_PERIOD); +} + + +bool generateNextDummyPage(const RsGxsMessageId &threadId, const int lines, const RsGxsGrpMsgIdPair &parentId, + const std::string *page_lines, const int num_pagelines, RsWikiSnapshot &snapshot) +{ + snapshot.mMeta.mGroupId = parentId.first; + + // Create an About Page. +#define NUM_SUB_PAGES 3 + + if ((lines % NUM_SUB_PAGES == 0) || (lines == num_pagelines)) + { + /* do a new baseline */ + snapshot.mMeta.mOrigMsgId = threadId; + } + else + { + snapshot.mMeta.mParentId = parentId.second; + snapshot.mMeta.mThreadId = threadId; + } + + std::string page; + for(int i = 0; (i < lines) && (i < num_pagelines); i++) + { + snapshot.mPage += page_lines[i]; + snapshot.mPage += '\n'; + } + + return (lines <= num_pagelines); +} + + +#include + +std::string chooseRandomAuthorId() +{ + /* chose a random Id to sign with */ + std::list ownIds; + std::list::iterator it; + + rsIdentity->getOwnIds(ownIds); + + uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); + int i = 0; + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + + std::string answer; + if (it != ownIds.end()) + { + answer = *it; + } + return answer; +} + + + +void p3Wiki::dummyTick() +{ + if (mAboutActive) + { + std::cerr << "p3Wiki::dummyTick() AboutActive"; + std::cerr << std::endl; + + uint32_t status = RsGenExchange::getTokenService()->requestStatus(mAboutToken); + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::cerr << "p3Wiki::dummyTick() AboutActive, Lines: " << mAboutLines; + std::cerr << std::endl; + + if (mAboutLines == 0) + { + /* get the group Id */ + RsGxsGroupId groupId; + if (!acknowledgeTokenGrp(mAboutToken, groupId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mAboutActive = false; + } + + /* create baseline snapshot */ + RsWikiSnapshot page; + page.mMeta.mGroupId = groupId; + page.mPage = "Baseline page... a placeholder for About Wiki"; + page.mMeta.mMsgName = "About RsWiki"; + page.mMeta.mAuthorId = chooseRandomAuthorId(); + + submitSnapshot(mAboutToken, page); + mAboutLines++; + } + else + { + /* get the msg Id, and generate next snapshot */ + RsGxsGrpMsgIdPair msgId; + if (!acknowledgeTokenMsg(mAboutToken, msgId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mAboutActive = false; + } + + if (mAboutLines == 1) + { + mAboutThreadId = msgId.second; + } + + RsWikiSnapshot page; + page.mMeta.mMsgName = "About RsWiki"; + page.mMeta.mAuthorId = chooseRandomAuthorId(); + if (!generateNextDummyPage(mAboutThreadId, mAboutLines, msgId, about_txt, about_len, page)) + { + std::cerr << "About Pages Done"; + std::cerr << std::endl; + mAboutActive = false; + } + else + { + mAboutLines++; + submitSnapshot(mAboutToken, page); + } + } + } + } + + if (mImprovActive) + { + std::cerr << "p3Wiki::dummyTick() ImprovActive"; + std::cerr << std::endl; + + uint32_t status = RsGenExchange::getTokenService()->requestStatus(mImprovToken); + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::cerr << "p3Wiki::dummyTick() ImprovActive, Lines: " << mImprovLines; + std::cerr << std::endl; + + if (mImprovLines == 0) + { + /* get the group Id */ + RsGxsGroupId groupId; + if (!acknowledgeTokenGrp(mImprovToken, groupId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mImprovActive = false; + } + + /* create baseline snapshot */ + RsWikiSnapshot page; + page.mMeta.mGroupId = groupId; + page.mPage = "Baseline page... a placeholder for Improv Wiki"; + page.mMeta.mMsgName = "Improv RsWiki"; + page.mMeta.mAuthorId = chooseRandomAuthorId(); + + submitSnapshot(mImprovToken, page); + mImprovLines++; + } + else + { + /* get the msg Id, and generate next snapshot */ + RsGxsGrpMsgIdPair msgId; + if (!acknowledgeTokenMsg(mImprovToken, msgId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mImprovActive = false; + } + + if (mImprovLines == 1) + { + mImprovThreadId = msgId.second; + } + + RsWikiSnapshot page; + page.mMeta.mMsgName = "Improv RsWiki"; + page.mMeta.mAuthorId = chooseRandomAuthorId(); + if (!generateNextDummyPage(mImprovThreadId, mImprovLines, msgId, improvements_txt, improvements_len, page)) + { + std::cerr << "Improv Pages Done"; + std::cerr << std::endl; + mImprovActive = false; + } + else + { + mImprovLines++; + submitSnapshot(mImprovToken, page); + } + } + } + } + + + if (mMarkdownActive) + { + std::cerr << "p3Wiki::dummyTick() MarkdownActive"; + std::cerr << std::endl; + + uint32_t status = RsGenExchange::getTokenService()->requestStatus(mMarkdownToken); + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::cerr << "p3Wiki::dummyTick() MarkdownActive, Lines: " << mMarkdownLines; + std::cerr << std::endl; + + if (mMarkdownLines == 0) + { + /* get the group Id */ + RsGxsGroupId groupId; + if (!acknowledgeTokenGrp(mMarkdownToken, groupId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mMarkdownActive = false; + } + + /* create baseline snapshot */ + RsWikiSnapshot page; + page.mMeta.mGroupId = groupId; + page.mPage = "Baseline page... a placeholder for Markdown Wiki"; + page.mMeta.mMsgName = "Markdown RsWiki"; + page.mMeta.mAuthorId = chooseRandomAuthorId(); + + submitSnapshot(mMarkdownToken, page); + mMarkdownLines++; + } + else + { + /* get the msg Id, and generate next snapshot */ + RsGxsGrpMsgIdPair msgId; + if (!acknowledgeTokenMsg(mMarkdownToken, msgId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mMarkdownActive = false; + } + + if (mMarkdownLines == 1) + { + mMarkdownThreadId = msgId.second; + } + + RsWikiSnapshot page; + page.mMeta.mMsgName = "Markdown RsWiki"; + page.mMeta.mAuthorId = chooseRandomAuthorId(); + if (!generateNextDummyPage(mMarkdownThreadId, mMarkdownLines, msgId, markdown_txt, markdown_len, page)) + { + std::cerr << "Markdown Pages Done"; + std::cerr << std::endl; + mMarkdownActive = false; + } + else + { + mMarkdownLines++; + submitSnapshot(mMarkdownToken, page); + } + } + } + } + + if ((mAboutActive) || (mImprovActive) || (mMarkdownActive)) + { + /* reschedule next one */ + RsTickEvent::schedule_in(WIKI_EVENT_DUMMYTICK, DUMMYTICK_PERIOD); + } +} + + + + + + // Overloaded from RsTickEvent for Event callbacks. +void p3Wiki::handle_event(uint32_t event_type, const std::string &elabel) +{ + std::cerr << "p3Wiki::handle_event(" << event_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(event_type) + { + case WIKI_EVENT_DUMMYSTART: + generateDummyData(); + break; + + case WIKI_EVENT_DUMMYTICK: + dummyTick(); + break; + + default: + /* error */ + std::cerr << "p3Wiki::handle_event() Unknown Event Type: " << event_type; + std::cerr << std::endl; + break; + } +} + + diff --git a/libretroshare/src/services/p3wiki.h b/libretroshare/src/services/p3wiki.h new file mode 100644 index 000000000..94b60c696 --- /dev/null +++ b/libretroshare/src/services/p3wiki.h @@ -0,0 +1,99 @@ +/* + * libretroshare/src/services: p3wikiservice.h + * + * Wiki interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_WIKI_SERVICE_HEADER +#define P3_WIKI_SERVICE_HEADER + +#include "retroshare/rswiki.h" +#include "gxs/rsgenexchange.h" + +#include "util/rstickevent.h" + +#include +#include + +/* + * Wiki Service + * + * + */ + +class p3Wiki: public RsGenExchange, public RsWiki, + public RsTickEvent +{ +public: + p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes); + +protected: + +virtual void notifyChanges(std::vector& changes) ; + + // Overloaded from RsTickEvent. +virtual void handle_event(uint32_t event_type, const std::string &elabel); + +public: + +virtual void service_tick(); + + /* Specific Service Data */ +virtual bool getCollections(const uint32_t &token, std::vector &collections); +virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots); +virtual bool getComments(const uint32_t &token, std::vector &comments); + +virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &snapshots); + +virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection); +virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot); +virtual bool submitComment(uint32_t &token, RsWikiComment &comment); + + + private: + +std::string genRandomId(); +// RsMutex mWikiMtx; + + +virtual void generateDummyData(); + + // Dummy Stuff. + void dummyTick(); + + bool mAboutActive; + uint32_t mAboutToken; + int mAboutLines; + RsGxsMessageId mAboutThreadId; + + bool mImprovActive; + uint32_t mImprovToken; + int mImprovLines; + RsGxsMessageId mImprovThreadId; + + bool mMarkdownActive; + uint32_t mMarkdownToken; + int mMarkdownLines; + RsGxsMessageId mMarkdownThreadId; +}; + +#endif diff --git a/libretroshare/src/services/p3wikiservice.cc b/libretroshare/src/services/p3wikiservice.cc deleted file mode 100644 index 94c45376f..000000000 --- a/libretroshare/src/services/p3wikiservice.cc +++ /dev/null @@ -1,595 +0,0 @@ -/* - * libretroshare/src/services p3wikiservice.cc - * - * Wiki interface for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/p3wikiservice.h" - -#include "util/rsrandom.h" - -/**** - * #define WIKI_DEBUG 1 - ****/ - -RsWiki *rsWiki = NULL; - - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3WikiService::p3WikiService(uint16_t type) - :p3GxsDataService(type, new WikiDataProxy()), mWikiMtx("p3WikiService"), mUpdated(true) -{ - RsStackMutex stack(mWikiMtx); /********** STACK LOCKED MTX ******/ - - mWikiProxy = (WikiDataProxy *) mProxy; - return; -} - - -int p3WikiService::tick() -{ - std::cerr << "p3WikiService::tick()"; - std::cerr << std::endl; - - fakeprocessrequests(); - - return 0; -} - -bool p3WikiService::updated() -{ - RsStackMutex stack(mWikiMtx); /********** STACK LOCKED MTX ******/ - - if (mUpdated) - { - mUpdated = false; - return true; - } - return false; -} - - - - /* Data Requests */ -bool p3WikiService::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3WikiService::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3WikiService::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3WikiService::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3WikiService::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3WikiService::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3WikiService::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3WikiService::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3WikiService::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3WikiService::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3WikiService::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3WikiService::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3WikiService::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3WikiService::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3WikiService::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3WikiService::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3WikiService::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3WikiService::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3WikiService::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3WikiService::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3WikiService::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3WikiService::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - - /* Specific Service Data */ -bool p3WikiService::getGroupData(const uint32_t &token, RsWikiGroup &group) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3WikiService::getGroupData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3WikiService::getGroupData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3WikiService::getGroupData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsWikiAlbum */ - bool ans = mWikiProxy->getGroup(id, group); - return ans; -} - - -bool p3WikiService::getMsgData(const uint32_t &token, RsWikiPage &page) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3WikiService::getMsgData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3WikiService::getMsgData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3WikiService::getMsgData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsWikiAlbum */ - bool ans = mWikiProxy->getPage(id, page); - return ans; -} - - - - /* Poll */ -uint32_t p3WikiService::requestStatus(const uint32_t token) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - return status; -} - - - /* Cancel Request */ -bool p3WikiService::cancelRequest(const uint32_t &token) -{ - return clearRequest(token); -} - - - ////////////////////////////////////////////////////////////////////////////// -bool p3WikiService::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) -{ - return mWikiProxy->setMessageStatus(msgId, status, statusMask); -} - -bool p3WikiService::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mWikiProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3WikiService::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mWikiProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3WikiService::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mWikiProxy->setMessageServiceString(msgId, str); -} - -bool p3WikiService::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mWikiProxy->setGroupServiceString(grpId, str); -} - - -bool p3WikiService::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3WikiService::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - -/********************************************************************************************/ - - -std::string p3WikiService::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3WikiService::createGroup(uint32_t &token, RsWikiGroup &group, bool isNew) -{ - if (group.mMeta.mGroupId.empty()) - { - /* new photo */ - - /* generate a temp id */ - group.mMeta.mGroupId = genRandomId(); - } - else - { - std::cerr << "p3WikiService::createGroup() Group with existing Id... dropping"; - std::cerr << std::endl; - return false; - } - - { - RsStackMutex stack(mWikiMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mWikiProxy->addGroup(group); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3WikiService::createGroup() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - - - -bool p3WikiService::createPage(uint32_t &token, RsWikiPage &page, bool isNew) -{ - if (page.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3WikiService::createPage() Missing PageID"; - std::cerr << std::endl; - return false; - } - - /* check if its a mod or new page */ - if (page.mMeta.mOrigMsgId.empty()) - { - std::cerr << "p3WikiService::createPage() New Page"; - std::cerr << std::endl; - - /* new page, generate a new OrigPageId */ - page.mMeta.mOrigMsgId = genRandomId(); - page.mMeta.mMsgId = page.mMeta.mOrigMsgId; - } - else - { - std::cerr << "p3WikiService::createPage() Modified Page"; - std::cerr << std::endl; - - /* mod page, keep orig page id, generate a new PageId */ - page.mMeta.mMsgId = genRandomId(); - } - - std::cerr << "p3WikiService::createPage() GroupId: " << page.mMeta.mGroupId; - std::cerr << std::endl; - std::cerr << "p3WikiService::createPage() PageId: " << page.mMeta.mMsgId; - std::cerr << std::endl; - std::cerr << "p3WikiService::createPage() OrigPageId: " << page.mMeta.mOrigMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mWikiMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mWikiProxy->addPage(page); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(page.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3WikiService::createPage() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - - - -bool WikiDataProxy::getGroup(const std::string &id, RsWikiGroup &group) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsWikiGroup *pG = (RsWikiGroup *) groupData; - group = *pG; - - // update definitive version of the metadata. - group.mMeta = meta; - - std::cerr << "WikiDataProxy::getGroup() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; - return true; - } - - std::cerr << "WikiDataProxy::getGroup() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool WikiDataProxy::getPage(const std::string &id, RsWikiPage &page) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsWikiPage *pP = (RsWikiPage *) msgData; - // Shallow copy of thumbnail. - page = *pP; - - // update definitive version of the metadata. - page.mMeta = meta; - - std::cerr << "WikiDataProxy::getPage() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - - std::cerr << "WikiDataProxy::getPage() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool WikiDataProxy::addGroup(const RsWikiGroup &group) -{ - // Make duplicate. - RsWikiGroup *pG = new RsWikiGroup(); - *pG = group; - - std::cerr << "WikiDataProxy::addGroup()"; - std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; - std::cerr << std::endl; - - return createGroup(pG); -} - - -bool WikiDataProxy::addPage(const RsWikiPage &page) -{ - // Make duplicate. - RsWikiPage *pP = new RsWikiPage(); - *pP = page; - - std::cerr << "WikiDataProxy::addPage()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - - - /* These Functions must be overloaded to complete the service */ -bool WikiDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsWikiGroup *group = (RsWikiGroup *) groupData; - meta = group->mMeta; - - return true; -} - -bool WikiDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsWikiPage *page = (RsWikiPage *) msgData; - meta = page->mMeta; - - return true; -} diff --git a/libretroshare/src/services/p3wikiservice.h b/libretroshare/src/services/p3wikiservice.h deleted file mode 100644 index a7a2cbe04..000000000 --- a/libretroshare/src/services/p3wikiservice.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * libretroshare/src/services: p3wikiservice.h - * - * Wiki interface for RetroShare. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef P3_WIKI_SERVICE_HEADER -#define P3_WIKI_SERVICE_HEADER - -#include "services/p3gxsservice.h" -#include "retroshare/rswiki.h" - -#include -#include - -/* - * Wiki Service - * - * This is an example service for the new cache system. - * For the moment, it will only hold data passed to it from the GUI. - * and spew that back when asked.... - * - * We are doing it like this - so we can check the required interface functionality. - * - * Expect it won't take long before it'll be properly linked into the backend! - * - * This will be transformed into a Plugin Service, once the basics have been worked out. - * - */ - -class WikiDataProxy: public GxsDataProxy -{ - public: - - bool getGroup(const std::string &id, RsWikiGroup &group); - bool getPage(const std::string &id, RsWikiPage &wiki); - - bool addGroup(const RsWikiGroup &group); - bool addPage(const RsWikiPage &page); - - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *msgData, RsMsgMetaData &meta); -}; - - -class p3WikiService: public p3GxsDataService, public RsWiki -{ - public: - - p3WikiService(uint16_t type); - -virtual int tick(); - - public: - - -virtual bool updated(); - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds); - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); - - /* Actual Data -> specific to Interface */ - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsWikiGroup &group); -virtual bool getMsgData(const uint32_t &token, RsWikiPage &page); - - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); - - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - -virtual bool createGroup(uint32_t &token, RsWikiGroup &group, bool isNew); -virtual bool createPage(uint32_t &token, RsWikiPage &page, bool isNew); - - private: - -std::string genRandomId(); - - WikiDataProxy *mWikiProxy; - - RsMutex mWikiMtx; - - bool mUpdated; - - -}; - -#endif diff --git a/libretroshare/src/services/p3wire.cc b/libretroshare/src/services/p3wire.cc index c06c9e58b..a25fe9112 100644 --- a/libretroshare/src/services/p3wire.cc +++ b/libretroshare/src/services/p3wire.cc @@ -24,575 +24,184 @@ */ #include "services/p3wire.h" +#include "serialiser/rswireitems.h" #include "util/rsrandom.h" /**** - * #define WIKI_DEBUG 1 + * #define WIRE_DEBUG 1 ****/ RsWire *rsWire = NULL; -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3Wire::p3Wire(uint16_t type) - :p3GxsDataService(type, new WireDataProxy()), mWireMtx("p3Wire"), mUpdated(true) +p3Wire::p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes) + :RsGenExchange(gds, nes, new RsGxsWireSerialiser(), RS_SERVICE_GXSV1_TYPE_WIRE), RsWire(this), mWireMtx("WireMtx") { - RsStackMutex stack(mWireMtx); /********** STACK LOCKED MTX ******/ - mWireProxy = (WireDataProxy *) mProxy; +} + +void p3Wire::service_tick() +{ return; } -int p3Wire::tick() +void p3Wire::notifyChanges(std::vector& changes) { - std::cerr << "p3Wire::tick()"; + std::cerr << "p3Wire::notifyChanges() New stuff"; std::cerr << std::endl; - fakeprocessrequests(); - - return 0; + receiveChanges(changes); } -bool p3Wire::updated() -{ - RsStackMutex stack(mWireMtx); /********** STACK LOCKED MTX ******/ - - if (mUpdated) - { - mUpdated = false; - return true; - } - return false; -} - - - - /* Data Requests */ -bool p3Wire::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3Wire::requestGroupInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; -} - -bool p3Wire::requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) -{ - generateToken(token); - std::cerr << "p3Wire::requestMsgInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGS, groupIds); - - return true; -} - -bool p3Wire::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds) -{ - generateToken(token); - std::cerr << "p3Wire::requestMsgRelatedInfo() gets Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - /* Generic Lists */ -bool p3Wire::getGroupList( const uint32_t &token, std::list &groupIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3Wire::getGroupList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3Wire::getGroupList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3Wire::getGroupList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - - -bool p3Wire::getMsgList( const uint32_t &token, std::list &msgIds) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_LIST) - { - std::cerr << "p3Wire::getMsgList() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3Wire::getMsgList() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3Wire::getMsgList() ERROR Status Incomplete" << std::endl; - return false; - } - - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - return ans; -} - - - /* Generic Summary */ -bool p3Wire::getGroupSummary( const uint32_t &token, std::list &groupInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3Wire::getGroupSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if (reqtype != GXS_REQUEST_TYPE_GROUPS) - { - std::cerr << "p3Wire::getGroupSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3Wire::getGroupSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list groupIds; - bool ans = loadRequestOutList(token, groupIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsGroupMetaData */ - mProxy->getGroupSummary(groupIds, groupInfo); - - return ans; -} - -bool p3Wire::getMsgSummary( const uint32_t &token, std::list &msgInfo) -{ - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - - if (anstype != RS_TOKREQ_ANSTYPE_SUMMARY) - { - std::cerr << "p3Wire::getMsgSummary() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3Wire::getMsgSummary() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3Wire::getMsgSummary() ERROR Status Incomplete" << std::endl; - return false; - } - - std::list msgIds; - bool ans = loadRequestOutList(token, msgIds); - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - - /* convert to RsMsgMetaData */ - mProxy->getMsgSummary(msgIds, msgInfo); - - return ans; -} - - /* Specific Service Data */ -bool p3Wire::getGroupData(const uint32_t &token, RsWireGroup &group) +bool p3Wire::getGroupData(const uint32_t &token, std::vector &groups) { - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - + std::cerr << "p3Wire::getGroupData()"; + std::cerr << std::endl; - if (anstype != RS_TOKREQ_ANSTYPE_DATA) + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) { - std::cerr << "p3Wire::getGroupData() ERROR AnsType Wrong" << std::endl; - return false; + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsWireGroupItem* item = dynamic_cast(*vit); + + if (item) + { + RsWireGroup group = item->group; + group.mMeta = item->meta; + delete item; + groups.push_back(group); + + std::cerr << "p3Wire::getGroupData() Adding WireGroup to Vector: "; + std::cerr << std::endl; + std::cerr << group; + std::cerr << std::endl; + } + else + { + std::cerr << "Not a WireGroupItem, deleting!" << std::endl; + delete *vit; + } + + } } + return ok; +} + + +bool p3Wire::getPulseData(const uint32_t &token, std::vector &pulses) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); - if (reqtype != GXS_REQUEST_TYPE_GROUPS) + if(ok) { - std::cerr << "p3Wire::getGroupData() ERROR ReqType Wrong" << std::endl; - return false; + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsWirePulseItem* item = dynamic_cast(*vit); + + if(item) + { + RsWirePulse pulse = item->pulse; + pulse.mMeta = item->meta; + pulses.push_back(pulse); + delete item; + } + else + { + std::cerr << "Not a WikiPulse Item, deleting!" << std::endl; + delete *vit; + } + } + } } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3Wire::getGroupData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsWireGroup */ - bool ans = mWireProxy->getGroup(id, group); - return ans; + return ok; } -bool p3Wire::getMsgData(const uint32_t &token, RsWirePulse &pulse) +bool p3Wire::createGroup(uint32_t &token, RsWireGroup &group) { - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); - + RsGxsWireGroupItem* groupItem = new RsGxsWireGroupItem(); + groupItem->group = group; + groupItem->meta = group.mMeta; - if (anstype != RS_TOKREQ_ANSTYPE_DATA) - { - std::cerr << "p3Wire::getMsgData() ERROR AnsType Wrong" << std::endl; - return false; - } - - if ((reqtype != GXS_REQUEST_TYPE_MSGS) && (reqtype != GXS_REQUEST_TYPE_MSGRELATED)) - { - std::cerr << "p3Wire::getMsgData() ERROR ReqType Wrong" << std::endl; - return false; - } - - if (status != GXS_REQUEST_STATUS_COMPLETE) - { - std::cerr << "p3Wire::getMsgData() ERROR Status Incomplete" << std::endl; - return false; - } - - std::string id; - if (!popRequestOutList(token, id)) - { - /* finished */ - updateRequestStatus(token, GXS_REQUEST_STATUS_DONE); - return false; - } - - /* convert to RsWirePulse */ - bool ans = mWireProxy->getPulse(id, pulse); - return ans; + std::cerr << "p3Wire::createGroup(): "; + std::cerr << std::endl; + std::cerr << group; + std::cerr << std::endl; + + std::cerr << "p3Wire::createGroup() pushing to RsGenExchange"; + std::cerr << std::endl; + + RsGenExchange::publishGroup(token, groupItem); + return true; } - - /* Poll */ -uint32_t p3Wire::requestStatus(const uint32_t token) +bool p3Wire::createPulse(uint32_t &token, RsWirePulse &pulse) { - uint32_t status; - uint32_t reqtype; - uint32_t anstype; - time_t ts; - checkRequestStatus(token, status, reqtype, anstype, ts); + std::cerr << "p3Wire::createPulse(): " << pulse; + std::cerr << std::endl; - return status; + RsGxsWirePulseItem* pulseItem = new RsGxsWirePulseItem(); + pulseItem->pulse = pulse; + pulseItem->meta = pulse.mMeta; + + RsGenExchange::publishMsg(token, pulseItem); + return true; } - /* Cancel Request */ -bool p3Wire::cancelRequest(const uint32_t &token) +std::ostream &operator<<(std::ostream &out, const RsWireGroup &group) { - return clearRequest(token); + out << "RsWireGroup [ "; + out << " Name: " << group.mMeta.mGroupName; + out << " Desc: " << group.mDescription; + //out << " Category: " << group.mCategory; + out << " ]"; + return out; } - ////////////////////////////////////////////////////////////////////////////// - -bool p3Wire::setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask) +std::ostream &operator<<(std::ostream &out, const RsWirePulse &pulse) { - return mWireProxy->setMessageStatus(msgId, status, statusMask); + out << "RsWirePulse [ "; + out << "Title: " << pulse.mMeta.mMsgName; + out << "PulseText: " << pulse.mPulseText; + out << "]"; + return out; } +/***** FOR TESTING *****/ -bool p3Wire::setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask) -{ - return mWireProxy->setGroupStatus(groupId, status, statusMask); -} - -bool p3Wire::setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask) -{ - return mWireProxy->setGroupSubscribeFlags(groupId, subscribeFlags, subscribeMask); -} - -bool p3Wire::setMessageServiceString(const std::string &msgId, const std::string &str) -{ - return mWireProxy->setMessageServiceString(msgId, str); -} - -bool p3Wire::setGroupServiceString(const std::string &grpId, const std::string &str) -{ - return mWireProxy->setGroupServiceString(grpId, str); -} - - -bool p3Wire::groupRestoreKeys(const std::string &groupId) -{ - return false; -} - -bool p3Wire::groupShareKeys(const std::string &groupId, std::list& peers) -{ - return false; -} - - -/********************************************************************************************/ - - std::string p3Wire::genRandomId() { - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - + std::string randomId; + for(int i = 0; i < 20; i++) + { + randomId += (char) ('a' + (RSRandom::random_u32() % 26)); + } -bool p3Wire::createGroup(uint32_t &token, RsWireGroup &group, bool isNew) + return randomId; +} + +void p3Wire::generateDummyData() { - if (group.mMeta.mGroupId.empty()) - { - /* new photo */ - /* generate a temp id */ - group.mMeta.mGroupId = genRandomId(); - } - else - { - std::cerr << "p3Wire::createGroup() Group with existing Id... dropping"; - std::cerr << std::endl; - return false; - } - - { - RsStackMutex stack(mWireMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mWireProxy->addGroup(group); - } - - // Fake a request to return the GroupMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); // It will just return this one. - - std::cerr << "p3Wiree::createGroup() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_GROUPS, groupIds); - - return true; } - - -bool p3Wire::createPulse(uint32_t &token, RsWirePulse &pulse, bool isNew) -{ - if (pulse.mMeta.mGroupId.empty()) - { - /* new photo */ - std::cerr << "p3Wire::createPulse() Missing PulseID"; - std::cerr << std::endl; - return false; - } - - /* check if its a mod or new pulse */ - if (pulse.mMeta.mOrigMsgId.empty()) - { - std::cerr << "p3Wire::createPulse() New Pulse"; - std::cerr << std::endl; - - /* new pulse, generate a new OrigPulseId */ - pulse.mMeta.mOrigMsgId = genRandomId(); - pulse.mMeta.mMsgId = pulse.mMeta.mOrigMsgId; - } - else - { - std::cerr << "p3Wire::createPulse() Modified Pulse"; - std::cerr << std::endl; - - /* mod pulse, keep orig pulse id, generate a new PulseId */ - pulse.mMeta.mMsgId = genRandomId(); - } - - std::cerr << "p3Wire::createPulse() GroupId: " << pulse.mMeta.mGroupId; - std::cerr << std::endl; - std::cerr << "p3Wire::createPulse() PulseId: " << pulse.mMeta.mMsgId; - std::cerr << std::endl; - std::cerr << "p3Wire::createPulse() OrigPulseId: " << pulse.mMeta.mOrigMsgId; - std::cerr << std::endl; - - { - RsStackMutex stack(mWireMtx); /********** STACK LOCKED MTX ******/ - - mUpdated = true; - mWireProxy->addPulse(pulse); - } - - // Fake a request to return the MsgMetaData. - generateToken(token); - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; // NULL is good. - std::list msgIds; - msgIds.push_back(pulse.mMeta.mMsgId); // It will just return this one. - - std::cerr << "p3Wire::createPulse() Generating Request Token: " << token << std::endl; - storeRequest(token, ansType, opts, GXS_REQUEST_TYPE_MSGRELATED, msgIds); - - return true; -} - - - -/********************************************************************************************/ - - - -bool WireDataProxy::getGroup(const std::string &id, RsWireGroup &group) -{ - void *groupData = NULL; - RsGroupMetaData meta; - if (getGroupData(id, groupData) && getGroupSummary(id, meta)) - { - RsWireGroup *pG = (RsWireGroup *) groupData; - group = *pG; - - // update definitive version of the metadata. - group.mMeta = meta; - - std::cerr << "WireDataProxy::getGroup() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << groupData; - std::cerr << std::endl; - return true; - } - - std::cerr << "WireDataProxy::getGroup() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool WireDataProxy::getPulse(const std::string &id, RsWirePulse &pulse) -{ - void *msgData = NULL; - RsMsgMetaData meta; - if (getMsgData(id, msgData) && getMsgSummary(id, meta)) - { - RsWirePulse *pP = (RsWirePulse *) msgData; - // Shallow copy of thumbnail. - pulse = *pP; - - // update definitive version of the metadata. - pulse.mMeta = meta; - - std::cerr << "WireDataProxy::getPulse() Id: " << id; - std::cerr << " MetaData: " << meta << " DataPointer: " << msgData; - std::cerr << std::endl; - return true; - } - - std::cerr << "WireDataProxy::getPulse() FAILED Id: " << id; - std::cerr << std::endl; - - return false; -} - -bool WireDataProxy::addGroup(const RsWireGroup &group) -{ - // Make duplicate. - RsWireGroup *pG = new RsWireGroup(); - *pG = group; - - std::cerr << "WireDataProxy::addGroup()"; - std::cerr << " MetaData: " << pG->mMeta << " DataPointer: " << pG; - std::cerr << std::endl; - - return createGroup(pG); -} - - -bool WireDataProxy::addPulse(const RsWirePulse &pulse) -{ - // Make duplicate. - RsWirePulse *pP = new RsWirePulse(); - *pP = pulse; - - std::cerr << "WireDataProxy::addPulse()"; - std::cerr << " MetaData: " << pP->mMeta << " DataPointer: " << pP; - std::cerr << std::endl; - - return createMsg(pP); -} - - - - /* These Functions must be overloaded to complete the service */ -bool WireDataProxy::convertGroupToMetaData(void *groupData, RsGroupMetaData &meta) -{ - RsWireGroup *group = (RsWireGroup *) groupData; - meta = group->mMeta; - - return true; -} - -bool WireDataProxy::convertMsgToMetaData(void *msgData, RsMsgMetaData &meta) -{ - RsWirePulse *page = (RsWirePulse *) msgData; - meta = page->mMeta; - - return true; -} diff --git a/libretroshare/src/services/p3wire.h b/libretroshare/src/services/p3wire.h index 4e83131e6..8d93961e8 100644 --- a/libretroshare/src/services/p3wire.h +++ b/libretroshare/src/services/p3wire.h @@ -1,13 +1,13 @@ /* * libretroshare/src/services: p3wire.h * - * Wire interface for RetroShare. + * Wiki interface for RetroShare. * * Copyright 2012-2012 by Robert Fernie. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. + * License Version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,94 +26,45 @@ #ifndef P3_WIRE_SERVICE_HEADER #define P3_WIRE_SERVICE_HEADER -#include "services/p3gxsservice.h" - #include "retroshare/rswire.h" +#include "gxs/rsgenexchange.h" #include #include /* - * Wire Service + * Wiki Service + * * */ -class WireDataProxy: public GxsDataProxy + +class p3Wire: public RsGenExchange, public RsWire { - public: +public: + p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes); - bool getGroup(const std::string &id, RsWireGroup &group); - bool getPulse(const std::string &id, RsWirePulse &pulse); +protected: - bool addGroup(const RsWireGroup &group); - bool addPulse(const RsWirePulse &pulse); +virtual void notifyChanges(std::vector& changes) ; - /* These Functions must be overloaded to complete the service */ -virtual bool convertGroupToMetaData(void *groupData, RsGroupMetaData &meta); -virtual bool convertMsgToMetaData(void *msgData, RsMsgMetaData &meta); -}; +public: +virtual void service_tick(); -class p3Wire: public p3GxsDataService, public RsWire -{ - public: - - p3Wire(uint16_t type); - -virtual int tick(); - - public: - - -virtual bool updated(); - - /* Data Requests */ -virtual bool requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds); -virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &msgIds); - - /* Generic Lists */ -virtual bool getGroupList( const uint32_t &token, std::list &groupIds); -virtual bool getMsgList( const uint32_t &token, std::list &msgIds); - - /* Generic Summary */ -virtual bool getGroupSummary( const uint32_t &token, std::list &groupInfo); -virtual bool getMsgSummary( const uint32_t &token, std::list &msgInfo); - - /* Actual Data -> specific to Interface */ /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, RsWireGroup &group); -virtual bool getMsgData(const uint32_t &token, RsWirePulse &page); +virtual bool getGroupData(const uint32_t &token, std::vector &groups); +virtual bool getPulseData(const uint32_t &token, std::vector &pulses); - /* Poll */ -virtual uint32_t requestStatus(const uint32_t token); - - /* Cancel Request */ -virtual bool cancelRequest(const uint32_t &token); - - ////////////////////////////////////////////////////////////////////////////// -virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupStatus(const std::string &groupId, const uint32_t status, const uint32_t statusMask); -virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); -virtual bool setMessageServiceString(const std::string &msgId, const std::string &str); -virtual bool setGroupServiceString(const std::string &grpId, const std::string &str); - -virtual bool groupRestoreKeys(const std::string &groupId); -virtual bool groupShareKeys(const std::string &groupId, std::list& peers); - -virtual bool createGroup(uint32_t &token, RsWireGroup &group, bool isNew); -virtual bool createPulse(uint32_t &token, RsWirePulse &pulse, bool isNew); +virtual bool createGroup(uint32_t &token, RsWireGroup &group); +virtual bool createPulse(uint32_t &token, RsWirePulse &pulse); private: +virtual void generateDummyData(); std::string genRandomId(); - WireDataProxy *mWireProxy; - RsMutex mWireMtx; - /***** below here is locked *****/ - - bool mUpdated; }; diff --git a/libretroshare/src/tcponudp/tou.h b/libretroshare/src/tcponudp/tou.h index 0c2522764..da72bb85d 100644 --- a/libretroshare/src/tcponudp/tou.h +++ b/libretroshare/src/tcponudp/tou.h @@ -40,10 +40,8 @@ #include #else - #include "util/rswin.h" #include #include - #include #include // #include typedef int socklen_t; diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h index 74b07b517..1f55f241b 100644 --- a/libretroshare/src/tcponudp/udpstunner.h +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -25,10 +25,6 @@ * */ -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif - #ifndef WINDOWS_SYS #include #endif diff --git a/libretroshare/src/tests/gxs/data_support.cc b/libretroshare/src/tests/gxs/data_support.cc index 272c9255e..8d286b28c 100644 --- a/libretroshare/src/tests/gxs/data_support.cc +++ b/libretroshare/src/tests/gxs/data_support.cc @@ -62,9 +62,8 @@ void init_item(RsGxsGrpMetaData* metaGrp) randString(SHORT_STR, metaGrp->mAuthorId); randString(SHORT_STR, metaGrp->mGroupName); - init_item(metaGrp->adminSign); + init_item(metaGrp->signSet); init_item(metaGrp->keys); - init_item(metaGrp->idSign); metaGrp->mPublishTs = rand()%3452; metaGrp->mGroupFlags = rand()%43; @@ -87,8 +86,7 @@ void init_item(RsGxsMsgMetaData* metaMsg) randString(SHORT_STR, metaMsg->mOrigMsgId); randString(SHORT_STR, metaMsg->mMsgName); - init_item(metaMsg->pubSign); - init_item(metaMsg->idSign); + init_item(metaMsg->signSet); metaMsg->mPublishTs = rand()%313; metaMsg->mMsgFlags = rand()%224; diff --git a/libretroshare/src/tests/gxs/genexchangetester.cpp b/libretroshare/src/tests/gxs/genexchangetester.cpp new file mode 100644 index 000000000..203b57bc0 --- /dev/null +++ b/libretroshare/src/tests/gxs/genexchangetester.cpp @@ -0,0 +1,1965 @@ +#include "genexchangetester.h" +#include "support.h" +#include "gxs/rsdataservice.h" +#include "gxs/rsgxsflags.h" + +#define TEST_FLAG 0x00004; +#define TEST_MASK 0x0000f; + +GenExchangeTester::GenExchangeTester() + : mGenTestMutex("genTest") +{ + remove("testServiceDb"); +} + + +void GenExchangeTester::setUp() +{ + mDataStore = new RsDataService("./", "testServiceDb", RS_SERVICE_TYPE_DUMMY, NULL); + mNxs = new RsDummyNetService(); + + RsGixsDummy* gixsDummy = new RsGixsDummy("incoming", "outgoing"); + + uint32_t serviceAuthenPolicy = 0; + + uint8_t flag = 0; + + flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, serviceAuthenPolicy, + RsGenExchange::RESTRICTED_GRP_BITS); + + + mTestService = new GenExchangeTestService(mDataStore, mNxs, gixsDummy, serviceAuthenPolicy); + mTokenService = mTestService->getTokenService(); + mTestService->start(); +} + +void GenExchangeTester::setUpGrps(uint32_t grpFlags) +{ + // create some random grps to allow msg testing + + RsDummyGrp* dgrp1 = new RsDummyGrp(); + RsDummyGrp* dgrp2 = new RsDummyGrp(); + RsDummyGrp* dgrp3 = new RsDummyGrp(); + + init(dgrp1); + dgrp1->meta.mGroupFlags = grpFlags; + uint32_t token; + mTestService->publishDummyGrp(token, dgrp1); + + RsTokReqOptions opts; + opts.mReqType = 45000; + pollForToken(token, opts); + + RsGxsGroupId grpId; + mTestService->acknowledgeTokenGrp(token, grpId); + mRandGrpIds.push_back(grpId); + + init(dgrp2); + dgrp2->meta.mGroupFlags = grpFlags; + mTestService->publishDummyGrp(token, dgrp2); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + mRandGrpIds.push_back(grpId); + + init(dgrp3); + dgrp3->meta.mGroupFlags = grpFlags; + mTestService->publishDummyGrp(token, dgrp3); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + mRandGrpIds.push_back(grpId); +} + + +void GenExchangeTester::breakDown() +{ + mTestService->join(); + + delete mTestService; + + // a bit protracted, but start a new db and use to clear up junk + mDataStore = new RsDataService("./", "testServiceDb", RS_SERVICE_TYPE_DUMMY, NULL); + mDataStore->resetDataStore(); + delete mDataStore; + mTokenService = NULL; + // remove data base file + remove("testServiceDb"); + + // clear up all latent data + GxsMsgDataMap::iterator gmd_mit = mMsgDataIn.begin(); + + for(; gmd_mit != mMsgDataIn.end(); gmd_mit++) + { + std::vector& msgV = gmd_mit->second; + std::vector::iterator vit = msgV.begin(); + + for(; vit != msgV.end(); vit++) + { + delete *vit; + } + } + mMsgDataIn.clear(); + + gmd_mit = mMsgDataOut.begin(); + + for(; gmd_mit != mMsgDataOut.end(); gmd_mit++) + { + std::vector& msgV = gmd_mit->second; + std::vector::iterator vit = msgV.begin(); + + for(; vit != msgV.end(); vit++) + { + delete *vit; + } + } + + mMsgDataOut.clear(); + + std::vector::iterator g_mit = mGrpDataIn.begin(); + + for(; g_mit != mGrpDataIn.end(); g_mit++) + { + delete *g_mit; + } + + mGrpDataIn.clear(); + g_mit = mGrpDataOut.begin(); + + for(; g_mit != mGrpDataOut.end(); g_mit++) + { + delete *g_mit; + } + mGrpDataOut.clear(); + + + // these don't hold any dynamic memory + mGrpIdsIn.clear(); + mGrpIdsOut.clear(); + mMsgIdsIn.clear(); + mMsgIdsOut.clear(); + mRandGrpIds.clear(); + mMsgMetaDataIn.clear(); + mMsgMetaDataOut.clear(); + mGrpMetaDataIn.clear(); + mGrpMetaDataOut.clear(); +} + +bool GenExchangeTester::testGrpSubmissionRetrieval() +{ + + + setUp(); + + // create some random grps to allow msg testing + + RsDummyGrp* dgrp1 = new RsDummyGrp(); + RsDummyGrp* dgrp2 = new RsDummyGrp(); + RsDummyGrp* dgrp3 = new RsDummyGrp(); + + RsDummyGrp* dgrp1_copy = new RsDummyGrp(); + RsDummyGrp* dgrp2_copy = new RsDummyGrp(); + RsDummyGrp* dgrp3_copy = new RsDummyGrp(); + + init(dgrp1); + init(dgrp2); + init(dgrp3); + + RsTokReqOptions opts; + opts.mReqType = 45000; + uint32_t token; + RsGxsGroupId grpId; + + *dgrp1_copy = *dgrp1; + mTestService->publishDummyGrp(token, dgrp1); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + dgrp1_copy->meta.mGroupId = grpId; + mGrpDataOut.push_back(dgrp1_copy); + + *dgrp2_copy = *dgrp2; + mTestService->publishDummyGrp(token, dgrp2); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + dgrp2_copy->meta.mGroupId = grpId; + mGrpDataOut.push_back(dgrp2_copy); + + *dgrp3_copy = *dgrp3; + mTestService->publishDummyGrp(token, dgrp3); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + dgrp3_copy->meta.mGroupId = grpId; + mGrpDataOut.push_back(dgrp3_copy); + + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list grpIds; + mTokenService->requestGroupInfo(token, 0, opts); + + pollForToken(token, opts); + + std::vector::iterator lit_out = mGrpDataOut.begin(); + + bool ok = true; + + for(; lit_out != mGrpDataOut.end(); lit_out++) + { + RsDummyGrp* grpOut = dynamic_cast(*lit_out); + if(!grpOut) + { + ok = false; + break; + } + + + + std::vector::iterator lit_in = mGrpDataIn.begin(); + + bool found = true; + for(; lit_in != mGrpDataIn.end(); lit_in++) + { + RsDummyGrp* grpIn = dynamic_cast(*lit_in); + + if(!grpIn) + { + ok = false; + break; + } + + if(grpIn->meta.mGroupId == grpOut->meta.mGroupId) + { + found = true; + ok &= *grpIn == *grpOut; + } + } + + if(!found) + { + ok = false; + break; + } + } + + breakDown(); + return ok; +} + +bool GenExchangeTester::testGrpMetaRetrieval() +{ + setUp(); + + // create some random grps to allow msg testing + + RsDummyGrp* dgrp1 = new RsDummyGrp(); + RsDummyGrp* dgrp2 = new RsDummyGrp(); + RsDummyGrp* dgrp3 = new RsDummyGrp(); + + init(dgrp1); + init(dgrp2); + init(dgrp3); + + RsTokReqOptions opts; + opts.mReqType = 45000; + uint32_t token; + RsGxsGroupId grpId; + + RsGroupMetaData tempMeta; + + tempMeta = dgrp1->meta; + mTestService->publishDummyGrp(token, dgrp1); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + tempMeta.mGroupId = grpId; + mGrpMetaDataOut.push_back(tempMeta); + + + tempMeta = dgrp2->meta; + mTestService->publishDummyGrp(token, dgrp2); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + tempMeta.mGroupId = grpId; + mGrpMetaDataOut.push_back(tempMeta); + + tempMeta = dgrp3->meta; + mTestService->publishDummyGrp(token, dgrp3); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + tempMeta.mGroupId = grpId; + mGrpMetaDataOut.push_back(tempMeta); + + + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + mTokenService->requestGroupInfo(token, 0, opts); + + pollForToken(token, opts); + + std::list::iterator lit_out = mGrpMetaDataOut.begin(); + + bool ok = true; + + for(; lit_out != mGrpMetaDataOut.end(); lit_out++) + { + const RsGroupMetaData& grpMetaOut = *lit_out; + + std::list::iterator lit_in = mGrpMetaDataIn.begin(); + + bool found = true; + for(; lit_in != mGrpMetaDataIn.end(); lit_in++) + { + const RsGroupMetaData& grpMetaIn = *lit_in; + + if(grpMetaOut.mGroupId == grpMetaIn.mGroupId) + { + found = true; + ok &= grpMetaIn == grpMetaOut; + } + } + + if(!found) + { + ok = false; + break; + } + } + + breakDown(); + return ok; +} + +bool GenExchangeTester::testGrpIdRetrieval() +{ + setUp(); + setUpLargeGrps(30); // create a large amount of grps + + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + uint32_t token; + std::list grpIds; + mTokenService->requestGroupInfo(token, 0, opts); + + pollForToken(token, opts); + + std::list::iterator lit_out = mGrpIdsOut.begin(); + + bool ok = true; + + for(; lit_out != mGrpIdsOut.end(); lit_out++) + { + std::list::iterator lit_in = mGrpIdsIn.begin(); + + bool found = true; + for(; lit_in != mGrpIdsIn.end(); lit_in++) + { + + if(*lit_out == *lit_in) + { + found = true; + } + } + + if(!found) + { + ok = false; + break; + } + } + + breakDown(); + return ok; +} + + +bool GenExchangeTester::testGrpMetaModRequest() +{ + + setUp(); + + // create some random grps to allow msg testing + + RsDummyGrp* dgrp1 = new RsDummyGrp(); + RsDummyGrp* dgrp2 = new RsDummyGrp(); + RsDummyGrp* dgrp3 = new RsDummyGrp(); + init(dgrp1); + init(dgrp2); + init(dgrp3); + dgrp1->meta.mSubscribeFlags = 0; + dgrp1->meta.mGroupStatus = 0; + + uint32_t token; + RsTokReqOptions opts; + opts.mReqType = 45000; + std::vector grpIds; + RsGxsGroupId grpId; + + mTestService->publishDummyGrp(token, dgrp1); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + grpIds.push_back(grpId); + + mTestService->publishDummyGrp(token, dgrp2); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + grpIds.push_back(grpId); + + mTestService->publishDummyGrp(token, dgrp3); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + grpIds.push_back(grpId); + + bool ok = true; + + std::string newServiceString; + uint32_t newGrpStatus = TEST_FLAG; + uint32_t newSubscribeGrpFlag = TEST_FLAG; + uint32_t testMask = TEST_MASK; + randString(SHORT_STR, newServiceString); + + // mod service flag for first grp + mTestService->setGroupServiceStringTS(token, grpIds[0], newServiceString); + pollForToken(token, opts); + ok = mTestService->acknowledgeTokenGrp(token, grpId); + + mTestService->setGroupStatusFlagTS(token, grpIds[0], newGrpStatus, testMask); + pollForToken(token, opts); + ok = mTestService->acknowledgeTokenGrp(token, grpId); + + mTestService->setGroupSubscribeFlagTS(token, grpIds[0], newSubscribeGrpFlag, testMask); + pollForToken(token, opts); + ok = mTestService->acknowledgeTokenGrp(token, grpId); + + std::list reqGrpIds; + reqGrpIds.push_back(grpIds[0]); + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + mTokenService->requestGroupInfo(token, 0, opts, reqGrpIds); + pollForToken(token, opts); + + + + if(mGrpMetaDataIn.empty()) + ok = false; + + if(ok) + { + RsGroupMetaData meta = *(mGrpMetaDataIn.begin()); + + if(meta.mServiceString != newServiceString) + ok = false; + + if(!(meta.mSubscribeFlags & newSubscribeGrpFlag)) + ok = false; + + if(!(meta.mGroupStatus & newGrpStatus)) + ok = false; + + + } + + breakDown(); + return ok; +} + + +void GenExchangeTester::setUpLargeGrps(uint32_t nGrps) +{ + for(int i=0; i < nGrps; i++) + { + RsDummyGrp* dgrp = new RsDummyGrp(); + RsGxsGroupId grpId; + uint32_t token; + init(dgrp); + RsTokReqOptions opts; + opts.mReqType = 4000; + mTestService->publishDummyGrp(token, dgrp); + pollForToken(token, opts); + mTestService->acknowledgeTokenGrp(token, grpId); + mGrpIdsOut.push_back(grpId); + } +} + +bool GenExchangeTester::testMsgMetaModRequest() +{ + setUp(); + setUpGrps(); + + RsDummyMsg* msg = new RsDummyMsg(); + init(msg); + + msg->meta.mGroupId = mRandGrpIds[(rand()%3)]; + uint32_t token; + RsDummyMsg* msgOut = new RsDummyMsg(); + *msgOut = *msg; + msg->meta.mMsgStatus = 0; + mTestService->publishDummyMsg(token, msg); + + // poll will block until found + RsTokReqOptions opts; + opts.mReqType = 4200; + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + + mTestService->acknowledgeTokenMsg(token, msgId); + + if(msgId.first.empty() || msgId.second.empty()){ + breakDown(); + return false; + } + + std::string newServiceString; + randString(SHORT_STR, newServiceString); + + // first modify service string + mTestService->setMsgServiceStringTS(token, msgId, newServiceString); + pollForToken(token, opts); + + mTestService->acknowledgeTokenMsg(token, msgId); + + uint32_t newStatus = TEST_FLAG; + uint32_t testMask = TEST_MASK; + // first modify service string + mTestService->setMsgStatusFlagTS(token, msgId, newStatus, testMask); + pollForToken(token, opts); + + mTestService->acknowledgeTokenMsg(token, msgId); + + // now request msg + GxsMsgReq req; + std::vector msgV; + msgV.push_back(msgId.second); + req.insert(std::make_pair(msgId.first, msgV)); + + opts.mReqType = GXS_REQUEST_TYPE_MSG_META; + mTokenService->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, req); + + // poll again + pollForToken(token, opts); + + bool ok = true; + + if(mMsgMetaDataIn.empty()) + ok = false; + + if(ok){ + + GxsMsgMetaMap::iterator mit = mMsgMetaDataIn.begin(); + std::vector& metaV = mit->second; + + RsMsgMetaData meta; + if(metaV.empty()){ + ok = false; + }else{ + meta = *(metaV.begin()); + } + + + if(meta.mServiceString != newServiceString) + ok &= false; + + if(!(meta.mMsgStatus & newStatus)) + ok &= false; + + + } + + /********************/ + + // complete + breakDown(); + + return ok; + +} + +bool GenExchangeTester::testMsgSubmissionRetrieval() +{ + + // start up + setUp(); + setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + + /********************/ + + RsDummyMsg* msg = new RsDummyMsg(); + init(msg); + + msg->meta.mGroupId = mRandGrpIds[(rand()%3)]; + uint32_t token; + RsDummyMsg* msgOut = new RsDummyMsg(); + *msgOut = *msg; + mTestService->publishDummyMsg(token, msg); + + // poll will block until found + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + + mTestService->acknowledgeTokenMsg(token, msgId); + + // add msg sent to msg out + msgOut->meta.mMsgId = msgId.second; + std::vector msgDataV; + msgDataV.push_back(msgOut); + mMsgDataOut[msgId.first] = msgDataV; + + if(msgId.first.empty() || msgId.second.empty()){ + breakDown(); + return false; + } + + GxsMsgReq req; + std::vector msgV; + msgV.push_back(msgId.second); + req.insert(std::make_pair(msgId.first, msgV)); + + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + mTokenService->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, req); + + // poll again + pollForToken(token, opts); + + bool ok = true; + + if(mMsgDataIn.size() != mMsgDataOut.size()) + { + breakDown(); + return false; + } + + GxsMsgDataMap::iterator mit = mMsgDataOut.begin(); + + for(; mit != mMsgDataOut.end(); mit++) + { + const RsGxsGroupId& grpId = mit->first; + + std::vector& msgV_1 = mit->second, + msgV_2 = mMsgDataIn[grpId]; + std::vector::iterator vit1, vit2; + + for(vit1 = msgV_1.begin(); vit1 != msgV_1.end(); + vit1++) + { + RsDummyMsg* lMsg = dynamic_cast(*vit1); + for(vit2 = msgV_2.begin(); vit2 != msgV_2.end(); + vit2++) + { + RsDummyMsg* rMsg = dynamic_cast(*vit2); + + if(rMsg->meta.mMsgId == lMsg->meta.mMsgId) + ok &= *rMsg == *lMsg; + + } + } + } + + /********************/ + + // complete + breakDown(); + + return ok; +} + +bool GenExchangeTester::testMsgIdRetrieval() +{ + + // start up + setUp(); + setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + + /********************/ + + // first create several msgs for 3 different groups (the "this" rand groups) + // and store them + + // then make all requests immediately then poll afterwards for each and run outbound test + // we want only latest for now + int nMsgs = (rand()%121)+2; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + std::vector tokenV; + for(int i=0; i < nMsgs; i++) + { + mTestService->publishDummyMsg(token, msgs[i]); + tokenV.push_back(token); + } + + for(int i=0; i < nMsgs; i++) + { + pollForToken(tokenV[i], opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(tokenV[i], msgId); + mMsgIdsOut[msgId.first].push_back(msgId.second); + } + + // now do ask of all msg ids + + std::list req; + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + + // use empty grp ids request types, non specific msgs ids + for(int i=0; i < mRandGrpIds.size(); i++) + { + req.push_back(mRandGrpIds[i]); + } + + mTokenService->requestMsgInfo(token, 0, opts, req); + + pollForToken(token, opts); + + GxsMsgIdResult::iterator mit = mMsgIdsOut.begin(); + for(; mit != mMsgIdsOut.end(); mit++) + { + std::vector msgIdsOut, msgIdsIn; + msgIdsOut = mit->second; + + std::vector::iterator vit_out = msgIdsOut.begin(), vit_in; + + for(; vit_out != msgIdsOut.end(); vit_out++) + { + bool found = false; + msgIdsIn = mMsgIdsIn[mit->first]; + vit_in = msgIdsIn.begin(); + + for(; vit_in != msgIdsIn.end(); vit_in++) + { + if(*vit_in == *vit_out) + found = true; + } + + if(!found){ + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return true; +} +bool GenExchangeTester::testMsgAllVersions() +{ + // start up + setUp(); + setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + + // want to create several msgs of the same version (i.e. same origMsgId) + + + // create msgs + // then make all requests immediately then poll afterwards for each and run outbound test + // we want only latest for now + int nMsgs = (rand()%50)+2; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + bool first = true; + RsGxsGrpMsgIdPair firstMsgId; + + // everyone is a version of first msg + for(int i=0; i < nMsgs; i++) + { + RsDummyMsg* msg = msgs[i]; + + if(first){ + msg->meta.mParentId = ""; + msg->meta.mOrigMsgId = ""; // don't worry GXS sets origid to first + } + else + { + msg->meta.mParentId = ""; + msg->meta.mGroupId = firstMsgId.first; + msg->meta.mOrigMsgId = firstMsgId.second; + } + + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + + + // less than half have no parents + if(first){ + firstMsgId.second = msgId.second; + firstMsgId.first = msgId.first; + first = false; + + } + + mMsgRelatedIdsOut[firstMsgId].push_back(msgId.second); + } + + + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_IDS; + opts.mOptions = RS_TOKREQOPT_MSG_VERSIONS; + std::vector msgIdList; + msgIdList.push_back(firstMsgId); + mTokenService->requestMsgRelatedInfo(token, 0, opts, msgIdList); + + pollForToken(token, opts); + + MsgRelatedIdResult::iterator mit = mMsgRelatedIdsOut.begin(); + for(; mit != mMsgRelatedIdsOut.end(); mit++) + { + std::vector msgIdsOut, msgIdsIn; + msgIdsOut = mit->second; + + std::vector::iterator vit_out = msgIdsOut.begin(), vit_in; + + for(; vit_out != msgIdsOut.end(); vit_out++) + { + bool found = false; + msgIdsIn = mMsgRelatedIdsIn[mit->first]; + vit_in = msgIdsIn.begin(); + + for(; vit_in != msgIdsIn.end(); vit_in++) + { + if(*vit_in == *vit_out) + found = true; + } + + if(!found){ + breakDown(); + return false; + } + + } + } + + // complete + breakDown(); + + return true; +} + +bool GenExchangeTester::testMsgRelatedChildIdRetrieval() +{ +// // start up +// setUp(); +// setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + +// /********************/ + + +// // create msgs +// // then make all requests immediately then poll afterwards for each and run outbound test +// // we want only latest for now +// int nMsgs = (rand()%50)+2; // test a large number of msgs +// std::vector msgs; +// createMsgs(msgs, nMsgs); +// RsTokReqOptions opts; +// opts.mReqType = 4000; +// uint32_t token; + +// bool first = true; +// RsGxsGrpMsgIdPair firstMsgId; + +// // everyone is parent of first msg + +// for(int i=0; i < nMsgs; i++) +// { +// RsDummyMsg* msg = msgs[i]; + +// if(first){ +// msg->meta.mParentId = ""; +// msg->meta.mOrigMsgId = ""; +// } +// else +// { +// msg->meta.mParentId = firstMsgId.second; +// msg->meta.mGroupId = firstMsgId.first; +// msg->meta.mOrigMsgId = ""; +// } + +// mTestService->publishDummyMsg(token, msg); +// pollForToken(token, opts); +// RsGxsGrpMsgIdPair msgId; +// mTestService->acknowledgeTokenMsg(token, msgId); + + +// if(msgId.first.empty() || msgId.second.empty()) +// { +// breakDown(); +// std::cerr << "serious error: Acknowledgement failed! " << std::endl; +// return false; +// } + +// if(!first) +// { +// mMsgIdsOut[msgId.first].push_back(msgId.second); +// } + +// if(first){ +// firstMsgId.second = msgId.second; +// firstMsgId.first = msgId.first; +// first = false; +// } + + + +// opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; +// opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; +// std::vector msgIdList; +// msgIdList.push_back(firstMsgId); +// mTokenService->requestMsgRelatedInfo(token, 0, opts, msgIdList); + +// pollForToken(token, opts); + +// GxsMsgIdResult::iterator mit = mMsgIdsOut.begin(); +// for(; mit != mMsgIdsOut.end(); mit++) +// { +// std::vector msgIdsOut, msgIdsIn; +// msgIdsOut = mit->second; + +// std::vector::iterator vit_out = msgIdsOut.begin(), vit_in; + +// for(; vit_out != msgIdsOut.end(); vit_out++) +// { +// bool found = false; +// msgIdsIn = mMsgIdsIn[mit->first]; +// vit_in = msgIdsIn.begin(); + +// for(; vit_in != msgIdsIn.end(); vit_in++) +// { +// if(*vit_in == *vit_out) +// found = true; +// } + +// if(!found){ +// breakDown(); +// return false; +// } + +// } +// } + +// /********************/ + +// // complete +// breakDown(); + +// return true; +} + +bool GenExchangeTester::testMsgRelatedChildDataRetrieval() +{ + // start up + setUp(); + setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + + /********************/ + + + // create msgs + // then make all requests immediately then poll afterwards for each and run outbound test + // we want only latest for now + int nMsgs = (rand()%50)+2; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + bool first = true; + RsGxsGrpMsgIdPair firstMsgId; + + // everyone is parent of first msg + + for(int i=0; i < nMsgs; i++) + { + RsDummyMsg* msg = msgs[i]; + RsDummyMsg* msgCopy = NULL; + + if(first){ + msg->meta.mParentId = ""; + msg->meta.mOrigMsgId = ""; + } + else + { + msg->meta.mParentId = firstMsgId.second; + msg->meta.mGroupId = firstMsgId.first; + msg->meta.mOrigMsgId = ""; + msgCopy = new RsDummyMsg(); + } + + + // make a copy of msg for store in data out + if(msgCopy) + *msgCopy = *msg; + + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + // don't add the id to be related + if(!first) + { + msgCopy->meta.mMsgId = msgId.second; + mMsgRelatedDataMapOut[firstMsgId].push_back(msgCopy); + } + + if(first){ + firstMsgId.second = msgId.second; + firstMsgId.first = msgId.first; + first = false; + } + } + + + + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; + std::vector msgIdList; + msgIdList.push_back(firstMsgId); + mTokenService->requestMsgRelatedInfo(token, 0, opts, msgIdList); + + pollForToken(token, opts); + + GxsMsgRelatedDataMap::iterator mit = mMsgRelatedDataMapOut.begin(); + for(; mit != mMsgRelatedDataMapOut.end(); mit++) + { + std::vector& msgDataOut = mit->second; + + std::vector::iterator vit_out = msgDataOut.begin(), vit_in; + + for(; vit_out != msgDataOut.end(); vit_out++) + { + bool found = false; + std::vector& msgDataIn = mMsgRelatedDataMapIn[mit->first]; + vit_in = msgDataIn.begin(); + + RsGxsMsgItem* mItem = *vit_out; + RsDummyMsg* msgOut = dynamic_cast(*vit_out); + + if(msgOut) + { + for(; vit_in != msgDataIn.end(); vit_in++) + { + RsDummyMsg* msgIn = dynamic_cast(*vit_in); + + if(msgIn) + { + if(msgIn->meta.mMsgId == msgOut->meta.mMsgId) + found = true; + } + } + } + if(!found){ + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return true; +} + +bool GenExchangeTester::testMsgRelatedChildDataRetrieval_Multi() +{ + // start up + setUp(); + setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + + /********************/ + + + // create msgs + // then make all requests immediately then poll afterwards for each and run outbound test + // we want only latest for now + int nMsgs = 5; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + bool first = true; + RsGxsGrpMsgIdPair firstMsgId; + + // everyone is parent of first msg +RsGxsMessageId msgIdVersion; + for(int i=0; i < nMsgs; i++) + { + RsDummyMsg* msg = msgs[i]; + RsDummyMsg* msgCopy = NULL; + + bool getMsgVersionId= false; + + + if(first){ + msg->meta.mParentId = ""; + msg->meta.mOrigMsgId = ""; + } + else + { + + + // every even numbered msg is a version of the one before + + msg->meta.mParentId = firstMsgId.second; + msg->meta.mGroupId = firstMsgId.first; + msg->meta.mOrigMsgId = ""; + + // every even numbered msg is version of the previous odd numbered msg + if((i%2)) + { + + getMsgVersionId = true; + } + else + { + /** just in case put it to sleep so publish time is sufficiently later **/ + + double timeDelta = 2.; + + #ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); + #else + Sleep((int) (timeDelta * 1000)); + #endif + + + msg->meta.mOrigMsgId = msgIdVersion; + msgCopy = new RsDummyMsg(); + + } + } + + + // make a copy of msg for store in data out + if(msgCopy) + *msgCopy = *msg; + + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + // don't add the id to be related + if(!first) + { + if(getMsgVersionId) + { + msgIdVersion = msgId.second; + }else + { + + msgCopy->meta.mMsgId = msgId.second; + mMsgRelatedDataMapOut[firstMsgId].push_back(msgCopy); + } + } + + if(first){ + firstMsgId.second = msgId.second; + firstMsgId.first = msgId.first; + first = false; + } + } + + + + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; + std::vector msgIdList; + msgIdList.push_back(firstMsgId); + mTokenService->requestMsgRelatedInfo(token, 0, opts, msgIdList); + + pollForToken(token, opts); + + GxsMsgRelatedDataMap::iterator mit = mMsgRelatedDataMapOut.begin(); + for(; mit != mMsgRelatedDataMapOut.end(); mit++) + { + std::vector& msgDataOut = mit->second; + + std::vector::iterator vit_out = msgDataOut.begin(), vit_in; + + for(; vit_out != msgDataOut.end(); vit_out++) + { + bool found = false; + std::vector& msgDataIn = mMsgRelatedDataMapIn[mit->first]; + vit_in = msgDataIn.begin(); + + RsGxsMsgItem* mItem = *vit_out; + RsDummyMsg* msgOut = dynamic_cast(*vit_out); + + if(msgOut) + { + for(; vit_in != msgDataIn.end(); vit_in++) + { + RsDummyMsg* msgIn = dynamic_cast(*vit_in); + + if(msgIn) + { + if(msgIn->meta.mMsgId == msgOut->meta.mMsgId) + found = true; + } + } + } + if(!found){ + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return true; +} + + +bool GenExchangeTester::testSpecificMsgMetaRetrieval() +{ + + + // start up + setUp(); + setUpGrps(GXS_SERV::FLAG_PRIVACY_PUBLIC); + + /********************/ + + RsDummyMsg* msg = new RsDummyMsg(); + init(msg); + + msg->meta.mGroupId = mRandGrpIds[(rand()%3)]; + uint32_t token; + RsMsgMetaData msgMetaOut; + msgMetaOut = msg->meta; + mTestService->publishDummyMsg(token, msg); + + // poll will block until found + RsTokReqOptions opts; + opts.mReqType = 4200; + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + + mTestService->acknowledgeTokenMsg(token, msgId); + + // add msg sent to msg out + msgMetaOut.mMsgId = msgId.second; + + std::vector msgMetaDataV; + msgMetaDataV.push_back(msgMetaOut); + mMsgMetaDataOut[msgId.first] = msgMetaDataV; + + if(msgId.first.empty() || msgId.second.empty()){ + breakDown(); + return false; + } + + GxsMsgReq req; + std::vector msgV; + msgV.push_back(msgId.second); + req.insert(std::make_pair(msgId.first, msgV)); + + opts.mReqType = GXS_REQUEST_TYPE_MSG_META; + mTokenService->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, req); + + // poll again + pollForToken(token, opts); + + bool ok = true; + + if(mMsgMetaDataIn.size() != mMsgMetaDataOut.size()) + { + breakDown(); + return false; + } + + GxsMsgMetaMap::iterator mit = mMsgMetaDataOut.begin(); + + for(; mit != mMsgMetaDataOut.end(); mit++) + { + const RsGxsGroupId& grpId = mit->first; + + std::vector& msgV_1 = mit->second, + msgV_2 = mMsgMetaDataIn[grpId]; + std::vector::iterator vit1, vit2; + + for(vit1 = msgV_1.begin(); vit1 != msgV_1.end(); + vit1++) + { + bool found = false; + const RsMsgMetaData& lMsgMeta = *vit1; + for(vit2 = msgV_2.begin(); vit2 != msgV_2.end(); + vit2++) + { + const RsMsgMetaData& rMsgMeta = *vit2; + + if(rMsgMeta.mMsgId == lMsgMeta.mMsgId){ + found = true; + ok &= rMsgMeta == lMsgMeta; + } + + } + + if(!found) + { + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return ok; +} + +bool GenExchangeTester::testMsgIdRetrieval_OptParents() +{ + // start up + setUp(); + setUpGrps(); + + /********************/ + + + // create msgs + // then make all requests immediately then poll afterwards for each and run outbound test + // we want only latest for now + int nMsgs = (rand()%50)+2; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + + for(int i=0; i < nMsgs; i++) + { + RsDummyMsg* msg = msgs[i]; + + int j = rand()%5; + + + if(j<3) + msg->meta.mParentId = ""; + + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + if(j<3) + mMsgIdsOut[msgId.first].push_back(msgId.second); + + } + + std::list req; + + // use empty grp ids request types, non specific msgs ids + for(int i=0; i < mRandGrpIds.size(); i++) + { + req.push_back(mRandGrpIds[i]); + } + + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + opts.mOptions = RS_TOKREQOPT_MSG_THREAD; + mTokenService->requestMsgInfo(token, 0, opts, req); + + pollForToken(token, opts); + + GxsMsgIdResult::iterator mit = mMsgIdsOut.begin(); + for(; mit != mMsgIdsOut.end(); mit++) + { + std::vector msgIdsOut, msgIdsIn; + msgIdsOut = mit->second; + + std::vector::iterator vit_out = msgIdsOut.begin(), vit_in; + + for(; vit_out != msgIdsOut.end(); vit_out++) + { + bool found = false; + msgIdsIn = mMsgIdsIn[mit->first]; + vit_in = msgIdsIn.begin(); + + for(; vit_in != msgIdsIn.end(); vit_in++) + { + if(*vit_in == *vit_out) + found = true; + } + + if(!found){ + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return true; + +} + +bool GenExchangeTester::testMsgIdRetrieval_OptOrigMsgId() +{ + // start up + setUp(); + setUpGrps(); + + /********************/ + + + // create msgs + // then make all requests immediately then poll afterwards for each and run outbound test + // we want only latest for now + int nMsgs = (rand()%50)+2; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + + for(int i=0; i < nMsgs; i++) + { + RsDummyMsg* msg = msgs[i]; + + int j = rand()%5; + + if(j<3) + msg->meta.mOrigMsgId = ""; + + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + if(j<3) + mMsgIdsOut[msgId.first].push_back(msgId.second); + + } + + std::list req; + + // use empty grp ids request types, non specific msgs ids + for(int i=0; i < mRandGrpIds.size(); i++) + { + req.push_back(mRandGrpIds[i]); + } + + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + opts.mOptions = RS_TOKREQOPT_MSG_ORIGMSG; + mTokenService->requestMsgInfo(token, 0, opts, req); + + pollForToken(token, opts); + + GxsMsgIdResult::iterator mit = mMsgIdsOut.begin(); + for(; mit != mMsgIdsOut.end(); mit++) + { + std::vector msgIdsOut, msgIdsIn; + msgIdsOut = mit->second; + + std::vector::iterator vit_out = msgIdsOut.begin(), vit_in; + + for(; vit_out != msgIdsOut.end(); vit_out++) + { + bool found = false; + msgIdsIn = mMsgIdsIn[mit->first]; + vit_in = msgIdsIn.begin(); + + for(; vit_in != msgIdsIn.end(); vit_in++) + { + if(*vit_in == *vit_out) + found = true; + } + + if(!found){ + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return true; +} + + +bool GenExchangeTester::testMsgIdRetrieval_OptLatest() +{ + + // testing for latest, create msg which are origMsgIds then + // create another batch and select random msgs again to have + // id of the other, so selecting latest msg should only come up + // with this batch of msgs for the grp plus the others not selected + // start up + setUp(); + setUpGrps(); + + /********************/ + + + // create msgs which will be used later to set orig msg ids of latest msgs + int nMsgs = (rand()%50)+2; // test a large number of msgs + std::vector msgs; + createMsgs(msgs, nMsgs); + RsTokReqOptions opts; + opts.mReqType = 4000; + uint32_t token; + + + for(int i=0; i < nMsgs; i++) + { + RsDummyMsg* msg = msgs[i]; + + int j = rand()%5; + + if(j<3) + msg->meta.mOrigMsgId = ""; + + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + if(j<3) + mMsgIdsOut[msgId.first].push_back(msgId.second); + + } + + + /** just in case put it to sleep so publish time is sufficiently different **/ + + double timeDelta = 2.; + +#ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); +#else + Sleep((int) (timeDelta * 1000)); +#endif + + + /* now to create the later msgs */ + + nMsgs = (rand()%50)+2; // test a large number of msgs + msgs.clear(); + createMsgs(msgs, nMsgs); + opts.mReqType = 4000; + + // fist transfer to grpID->msgId(Set) pair in + // order to remove used msgs, that is + // msgs who ids have been used for orig id so not expected in result set + GxsMsgIdResult::iterator mit = mMsgIdsOut.begin(); + std::map > msgIdOutTemp; + + for(; mit != mMsgIdsOut.end(); mit++) + { + std::vector msgIdsOut; + msgIdsOut = mit->second; + std::vector::iterator vit = msgIdsOut.begin(); + + for(; vit != msgIdsOut.end(); vit++) + msgIdOutTemp[mit->first].insert(*vit); + } + + mMsgIdsOut.clear(); // to be repopulated later with expected result set + + std::vector::iterator vit = msgs.begin(); + + // loop over newly create msgs and assign a msg ids + // to origmsg id field from previously published msgs + for(; vit != msgs.end();) + { + RsDummyMsg* msg = *vit; + + // first find grp + const RsGxsGroupId& grpId = msg->meta.mGroupId; + + // if grp does not exist then don't pub msg + if(msgIdOutTemp.find(grpId) == msgIdOutTemp.end()){ + delete msg; + vit = msgs.erase(vit); + continue; + }else{ + + // now assign msg a rand msgId + std::set& msgIdS = msgIdOutTemp[grpId]; + + std::set::iterator sit = msgIdS.begin(); + std::vector tempMsgV; + + // store in vect for convenience + for(; sit != msgIdS.end(); sit++) + tempMsgV.push_back(*sit); + + if(tempMsgV.size() == 0) + { + delete msg; + vit = msgs.erase(vit); + continue; + } + int j = rand()%tempMsgV.size(); + + msg->meta.mOrigMsgId = tempMsgV[j]; + msgIdS.erase(tempMsgV[j]); // remove msg as it has been used + } + + // go on and publish msg + mTestService->publishDummyMsg(token, msg); + pollForToken(token, opts); + RsGxsGrpMsgIdPair msgId; + mTestService->acknowledgeTokenMsg(token, msgId); + + if(msgId.first.empty() || msgId.second.empty()) + { + breakDown(); + std::cerr << "serious error: Acknowledgement failed! " << std::endl; + return false; + } + + mMsgIdsOut[msgId.first].push_back(msgId.second); + vit++; + } + + // now add back unused msgs + std::map >::iterator mit_id_temp = msgIdOutTemp.begin(); + + for(; mit_id_temp != msgIdOutTemp.end(); mit_id_temp++){ + + std::set& idSet = mit_id_temp->second; + std::set::iterator sit = idSet.begin(); + + for(; sit != idSet.end(); sit++) + { + mMsgIdsOut[mit_id_temp->first].push_back(*sit); + } + } + + + // use empty grp ids request types, non specific msgs ids + std::list req; + for(int i=0; i < mRandGrpIds.size(); i++) + { + req.push_back(mRandGrpIds[i]); + } + + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + mTokenService->requestMsgInfo(token, 0, opts, req); + + pollForToken(token, opts); + + mit = mMsgIdsOut.begin(); + for(; mit != mMsgIdsOut.end(); mit++) + { + std::vector msgIdsOut, msgIdsIn; + msgIdsOut = mit->second; + + std::vector::iterator vit_out = msgIdsOut.begin(), vit_in; + + for(; vit_out != msgIdsOut.end(); vit_out++) + { + bool found = false; + msgIdsIn = mMsgIdsIn[mit->first]; + vit_in = msgIdsIn.begin(); + + for(; vit_in != msgIdsIn.end(); vit_in++) + { + if(*vit_in == *vit_out) + found = true; + } + + if(!found){ + breakDown(); + return false; + } + + } + } + + /********************/ + + // complete + breakDown(); + + return true; +} + +void GenExchangeTester::createMsgs(std::vector &msgs, int nMsgs) const +{ + for(int i = 0; i < nMsgs; i++) + { + RsDummyMsg* msg = new RsDummyMsg(); + init(msg); + msgs.push_back(msg); + int j = (rand()%3); + msg->meta.mGroupId = mRandGrpIds[j]; + } +} + + +// helper functions + +void GenExchangeTester::storeGrpMeta(std::list &grpMetaData){ + mGrpMetaDataIn = grpMetaData; +} + +void GenExchangeTester::storeMsgData(GxsMsgDataMap &msgData) +{ + + mMsgDataIn = msgData; + +} + +void GenExchangeTester::storeGrpData(std::vector &grpData) +{ + mGrpDataIn = grpData; +} + +void GenExchangeTester::storeGrpId(std::list &grpIds) +{ + mGrpIdsIn = grpIds; +} + + +void GenExchangeTester::storeMsgMeta(GxsMsgMetaMap &msgMetaData) +{ + mMsgMetaDataIn = msgMetaData; +} + +void GenExchangeTester::storeMsgIds(GxsMsgIdResult &msgIds) +{ + mMsgIdsIn = msgIds; +} + + +void GenExchangeTester::init(RsGroupMetaData &grpMeta) const +{ + randString(SHORT_STR, grpMeta.mGroupId); + randString(SHORT_STR, grpMeta.mAuthorId); + randString(SHORT_STR, grpMeta.mGroupName); + randString(SHORT_STR, grpMeta.mServiceString); + + + grpMeta.mGroupFlags = randNum(); + grpMeta.mLastPost = randNum(); + grpMeta.mGroupStatus = randNum(); + grpMeta.mMsgCount = randNum(); + grpMeta.mPop = randNum(); + grpMeta.mSignFlags = randNum(); + grpMeta.mPublishTs = randNum(); + grpMeta.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; + +} + +void GenExchangeTester::init(RsMsgMetaData &msgMeta) const +{ + randString(SHORT_STR, msgMeta.mAuthorId); + randString(SHORT_STR, msgMeta.mMsgName); + randString(SHORT_STR, msgMeta.mServiceString); + randString(SHORT_STR, msgMeta.mOrigMsgId); + randString(SHORT_STR, msgMeta.mParentId); + randString(SHORT_STR, msgMeta.mThreadId); + randString(SHORT_STR, msgMeta.mGroupId); + + msgMeta.mChildTs = randNum(); + msgMeta.mMsgStatus = randNum(); + msgMeta.mMsgFlags = randNum(); + msgMeta.mPublishTs = randNum(); +} + +uint32_t GenExchangeTester::randNum() const +{ + return rand()%23562424; +} + + +bool operator ==(const RsMsgMetaData& lMeta, const RsMsgMetaData& rMeta) +{ + + if(lMeta.mAuthorId != rMeta.mAuthorId) return false; + if(lMeta.mChildTs != rMeta.mChildTs) return false; + if(lMeta.mGroupId != rMeta.mGroupId) return false; + if(lMeta.mMsgFlags != rMeta.mMsgFlags) return false; + if(lMeta.mMsgId != rMeta.mMsgId) return false; + if(lMeta.mMsgName != rMeta.mMsgName) return false; + if(lMeta.mMsgStatus != rMeta.mMsgStatus) return false; + if(lMeta.mOrigMsgId != rMeta.mOrigMsgId) return false; + if(lMeta.mParentId != rMeta.mParentId) return false; + //if(lMeta.mPublishTs != rMeta.mPublishTs) return false; // don't compare this as internally set in gxs + if(lMeta.mThreadId != rMeta.mThreadId) return false; + if(lMeta.mServiceString != rMeta.mServiceString) return false; + + return true; +} + +bool operator ==(const RsGroupMetaData& lMeta, const RsGroupMetaData& rMeta) +{ + if(lMeta.mAuthorId != rMeta.mAuthorId) return false; + if(lMeta.mGroupFlags != rMeta.mGroupFlags) return false; + if(lMeta.mGroupId != rMeta.mGroupId) return false; + if(lMeta.mGroupName != rMeta.mGroupName) return false; + if(lMeta.mGroupStatus != rMeta.mGroupStatus) return false; + if(lMeta.mLastPost != rMeta.mLastPost) return false; + if(lMeta.mMsgCount != rMeta.mMsgCount) return false; + if(lMeta.mPop != rMeta.mPop) return false; + // if(lMeta.mPublishTs != rMeta.mPublishTs) return false; set in gxs + if(lMeta.mServiceString != rMeta.mServiceString) return false; + if(lMeta.mSignFlags != rMeta.mSignFlags) return false; + if(lMeta.mSubscribeFlags != rMeta.mSubscribeFlags) return false; + + return true; +} + +bool operator ==(const RsDummyGrp& lGrp, const RsDummyGrp& rGrp) +{ + + if(lGrp.grpData != rGrp.grpData) return false; + if(! (lGrp.meta == rGrp.meta)) return false; + + return true; + + +} + +bool operator ==(const RsDummyMsg& lMsg, const RsDummyMsg& rMsg) +{ + if(lMsg.msgData != rMsg.msgData) return false; + if(!(lMsg.meta == rMsg.meta)) return false; + + return true; +} + +void GenExchangeTester::init(RsDummyGrp *grpItem) const +{ + randString(SHORT_STR, grpItem->grpData); + init(grpItem->meta); +} + +void GenExchangeTester::init(RsDummyMsg *msgItem) const +{ + randString(SHORT_STR, msgItem->msgData); + init(msgItem->meta); +} + +void GenExchangeTester::pollForToken(uint32_t token, const RsTokReqOptions &opts) +{ + double timeDelta = 0.2; + + while(true) + { +#ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); +#else + Sleep((int) (timeDelta * 1000)); +#endif + + if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token)) + || (RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token))) + { + switch(opts.mReqType) + { + case GXS_REQUEST_TYPE_GROUP_DATA: + mTestService->getGroupDataTS(token, mGrpDataIn); + break; + case GXS_REQUEST_TYPE_GROUP_META: + mTestService->getGroupMetaTS(token, mGrpMetaDataIn); + break; + case GXS_REQUEST_TYPE_GROUP_IDS: + mTestService->getGroupListTS(token, mGrpIdsIn); + break; + case GXS_REQUEST_TYPE_MSG_DATA: + mTestService->getMsgDataTS(token, mMsgDataIn); + break; + case GXS_REQUEST_TYPE_MSG_META: + mTestService->getMsgMetaTS(token, mMsgMetaDataIn); + break; + case GXS_REQUEST_TYPE_MSG_IDS: + mTestService->getMsgListTS(token, mMsgIdsIn); + break; + case GXS_REQUEST_TYPE_MSG_RELATED_IDS: + mTestService->getMsgRelatedListTS(token, mMsgRelatedIdsIn); + break; + case GXS_REQUEST_TYPE_MSG_RELATED_DATA: + mTestService->getMsgRelatedDataTS(token, mMsgRelatedDataMapIn); + break; + } + break; + } + + } +} diff --git a/libretroshare/src/tests/gxs/genexchangetester.h b/libretroshare/src/tests/gxs/genexchangetester.h new file mode 100644 index 000000000..fac83a02d --- /dev/null +++ b/libretroshare/src/tests/gxs/genexchangetester.h @@ -0,0 +1,123 @@ +#ifndef GENEXCHANGETESTER_H +#define GENEXCHANGETESTER_H + +#include "genexchangetestservice.h" +#include "gxs/rsgds.h" +#include "gxs/rsnxs.h" +#include "gxs/gxscoreserver.h" + +bool operator ==(const RsMsgMetaData& lMeta, const RsMsgMetaData& rMeta); +bool operator ==(const RsDummyMsg& lMsg, const RsDummyMsg& rMsg); + +bool operator ==(const RsGroupMetaData& lMeta, const RsGroupMetaData& rMeta); +bool operator ==(const RsDummyGrp& lMsg, const RsDummyGrp& rMsg); + +/*! + * The job of the service tester is to send dummy msg items to the GenExchange service + * and then retrieve them (ignoring ackowledge message) + * Also it modifies local meta items and check if it worked out + */ +class GenExchangeTester +{ +public: + + void pollForToken(uint32_t, const RsTokReqOptions& opts); + + GenExchangeTester(); + + // message tests + bool testMsgSubmissionRetrieval(); + bool testMsgIdRetrieval(); + bool testMsgIdRetrieval_OptParents(); + bool testMsgIdRetrieval_OptOrigMsgId(); + bool testMsgIdRetrieval_OptLatest(); + bool testSpecificMsgMetaRetrieval(); + + // request msg related tests + bool testMsgRelatedChildIdRetrieval(); + bool testMsgRelatedChildDataRetrieval(); + bool testMsgRelatedChildDataRetrieval_Multi(); + bool testMsgAllVersions(); + + + // group tests + bool testGrpSubmissionRetrieval(); + bool testSpecificGrpRetrieval(); + bool testGrpIdRetrieval(); + bool testGrpMetaRetrieval(); + + bool testGrpMetaModRequest(); + bool testMsgMetaModRequest(); + + + // testing verification (publish). + // Strategy is + // inject a group which you only have the public signature for + // The injection can be done via + +private: + + // to be called at start + void setUp(); + + // and at end of test routines, resets db and clears out maps + void breakDown(); + + + void setUpGrps(uint32_t grpFlag=0); // to be called at start of msg tests + + /*! + * Can be called at start grpId or grpMeta test + * to help out + * ids are store is mGrpIdsOut + */ + void setUpLargeGrps(uint32_t nGrps); + + void storeMsgData(GxsMsgDataMap& msgData); + void storeMsgMeta(GxsMsgMetaMap& msgMetaData); + void storeMsgIds(GxsMsgIdResult& msgIds); + + void storeGrpData(std::vector& grpData); + void storeGrpMeta(std::list& grpMetaData); + void storeGrpId(std::list& grpIds); + + void init(RsDummyGrp* grpItem) const; + void init(RsGroupMetaData&) const; + void init(RsDummyMsg* msgItem) const; + void init(RsMsgMetaData&) const; + + uint32_t randNum() const; +private: + + void createMsgs(std::vector& msgs, int nMsgs) const; + +private: + + + RsMutex mGenTestMutex; + + std::vector mGrpDataOut, mGrpDataIn; + std::list mGrpMetaDataOut, mGrpMetaDataIn; + std::list mGrpIdsOut, mGrpIdsIn; + + GxsMsgDataMap mMsgDataOut, mMsgDataIn; + GxsMsgMetaMap mMsgMetaDataOut, mMsgMetaDataIn; + GxsMsgIdResult mMsgIdsOut, mMsgIdsIn; + + MsgRelatedIdResult mMsgRelatedIdsOut, mMsgRelatedIdsIn; + GxsMsgRelatedDataMap mMsgRelatedDataMapOut, mMsgRelatedDataMapIn; + + std::vector mRandGrpIds; // ids that exist to help group testing + +private: + + GenExchangeTestService* mTestService; + RsTokenService* mTokenService; + + RsNetworkExchangeService* mNxs; + RsGeneralDataService* mDataStore; + + +}; + +#endif // GENEXCHANGETESTER_H diff --git a/libretroshare/src/tests/gxs/genexchangetestservice.cpp b/libretroshare/src/tests/gxs/genexchangetestservice.cpp new file mode 100644 index 000000000..7e8b69957 --- /dev/null +++ b/libretroshare/src/tests/gxs/genexchangetestservice.cpp @@ -0,0 +1,93 @@ +#include "genexchangetestservice.h" + +GenExchangeTestService::GenExchangeTestService(RsGeneralDataService *dataServ, RsNetworkExchangeService * netService, + RsGixs* gixs, uint32_t authenPolicy) + : RsGenExchange(dataServ, netService, new RsDummySerialiser(), RS_SERVICE_TYPE_DUMMY, gixs, authenPolicy) +{ + +} + +void GenExchangeTestService::notifyChanges(std::vector &changes) +{ + return; +} + +void GenExchangeTestService::publishDummyGrp(uint32_t &token, RsDummyGrp *grp) +{ + publishGroup(token, grp); +} + +void GenExchangeTestService::publishDummyMsg(uint32_t &token, RsDummyMsg *msg) +{ + publishMsg(token, msg); +} + +bool GenExchangeTestService::getGroupListTS(const uint32_t &token, std::list &groupIds) +{ + return getGroupList(token, groupIds); +} + +bool GenExchangeTestService::getGroupMetaTS(const uint32_t &token, std::list &groupInfo) +{ + return getGroupMeta(token, groupInfo); +} + +bool GenExchangeTestService::getGroupDataTS(const uint32_t &token, std::vector &grpItem) +{ + return getGroupData(token, grpItem); +} + +bool GenExchangeTestService::getMsgDataTS(const uint32_t &token, GxsMsgDataMap &msgItems) +{ + return getMsgData(token, msgItems); +} + +bool GenExchangeTestService::getMsgRelatedDataTS(const uint32_t &token, GxsMsgRelatedDataMap &msgItems) +{ + return getMsgRelatedData(token, msgItems); +} + +bool GenExchangeTestService::getMsgMetaTS(const uint32_t &token, GxsMsgMetaMap &msgInfo) +{ + return getMsgMeta(token, msgInfo); +} + +bool GenExchangeTestService::getMsgListTS(const uint32_t &token, GxsMsgIdResult &msgIds) +{ + return getMsgList(token, msgIds); +} + +bool GenExchangeTestService::getMsgRelatedListTS(const uint32_t &token, MsgRelatedIdResult &msgIds) +{ + return getMsgRelatedList(token, msgIds); +} + +void GenExchangeTestService::setGroupServiceStringTS(uint32_t &token, const RsGxsGroupId &grpId, const std::string &servString) +{ + RsGenExchange::setGroupServiceString(token, grpId, servString); +} + +void GenExchangeTestService::setGroupStatusFlagTS(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t &status, const uint32_t& mask) +{ + RsGenExchange::setGroupStatusFlags(token, grpId, status, mask); +} + +void GenExchangeTestService::setGroupSubscribeFlagTS(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t &status, const uint32_t& mask) +{ + RsGenExchange::setGroupSubscribeFlags(token, grpId, status, mask); +} + +void GenExchangeTestService::setMsgServiceStringTS(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, const std::string &servString) +{ + RsGenExchange::setMsgServiceString(token, msgId, servString); +} + +void GenExchangeTestService::setMsgStatusFlagTS(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, const uint32_t &status, const uint32_t& mask) +{ + RsGenExchange::setMsgStatusFlags(token, msgId, status, mask); +} + +void GenExchangeTestService::service_tick() +{ + +} diff --git a/libretroshare/src/tests/gxs/genexchangetestservice.h b/libretroshare/src/tests/gxs/genexchangetestservice.h new file mode 100644 index 000000000..60fa0488b --- /dev/null +++ b/libretroshare/src/tests/gxs/genexchangetestservice.h @@ -0,0 +1,93 @@ +#ifndef GENEXCHANGETESTSERVICE_H +#define GENEXCHANGETESTSERVICE_H + +#include "gxs/rsgenexchange.h" +#include "gxs/rsgxsifaceimpl.h" +#include "rsdummyservices.h" + +class GenExchangeTestService : public RsGenExchange +{ +public: + GenExchangeTestService(RsGeneralDataService* dataServ, RsNetworkExchangeService*, RsGixs* gixs, uint32_t authenPolicy); + + void notifyChanges(std::vector& changes); + + void publishDummyGrp(uint32_t& token, RsDummyGrp* grp); + void publishDummyMsg(uint32_t& token, RsDummyMsg* msg); + + + /*! + * Retrieve group list for a given token + * @param token + * @param groupIds + * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready + */ + bool getGroupListTS(const uint32_t &token, std::list &groupIds); + + /*! + * Retrieve msg list for a given token sectioned by group Ids + * @param token token to be redeemed + * @param msgIds a map of grpId -> msgList (vector) + */ + bool getMsgListTS(const uint32_t &token, GxsMsgIdResult &msgIds); + + + /*! + * retrieve group meta data associated to a request token + * @param token + * @param groupInfo + */ + bool getGroupMetaTS(const uint32_t &token, std::list &groupInfo); + + /*! + * retrieves message meta data associated to a request token + * @param token token to be redeemed + * @param msgInfo the meta data to be retrieved for token store here + */ + bool getMsgMetaTS(const uint32_t &token, GxsMsgMetaMap &msgInfo); + + /*! + * retrieves group data associated to a request token + * @param token token to be redeemed for grpitem retrieval + * @param grpItem the items to be retrieved for token are stored here + */ + bool getGroupDataTS(const uint32_t &token, std::vector& grpItem); + + /*! + * retrieves message data associated to a request token + * @param token token to be redeemed for message item retrieval + * @param msgItems + */ + bool getMsgDataTS(const uint32_t &token, GxsMsgDataMap& msgItems); + + /*! + * Retrieve msg related list for a given token sectioned by group Ids + * @param token token to be redeemed + * @param msgIds a map of grpMsgIdPair -> msgList (vector) + */ + bool getMsgRelatedListTS(const uint32_t &token, MsgRelatedIdResult &msgIds); + + /*! + * retrieves msg related data msgItems as a map of msg-grpID pair to vector + * of items + * @param token token to be redeemed + * @param msgItems map of msg items + */ + bool getMsgRelatedDataTS(const uint32_t &token, GxsMsgRelatedDataMap& msgItems); + + + void setGroupSubscribeFlagTS(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); + + void setGroupStatusFlagTS(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); + + void setGroupServiceStringTS(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); + + void setMsgStatusFlagTS(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask); + + void setMsgServiceStringTS(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); + + void service_tick(); + +}; + +#endif // GENEXCHANGETESTSERVICE_H diff --git a/libretroshare/src/tests/gxs/nxs_tests.pro b/libretroshare/src/tests/gxs/nxs_tests.pro new file mode 100644 index 000000000..3bc6c4f02 --- /dev/null +++ b/libretroshare/src/tests/gxs/nxs_tests.pro @@ -0,0 +1,194 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-05-06T09:19:26 +# +#------------------------------------------------- + + +# +QT += core network + +QT -= gui + +CONFIG += gen_exchange_target +#CONFIG += nxs_net_test +#CONFIG += dstore_target +#CONFIG += gxsdata_target + +CONFIG += bitdht + + + +gen_exchange_target { + +#TARGET = gen_exchange_test + +} + +nxs_net_test { + +TARGET = nxs_net_test + +} + +gxsdata_target { + +#TARGET = gxsdata_test + +} + +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +CONFIG += debug + +debug { +# DEFINES *= DEBUG +# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG +# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG +# DEFINES *= P3TURTLE_DEBUG +# DEFINES *= NET_DEBUG +# DEFINES *= DISTRIB_DEBUG +# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG +# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG + + QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer + QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer +} +################################# Linux ########################################## +# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib +linux-* { + #CONFIG += version_detail_bash_script + QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 + + system(which gpgme-config >/dev/null 2>&1) { + INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") + } else { + message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) + } + + PRE_TARGETDEPS *= ../../lib/libretroshare.a + + LIBS += ../../lib/libretroshare.a + LIBS += ../../../../libbitdht/src/lib/libbitdht.a + LIBS += ../../../../openpgpsdk/src/lib/libops.a + LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lsqlite3 -lbz2 + LIBS *= -rdynamic -frtti + DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions + DEFINES *= UBUNTU +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +#################################### Windows ##################################### + +win32 { + + DEFINES *= WINDOWS_SYS \ + WIN32 \ + STATICLIB \ + MINGW + # Switch on extra warnings + QMAKE_CFLAGS += -Wextra + QMAKE_CXXFLAGS += -Wextra + + # Switch off optimization for release version + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O0 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE += -O0 + + # Switch on optimization for debug version + #QMAKE_CXXFLAGS_DEBUG += -O2 + #QMAKE_CFLAGS_DEBUG += -O2 + +# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a + PRE_TARGETDEPS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a + + LIBS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a + LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a + LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a + LIBS += -L"../../../../../lib" + LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 +# added after bitdht +# LIBS += -lws2_32 + LIBS += -luuid -lole32 -liphlpapi -lcrypt32-cygwin -lgdi32 + LIBS += -lole32 -lwinmm + + # export symbols for the plugins + #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a + + GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + GPGME_DIR = ../../../../gpgme-1.1.8 + GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 + GPGME_DIR = ../../../../lib/gpgme-1.1.8 + SSL_DIR = ../../../../../OpenSSL + OPENPGPSDK_DIR = ../../../../openpgpsdk/src + INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ + $${OPENPGPSDK_DIR} + + SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 + INCLUDEPATH += . \ + $${SQLITE_DIR} + + + + +} + +bitdht { + LIBS += C:\Development\Rs\v0.5-gxs-b1\libbitdht\libbitdht-build-desktop\lib\libbitdht.a + PRE_TARGETDEPS *= C:\Development\Rs\v0.5-gxs-b1\libbitdht\libbitdht-build-desktop\lib\libbitdht.a + + # Chris version. + #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a + #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a +} + +win32 { +# must be added after bitdht + LIBS += -lws2_32 +} + +version_detail_bash_script { + DEFINES += ADD_LIBRETROSHARE_VERSION_INFO + QMAKE_EXTRA_TARGETS += write_version_detail + PRE_TARGETDEPS = write_version_detail + write_version_detail.commands = ./version_detail.sh +} + +install_rs { + INSTALLS += binary_rs + binary_rs.path = $$(PREFIX)/usr/bin + binary_rs.files = ./RetroShare +} + + +gen_exchange_target { + + SOURCES += \ + support.cc \ + genexchangetester.cpp \ + genexchangetestservice.cpp \ + rsdummyservices.cc \ + rsgenexchange_test.cc + + HEADERS += support.h \ + rsdataservice_test.h \ + rsdummyservices.h \ + data_support.h + + +} + + + +INCLUDEPATH += ../../ diff --git a/libretroshare/src/tests/gxs/nxsnet_test.pro b/libretroshare/src/tests/gxs/nxsnet_test.pro new file mode 100644 index 000000000..054938374 --- /dev/null +++ b/libretroshare/src/tests/gxs/nxsnet_test.pro @@ -0,0 +1,92 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-05-06T09:19:26 +# +#------------------------------------------------- + +QT += core network + +QT -= gui + +TARGET = rs_test +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +CONFIG += debug + +debug { +# DEFINES *= DEBUG +# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG +# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG +# DEFINES *= P3TURTLE_DEBUG +# DEFINES *= NET_DEBUG +# DEFINES *= DISTRIB_DEBUG +# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG +# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG + + QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer + QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer +} +################################# Linux ########################################## +# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib +linux-* { + #CONFIG += version_detail_bash_script + QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 + + system(which gpgme-config >/dev/null 2>&1) { + INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") + } else { + message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) + } + + PRE_TARGETDEPS *= /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/lib/libretroshare.a + + LIBS += /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/lib/libretroshare.a + LIBS += /home/crispy/workspace/v0.5-gxs-b1/libbitdht/src/lib/libbitdht.a + LIBS += /home/crispy/workspace/v0.5-gxs-b1/openpgpsdk/src/lib/libops.a + LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lsqlite3 -lbz2 + LIBS *= -rdynamic -frtti + DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions + DEFINES *= UBUNTU +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +version_detail_bash_script { + DEFINES += ADD_LIBRETROSHARE_VERSION_INFO + QMAKE_EXTRA_TARGETS += write_version_detail + PRE_TARGETDEPS = write_version_detail + write_version_detail.commands = ./version_detail.sh +} + +install_rs { + INSTALLS += binary_rs + binary_rs.path = $$(PREFIX)/usr/bin + binary_rs.files = ./RetroShare +} + + +SOURCES += \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/data_support.cc \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/nxstesthub.cc \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/nxstestscenario.cc \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/rsgxsnetservice_test.cc \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/support.cc + + +HEADERS += \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/data_support.h \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/nxstesthub.h \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/nxstestscenario.h \ + /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src/tests/gxs/support.h + +INCLUDEPATH += /home/crispy/workspace/v0.5-gxs-b1/libretroshare/src + diff --git a/libretroshare/src/tests/gxs/nxstesthub.cc b/libretroshare/src/tests/gxs/nxstesthub.cc index d6ca55f01..e0c505464 100644 --- a/libretroshare/src/tests/gxs/nxstesthub.cc +++ b/libretroshare/src/tests/gxs/nxstesthub.cc @@ -1,78 +1,126 @@ #include "nxstesthub.h" -NxsTestHub::NxsTestHub(NxsTestScenario* nts) : mTestScenario(nts) +NxsTestHub::NxsTestHub(NxsTestScenario * nts, std::set &peers) : mTestScenario(nts) { - netServicePairs.first = new RsGxsNetService(mTestScenario->getServiceType(), - mTestScenario->dummyDataService1(), &netMgr1, mTestScenario); - netServicePairs.second = new RsGxsNetService(mTestScenario->getServiceType(), - mTestScenario->dummyDataService2(), &netMgr2, mTestScenario); + std::set::iterator sit = peers.begin(); - mServicePairs.first = netServicePairs.first; - mServicePairs.second = netServicePairs.second; + for(; sit != peers.end(); sit++) + { + std::set msgPeers = peers; - createThread(*(netServicePairs.first)); - createThread(*(netServicePairs.second)); + // add peers all peers except one iterator currently points to + msgPeers.erase(*sit); + NxsNetDummyMgr* dummyMgr = new NxsNetDummyMgr(*sit, msgPeers); + RsGeneralDataService* ds = mTestScenario->getDataService(*sit); + NxsMessageTestObserver* obs = new NxsMessageTestObserver(ds); + + RsGxsNetService* netService = + new RsGxsNetService(mTestScenario->getServiceType(), + ds, dummyMgr, obs); + + + mNetServices.insert(std::make_pair(*sit, netService)); + mObservers.insert(std::make_pair(*sit, obs)); + } + + sit = peers.begin(); + + // launch net services + for(; sit != peers.end(); sit++) + { + RsGxsNetService* n = mNetServices[*sit]; + createThread(*n); + mServices.insert(std::make_pair(*sit, n)); + } } NxsTestHub::~NxsTestHub() { - delete netServicePairs.first; - delete netServicePairs.second; + std::map::iterator mit = mNetServices.begin(); + + for(; mit != mNetServices.end(); mit++) + delete mit->second; } void NxsTestHub::run() { - - std::list send_queue_s1, send_queue_s2; + double timeDelta = .2; while(isRunning()){ - // make thread sleep for a couple secs - usleep(3000); + // make thread sleep for a bit + #ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); + #else + Sleep((int) (timeDelta * 1000)); + #endif - p3Service* s1 = mServicePairs.first; - p3Service* s2 = mServicePairs.second; - RsItem* item = NULL; - while((item = s1->send()) != NULL) - { - item->PeerId("PeerB"); - send_queue_s1.push_back(item); - } + std::map::iterator mit = mServices.begin(); - while((item = s2->send()) != NULL) - { - item->PeerId("PeerA"); - send_queue_s2.push_back(item); - } + for(; mit != mServices.end(); mit++) + { + p3Service* s = mit->second; + s->tick(); + } - while(!send_queue_s1.empty()){ - item = send_queue_s1.front(); - s2->receive(dynamic_cast(item)); - send_queue_s1.pop_front(); - } + mit = mServices.begin(); - while(!send_queue_s2.empty()){ - item = send_queue_s2.front(); - s1->receive(dynamic_cast(item)); - send_queue_s2.pop_front(); - } + // collect msgs to send to peers from peers + for(; mit != mServices.end(); mit++) + { + const std::string& peer = mit->first; + p3Service* s = mit->second; - // tick services so nxs net services process items - s1->tick(); - s2->tick(); + // first store all the sends from all services + RsItem* item = NULL; + + while((item = s->send()) != NULL){ + + const std::string peerToReceive = item->PeerId(); + + // set the peer this item comes from + item->PeerId(peer); + mPeerQueues[peerToReceive].push_back(item); + } + + + } + + // now route items to peers + std::map >::iterator mit_queue = mPeerQueues.begin(); + + for(; mit_queue != mPeerQueues.end(); mit_queue++) + { + std::vector& queueV = mit_queue->second; + std::vector::iterator vit = queueV.begin(); + const std::string peerToReceive = mit_queue->first; + for(; vit != queueV.end(); vit++) + { + + RsItem* item = *vit; + p3Service* service = mServices[peerToReceive]; + + service->receive(dynamic_cast(item)); + } + queueV.clear(); + } } - - // also shut down this net service peers if this goes down - netServicePairs.first->join(); - netServicePairs.second->join(); } void NxsTestHub::cleanUp() { - mTestScenario->cleanUp(); + std::map::iterator mit = mNetServices.begin(); + for(; mit != mNetServices.end(); mit++) + { + RsGxsNetService* n = mit->second; + n->join(); + } + + // also shut down this net service peers if this goes down + mTestScenario->cleanUp(); } bool NxsTestHub::testsPassed() diff --git a/libretroshare/src/tests/gxs/nxstesthub.h b/libretroshare/src/tests/gxs/nxstesthub.h index 46849aad9..15f10e0b4 100644 --- a/libretroshare/src/tests/gxs/nxstesthub.h +++ b/libretroshare/src/tests/gxs/nxstesthub.h @@ -11,14 +11,13 @@ // of peers -class NxsNetDummyMgr1 : public RsNxsNetMgr +class NxsNetDummyMgr : public RsNxsNetMgr { public: - NxsNetDummyMgr1() : mOwnId("peerA") { + NxsNetDummyMgr(std::string ownId, std::set peers) : mOwnId(ownId), mPeers(peers) { - mPeers.insert("peerB"); } std::string getOwnId() { return mOwnId; } @@ -31,26 +30,6 @@ private: }; -class NxsNetDummyMgr2 : public RsNxsNetMgr -{ - -public: - - NxsNetDummyMgr2() : mOwnId("peerB") { - - mPeers.insert("peerA"); - - } - - std::string getOwnId() { return mOwnId; } - void getOnlineList(std::set& ssl_peers) { ssl_peers = mPeers; } - -private: - - std::string mOwnId; - std::set mPeers; -}; - /*! * Testing of nxs services occurs through use of two services @@ -73,7 +52,7 @@ public: * This construct the test hub * for a give scenario in mind */ - NxsTestHub(NxsTestScenario*); + NxsTestHub(NxsTestScenario*, std::set& peers); /*! @@ -97,12 +76,13 @@ public: void cleanUp(); private: - std::pair mServicePairs; - std::pair netServicePairs; - NxsTestScenario *mTestScenario; + std::map mServices; + std::map mNetServices; + std::map mObservers; - NxsNetDummyMgr1 netMgr1; - NxsNetDummyMgr2 netMgr2; + std::map > mPeerQueues; + + NxsTestScenario *mTestScenario; }; diff --git a/libretroshare/src/tests/gxs/nxstestscenario.cc b/libretroshare/src/tests/gxs/nxstestscenario.cc index 901ed555a..73a720c36 100644 --- a/libretroshare/src/tests/gxs/nxstestscenario.cc +++ b/libretroshare/src/tests/gxs/nxstestscenario.cc @@ -7,15 +7,14 @@ #include "nxstestscenario.h" #include "gxs/rsdataservice.h" +#include "gxs/rsgxsflags.h" #include "data_support.h" +#include NxsMessageTest::NxsMessageTest(uint16_t servtype) -: mServType(servtype) +: mServType(servtype), mMsgTestMtx("mMsgTestMtx") { - mStorePair.first = new RsDataService(".", "dStore1", mServType); - mStorePair.second = new RsDataService(".", "dStore2", mServType); - setUpDataBases(); } std::string NxsMessageTest::getTestName() @@ -24,21 +23,33 @@ std::string NxsMessageTest::getTestName() } NxsMessageTest::~NxsMessageTest(){ - delete mStorePair.first; - delete mStorePair.second; + + std::map::iterator mit = mPeerStoreMap.begin(); + + for(; mit != mPeerStoreMap.end(); mit++) + { + delete mit->second; + } + + std::set::iterator sit = mStoreNames.begin(); + + // remove db file + for(; sit != mStoreNames.end(); sit++) + { + const std::string& name = *sit; + remove(name.c_str()); + } } -void NxsMessageTest::setUpDataBases() +RsGeneralDataService* NxsMessageTest::getDataService(const std::string& peer) { - // create several groups and then messages of that - // group for both second and first of pair - RsDataService* dStore = dynamic_cast(mStorePair.first); - populateStore(dStore); + if(mPeerStoreMap.find(peer) != mPeerStoreMap.end()) return NULL; - dStore = dynamic_cast(mStorePair.second); - populateStore(dStore); + RsDataService* dStore = new RsDataService("./", peer, mServType); + mStoreNames.insert(peer); + mPeerStoreMap.insert(std::make_pair(peer, dStore)); + populateStore(dStore); - dStore = NULL; - return; + return dStore; } uint16_t NxsMessageTest::getServiceType() @@ -49,7 +60,7 @@ uint16_t NxsMessageTest::getServiceType() void NxsMessageTest::populateStore(RsGeneralDataService* dStore) { - int nGrp = rand()%7; + int nGrp = (rand()%2)+1; std::vector grpIdList; std::map grps; RsNxsGrp* grp = NULL; @@ -72,16 +83,6 @@ void NxsMessageTest::populateStore(RsGeneralDataService* dStore) dStore->storeGroup(grps); - - std::map::iterator grp_it - = grps.begin(); - for(; grp_it != grps.end(); grp_it++) - { - delete grp_it->first; - delete grp_it->second; - } - - int nMsgs = rand()%23; std::map msgs; RsNxsMsg* msg = NULL; @@ -109,53 +110,68 @@ void NxsMessageTest::populateStore(RsGeneralDataService* dStore) dStore->storeMessage(msgs); - // clean up - std::map::iterator msg_it - = msgs.begin(); + return; +} - for(; msg_it != msgs.end(); msg_it++) +void NxsMessageTest::cleanUp() +{ + + std::map::iterator mit = mPeerStoreMap.begin(); + + for(; mit != mPeerStoreMap.end(); mit++) { - delete msg_it->first; - delete msg_it->second; + RsGeneralDataService* d = mit->second; + d->resetDataStore(); } return; } -void NxsMessageTest::notifyNewMessages(std::vector& messages) +bool NxsMessageTest::testPassed(){ + return false; +} + +/*******************************/ + +NxsMessageTestObserver::NxsMessageTestObserver(RsGeneralDataService *dStore) + :mStore(dStore) { + +} + +void NxsMessageTestObserver::notifyNewGroups(std::vector &groups) +{ + std::vector::iterator vit = groups.begin(); + std::map grps; + + for(; vit != groups.end(); vit++) + { + RsNxsGrp* grp = *vit; + RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); + meta->deserialise(grp->meta.bin_data, grp->meta.bin_len); + meta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED; + meta->mGroupId = grp->grpId; + grps.insert(std::make_pair(grp, meta)); + } + + mStore->storeGroup(grps); +} + +void NxsMessageTestObserver::notifyNewMessages(std::vector &messages) +{ + std::vector::iterator vit = messages.begin(); + std::map msgs; for(; vit != messages.end(); vit++) { - mPeerMsgs[(*vit)->PeerId()].push_back(*vit); + RsNxsMsg* msg = *vit; + RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); + meta->mGroupId = msg->grpId; + meta->mMsgId = msg->msgId; + msgs.insert(std::make_pair(msg, meta)); } + + mStore->storeMessage(msgs); } -void NxsMessageTest::notifyNewGroups(std::vector& groups) -{ - std::vector::iterator vit = groups.begin(); - - for(; vit != groups.end(); vit++) - { - mPeerGrps[(*vit)->PeerId()].push_back(*vit); - } -} - -RsGeneralDataService* NxsMessageTest::dummyDataService1() -{ - return mStorePair.first; -} - -RsGeneralDataService* NxsMessageTest::dummyDataService2() -{ - return mStorePair.second; -} - -void NxsMessageTest::cleanUp() -{ - mStorePair.first->resetDataStore(); - mStorePair.second->resetDataStore(); - - return; -} diff --git a/libretroshare/src/tests/gxs/nxstestscenario.h b/libretroshare/src/tests/gxs/nxstestscenario.h index 66efe0084..72500e4d3 100644 --- a/libretroshare/src/tests/gxs/nxstestscenario.h +++ b/libretroshare/src/tests/gxs/nxstestscenario.h @@ -15,14 +15,26 @@ /*! * This scenario module provides data resources */ -class NxsTestScenario : public RsNxsObserver +class NxsTestScenario { public: virtual std::string getTestName() = 0; - virtual RsGeneralDataService* dummyDataService1() = 0; - virtual RsGeneralDataService* dummyDataService2() = 0; + + /*! + * @param peer + * @param namePath + * @return data service with populated with random grp/msg data, null if peer or pathname exists + */ + virtual RsGeneralDataService* getDataService(const std::string& peer) = 0; + + + virtual bool testPassed() = 0; + /*! + * Service type for this test + * should correspond to serialiser service type + */ virtual uint16_t getServiceType() = 0; /*! @@ -34,25 +46,11 @@ public: }; -class NxsMessageTest : public NxsTestScenario +class NxsMessageTestObserver : public RsNxsObserver { - public: - NxsMessageTest(uint16_t servtype); - virtual ~NxsMessageTest(); - std::string getTestName(); - uint16_t getServiceType(); - RsGeneralDataService* dummyDataService1(); - RsGeneralDataService* dummyDataService2(); - - /*! - * Call to remove files created - * in the test directory - */ - void cleanUp(); - -public: + NxsMessageTestObserver(RsGeneralDataService* dStore); /*! * @param messages messages are deleted after function returns @@ -64,6 +62,30 @@ public: */ void notifyNewGroups(std::vector& groups); +private: + + RsGeneralDataService* mStore; + +}; + +class NxsMessageTest : public NxsTestScenario +{ + +public: + + NxsMessageTest(uint16_t servtype); + virtual ~NxsMessageTest(); + std::string getTestName(); + uint16_t getServiceType(); + RsGeneralDataService* getDataService(const std::string& peer); + + /*! + * Call to remove files created + * in the test directory + */ + void cleanUp(); + + bool testPassed(); private: void setUpDataBases(); @@ -72,11 +94,12 @@ private: private: std::string mTestName; - std::pair mStorePair; - std::map > mPeerMsgs; - std::map > mPeerGrps; + std::map mPeerStoreMap; + std::set mStoreNames; uint16_t mServType; + RsMutex mMsgTestMtx; + }; diff --git a/libretroshare/src/tests/gxs/rsdataservice_test.cc b/libretroshare/src/tests/gxs/rsdataservice_test.cc index 790a265c2..90f800355 100644 --- a/libretroshare/src/tests/gxs/rsdataservice_test.cc +++ b/libretroshare/src/tests/gxs/rsdataservice_test.cc @@ -2,6 +2,7 @@ #include "support.h" #include "data_support.h" #include "rsdataservice_test.h" +#include "gxs/rsgds.h" #include "gxs/rsdataservice.h" #define DATA_BASE_NAME "msg_grp_Store" @@ -37,7 +38,7 @@ void test_groupStoreAndRetrieve(){ setUp(); int nGrp = rand()%32; - std::map grps; + std::map grps, grps_copy; RsNxsGrp* grp; RsGxsGrpMetaData* grpMeta; for(int i = 0; i < nGrp; i++){ @@ -50,16 +51,24 @@ void test_groupStoreAndRetrieve(){ init_item(grpMeta); grpMeta->mGroupId = grp->grpId; grps.insert(p); - + RsNxsGrp* grp_copy = new RsNxsGrp(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); + *grp_copy = *grp; + RsGxsGrpMetaData* grpMeta_copy = new RsGxsGrpMetaData(); + *grpMeta_copy = *grpMeta; + grps_copy.insert(std::make_pair(grp_copy, grpMeta_copy )); grpMeta = NULL; grp = NULL; } dStore->storeGroup(grps); - std::map gR; - std::map grpMetaR; - dStore->retrieveNxsGrps(gR, false); + //use copy, a grps are deleted in store + grps.clear(); + grps = grps_copy; + + std::map gR; + std::map grpMetaR; + dStore->retrieveNxsGrps(gR, false, false); dStore->retrieveGxsGrpMetaData(grpMetaR); std::map::iterator mit = grps.begin(); @@ -140,6 +149,7 @@ void test_messageStoresAndRetrieve() grpV.push_back(grpId1); std::map msgs; + std::map msgs_copy; RsNxsMsg* msg = NULL; RsGxsMsgMetaData* msgMeta = NULL; int nMsgs = rand()%120; @@ -164,14 +174,20 @@ void test_messageStoresAndRetrieve() const std::string& grpId = grpV[chosen]; if(chosen) - req[grpId].insert(msg->msgId); + req[grpId].push_back(msg->msgId); msgMeta->mMsgId = msg->msgId; msgMeta->mGroupId = msg->grpId = grpId; + RsNxsMsg* msg_copy = new RsNxsMsg(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); + RsGxsMsgMetaData* msgMeta_copy = new RsGxsMsgMetaData(); + + *msg_copy = *msg; + *msgMeta_copy = *msgMeta; + // store msgs in map to use for verification - std::pair vP(msg->msgId, msg); - std::pair vPmeta(msg->msgId, msgMeta); + std::pair vP(msg->msgId, msg_copy); + std::pair vPmeta(msg->msgId, msgMeta_copy); if(!chosen) { @@ -183,15 +199,21 @@ void test_messageStoresAndRetrieve() VergrpId1.insert(vP); VerMetagrpId0.insert(vPmeta); } + + + msg = NULL; msgMeta = NULL; msgs.insert(p); + msgs_copy.insert(std::make_pair(msg_copy, msgMeta_copy)); } - req[grpV[0]] = std::set(); // assign empty list for other + req[grpV[0]] = std::vector(); // assign empty list for other dStore->storeMessage(msgs); + msgs.clear(); + msgs = msgs_copy; // now retrieve msgs for comparison // first selective retrieval @@ -199,7 +221,8 @@ void test_messageStoresAndRetrieve() GxsMsgResult msgResult; GxsMsgMetaResult msgMetaResult; dStore->retrieveNxsMsgs(req, msgResult, false); - dStore->retrieveGxsMsgMetaData(grpV, msgMetaResult); + + dStore->retrieveGxsMsgMetaData(req, msgMetaResult); // now look at result for grpId 1 std::vector& result0 = msgResult[grpId0]; @@ -316,8 +339,7 @@ void tearDown(){ bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r) { - if(!(l.adminSign == r.adminSign)) return false; - if(!(l.idSign == r.idSign)) return false; + if(!(l.signSet == r.signSet)) return false; if(!(l.keys == r.keys)) return false; if(l.mGroupFlags != r.mGroupFlags) return false; if(l.mPublishTs != r.mPublishTs) return false; @@ -335,8 +357,7 @@ bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r) bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r) { - if(!(l.idSign == r.idSign)) return false; - if(!(l.pubSign == r.pubSign)) return false; + if(!(l.signSet == r.signSet)) return false; if(l.mGroupId != r.mGroupId) return false; if(l.mAuthorId != r.mAuthorId) return false; if(l.mParentId != r.mParentId) return false; diff --git a/libretroshare/src/tests/gxs/rsdummyservices.cc b/libretroshare/src/tests/gxs/rsdummyservices.cc new file mode 100644 index 000000000..4d8dd4984 --- /dev/null +++ b/libretroshare/src/tests/gxs/rsdummyservices.cc @@ -0,0 +1,226 @@ + + +#include "rsdummyservices.h" + + +uint32_t RsDummySerialiser::size(RsItem *item) +{ + RsDummyMsg* msg; + RsDummyGrp* grp; + + if( (msg = dynamic_cast(item)) != NULL ) + { + return sizeDummyMsgItem(msg); + }else if( (grp = dynamic_cast(item)) != NULL ) + { + return sizeDummyGrpItem(grp); + }else + { + std::cerr << "RsDummySerialiser::size(RsItem *item) Error with dummy cast!\n"; + } + + return 0; +} + + +bool RsDummySerialiser::serialise(RsItem *item, void *data, uint32_t *size) +{ + RsDummyMsg* msg; + RsDummyGrp* grp; + + if( (msg = dynamic_cast(item)) != NULL ) + { + return serialiseDummyMsgItem(msg, data, size); + }else if( (grp = dynamic_cast(item)) != NULL ) + { + return serialiseDummyGrpItem(grp, data, size); + }else + { + std::cerr << "RsDummySerialiser::size(RsItem *item) Error with dummy cast!\n"; + } + + return false; +} + +RsItem* RsDummySerialiser::deserialise(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DUMMY_MSG: + return deserialiseDummyMsgItem(data, size); + case RS_PKT_SUBTYPE_DUMMY_GRP: + return deserialiseDummyGrpItem(data, size); + default: + return NULL; + } + + return NULL; +} + + +uint32_t RsDummySerialiser::sizeDummyMsgItem(RsDummyMsg *item) +{ + uint32_t s = 8; // header + s += GetTlvStringSize(item->msgData); + + return s; +} + +bool RsDummySerialiser::serialiseDummyMsgItem (RsDummyMsg *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = sizeDummyMsgItem(item); + uint32_t offset = 0; + + if (*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + + ok &= SetTlvString(data, *size, &offset, 1, item->msgData); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsDummySerialiser::serialiseDummyMsgItem Size Error! " << std::endl; + } + + return ok; +} + +RsDummyMsg * RsDummySerialiser::deserialiseDummyMsgItem(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DUMMY_MSG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + /* ready to load */ + RsDummyMsg *item = new RsDummyMsg(); + + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, *size, &offset, 1, item->msgData); + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +uint32_t RsDummySerialiser::sizeDummyGrpItem(RsDummyGrp *item) +{ + uint32_t s = 8; + s += GetTlvStringSize(item->grpData); + + return s; +} + +bool RsDummySerialiser::serialiseDummyGrpItem (RsDummyGrp *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = sizeDummyGrpItem(item); + uint32_t offset = 0; + + if (*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + ok &= SetTlvString(data, *size, &offset, 1, item->grpData); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsDummySerialiser::serialiseDummyGrpItem Size Error! " << std::endl; + } + + return ok; +} + +RsDummyGrp * RsDummySerialiser::deserialiseDummyGrpItem(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DUMMY_GRP != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + /* ready to load */ + RsDummyGrp *item = new RsDummyGrp(); + + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, *size, &offset, 1, item->grpData); + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + diff --git a/libretroshare/src/tests/gxs/rsdummyservices.h b/libretroshare/src/tests/gxs/rsdummyservices.h new file mode 100644 index 000000000..0ba00a906 --- /dev/null +++ b/libretroshare/src/tests/gxs/rsdummyservices.h @@ -0,0 +1,165 @@ +#ifndef RSDUMMYSERVICES_H +#define RSDUMMYSERVICES_H + + +// dummy services to make + +#include "gxs/rsnxs.h" +#include "gxs/rsgixs.h" +#include "serialiser/rsgxsitems.h" + +class RsDummyNetService: public RsNetworkExchangeService +{ +public: + + RsDummyNetService(){ return;} + + void setSyncAge(uint32_t age){} + + void requestGroupsOfPeer(const std::string& peerId){} + + void requestMessagesOfPeer(const std::string& peerId, const std::string& grpId){} + + void pauseSynchronisation(bool enabled) {} + + int requestMsg(const std::string& msgId, uint8_t hops){ return 0;} + + int requestGrp(const std::list& grpId, uint8_t hops) { return 0;} +}; + + + +const uint16_t RS_SERVICE_TYPE_DUMMY = 0x01; +const uint8_t RS_PKT_SUBTYPE_DUMMY_MSG = 0x02; +const uint8_t RS_PKT_SUBTYPE_DUMMY_GRP = 0x03; + + +class RsDummyMsg : public RsGxsMsgItem +{ +public: + RsDummyMsg() : RsGxsMsgItem(RS_SERVICE_TYPE_DUMMY, RS_PKT_SUBTYPE_DUMMY_MSG) { return; } + virtual ~RsDummyMsg() { return; } + + std::string msgData; + + std::ostream &print(std::ostream &out, uint16_t indent = 0){ return out; } + void clear() { msgData.clear(); } + +}; + +class RsDummyGrp : public RsGxsGrpItem +{ +public: + + RsDummyGrp() : RsGxsGrpItem(RS_SERVICE_TYPE_DUMMY, RS_PKT_SUBTYPE_DUMMY_GRP) { return; } + virtual ~RsDummyGrp() { return; } + + + + std::string grpData; + void clear() { grpData.clear(); } + std::ostream &print(std::ostream &out, uint16_t indent = 0){ return out; } +}; + + + +class RsDummySerialiser : public RsSerialType +{ + +public: + + + RsDummySerialiser() + : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DUMMY) + { return; } + virtual ~RsDummySerialiser() { return; } + + uint32_t size(RsItem *item); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + private: + + uint32_t sizeDummyMsgItem(RsDummyMsg *item); + bool serialiseDummyMsgItem (RsDummyMsg *item, void *data, uint32_t *size); + RsDummyMsg * deserialiseDummyMsgItem(void *data, uint32_t *size); + + uint32_t sizeDummyGrpItem(RsDummyGrp *item); + bool serialiseDummyGrpItem (RsDummyGrp *item, void *data, uint32_t *size); + RsDummyGrp * deserialiseDummyGrpItem(void *data, uint32_t *size); + + +}; + +/*! + * Dummy implementation of Gixs service for + * testing + * Limited to creating two ids upon construction which can be used + * for signing data + */ +class RsGixsDummy : public RsGixs +{ + +public: + + /*! + * constructs keys for both incoming and outgoing id (no private keys for incoming id) + * @param + * @param dummyId This is is the only id thats exists in this dummy interface + */ + RsGixsDummy(const RsGxsId& incomingId, const RsGxsId& outgoingId){} + + /*! + * + * @return id used for signing incoming data (should have both public and private components) + */ + const RsGxsId& getOutgoing(){ return mOutgoingId; } + + /*! + * + * @return id used for signing outgoing data(only have public parts) + */ + const RsGxsId& getIncoming(){ return mIncomingId; } + + // Key related interface - used for validating msgs and groups. + /*! + * Use to query a whether given key is available by its key reference + * @param keyref the keyref of key that is being checked for + * @return true if available, false otherwise + */ + bool haveKey(const RsGxsId &id){ return false;} + + /*! + * Use to query whether private key member of the given key reference is available + * @param keyref the KeyRef of the key being checked for + * @return true if private key is held here, false otherwise + */ + bool havePrivateKey(const RsGxsId &id){ return false; } + + // The fetchKey has an optional peerList.. this is people that had the msg with the signature. + // These same people should have the identity - so we ask them first. + /*! + * Use to request a given key reference + * @param keyref the KeyRef of the key being requested + * @return will + */ + bool requestKey(const RsGxsId &id, const std::list &peers){ return false ;} + bool requestPrivateKey(const RsGxsId &id){ return false;} + + + /*! + * Retrieves a key identity + * @param keyref + * @return a pointer to a valid profile if successful, otherwise NULL + * + */ + int getKey(const RsGxsId &id, RsTlvSecurityKey &key){ return false; } + int getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key){ return false; } // For signing outgoing messages. + +private: + + RsGxsId mIncomingId, mOutgoingId; +}; + + +#endif // RSDUMMYSERVICES_H diff --git a/libretroshare/src/tests/gxs/rsgenexchange_test.cc b/libretroshare/src/tests/gxs/rsgenexchange_test.cc new file mode 100644 index 000000000..7932a6c41 --- /dev/null +++ b/libretroshare/src/tests/gxs/rsgenexchange_test.cc @@ -0,0 +1,36 @@ + + +#include "genexchangetester.h" +#include "genexchangetestservice.h" +#include "util/utest.h" +#include "gxs/gxscoreserver.h" +#include "gxs/rsdataservice.h" +#include "rsdummyservices.h" + +INITTEST(); + + +int main() +{ + GenExchangeTester tester; + + CHECK(tester.testMsgSubmissionRetrieval()); REPORT("testMsgSubmissionRetrieval()"); + CHECK(tester.testSpecificMsgMetaRetrieval()); REPORT("testSpecificMsgMetaRetrieval()"); + CHECK(tester.testMsgIdRetrieval()); REPORT("tester.testMsgIdRetrieval()"); + CHECK(tester.testMsgIdRetrieval_OptParents()); REPORT("tester.testRelatedMsgIdRetrieval_Parents()"); + CHECK(tester.testMsgIdRetrieval_OptOrigMsgId()); REPORT("tester.testRelatedMsgIdRetrieval_OrigMsgId()"); + CHECK(tester.testMsgIdRetrieval_OptLatest()); REPORT("tester.testRelatedMsgIdRetrieval_Latest()"); + CHECK(tester.testMsgMetaModRequest()); REPORT("tester.testMsgMetaModRequest()"); + CHECK(tester.testMsgRelatedChildDataRetrieval()); REPORT("tester.testMsgRelatedChildDataRetrieval()"); + CHECK(tester.testMsgRelatedChildDataRetrieval_Multi()); REPORT("tester.testMsgRelatedChildDataRetrieval_Multi()"); + CHECK(tester.testMsgAllVersions()); REPORT("tester.testMsgAllVersions()"); + + CHECK(tester.testGrpSubmissionRetrieval()); REPORT("tester.testGrpSubmissionRetrieval()"); + CHECK(tester.testGrpMetaRetrieval()); REPORT("tester.testGrpMetaRetrieval()"); + CHECK(tester.testGrpIdRetrieval()); REPORT("tester.testGrpIdRetrieval()"); + CHECK(tester.testGrpMetaModRequest()); REPORT("tester.testGrpMetaModRequest()"); + + FINALREPORT("RsGenExchangeTest"); + + return 0; +} diff --git a/libretroshare/src/tests/gxs/rsgenexhchange_test.pro b/libretroshare/src/tests/gxs/rsgenexhchange_test.pro new file mode 100644 index 000000000..0346c5f34 --- /dev/null +++ b/libretroshare/src/tests/gxs/rsgenexhchange_test.pro @@ -0,0 +1,71 @@ + +TEMPLATE = app +TARGET = rsgenexcahnge_test +CONFIG += debug + +win32 { + + DEFINES *= WINDOWS_SYS \ + WIN32 \ + STATICLIB \ + MINGW + + # Switch on extra warnings + QMAKE_CFLAGS += -Wextra + QMAKE_CXXFLAGS += -Wextra + + # Switch off optimization for release version + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O0 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE += -O0 + + # Switch on optimization for debug version + #QMAKE_CXXFLAGS_DEBUG += -O2 + #QMAKE_CFLAGS_DEBUG += -O2 + +# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a + PRE_TARGETDEPS += C:\Development\Rs\v0.5-gxs-b1/libretroshare/libretroshare-build-desktop/lib/libretroshare.a + + LIBS += C:\Development\Rs\v0.5-gxs-b1/libretroshare/libretroshare-build-desktop/lib/libretroshare.a + LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a + LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a + LIBS += -L"../lib" + LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 +# added after bitdht +# LIBS += -lws2_32 + LIBS += -luuid -lole32 -liphlpapi -lcrypt32-cygwin -lgdi32 + LIBS += -lole32 -lwinmm + + # export symbols for the plugins + #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a + + GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + GPGME_DIR = ../../../../gpgme-1.1.8 + GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 + GPGME_DIR = ../../../../lib/gpgme-1.1.8 + INCLUDEPATH += . $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src + SQLITE_DIR = ../../Libraries/sqlite/sqlite-autoconf-3070900 + INCLUDEPATH += . \ + $${SQLITE_DIR} + + LIBS += -lws2_32 + + + +} + +INCLUDEPATH += C:\Development\Rs\v0.5-gxs-b1\libretroshare\src + +HEADERS += \ + genexchangetestservice.h \ + genexchangetester.h \ + rsdummyservices.h \ + support.h + +SOURCES += \ + genexchangetestservice.cpp \ + genexchangetester.cpp \ + rsgenexchange_test.cc \ + support.cc \ + rsdummyservices.cc diff --git a/libretroshare/src/tests/gxs/rsgxsdata_test.cc b/libretroshare/src/tests/gxs/rsgxsdata_test.cc index 990240f8a..fa5dc3c6b 100644 --- a/libretroshare/src/tests/gxs/rsgxsdata_test.cc +++ b/libretroshare/src/tests/gxs/rsgxsdata_test.cc @@ -49,8 +49,7 @@ int main() bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r) { - if(!(l.adminSign == r.adminSign)) return false; - if(!(l.idSign == r.idSign)) return false; + if(!(l.signSet == r.signSet)) return false; if(!(l.keys == r.keys)) return false; if(l.mGroupFlags != r.mGroupFlags) return false; if(l.mPublishTs != r.mPublishTs) return false; @@ -64,8 +63,7 @@ bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r) bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r) { - if(!(l.idSign == r.idSign)) return false; - if(!(l.pubSign == r.pubSign)) return false; + if(!(l.signSet == r.signSet)) return false; if(l.mGroupId != r.mGroupId) return false; if(l.mAuthorId != r.mAuthorId) return false; if(l.mParentId != r.mParentId) return false; diff --git a/libretroshare/src/tests/gxs/rsgxsnetservice_test.cc b/libretroshare/src/tests/gxs/rsgxsnetservice_test.cc index 68ccbe10a..ddcc2f6c0 100644 --- a/libretroshare/src/tests/gxs/rsgxsnetservice_test.cc +++ b/libretroshare/src/tests/gxs/rsgxsnetservice_test.cc @@ -17,13 +17,23 @@ int main() // first setup NxsMessageTest msgTest(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - NxsTestHub hub(&msgTest); + std::set peers; + peers.insert("PeerA"); + peers.insert("PeerB"); + NxsTestHub hub(&msgTest, peers); // now get things started createThread(hub); + double timeDelta = 50; + // put this thread to sleep for 10 secs - sleep(10); + // make thread sleep for a bit +#ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); +#else + Sleep((int) (timeDelta * 1000)); +#endif hub.join(); CHECK(hub.testsPassed()); diff --git a/libretroshare/src/tests/gxs/support.cc b/libretroshare/src/tests/gxs/support.cc index e726cef33..9003b6b60 100644 --- a/libretroshare/src/tests/gxs/support.cc +++ b/libretroshare/src/tests/gxs/support.cc @@ -103,6 +103,30 @@ bool operator==(const RsTlvSecurityKey& sk1, const RsTlvSecurityKey& sk2) return true; } +bool operator==(const RsTlvKeySignatureSet& kss1, const RsTlvKeySignatureSet& kss2) +{ + const std::map& set1 = kss1.keySignSet, + &set2 = kss2.keySignSet; + + if(set1.size() != set2.size()) return false; + + std::map::const_iterator it1 = set1.begin(), it2; + + for(; it1 != set1.end(); it1++) + { + SignType st1 = it1->first; + + if( (it2 =set2.find(st1)) == set2.end()) + return false; + + if(!(it1->second == it2->second)) + return false; + + } + + return true; +} + bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) { @@ -138,6 +162,19 @@ void init_item(RsTlvImage& im) return; } +void init_item(RsTlvKeySignatureSet &kss) +{ + int numSign = rand()%21; + + for(int i=0; i < numSign; i++) + { + RsTlvKeySignature sign; + SignType sType = rand()%2452; + init_item(sign); + kss.keySignSet.insert(std::make_pair(sType, sign)); + } +} + bool operator==(const RsTlvBinaryData& bd1, const RsTlvBinaryData& bd2) { if(bd1.tlvtype != bd2.tlvtype) return false; diff --git a/libretroshare/src/tests/gxs/support.h b/libretroshare/src/tests/gxs/support.h index 901b2f4ef..bf33716af 100644 --- a/libretroshare/src/tests/gxs/support.h +++ b/libretroshare/src/tests/gxs/support.h @@ -56,6 +56,7 @@ void randString(const uint32_t, std::wstring&); void init_item(RsTlvSecurityKey&); void init_item(RsTlvKeySignature&); +void init_item(RsTlvKeySignatureSet&); void init_item(RsTlvBinaryData&); void init_item(RsTlvFileItem&); void init_item(RsTlvFileSet&); @@ -74,6 +75,7 @@ bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); bool operator==(const RsTlvImage&, const RsTlvImage& ); bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); bool operator==(const RsTlvSecurityKeySet& , const RsTlvSecurityKeySet& ); +bool operator==(const RsTlvKeySignatureSet& , const RsTlvKeySignatureSet& ); diff --git a/libretroshare/src/tests/serialiser/rsphotoitem_test.cc b/libretroshare/src/tests/serialiser/rsphotoitem_test.cc new file mode 100644 index 000000000..fafd1650d --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsphotoitem_test.cc @@ -0,0 +1,139 @@ +/* + * libretroshare/src/test rsphotoitem_test.cc + * + * Test for photo item serialisation + * + * Copyright 2012-2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rsphotoitem_test.h" + + +RsSerialType* init_item(RsGxsPhotoAlbumItem &album) +{ + RsPhotoAlbum& a = album.album; + + randString(SHORT_STR, a.mCaption); + randString(SHORT_STR, a.mCategory); + randString(SHORT_STR, a.mDescription); + randString(SHORT_STR, a.mHashTags); + randString(SHORT_STR, a.mOther); + randString(SHORT_STR, a.mPhotoPath); + randString(SHORT_STR, a.mPhotographer); + randString(SHORT_STR, a.mWhen); + randString(SHORT_STR, a.mWhere); + randString(SHORT_STR, a.mThumbnail.type); + std::string rStr; + randString(SHORT_STR, rStr); + + a.mThumbnail.data = new uint8_t[SHORT_STR]; + memcpy(a.mThumbnail.data, rStr.data(), SHORT_STR); + a.mThumbnail.size = SHORT_STR; + + return new RsGxsPhotoSerialiser(); +} + +RsSerialType* init_item(RsGxsPhotoPhotoItem &photo) +{ + + RsPhotoPhoto& p = photo.photo; + + randString(SHORT_STR, p.mCaption); + randString(SHORT_STR, p.mCategory); + randString(SHORT_STR, p.mDescription); + randString(SHORT_STR, p.mHashTags); + randString(SHORT_STR, p.mOther); + randString(SHORT_STR, p.mPhotographer); + randString(SHORT_STR, p.mWhen); + randString(SHORT_STR, p.mWhere); + randString(SHORT_STR, p.mThumbnail.type); + std::string rStr; + randString(SHORT_STR, rStr); + + p.mThumbnail.data = new uint8_t[SHORT_STR]; + memcpy(p.mThumbnail.data, rStr.data(), SHORT_STR); + p.mThumbnail.size = SHORT_STR; + + return new RsGxsPhotoSerialiser(); +} + + +bool operator == (RsGxsPhotoAlbumItem& l, RsGxsPhotoAlbumItem& r) +{ + RsPhotoAlbum& la = l.album; + RsPhotoAlbum& ra = r.album; + + if(la.mCaption != ra.mCaption) return false; + if(la.mCategory != ra.mCategory) return false; + if(la.mDescription != ra.mDescription) return false; + if(la.mHashTags != ra.mHashTags) return false; + if(la.mOther != ra.mOther) return false; + if(la.mPhotographer!= ra.mPhotographer) return false; + if(la.mPhotoPath != ra.mPhotoPath) return false; + if(la.mWhere != ra.mWhere) return false; + if(la.mWhen != ra.mWhen) return false; + if(!(la.mThumbnail == ra.mThumbnail)) return false; + + return true; +} + + + +bool operator == (RsGxsPhotoPhotoItem& l, RsGxsPhotoPhotoItem& r) +{ + RsPhotoPhoto& la = l.photo; + RsPhotoPhoto& ra = r.photo; + + if(la.mCaption != ra.mCaption) return false; + if(la.mCategory != ra.mCategory) return false; + if(la.mDescription != ra.mDescription) return false; + if(la.mHashTags != ra.mHashTags) return false; + if(la.mOther != ra.mOther) return false; + if(la.mPhotographer!= ra.mPhotographer) return false; + if(la.mWhere != ra.mWhere) return false; + if(la.mWhen != ra.mWhen) return false; + if(!(la.mThumbnail == ra.mThumbnail)) return false; + + return true; +} + +bool operator == (RsPhotoThumbnail& l, RsPhotoThumbnail& r) +{ + if(l.size != r.size) return false; + if(l.type != r.type) return false; + if(memcmp(l.data, r.data,l.size) != 0) return false; + + return true; +} + +INITTEST() + +int main() +{ + std::cerr << "RsPhotoItem Tests" << std::endl; + + test_RsItem(); REPORT("Serialise/Deserialise RsGxsPhotoAlbumItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsGxsPhotoPhotoItem"); + + FINALREPORT("RsPhotoItem Tests"); + + return TESTRESULT(); +} diff --git a/libretroshare/src/tests/serialiser/rsphotoitem_test.h b/libretroshare/src/tests/serialiser/rsphotoitem_test.h new file mode 100644 index 000000000..cd726198e --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsphotoitem_test.h @@ -0,0 +1,41 @@ +/* + * libretroshare/src/test rsphotoitem_test.h + * + * Test for photo item serialisation + * + * Copyright 2012-2012 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RSPHOTOITEM_TEST_H_ +#define RSPHOTOITEM_TEST_H_ + +#include "serialiser/rsphotov2items.h" +#include "support.h" + + + +RsSerialType* init_item(RsGxsPhotoAlbumItem& album); +RsSerialType* init_item(RsGxsPhotoPhotoItem& photo); + +bool operator == (RsGxsPhotoAlbumItem& l, RsGxsPhotoAlbumItem& r); +bool operator == (RsGxsPhotoPhotoItem& l, RsGxsPhotoPhotoItem& r); +bool operator == (RsPhotoThumbnail& l, RsPhotoThumbnail& r); + +#endif /* RSPHOTOITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/support.cc b/libretroshare/src/tests/serialiser/support.cc index 9b4a22390..5207590b6 100644 --- a/libretroshare/src/tests/serialiser/support.cc +++ b/libretroshare/src/tests/serialiser/support.cc @@ -81,6 +81,30 @@ bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) return true; } +bool operator==(const RsTlvKeySignatureSet& kss1, const RsTlvKeySignatureSet& kss2) +{ + const std::map& set1 = kss1.keySignSet, + &set2 = kss2.keySignSet; + + if(set1.size() != set2.size()) return false; + + std::map::const_iterator it1 = set1.begin(), it2; + + for(; it1 != set1.end(); it1++) + { + SignType st1 = it1->first; + + if( (it2 =set2.find(st1)) == set2.end()) + return false; + + if(!(it1->second == it2->second)) + return false; + + } + + return true; +} + bool operator==(const RsTlvPeerIdSet& pids1, const RsTlvPeerIdSet& pids2) { std::list::const_iterator it1 = pids1.ids.begin(), @@ -153,6 +177,18 @@ void init_item(RsTlvKeySignature& ks) return; } +void init_item(RsTlvKeySignatureSet &kss) +{ + int numSign = rand()%21; + + for(int i=0; i < numSign; i++) + { + RsTlvKeySignature sign; + SignType sType = rand()%2452; + init_item(sign); + kss.keySignSet.insert(std::make_pair(sType, sign)); + } +} bool operator==(const RsTlvImage& img1, const RsTlvImage& img2) diff --git a/libretroshare/src/tests/serialiser/support.h b/libretroshare/src/tests/serialiser/support.h index 9f2f8868d..3d1e23f6d 100644 --- a/libretroshare/src/tests/serialiser/support.h +++ b/libretroshare/src/tests/serialiser/support.h @@ -56,6 +56,7 @@ void randString(const uint32_t, std::wstring&); void init_item(RsTlvSecurityKey&); void init_item(RsTlvKeySignature&); +void init_item(RsTlvKeySignatureSet&); void init_item(RsTlvBinaryData&); void init_item(RsTlvFileItem&); void init_item(RsTlvFileSet&); @@ -72,6 +73,7 @@ bool operator==(const RsTlvFileSet&, const RsTlvFileSet& ); bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); bool operator==(const RsTlvImage&, const RsTlvImage& ); bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); +bool operator==(const RsTlvKeySignatureSet& , const RsTlvKeySignatureSet& ); diff --git a/libretroshare/src/tests/serialiser/tlvkey_test.cc b/libretroshare/src/tests/serialiser/tlvkey_test.cc new file mode 100644 index 000000000..23c87a715 --- /dev/null +++ b/libretroshare/src/tests/serialiser/tlvkey_test.cc @@ -0,0 +1,36 @@ + + +#include "support.h" +#include "serialiser/rstlvkeys.h" + +INITTEST(); + +bool test_RsTlvKeySignatureSet(); + +int main() +{ + test_RsTlvKeySignatureSet(); REPORT("test_RsTlvKeySignatureSet()"); + + FINALREPORT("RsTlvKey Test"); +} + + + +bool test_RsTlvKeySignatureSet() +{ + RsTlvKeySignatureSet set; + + init_item(set); + + char data[set.TlvSize()]; + uint32_t offset = 0; + set.SetTlv(data, set.TlvSize(), &offset); + + RsTlvKeySignatureSet setConfirm; + + offset = 0; + setConfirm.GetTlv(data, set.TlvSize(), &offset); + + CHECK(setConfirm == set); + +} diff --git a/libretroshare/src/upnp/upnphandler_linux.cc b/libretroshare/src/upnp/upnphandler_linux.cc new file mode 100644 index 000000000..5d54b5581 --- /dev/null +++ b/libretroshare/src/upnp/upnphandler_linux.cc @@ -0,0 +1,431 @@ +//Linux only +/* This stuff is actually C */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern C */ +#endif +/* This stuff is actually C */ + +#include "upnp/upnphandler_linux.h" + +#include "util/rsnet.h" + +bool upnphandler::initUPnPState() +{ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState" << std::endl; + #endif + cUPnPControlPoint = new CUPnPControlPoint(2000); + + bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); + + if (IGWDetected) { + /* MODIFY STATE */ + dataMtx.lock(); /* LOCK MUTEX */ + upnpState = RS_UPNP_S_READY; + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; + std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; + #endif + + //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); + inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); + upnp_iaddr.sin_port = htons(iport); + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState READY" << std::endl; + #endif + dataMtx.unlock(); /* UNLOCK MUTEX */ + + } else { + upnpState = RS_UPNP_S_UNAVAILABLE; + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; + #endif + } + + return 0; +} + +class upnpThreadData +{ + public: + upnphandler *handler; + bool start; + bool stop; +}; + + /* Thread routines */ +extern "C" void* doSetupUPnP(void* p) +{ + #ifdef UPNP_DEBUG + std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; + #endif + upnpThreadData *data = (upnpThreadData *) p; + if ((!data) || (!data->handler)) + { + pthread_exit(NULL); + } + + /* publish it! */ + if (data -> stop) + { + data->handler->shutdown_upnp(); + } + + if (data -> start) + { + data->handler->initUPnPState(); + data->handler->start_upnp(); + } + + delete data; + pthread_exit(NULL); + + return NULL; +} + +bool upnphandler::background_setup_upnp(bool start, bool stop) +{ + pthread_t tid; + + /* launch thread */ + #ifdef UPNP_DEBUG + std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; + #endif + upnpThreadData *data = new upnpThreadData(); + data->handler = this; + data->start = start; + data->stop = stop; + + pthread_create(&tid, 0, &doSetupUPnP, (void *) data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + return true; +} + +bool upnphandler::start_upnp() +{ + if (!(upnpState >= RS_UPNP_S_READY)) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; + #endif + return false; + } + + struct sockaddr_in localAddr; + { + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + /* if we're to load -> load */ + /* select external ports */ + eport_curr = eport; + if (!eport_curr) + { + /* use local port if eport is zero */ + eport_curr = iport; + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; + #endif + } + + if (!eport_curr) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; + #endif + return false; + } + + /* our port */ + char in_addr[256]; + char in_port1[256]; + + upnp_iaddr.sin_port = htons(iport); + localAddr = upnp_iaddr; + uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); + snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); + snprintf(in_addr, 256, "%d.%d.%d.%d", + ((linaddr >> 24) & 0xff), + ((linaddr >> 16) & 0xff), + ((linaddr >> 8) & 0xff), + ((linaddr >> 0) & 0xff)); + + #ifdef UPNP_DEBUG + std::cerr << "Attempting Redirection: InAddr: " << in_addr; + std::cerr << " InPort: " << in_port1; + std::cerr << " ePort: " << eport_curr; + std::cerr << " eProt: " << "TCP and UDP"; + std::cerr << std::endl; + #endif + } + + //first of all, build the mappings + std::vector upnpPortMapping1; + CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); + upnpPortMapping1.push_back(cUPnPPortMapping1); + std::vector upnpPortMapping2; + CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); + upnpPortMapping2.push_back(cUPnPPortMapping2); + + //attempt to remove formal port redirection rules + cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); + + //add new rules + bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); + bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); + + struct sockaddr_in extAddr; + bool extAddrResult = getExternalAddress(extAddr); + + { + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + if (extAddrResult && (res || res2)) { + upnpState = RS_UPNP_S_ACTIVE; + } else { + upnpState = RS_UPNP_S_TCP_AND_FAILED; + } + + toStart = false; + } + + return (upnpState == RS_UPNP_S_ACTIVE); + +} + +bool upnphandler::shutdown_upnp() +{ + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + /* always attempt this (unless no port number) */ + if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; + std::cerr << " Prot: TCP"; + std::cerr << std::endl; + #endif + + std::vector upnpPortMapping1; + CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); + upnpPortMapping1.push_back(cUPnPPortMapping1); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; + std::cerr << " Prot: UDP"; + std::cerr << std::endl; + #endif + + std::vector upnpPortMapping2; + CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); + upnpPortMapping2.push_back(cUPnPPortMapping2); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); + + //destroy the upnp object + cUPnPControlPoint->~CUPnPControlPoint(); + } else { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; + #endif + } + + //stopping os ok, set starting to true for next net reset + toStop = false; + toStart = true; + upnpState = RS_UPNP_S_UNINITIALISED; + + return true; + +} + +/************************ External Interface ***************************** + * + * + * + */ + +upnphandler::upnphandler() + : + upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"), + cUPnPControlPoint(NULL), + toEnable(false), toStart(false), toStop(false), + iport(0),eport(0), eport_curr(0) +{ +} + +upnphandler::~upnphandler() +{ + return; +} + + /* RsIface */ +void upnphandler::enable(bool active) +{ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; + std::cerr << "toEnable : " << toEnable << std::endl; + std::cerr << "toStart : " << toStart << std::endl; + #endif + + dataMtx.lock(); /*** LOCK MUTEX ***/ + if (active != toEnable) + { + if (active) + { + toStart = true; + } + else + { + toStop = true; + } + } + toEnable = active; + + bool start = toStart; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + if (start) + { + /* make background thread to startup UPnP */ + background_setup_upnp(true, false); + } +} + + +void upnphandler::shutdown() +{ + /* blocking call to shutdown upnp */ + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown() called." << std::endl; + #endif + shutdown_upnp(); +} + + +void upnphandler::restart() +{ + /* non-blocking call to shutdown upnp, and startup again. */ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::restart() called." << std::endl; + #endif + background_setup_upnp(true, true); +} + + + +bool upnphandler::getEnabled() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + bool on = toEnable; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + +bool upnphandler::getActive() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + #ifdef UPNP_DEBUG + std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; + #endif + + bool on = (upnpState == RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + + /* the address that the listening port is on */ +void upnphandler::setInternalPort(unsigned short iport_in) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + if (iport != iport_in) + { + iport = iport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + +void upnphandler::setExternalPort(unsigned short eport_in) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + /* flag both shutdown/start -> for restart */ + if (eport != eport_in) + { + eport = eport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + + /* as determined by uPnP */ +bool upnphandler::getInternalAddress(struct sockaddr_in &addr) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + addr = upnp_iaddr; + bool valid = (upnpState >= RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return valid; +} + +bool upnphandler::getExternalAddress(struct sockaddr_in &addr) +{ + std::string externalAdress = cUPnPControlPoint->getExternalAddress(); + + if(!externalAdress.empty() && externalAdress != "") + { + const char* externalIPAddress = externalAdress.c_str(); + + #ifdef UPNP_DEBUG + std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; + std::cerr << ":" << eport_curr; + std::cerr << std::endl; + #endif + + dataMtx.lock(); /*** LOCK MUTEX ***/ + sockaddr_clear(&upnp_eaddr); + inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); + upnp_eaddr.sin_family = AF_INET; + upnp_eaddr.sin_port = htons(eport_curr); + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + addr = upnp_eaddr; + return true; + } + else + { + return false; + } +} + + + diff --git a/libretroshare/src/upnp/upnphandler_linux.h b/libretroshare/src/upnp/upnphandler_linux.h new file mode 100644 index 000000000..e0b8588a2 --- /dev/null +++ b/libretroshare/src/upnp/upnphandler_linux.h @@ -0,0 +1,82 @@ +#ifndef _RS_UPNP_IFACE_H +#define _RS_UPNP_IFACE_H + +#include + +/* platform independent networking... */ +#include "pqi/pqinetwork.h" +#include "pqi/pqiassist.h" + +#include "util/rsthreads.h" + +#include +#include "upnp/UPnPBase.h" + +#define RS_UPNP_S_UNINITIALISED 0 +#define RS_UPNP_S_UNAVAILABLE 1 +#define RS_UPNP_S_READY 2 +#define RS_UPNP_S_TCP_AND_FAILED 3 +//#define RS_UPNP_S_UDP_FAILED 4 +#define RS_UPNP_S_ACTIVE 5 + +class upnphandler: public pqiNetAssistFirewall +{ + public: + + upnphandler(); + virtual ~upnphandler(); + + /* External Interface (pqiNetAssistFirewall) */ + virtual void enable(bool active); + virtual void shutdown(); + virtual void restart(); + + virtual bool getEnabled(); + virtual bool getActive(); + + virtual void setInternalPort(unsigned short iport_in); + virtual void setExternalPort(unsigned short eport_in); + virtual bool getInternalAddress(struct sockaddr_in &addr); + virtual bool getExternalAddress(struct sockaddr_in &addr); + + /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ + virtual bool requestPortForward(const PortForwardParams ¶ms) { return false; } + virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams ¶ms) { return false; } + + /* Public functions - for background thread operation, + * but effectively private from rest of RS, as in derived class + */ + unsigned int upnpState; + + bool start_upnp(); + bool shutdown_upnp(); + + bool initUPnPState(); + + /* Mutex for data below */ + RsMutex dataMtx; + + private: + + CUPnPControlPoint *cUPnPControlPoint; + + bool background_setup_upnp(bool, bool); + + + bool toEnable; /* overall on/off switch */ + bool toStart; /* if set start forwarding */ + bool toStop; /* if set stop forwarding */ + + unsigned short iport; + unsigned short eport; /* config */ + unsigned short eport_curr; /* current forwarded */ + + /* info from upnp */ + struct sockaddr_in upnp_iaddr; + struct sockaddr_in upnp_eaddr; +}; + +/* info from upnp */ +int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); + +#endif /* _RS_UPNP_IFACE_H */ diff --git a/libretroshare/src/upnp/upnphandler.cc b/libretroshare/src/upnp/upnphandler_miniupnp.cc similarity index 53% rename from libretroshare/src/upnp/upnphandler.cc rename to libretroshare/src/upnp/upnphandler_miniupnp.cc index d77aa90d1..b4cb3c199 100644 --- a/libretroshare/src/upnp/upnphandler.cc +++ b/libretroshare/src/upnp/upnphandler_miniupnp.cc @@ -1,440 +1,4 @@ -//Linux only -#if !defined(WINDOWS_SYS) && !defined(__APPLE__) - -/* This stuff is actually C */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern C */ -#endif -/* This stuff is actually C */ - -#include "upnp/upnphandler.h" - -#include "util/rsnet.h" - -bool upnphandler::initUPnPState() -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState" << std::endl; - #endif - cUPnPControlPoint = new CUPnPControlPoint(2000); - - bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); - - if (IGWDetected) { - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - upnpState = RS_UPNP_S_READY; - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; - std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; - #endif - - //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); - inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); - upnp_iaddr.sin_port = htons(iport); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState READY" << std::endl; - #endif - dataMtx.unlock(); /* UNLOCK MUTEX */ - - } else { - upnpState = RS_UPNP_S_UNAVAILABLE; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; - #endif - } - - return 0; -} - -class upnpThreadData -{ - public: - upnphandler *handler; - bool start; - bool stop; -}; - - /* Thread routines */ -extern "C" void* doSetupUPnP(void* p) -{ - #ifdef UPNP_DEBUG - std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = (upnpThreadData *) p; - if ((!data) || (!data->handler)) - { - pthread_exit(NULL); - } - - /* publish it! */ - if (data -> stop) - { - data->handler->shutdown_upnp(); - } - - if (data -> start) - { - data->handler->initUPnPState(); - data->handler->start_upnp(); - } - - delete data; - pthread_exit(NULL); - - return NULL; -} - -bool upnphandler::background_setup_upnp(bool start, bool stop) -{ - pthread_t tid; - - /* launch thread */ - #ifdef UPNP_DEBUG - std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = new upnpThreadData(); - data->handler = this; - data->start = start; - data->stop = stop; - - pthread_create(&tid, 0, &doSetupUPnP, (void *) data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - return true; -} - -bool upnphandler::start_upnp() -{ - if (!(upnpState >= RS_UPNP_S_READY)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; - #endif - return false; - } - - struct sockaddr_in localAddr; - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* if we're to load -> load */ - /* select external ports */ - eport_curr = eport; - if (!eport_curr) - { - /* use local port if eport is zero */ - eport_curr = iport; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; - #endif - } - - if (!eport_curr) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; - #endif - return false; - } - - /* our port */ - char in_addr[256]; - char in_port1[256]; - - upnp_iaddr.sin_port = htons(iport); - localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - #ifdef UPNP_DEBUG - std::cerr << "Attempting Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport_curr; - std::cerr << " eProt: " << "TCP and UDP"; - std::cerr << std::endl; - #endif - } - - //first of all, build the mappings - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - - //attempt to remove formal port redirection rules - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //add new rules - bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); - bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); - - struct sockaddr_in extAddr; - bool extAddrResult = getExternalAddress(extAddr); - - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - if (extAddrResult && (res || res2)) { - upnpState = RS_UPNP_S_ACTIVE; - } else { - upnpState = RS_UPNP_S_TCP_AND_FAILED; - } - - toStart = false; - } - - return (upnpState == RS_UPNP_S_ACTIVE); - -} - -bool upnphandler::shutdown_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* always attempt this (unless no port number) */ - if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: TCP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: UDP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //destroy the upnp object - cUPnPControlPoint->~CUPnPControlPoint(); - } else { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; - #endif - } - - //stopping os ok, set starting to true for next net reset - toStop = false; - toStart = true; - upnpState = RS_UPNP_S_UNINITIALISED; - - return true; - -} - -/************************ External Interface ***************************** - * - * - * - */ - -upnphandler::upnphandler() - : - upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"), - cUPnPControlPoint(NULL), - toEnable(false), toStart(false), toStop(false), - iport(0),eport(0), eport_curr(0) -{ -} - -upnphandler::~upnphandler() -{ - return; -} - - /* RsIface */ -void upnphandler::enable(bool active) -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; - std::cerr << "toEnable : " << toEnable << std::endl; - std::cerr << "toStart : " << toStart << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (active != toEnable) - { - if (active) - { - toStart = true; - } - else - { - toStop = true; - } - } - toEnable = active; - - bool start = toStart; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - if (start) - { - /* make background thread to startup UPnP */ - background_setup_upnp(true, false); - } -} - - -void upnphandler::shutdown() -{ - /* blocking call to shutdown upnp */ - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown() called." << std::endl; - #endif - shutdown_upnp(); -} - - -void upnphandler::restart() -{ - /* non-blocking call to shutdown upnp, and startup again. */ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::restart() called." << std::endl; - #endif - background_setup_upnp(true, true); -} - - - -bool upnphandler::getEnabled() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = toEnable; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - -bool upnphandler::getActive() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - #ifdef UPNP_DEBUG - std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; - #endif - - bool on = (upnpState == RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - - /* the address that the listening port is on */ -void upnphandler::setInternalPort(unsigned short iport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (iport != iport_in) - { - iport = iport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -void upnphandler::setExternalPort(unsigned short eport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - /* flag both shutdown/start -> for restart */ - if (eport != eport_in) - { - eport = eport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - - /* as determined by uPnP */ -bool upnphandler::getInternalAddress(struct sockaddr_in &addr) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - addr = upnp_iaddr; - bool valid = (upnpState >= RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return valid; -} - -bool upnphandler::getExternalAddress(struct sockaddr_in &addr) -{ - std::string externalAdress = cUPnPControlPoint->getExternalAddress(); - - if(!externalAdress.empty() && externalAdress != "") - { - const char* externalIPAddress = externalAdress.c_str(); - - #ifdef UPNP_DEBUG - std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; - std::cerr << ":" << eport_curr; - std::cerr << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - sockaddr_clear(&upnp_eaddr); - inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); - upnp_eaddr.sin_family = AF_INET; - upnp_eaddr.sin_port = htons(eport_curr); - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - addr = upnp_eaddr; - return true; - } - else - { - return false; - } -} -#endif - - - // Windows / Mac version. -#if defined(WINDOWS_SYS) || defined(__APPLE__) - /* This stuff is actually C */ #ifdef __cplusplus @@ -446,7 +10,7 @@ extern "C" { #endif /* This stuff is actually C */ -#include "upnp/upnphandler.h" +#include "upnp/upnphandler_miniupnp.h" #include "upnp/upnputil.h" class uPnPConfigData @@ -838,6 +402,7 @@ bool upnphandler::shutdown_upnp() * */ + upnphandler::upnphandler() : dataMtx("upnpState"), toEnable(false), toStart(false), toStop(false), eport(0), eport_curr(0), @@ -1001,4 +566,3 @@ bool upnphandler::getExternalAddress(struct sockaddr_in &addr) return valid; } -#endif diff --git a/libretroshare/src/upnp/upnphandler.h b/libretroshare/src/upnp/upnphandler_miniupnp.h similarity index 50% rename from libretroshare/src/upnp/upnphandler.h rename to libretroshare/src/upnp/upnphandler_miniupnp.h index 80b8560de..e734f8413 100644 --- a/libretroshare/src/upnp/upnphandler.h +++ b/libretroshare/src/upnp/upnphandler_miniupnp.h @@ -1,94 +1,4 @@ -//Linux only... -#if !defined(WINDOWS_SYS) && !defined(__APPLE__) - -#ifndef _RS_UPNP_IFACE_H -#define _RS_UPNP_IFACE_H - -#include - -/* platform independent networking... */ -#include "pqi/pqinetwork.h" -#include "pqi/pqiassist.h" - -#include "util/rsthreads.h" - -#include -#include "upnp/UPnPBase.h" - -#define RS_UPNP_S_UNINITIALISED 0 -#define RS_UPNP_S_UNAVAILABLE 1 -#define RS_UPNP_S_READY 2 -#define RS_UPNP_S_TCP_AND_FAILED 3 -//#define RS_UPNP_S_UDP_FAILED 4 -#define RS_UPNP_S_ACTIVE 5 - -class upnphandler: public pqiNetAssistFirewall -{ - public: - - upnphandler(); - virtual ~upnphandler(); - - /* External Interface (pqiNetAssistFirewall) */ - virtual void enable(bool active); - virtual void shutdown(); - virtual void restart(); - - virtual bool getEnabled(); - virtual bool getActive(); - - virtual void setInternalPort(unsigned short iport_in); - virtual void setExternalPort(unsigned short eport_in); - virtual bool getInternalAddress(struct sockaddr_in &addr); - virtual bool getExternalAddress(struct sockaddr_in &addr); - - /* Public functions - for background thread operation, - * but effectively private from rest of RS, as in derived class - */ - unsigned int upnpState; - - bool start_upnp(); - bool shutdown_upnp(); - - bool initUPnPState(); - - /* Mutex for data below */ - RsMutex dataMtx; - - private: - - CUPnPControlPoint *cUPnPControlPoint; - - bool background_setup_upnp(bool, bool); - - - bool toEnable; /* overall on/off switch */ - bool toStart; /* if set start forwarding */ - bool toStop; /* if set stop forwarding */ - - unsigned short iport; - unsigned short eport; /* config */ - unsigned short eport_curr; /* current forwarded */ - - /* info from upnp */ - struct sockaddr_in upnp_iaddr; - struct sockaddr_in upnp_eaddr; -}; - -/* info from upnp */ -int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); - -#endif /* _RS_UPNP_IFACE_H */ - -#endif - - - - - -#if defined(WINDOWS_SYS) || defined(__APPLE__) - -//windows implementation +//windows/osx (miniupnpc) implementation #ifndef _RS_UPNP_IFACE_H #define _RS_UPNP_IFACE_H @@ -155,6 +65,10 @@ virtual void setExternalPort(unsigned short eport_in); virtual bool getInternalAddress(struct sockaddr_in &addr); virtual bool getExternalAddress(struct sockaddr_in &addr); + /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ +virtual bool requestPortForward(const PortForwardParams ¶ms) { return false; } +virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams ¶ms) { return false; } + /* Public functions - for background thread operation, * but effectively private from rest of RS, as in derived class */ @@ -194,4 +108,3 @@ bool checkUPnPActive(); }; #endif /* _RS_UPNP_IFACE_H */ -#endif diff --git a/libretroshare/src/util/contentvalue.cc b/libretroshare/src/util/contentvalue.cc new file mode 100644 index 000000000..cce492df3 --- /dev/null +++ b/libretroshare/src/util/contentvalue.cc @@ -0,0 +1,312 @@ + +/* + * util/contentvalue.cc, key val container + * + * Copyright 2012 Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include + +#include "contentvalue.h" + + + + +const uint8_t ContentValue::BOOL_TYPE = 1; +const uint8_t ContentValue::DATA_TYPE = 2; +const uint8_t ContentValue::STRING_TYPE = 3; +const uint8_t ContentValue::DOUBLE_TYPE = 4; +const uint8_t ContentValue::INT32_TYPE = 5; +const uint8_t ContentValue::INT64_TYPE = 6; + + +/**************** content value implementation ******************/ + +typedef std::pair KeyTypePair; + +ContentValue::ContentValue(){ + +} + +ContentValue::~ContentValue(){ + // release resources held in data + clearData(); +} + +ContentValue::ContentValue(ContentValue &from){ + + std::map keyTypeMap; + from.getKeyTypeMap(keyTypeMap); + std::map::const_iterator cit = + keyTypeMap.begin(); + + uint8_t type = 0; + std::string currKey; + std::string val = ""; + char *src = NULL; + uint32_t data_len = 0; + + for(; cit != keyTypeMap.end(); cit++){ + + type = cit->second; + currKey = cit->first; + + switch(type){ + + case INT32_TYPE: + { + int32_t value; + from.getAsInt32(currKey, value); + put(currKey, value); + break; + } + case INT64_TYPE: + { + int64_t value; + from.getAsInt64(currKey, value); + put(currKey, value); + break; + } + case STRING_TYPE: + { + from.getAsString(currKey, val); + put(currKey, val); + break; + } + case BOOL_TYPE: + { + bool value; + from.getAsBool(currKey, value); + put(currKey, value); + break; + } + case DATA_TYPE: + { + from.getAsData(currKey, data_len, src); + put(currKey, data_len, src); + break; + } + case DOUBLE_TYPE: + double value; + from.getAsDouble(currKey, value); + put(currKey, value); + break; + default: + std::cerr << "ContentValue::ContentValue(ContentValue &from):" + << "Error! Unrecognised data type!" << std::endl; + break; + } + } +} + +void ContentValue::put(const std::string &key, bool value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); + mKvBool.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, const std::string &value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, STRING_TYPE)); + mKvString.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, double value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); + mKvDouble.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, int32_t value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, INT32_TYPE)); + mKvInt32.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, int64_t value){ + + if(mKvSet.find(key) != mKvSet.end()) + removeKeyValue(key); + + mKvSet.insert(KeyTypePair(key, INT64_TYPE)); + mKvInt64.insert(std::pair(key, value)); +} + +void ContentValue::put(const std::string &key, uint32_t len, const char* value){ + + + // release memory from old key value if key + // exists + if(mKvSet.find(key) != mKvSet.end()) { + removeKeyValue(key); + } + + mKvSet.insert(KeyTypePair(key, DATA_TYPE)); + char* dest = NULL; + + // len is zero then just put a NULL entry + if(len != 0){ + dest = new char[len]; + memcpy(dest, value, len); + } + + mKvData.insert(std::pair > + (key, std::pair(len, dest))); +} + +bool ContentValue::getAsBool(const std::string &key, bool& value) const{ + + std::map::const_iterator it; + if((it = mKvBool.find(key)) == mKvBool.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ + + std::map::const_iterator it; + if((it = mKvInt32.find(key)) == mKvInt32.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ + + std::map::const_iterator it; + if((it = mKvInt64.find(key)) == mKvInt64.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsString(const std::string &key, std::string &value) const{ + + std::map::const_iterator it; + if((it = mKvString.find(key)) == mKvString.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ + + std::map >::const_iterator it; + if((it = mKvData.find(key)) == mKvData.end()) + return false; + + const std::pair &kvRef = it->second; + + len = kvRef.first; + value = kvRef.second; + return true; +} + +bool ContentValue::getAsDouble(const std::string &key, double& value) const{ + + std::map::const_iterator it; + if((it = mKvDouble.find(key)) == mKvDouble.end()) + return false; + + value = it->second; + return true; +} + +bool ContentValue::removeKeyValue(const std::string &key){ + + std::map::iterator mit; + + if((mit = mKvSet.find(key)) == mKvSet.end()) + return false; + + if(mit->second == BOOL_TYPE) + mKvBool.erase(key); + + if(mit->second == INT64_TYPE) + mKvInt64.erase(key); + + if(mit->second == DATA_TYPE){ + delete[] (mKvData[key].second); + mKvData.erase(key); + } + + if(mit->second == DOUBLE_TYPE) + mKvDouble.erase(key); + + if(mit->second == STRING_TYPE) + mKvString.erase(key); + + if(mit->second == INT32_TYPE) + mKvInt32.erase(key); + + + mKvSet.erase(key); + return true; +} + + +void ContentValue::getKeyTypeMap(std::map &keySet) const { + keySet = mKvSet; +} + +void ContentValue::clear(){ + mKvSet.clear(); + mKvBool.clear(); + mKvDouble.clear(); + mKvString.clear(); + mKvInt32.clear(); + mKvInt64.clear(); + clearData(); +} + +void ContentValue::clearData(){ + + std::map >::iterator + mit = mKvData.begin(); + + for(; mit != mKvData.end(); mit++){ + + if(mit->second.first != 0) + delete[] (mit->second.second); + } + + mKvData.clear(); +} + + + diff --git a/libretroshare/src/util/contentvalue.h b/libretroshare/src/util/contentvalue.h new file mode 100644 index 000000000..50b12af48 --- /dev/null +++ b/libretroshare/src/util/contentvalue.h @@ -0,0 +1,183 @@ +#ifndef CONTENTVALUE_H +#define CONTENTVALUE_H + +/* + * util/contentvalue.h, key val container + * + * Copyright 2012 Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +/*! + * @brief Convenience container for making additions to databases + * This class provides a means of holding column values to insert into a database + */ +class ContentValue { + +public: + + static const uint8_t INT32_TYPE; + static const uint8_t INT64_TYPE; + static const uint8_t DOUBLE_TYPE; + static const uint8_t STRING_TYPE; + static const uint8_t DATA_TYPE; + static const uint8_t BOOL_TYPE; + + ContentValue(); + + /*! + * copy constructor that copys the key value set from another \n + * ContentValue object to this one + * makes a deep copy of raw data + * @param from ContentValue instance to copy key value set from + */ + ContentValue(ContentValue& from); + + /*! + * + * + * + */ + ~ContentValue(); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + * @warning cast string literals explicitly as string, observed string literal \n + * being casted to bool instead e.g. string("hello") rather than "hello" + */ + void put(const std::string& key, const std::string& value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, bool value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, int64_t value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, int32_t value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, double value); + + /*! + * Adds a value to the set + * @param key the name of the value to put + * @param value the data for the value to put + */ + void put(const std::string& key, uint32_t len, const char* value); + + + /*! + * get value as 32 bit signed integer + * @param key the value to get + */ + bool getAsInt32(const std::string& key, int32_t& value) const; + + /*! + * get value as 64 bit signed integer + * @param key the value to get + */ + bool getAsInt64(const std::string& key, int64_t& value) const; + + /*! + * get value as bool + * @param key the value to get + */ + bool getAsBool(const std::string& key, bool& value) const; + + /*! + * get as value double + * @param key the value to get + */ + bool getAsDouble(const std::string& key, double& value) const; + + /*! + * get as value as string + * @param key the value to get + * @param value the data retrieved + */ + bool getAsString(const std::string& key, std::string& value) const; + + /*! + * get as value as raw data + * @warning Deep copy of data reference should be made, if this instance ContentValue \n + * is destroyed pointer returned (value) is pointing to invalid memory + * @param key the value to get + */ + bool getAsData(const std::string&, uint32_t& len, char*& value) const; + + /*! + * @param keySet the is set with key to type pairs contained in the ContentValue instance + */ + void getKeyTypeMap(std::map& keySet) const; + + /*! + * @param key the key of the key value pair to remove + * @return true if key was found and removed, false otherwise + */ + bool removeKeyValue(const std::string& key); + + /*! + * clears this data structure of all its key value pairs held + */ + void clear(); + +private: + + /*! + * release memory resource associated with mKvData + */ + void clearData(); + +private: + + std::map mKvInt32; + std::map mKvInt64; + std::map mKvDouble; + std::map mKvString; + std::map > mKvData; + std::map mKvBool; + + std::map mKvSet; + +}; + +#endif // CONTENTVALUE_H diff --git a/libretroshare/src/util/folderiterator.h b/libretroshare/src/util/folderiterator.h index bfddc6b74..8007db1a1 100644 --- a/libretroshare/src/util/folderiterator.h +++ b/libretroshare/src/util/folderiterator.h @@ -6,7 +6,6 @@ #include #ifdef WINDOWS_SYS - #include "util/rswin.h" #include #include #include diff --git a/libretroshare/src/util/retrodb.cc b/libretroshare/src/util/retrodb.cc index 3af1e67aa..c7402a8a3 100644 --- a/libretroshare/src/util/retrodb.cc +++ b/libretroshare/src/util/retrodb.cc @@ -32,6 +32,8 @@ //#define RETRODB_DEBUG + + void free_blob(void* dat){ char* c = (char*) dat; @@ -40,13 +42,6 @@ void free_blob(void* dat){ } -const uint8_t ContentValue::BOOL_TYPE = 1; -const uint8_t ContentValue::DATA_TYPE = 2; -const uint8_t ContentValue::STRING_TYPE = 3; -const uint8_t ContentValue::DOUBLE_TYPE = 4; -const uint8_t ContentValue::INT32_TYPE = 5; -const uint8_t ContentValue::INT64_TYPE = 6; - const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY; const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE; const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; @@ -234,25 +229,23 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH uint8_t type = mit->second; std::string key = mit->first; - switch(type){ - case ContentValue::BOOL_TYPE: + + if(ContentValue::BOOL_TYPE == type) { bool value; cv.getAsBool(key, value); oStrStream << value; qValues += oStrStream.str(); - break; } - case ContentValue::DOUBLE_TYPE: + else if( ContentValue::DOUBLE_TYPE == type) { double value; cv.getAsDouble(key, value); oStrStream << value; qValues += oStrStream.str(); - break; } - case ContentValue::DATA_TYPE: + else if( ContentValue::DATA_TYPE == type) { char* value; uint32_t len; @@ -263,32 +256,28 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH b.index = ++index; blobL.push_back(b); qValues += "?"; // parameter - break; } - case ContentValue::STRING_TYPE: + else if ( ContentValue::STRING_TYPE == type) { std::string value; cv.getAsString(key, value); qValues += "'" + value +"'"; - break; } - case ContentValue::INT32_TYPE: + else if ( ContentValue::INT32_TYPE == type) { int32_t value; cv.getAsInt32(key, value); oStrStream << value; qValues += oStrStream.str(); - break; } - case ContentValue::INT64_TYPE: + else if( ContentValue::INT64_TYPE == type) { int64_t value; cv.getAsInt64(key, value); oStrStream << value; qValues += oStrStream.str(); - break; } - } + mit++; if(mit != keyTypeMap.end()){ // add comma if more columns left @@ -419,57 +408,48 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c uint8_t type = mit->second; std::string key = mit->first; - switch(type){ - - case ContentValue::BOOL_TYPE: + if( ContentValue::BOOL_TYPE == type) { bool value; cv.getAsBool(key, value); oStrStream << value; qValues += key + "='" + oStrStream.str(); - break; } - case ContentValue::DOUBLE_TYPE: + else if( ContentValue::DOUBLE_TYPE == type) { double value; cv.getAsDouble(key, value); oStrStream << value; qValues += key + "='" + oStrStream.str(); - break; } - case ContentValue::DATA_TYPE: + else if( ContentValue::DATA_TYPE == type) { char* value; uint32_t len; cv.getAsData(key, len, value); oStrStream.write(value, len); qValues += key + "='" + oStrStream.str() + "' "; - break; } - case ContentValue::STRING_TYPE: + else if( ContentValue::STRING_TYPE == type) { std::string value; cv.getAsString(key, value); qValues += key + "='" + value + "' "; - break; } - case ContentValue::INT32_TYPE: + else if( ContentValue::INT32_TYPE == type) { int32_t value; cv.getAsInt32(key, value); oStrStream << value; qValues += key + "='" + oStrStream.str() + "' "; - break; } - case ContentValue::INT64_TYPE: + else if( ContentValue::INT64_TYPE == type) { int64_t value; cv.getAsInt64(key, value); oStrStream << value; qValues += key + "='" + oStrStream.str() + "' "; - break; } - } mit++; if(mit != keyTypeMap.end()){ // add comma if more columns left @@ -496,7 +476,6 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c // execute query return execSQL(sqlQuery); - } @@ -715,276 +694,3 @@ const void* RetroCursor::getData(int columnIndex, uint32_t &datSize){ } - - -/**************** content value implementation ******************/ - -typedef std::pair KeyTypePair; - -ContentValue::ContentValue(){ - -} - -ContentValue::~ContentValue(){ - // release resources held in data - clearData(); -} - -ContentValue::ContentValue(ContentValue &from){ - - std::map keyTypeMap; - from.getKeyTypeMap(keyTypeMap); - std::map::const_iterator cit = - keyTypeMap.begin(); - - uint8_t type = 0; - std::string currKey; - std::string val = ""; - char *src = NULL; - uint32_t data_len = 0; - - for(; cit != keyTypeMap.end(); cit++){ - - type = cit->second; - currKey = cit->first; - - switch(type){ - - case INT32_TYPE: - { - int32_t value; - from.getAsInt32(currKey, value); - put(currKey, value); - break; - } - case INT64_TYPE: - { - int64_t value; - from.getAsInt64(currKey, value); - put(currKey, value); - break; - } - case STRING_TYPE: - { - from.getAsString(currKey, val); - put(currKey, val); - break; - } - case BOOL_TYPE: - { - bool value; - from.getAsBool(currKey, value); - put(currKey, value); - break; - } - case DATA_TYPE: - { - from.getAsData(currKey, data_len, src); - put(currKey, data_len, src); - break; - } - case DOUBLE_TYPE: - double value; - from.getAsDouble(currKey, value); - put(currKey, value); - break; - default: - std::cerr << "ContentValue::ContentValue(ContentValue &from):" - << "Error! Unrecognised data type!" << std::endl; - } - } -} - -void ContentValue::put(const std::string &key, bool value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); - mKvBool.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, const std::string &value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, STRING_TYPE)); - mKvString.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, double value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); - mKvDouble.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int32_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT32_TYPE)); - mKvInt32.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int64_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT64_TYPE)); - mKvInt64.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, uint32_t len, const char* value){ - - - // release memory from old key value if key - // exists - if(mKvSet.find(key) != mKvSet.end()) { - removeKeyValue(key); - } - - mKvSet.insert(KeyTypePair(key, DATA_TYPE)); - char* dest = NULL; - - // len is zero then just put a NULL entry - if(len != 0){ - dest = new char[len]; - memcpy(dest, value, len); - } - - mKvData.insert(std::pair > - (key, std::pair(len, dest))); -} - -bool ContentValue::getAsBool(const std::string &key, bool& value) const{ - - std::map::const_iterator it; - if((it = mKvBool.find(key)) == mKvBool.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt32.find(key)) == mKvInt32.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt64.find(key)) == mKvInt64.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsString(const std::string &key, std::string &value) const{ - - std::map::const_iterator it; - if((it = mKvString.find(key)) == mKvString.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ - - std::map >::const_iterator it; - if((it = mKvData.find(key)) == mKvData.end()) - return false; - - const std::pair &kvRef = it->second; - - len = kvRef.first; - value = kvRef.second; - return true; -} - -bool ContentValue::getAsDouble(const std::string &key, double& value) const{ - - std::map::const_iterator it; - if((it = mKvDouble.find(key)) == mKvDouble.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::removeKeyValue(const std::string &key){ - - std::map::iterator mit; - - if((mit = mKvSet.find(key)) == mKvSet.end()) - return false; - - if(mit->second == BOOL_TYPE) - mKvBool.erase(key); - - if(mit->second == INT64_TYPE) - mKvInt64.erase(key); - - if(mit->second == DATA_TYPE){ - delete[] (mKvData[key].second); - mKvData.erase(key); - } - - if(mit->second == DOUBLE_TYPE) - mKvDouble.erase(key); - - if(mit->second == STRING_TYPE) - mKvString.erase(key); - - if(mit->second == INT32_TYPE) - mKvInt32.erase(key); - - - mKvSet.erase(key); - return true; -} - - -void ContentValue::getKeyTypeMap(std::map &keySet) const { - keySet = mKvSet; -} - -void ContentValue::clear(){ - mKvSet.clear(); - mKvBool.clear(); - mKvDouble.clear(); - mKvString.clear(); - mKvInt32.clear(); - mKvInt64.clear(); - clearData(); -} - -void ContentValue::clearData(){ - - std::map >::iterator - mit = mKvData.begin(); - - for(; mit != mKvData.end(); mit++){ - - if(mit->second.first != 0) - delete[] (mit->second.second); - } - - mKvData.clear(); -} - - - diff --git a/libretroshare/src/util/retrodb.h b/libretroshare/src/util/retrodb.h index d1e773357..38706547f 100644 --- a/libretroshare/src/util/retrodb.h +++ b/libretroshare/src/util/retrodb.h @@ -31,8 +31,8 @@ #include #include +#include "contentvalue.h" -class ContentValue; class RetroCursor; /*! @@ -288,157 +288,7 @@ private: }; -/*! - * @brief Convenience container for making additions to databases - * This class provides a means of holding column values to insert into a database - */ -class ContentValue { -public: - - static const uint8_t INT32_TYPE; - static const uint8_t INT64_TYPE; - static const uint8_t DOUBLE_TYPE; - static const uint8_t STRING_TYPE; - static const uint8_t DATA_TYPE; - static const uint8_t BOOL_TYPE; - - ContentValue(); - - /*! - * copy constructor that copys the key value set from another \n - * ContentValue object to this one - * makes a deep copy of raw data - * @param from ContentValue instance to copy key value set from - */ - ContentValue(ContentValue& from); - - /*! - * - * - * - */ - ~ContentValue(); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - * @warning cast string literals explicitly as string, observed string literal \n - * being casted to bool instead e.g. string("hello") rather than "hello" - */ - void put(const std::string& key, const std::string& value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, bool value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int64_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int32_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, double value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, uint32_t len, const char* value); - - - /*! - * get value as 32 bit signed integer - * @param key the value to get - */ - bool getAsInt32(const std::string& key, int32_t& value) const; - - /*! - * get value as 64 bit signed integer - * @param key the value to get - */ - bool getAsInt64(const std::string& key, int64_t& value) const; - - /*! - * get value as bool - * @param key the value to get - */ - bool getAsBool(const std::string& key, bool& value) const; - - /*! - * get as value double - * @param key the value to get - */ - bool getAsDouble(const std::string& key, double& value) const; - - /*! - * get as value as string - * @param key the value to get - * @param value the data retrieved - */ - bool getAsString(const std::string& key, std::string& value) const; - - /*! - * get as value as raw data - * @warning Deep copy of data reference should be made, if this instance ContentValue \n - * is destroyed pointer returned (value) is pointing to invalid memory - * @param key the value to get - */ - bool getAsData(const std::string&, uint32_t& len, char*& value) const; - - /*! - * @param keySet the is set with key to type pairs contained in the ContentValue instance - */ - void getKeyTypeMap(std::map& keySet) const; - - /*! - * @param key the key of the key value pair to remove - * @return true if key was found and removed, false otherwise - */ - bool removeKeyValue(const std::string& key); - - /*! - * clears this data structure of all its key value pairs held - */ - void clear(); - -private: - - /*! - * release memory resource associated with mKvData - */ - void clearData(); - -private: - - std::map mKvInt32; - std::map mKvInt64; - std::map mKvDouble; - std::map mKvString; - std::map > mKvData; - std::map mKvBool; - - std::map mKvSet; - -}; #endif // RSSQLITE_H diff --git a/libretroshare/src/util/rsid.h b/libretroshare/src/util/rsid.h index 2c29a1f7e..bfcf845c0 100644 --- a/libretroshare/src/util/rsid.h +++ b/libretroshare/src/util/rsid.h @@ -25,6 +25,7 @@ // Warning: never store references to a t_RsGenericIdType accross threads, since the // cached string convertion is not thread safe. // + #pragma once #include @@ -63,6 +64,14 @@ template class t_RsGenericIdType return !operator==(fp) ; } + bool operator<(const t_RsGenericIdType& fp) const + { + for(uint32_t i=0;i +#include +#include +#include +#include + +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* Generic Memoory Cache + * + * This is probably crude and crap to start with. + * Want Least Recently Used (LRU) discard policy, without having to search whole cache. + * Use two maps: + * - mDataMap[key] => data. + * - mLruMap[AccessTS] => key (multimap) + */ + +#define DEFAULT_MEM_CACHE_SIZE 100 + +template class RsMemCache +{ + public: + + RsMemCache(uint32_t max_size = DEFAULT_MEM_CACHE_SIZE, std::string name = "UnknownMemCache") + :mDataCount(0), mMaxSize(max_size), mName(name) + { + clearStats(); + return; + } + + bool is_cached(const Key &key) const; + bool fetch(const Key &key, Value &data); + Value &ref(const Key &key); // like map[] installs empty one if non-existent. + bool store(const Key &key, const Value &data); + + bool resize(); // should be called periodically to cleanup old entries. + + private: + + bool update_lrumap(const Key &key, time_t old_ts, time_t new_ts); + bool discard_LRU(int count_to_clear); + + // internal class. + class cache_data + { + public: + cache_data() { return; } + cache_data(Key in_key, Value in_data, time_t in_ts) + :key(in_key), data(in_data), ts(in_ts) { return; } + Key key; + Value data; + time_t ts; + }; + + + std::map mDataMap; + std::multimap mLruMap; + uint32_t mDataCount; + uint32_t mMaxSize; + std::string mName; + + // some statistics. + void printStats(std::ostream &out); + void clearStats(); + + mutable uint32_t mStats_inserted; + mutable uint32_t mStats_dropped; + mutable uint32_t mStats_iscached; + mutable uint32_t mStats_cachemiss; + mutable uint32_t mStats_access; + mutable uint32_t mStats_accessmiss; +}; + + +template bool RsMemCache::is_cached(const Key &key) const +{ + typename std::map::const_iterator it; + it = mDataMap.find(key); + if (it == mDataMap.end()) + { + std::cerr << "RsMemCache::is_cached(" << key << ") false"; + std::cerr << std::endl; + + mStats_cachemiss++; + return false; + } + std::cerr << "RsMemCache::is_cached(" << key << ") false"; + std::cerr << std::endl; + mStats_iscached++; + return true; + +} + + +template bool RsMemCache::fetch(const Key &key, Value &data) +{ + printStats(std::cerr); + typename std::map::iterator it; + it = mDataMap.find(key); + if (it == mDataMap.end()) + { + std::cerr << "RsMemCache::fetch(" << key << ") false"; + std::cerr << std::endl; + + mStats_accessmiss++; + return false; + } + + std::cerr << "RsMemCache::fetch(" << key << ") OK"; + std::cerr << std::endl; + + data = it->second.data; + + /* update ts on data */ + time_t old_ts = it->second.ts; + time_t new_ts = time(NULL); + it->second.ts = new_ts; + + update_lrumap(key, old_ts, new_ts); + + mStats_access++; + return true; +} + + +template Value &RsMemCache::ref(const Key &key) +{ + printStats(std::cerr); + typename std::map::iterator it; + it = mDataMap.find(key); + if (it == mDataMap.end()) + { + std::cerr << "RsMemCache::ref(" << key << ") ERROR missing Key inserting Empty Data in LRU slot"; + std::cerr << std::endl; + + // insert operation. + time_t new_ts = 0; + Value data; + mDataMap[key] = cache_data(key, data, new_ts); + mDataCount++; + + update_lrumap(key, 0, new_ts); + it = mDataMap.find(key); + + mStats_accessmiss++; + } + else + { + std::cerr << "RsMemCache::ref(" << key << ") OK"; + std::cerr << std::endl; + + /* update ts on data */ + time_t old_ts = it->second.ts; + time_t new_ts = time(NULL); + it->second.ts = new_ts; + + update_lrumap(key, old_ts, new_ts); + + mStats_access++; + } + return it->second.data; +} + +template bool RsMemCache::store(const Key &key, const Value &data) +{ + std::cerr << "RsMemCache::store()"; + std::cerr << std::endl; + printStats(std::cerr); + + /* update lrumap entry */ + time_t old_ts = 0; + time_t new_ts = time(NULL); + + // For consistency + typename std::map::const_iterator it; + it = mDataMap.find(key); + if (it != mDataMap.end()) + { + // ERROR. + std::cerr << "RsMemCache::store() WARNING overriding existing entry"; + std::cerr << std::endl; + + old_ts = it->second.ts; + } + else + { + mDataCount++; + } + + mDataMap[key] = cache_data(key, data, new_ts); + + update_lrumap(key, old_ts, new_ts); + + mStats_inserted++; + return true; +} + + +template bool RsMemCache::update_lrumap(const Key &key, time_t old_ts, time_t new_ts) +{ + if (old_ts == 0) + { + std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") just insert!"; + std::cerr << std::endl; + + /* new insertion */ + mLruMap.insert(std::make_pair(new_ts, key)); + return true; + } + + /* find old entry */ + typename std::multimap::iterator mit; + typename std::multimap::iterator sit = mLruMap.lower_bound(old_ts); + typename std::multimap::iterator eit = mLruMap.upper_bound(old_ts); + + for(mit = sit; mit != eit; mit++) + { + if (mit->second == key) + { + mLruMap.erase(mit); + std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") rm old"; + std::cerr << std::endl; + + if (new_ts != 0) // == 0, means remove. + { + std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") added new_ts"; + std::cerr << std::endl; + mLruMap.insert(std::make_pair(new_ts, key)); + } + return true; + } + } + std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") ERROR"; + std::cerr << std::endl; + + return false; +} + +template bool RsMemCache::resize() +{ + std::cerr << "RsMemCache::resize()"; + std::cerr << std::endl; + printStats(std::cerr); + + int count_to_clear = 0; + { + // consistency check. + if ((mDataMap.size() != mDataCount) || + (mLruMap.size() != mDataCount)) + { + // ERROR. + std::cerr << "RsMemCache::resize() CONSISTENCY ERROR"; + std::cerr << std::endl; + } + + if (mDataCount > mMaxSize) + { + count_to_clear = mDataCount - mMaxSize; + std::cerr << "RsMemCache::resize() to_clear: " << count_to_clear; + std::cerr << std::endl; + } + } + + if (count_to_clear > 0) + { + discard_LRU(count_to_clear); + } + return true; +} + + + +template bool RsMemCache::discard_LRU(int count_to_clear) +{ + while(count_to_clear > 0) + { + typename std::multimap::iterator mit = mLruMap.begin(); + if (mit != mLruMap.end()) + { + Key key = mit->second; + mLruMap.erase(mit); + + /* now clear from real cache */ + //std::map >::iterator it; + typename std::map::iterator it; + it = mDataMap.find(key); + if (it == mDataMap.end()) + { + // ERROR + std::cerr << "RsMemCache::discard_LRU(): ERROR Missing key: " << key; + std::cerr << std::endl; + return false; + } + else + { + std::cerr << "RsMemCache::discard_LRU() removing: " << key; + std::cerr << std::endl; + mDataMap.erase(it); + mDataCount--; + mStats_dropped++; + } + } + else + { + // No More Data, ERROR. + std::cerr << "RsMemCache::discard_LRU(): INFO more more cache data"; + std::cerr << std::endl; + return true; + } + count_to_clear--; + } + return true; +} + +// These aren't templated functions. +template void RsMemCache::printStats(std::ostream &out) +{ + typename std::multimap::iterator mit = mLruMap.begin(); + time_t age = 0; + if (mit != mLruMap.end()) + { + age = time(NULL) - mit->first; + } + + out << "RsMemCache<" << mName << ">::printStats() Size: " << mDataCount << " Size2: " << mDataMap.size() << " Size3: " << mLruMap.size() << " MaxSize: " << mMaxSize << " LRU Age: " << age; + out << std::endl; + + out << "\tInsertions: " << mStats_inserted << " Drops: " << mStats_dropped; + out << std::endl; + + out << "\tCache Hits: " << mStats_iscached << " Misses: " << mStats_cachemiss; + out << std::endl; + + out << "\tAccess Hits: " << mStats_access << " Misses: " << mStats_accessmiss; + out << std::endl; +} + +template void RsMemCache::clearStats() +{ + mStats_inserted = 0; + mStats_dropped = 0; + mStats_iscached = 0; + mStats_cachemiss = 0; + mStats_access = 0; + mStats_accessmiss = 0; +} + + + + +#endif // RS_UTIL_MEM_CACHE diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index c8442f1c6..15bf5749a 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -44,10 +44,8 @@ #else -#include "util/rswin.h" #include -#include #include /* for ssize_t */ //typedef uint32_t socklen_t; diff --git a/libretroshare/src/util/rsthreads.h b/libretroshare/src/util/rsthreads.h index 34dc098f4..204fdd630 100644 --- a/libretroshare/src/util/rsthreads.h +++ b/libretroshare/src/util/rsthreads.h @@ -27,10 +27,6 @@ */ -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif - #include #include #include @@ -119,7 +115,7 @@ class RsThread RsThread(); virtual ~RsThread() {} -virtual void start() { createThread(*this); } +virtual void start() { mIsRunning = true; createThread(*this); } virtual void run() = 0; /* called once the thread is started */ virtual void join(); /* waits for the the mTid thread to stop */ virtual void stop(); /* calls pthread_exit() */ diff --git a/libretroshare/src/util/rstickevent.cc b/libretroshare/src/util/rstickevent.cc new file mode 100644 index 000000000..f91b2edf5 --- /dev/null +++ b/libretroshare/src/util/rstickevent.cc @@ -0,0 +1,198 @@ +/* + * libretroshare/src/util: rstickevent.cc + * + * Identity interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rstickevent.h" + +#include +#include + +//#define DEBUG_EVENTS 1 + +void RsTickEvent::tick_events() +{ +#ifdef DEBUG_EVENTS + std::cerr << "RsTickEvent::tick_events() Event List:"; + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + { + RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ + +#ifdef DEBUG_EVENTS + if (!mEvents.empty()) + { + std::multimap::iterator it; + + for(it = mEvents.begin(); it != mEvents.end(); it++) + { + std::cerr << "\tEvent type: "; + std::cerr << it->second << " in " << it->first - now << " secs"; + std::cerr << std::endl; + } + } +#endif + + if (mEvents.empty()) + { + return; + } + + /* all events in the future */ + if (mEvents.begin()->first > now) + { + return; + } + } + + std::list toProcess; + std::list::iterator it; + + { + RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ + while((!mEvents.empty()) && (mEvents.begin()->first <= now)) + { + std::multimap::iterator it = mEvents.begin(); + uint32_t event_type = it->second.mEventType; + toProcess.push_back(it->second); + mEvents.erase(it); + + count_adjust_locked(event_type, -1); + } + } + + for(it = toProcess.begin(); it != toProcess.end(); it++) + { + std::cerr << "RsTickEvent::tick_events() calling handle_event("; + std::cerr << it->mEventType << ", " << it->mEventLabel << ")"; + std::cerr << std::endl; + handle_event(it->mEventType, it->mEventLabel); + } +} + +void RsTickEvent::schedule_now(uint32_t event_type) +{ + std::string elabel; + RsTickEvent::schedule_in(event_type, 0, elabel); +} + + +void RsTickEvent::schedule_now(uint32_t event_type, const std::string &elabel) +{ + RsTickEvent::schedule_in(event_type, 0, elabel); +} + +void RsTickEvent::schedule_event(uint32_t event_type, time_t when, const std::string &elabel) +{ + RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ + mEvents.insert(std::make_pair(when, EventData(event_type, elabel))); + + count_adjust_locked(event_type, 1); +} + +void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs) +{ + std::string elabel; + RsTickEvent::schedule_in(event_type, in_secs, elabel); +} + + +void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel) +{ + std::cerr << "RsTickEvent::schedule_in(" << event_type << ", " << elabel << ") in " << in_secs << " secs"; + std::cerr << std::endl; + + time_t event_time = time(NULL) + in_secs; + RsTickEvent::schedule_event(event_type, event_time, elabel); +} + + +void RsTickEvent::handle_event(uint32_t event_type, const std::string &elabel) +{ + std::cerr << "RsTickEvent::handle_event(" << event_type << ", " << elabel; + std::cerr << ") ERROR Not Handled"; + std::cerr << std::endl; +} + + +int32_t RsTickEvent::event_count(uint32_t event_type) +{ + RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ + std::map::iterator it; + + it = mEventCount.find(event_type); + if (it == mEventCount.end()) + { + return 0; + } + + return it->second; +} + + +bool RsTickEvent::prev_event_ago(uint32_t event_type, int32_t &age) +{ + RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ + std::map::iterator it; + + it = mPreviousEvent.find(event_type); + if (it == mPreviousEvent.end()) + { + return false; + } + + age = time(NULL) - it->second; + return true; +} + + +void RsTickEvent::count_adjust_locked(uint32_t event_type, int32_t change) +{ + std::map::iterator it; + + it = mEventCount.find(event_type); + if (it == mEventCount.end()) + { + mEventCount[event_type] = 0; + it = mEventCount.find(event_type); + } + + it->second += change; + if (it->second < 0) + { + std::cerr << "RsTickEvent::count_adjust() ERROR: COUNT < 0"; + std::cerr << std::endl; + + it->second = 0; + } +} + + +void RsTickEvent::note_event_locked(uint32_t event_type) +{ + mPreviousEvent[event_type] = time(NULL); +} + + diff --git a/libretroshare/src/util/rstickevent.h b/libretroshare/src/util/rstickevent.h new file mode 100644 index 000000000..1b26c6b43 --- /dev/null +++ b/libretroshare/src/util/rstickevent.h @@ -0,0 +1,84 @@ +/* + * libretroshare/src/util: rstickevent.h + * + * Identity interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ +#ifndef RS_UTIL_TICK_EVENT +#define RS_UTIL_TICK_EVENT + + +/* + * + * A simple event queue... to avoid having to continually write separate one. + */ + +#include +#include + +#include "util/rsthreads.h" + +class RsTickEvent +{ + public: + RsTickEvent():mEventMtx("TickEventMtx") { return; } + +void tick_events(); + +void schedule_now(uint32_t event_type); +void schedule_now(uint32_t event_type, const std::string &elabel); + +void schedule_event(uint32_t event_type, time_t when, const std::string &elabel); + +void schedule_in(uint32_t event_type, uint32_t in_secs); +void schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel); + +int32_t event_count(uint32_t event_type); +bool prev_event_ago(uint32_t event_type, int32_t &age); + + protected: + + // Overloaded to handle the events. +virtual void handle_event(uint32_t event_type, const std::string &event_label); + + private: + + class EventData + { + public: + EventData() :mEventType(0) { return; } + EventData(uint32_t etype) :mEventType(etype) { return; } + EventData(uint32_t etype, std::string elabel) :mEventLabel(elabel), mEventType(etype) { return; } + + std::string mEventLabel; + uint32_t mEventType; + }; + +void count_adjust_locked(uint32_t event_type, int32_t change); +void note_event_locked(uint32_t event_type); + + RsMutex mEventMtx; + std::map mEventCount; + std::map mPreviousEvent; + std::multimap mEvents; +}; + +#endif // RS_UTIL_TICK_EVENT diff --git a/libretroshare/src/zeroconf/p3zcnatassist.h b/libretroshare/src/zeroconf/p3zcnatassist.h index 5171107ee..72bde8dea 100644 --- a/libretroshare/src/zeroconf/p3zcnatassist.h +++ b/libretroshare/src/zeroconf/p3zcnatassist.h @@ -64,6 +64,9 @@ virtual void setExternalPort(unsigned short eport_in); virtual bool getInternalAddress(struct sockaddr_in &addr); virtual bool getExternalAddress(struct sockaddr_in &addr); + /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ +virtual bool requestPortForward(const PortForwardParams ¶ms) { return false; } +virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams ¶ms) { return false; } /* pqiNetAssistConnect - external interface functions */ diff --git a/plugins/FeedReader/FeedReader.pro b/plugins/FeedReader/FeedReader.pro new file mode 100644 index 000000000..450ea6d66 --- /dev/null +++ b/plugins/FeedReader/FeedReader.pro @@ -0,0 +1,64 @@ +!include("../Common/retroshare_plugin.pri"): error("Could not include file ../Common/retroshare_plugin.pri") + +CONFIG += qt uic qrc resources + +SOURCES = FeedReaderPlugin.cpp \ + services/p3FeedReader.cc \ + services/p3FeedReaderThread.cc \ + services/rsFeedReaderItems.cc \ + gui/FeedReaderDialog.cpp \ + gui/AddFeedDialog.cpp \ + gui/PreviewFeedDialog.cpp \ + gui/FeedReaderNotify.cpp \ + gui/FeedReaderConfig.cpp \ + gui/FeedReaderStringDefs.cpp \ + util/CURLWrapper.cpp \ + util/XMLWrapper.cpp \ + util/HTMLWrapper.cpp \ + util/XPathWrapper.cpp + +HEADERS = FeedReaderPlugin.h \ + interface/rsFeedReader.h \ + services/p3FeedReader.h \ + services/p3FeedReaderThread.h \ + services/rsFeedReaderItems.h \ + gui/FeedReaderDialog.h \ + gui/AddFeedDialog.h \ + gui/PreviewFeedDialog.h \ + gui/FeedReaderNotify.h \ + gui/FeedReaderConfig.h \ + gui/FeedReaderStringDefs.h \ + util/CURLWrapper.h \ + util/XMLWrapper.h \ + util/HTMLWrapper.h \ + util/XPathWrapper.h + +FORMS = gui/FeedReaderDialog.ui \ + gui/AddFeedDialog.ui \ + gui/PreviewFeedDialog.ui \ + gui/FeedReaderConfig.ui + +TARGET = FeedReader + +RESOURCES = gui/FeedReader_images.qrc \ + lang/lang.qrc + +linux-* { + LIBXML2_DIR = /usr/include/libxml2 + + INCLUDEPATH += $${LIBXML2_DIR} + + LIBS += -lcurl -lxml2 +} + +win32 { + DEFINES += CURL_STATICLIB LIBXML_STATIC + + CURL_DIR = ../../../curl-7.26.0 + LIBXML2_DIR = ../../../libxml2-2.8.0 + LIBICONV_DIR = ../../../libiconv-1.14 + + INCLUDEPATH += $${CURL_DIR}/include $${LIBXML2_DIR}/include $${LIBICONV_DIR}/include + + LIBS += -lcurl -lxml2 -lws2_32 -lwldap32 +} diff --git a/plugins/FeedReader/FeedReaderPlugin.cpp b/plugins/FeedReader/FeedReaderPlugin.cpp new file mode 100644 index 000000000..c83be2c37 --- /dev/null +++ b/plugins/FeedReader/FeedReaderPlugin.cpp @@ -0,0 +1,138 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include +#include + +#include "FeedReaderPlugin.h" +#include "gui/FeedReaderDialog.h" +#include "gui/FeedReaderConfig.h" +#include "services/p3FeedReader.h" + +#define IMAGE_FEEDREADER ":/images/FeedReader.png" + +static void *inited = new FeedReaderPlugin(); + +extern "C" { +#ifdef WIN32 + __declspec(dllexport) +#endif + void *RETROSHARE_PLUGIN_provide() + { + static FeedReaderPlugin *p = new FeedReaderPlugin(); + + return (void*)p; + } +} + +void FeedReaderPlugin::getPluginVersion(int& major,int& minor,int& svn_rev) const +{ + major = 5; + minor = 1; + svn_rev = 4350; +} + +FeedReaderPlugin::FeedReaderPlugin() +{ + mainpage = NULL ; + mIcon = NULL ; + mPlugInHandler = NULL; + mFeedReader = NULL; +} + +void FeedReaderPlugin::setInterfaces(RsPlugInInterfaces &/*interfaces*/) +{ +} + +ConfigPage *FeedReaderPlugin::qt_config_page() const +{ + return new FeedReaderConfig(); +} + +MainPage *FeedReaderPlugin::qt_page() const +{ + if (mainpage == NULL) { + mainpage = new FeedReaderDialog(mFeedReader); + } + + return mainpage; +} + +RsPQIService *FeedReaderPlugin::rs_pqi_service() const +{ + if (mFeedReader == NULL) { + mFeedReader = new p3FeedReader(mPlugInHandler); + rsFeedReader = mFeedReader; + } + + return mFeedReader; +} + +void FeedReaderPlugin::stop() +{ + if (mFeedReader) { + mFeedReader->stop(); + } +} + +void FeedReaderPlugin::setPlugInHandler(RsPluginHandler *pgHandler) +{ + mPlugInHandler = pgHandler; +} + +QIcon *FeedReaderPlugin::qt_icon() const +{ + if (mIcon == NULL) { + Q_INIT_RESOURCE(FeedReader_images); + + mIcon = new QIcon(IMAGE_FEEDREADER); + } + + return mIcon; +} + +std::string FeedReaderPlugin::getShortPluginDescription() const +{ + return QApplication::translate("FeedReaderPlugin", "This plugin provides a Feedreader.").toUtf8().constData(); +} + +std::string FeedReaderPlugin::getPluginName() const +{ + return QApplication::translate("FeedReaderPlugin", "FeedReader").toUtf8().constData(); +} + +QTranslator* FeedReaderPlugin::qt_translator(QApplication */*app*/, const QString& languageCode) const +{ + if (languageCode == "en") { + return NULL; + } + + QTranslator* translator = new QTranslator(); + if (translator->load(":/lang/FeedReader_" + languageCode + ".qm")) { + return translator; + } + + delete(translator); + return NULL; +} diff --git a/plugins/FeedReader/FeedReaderPlugin.h b/plugins/FeedReader/FeedReaderPlugin.h new file mode 100644 index 000000000..2c4fd5d81 --- /dev/null +++ b/plugins/FeedReader/FeedReaderPlugin.h @@ -0,0 +1,61 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#pragma once + +#include +#include +#include +#include "services/p3FeedReader.h" + +class p3FeedReader; +class RsForums; + +class FeedReaderPlugin: public RsPlugin +{ +public: + FeedReaderPlugin(); + + virtual uint16_t rs_service_id() const { return RS_SERVICE_TYPE_PLUGIN_FEEDREADER; } + virtual RsPQIService *rs_pqi_service() const; + virtual void stop(); + + virtual MainPage *qt_page() const; + virtual QIcon *qt_icon() const; + virtual QTranslator *qt_translator(QApplication *app, const QString &languageCode) const; + + virtual void getPluginVersion(int &major, int &minor, int &svn_rev) const; + virtual void setPlugInHandler(RsPluginHandler *pgHandler); + + virtual std::string configurationFileName() const { return "feedreader.cfg" ; } + + virtual std::string getShortPluginDescription() const; + virtual std::string getPluginName() const; + virtual void setInterfaces(RsPlugInInterfaces& interfaces); + virtual ConfigPage *qt_config_page() const; + +private: + mutable p3FeedReader *mFeedReader; + mutable RsPluginHandler *mPlugInHandler; + mutable MainPage *mainpage; + mutable QIcon *mIcon; +}; + diff --git a/plugins/FeedReader/gui/AddFeedDialog.cpp b/plugins/FeedReader/gui/AddFeedDialog.cpp new file mode 100644 index 000000000..fcfb3c947 --- /dev/null +++ b/plugins/FeedReader/gui/AddFeedDialog.cpp @@ -0,0 +1,347 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include "AddFeedDialog.h" +#include "ui_AddFeedDialog.h" +#include "PreviewFeedDialog.h" +#include "FeedReaderStringDefs.h" +#include "gui/settings/rsharesettings.h" + +#include "retroshare/rsforums.h" + +bool sortForumInfo(const ForumInfo& info1, const ForumInfo& info2) +{ + return QString::fromStdWString(info1.forumName).compare(QString::fromStdWString(info2.forumName), Qt::CaseInsensitive); +} + +AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent) + : QDialog(parent, Qt::Window), mFeedReader(feedReader), mNotify(notify), ui(new Ui::AddFeedDialog) +{ + ui->setupUi(this); + + connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(createFeed())); + connect(ui->buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject())); + + connect(ui->useAuthenticationCheckBox, SIGNAL(toggled(bool)), this, SLOT(authenticationToggled())); + connect(ui->useStandardStorageTimeCheckBox, SIGNAL(toggled(bool)), this, SLOT(useStandardStorageTimeToggled())); + connect(ui->useStandardUpdateInterval, SIGNAL(toggled(bool)), this, SLOT(useStandardUpdateIntervalToggled())); + connect(ui->useStandardProxyCheckBox, SIGNAL(toggled(bool)), this, SLOT(useStandardProxyToggled())); + connect(ui->typeForumRadio, SIGNAL(toggled(bool)), this, SLOT(typeForumToggled())); + connect(ui->previewButton, SIGNAL(clicked()), this, SLOT(preview())); + + /* currently only for loacl feeds */ + connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled())); + connect(ui->embedImagesCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled())); + + connect(ui->urlLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate())); + connect(ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate())); + connect(ui->useInfoFromFeedCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate())); + connect(ui->typeLocalRadio, SIGNAL(toggled(bool)), this, SLOT(validate())); + connect(ui->typeForumRadio, SIGNAL(toggled(bool)), this, SLOT(validate())); + + ui->activatedCheckBox->setChecked(true); + ui->forumComboBox->setEnabled(false); + ui->useInfoFromFeedCheckBox->setChecked(true); + ui->updateForumInfoCheckBox->setEnabled(false); + ui->updateForumInfoCheckBox->setChecked(true); + ui->forumNameLabel->hide(); + ui->useAuthenticationCheckBox->setChecked(false); + ui->useStandardStorageTimeCheckBox->setChecked(true); + ui->useStandardUpdateInterval->setChecked(true); + ui->useStandardProxyCheckBox->setChecked(true); + + /* not yet supported */ + ui->authenticationGroupBox->setEnabled(false); + + /* fill own forums */ + std::list forumList; + if (rsForums->getForumList(forumList)) { + forumList.sort(sortForumInfo); + for (std::list::iterator it = forumList.begin(); it != forumList.end(); ++it) { + ForumInfo &forumInfo = *it; + /* show only own anonymous forums */ + if ((forumInfo.subscribeFlags & RS_DISTRIB_ADMIN) && (forumInfo.forumFlags & RS_DISTRIB_AUTHEN_ANON)) { + ui->forumComboBox->addItem(QString::fromStdWString(forumInfo.forumName), QString::fromStdString(forumInfo.forumId)); + } + } + } + /* insert item to create a new forum */ + ui->forumComboBox->insertItem(0, tr("Create a new anonymous public forum"), ""); + ui->forumComboBox->setCurrentIndex(0); + + validate(); + + ui->urlLineEdit->setFocus(); + + /* load settings */ + processSettings(true); +} + +AddFeedDialog::~AddFeedDialog() +{ + /* save settings */ + processSettings(false); + + delete ui; +} + +void AddFeedDialog::processSettings(bool load) +{ + Settings->beginGroup(QString("AddFeedDialog")); + + if (load) { + // load settings + QByteArray geometry = Settings->value("Geometry").toByteArray(); + if (!geometry.isEmpty()) { + restoreGeometry(geometry); + } + } else { + // save settings + Settings->setValue("Geometry", saveGeometry()); + } + + Settings->endGroup(); +} + +void AddFeedDialog::authenticationToggled() +{ + bool checked = ui->useAuthenticationCheckBox->isChecked(); + ui->userLineEdit->setEnabled(checked); + ui->passwordLineEdit->setEnabled(checked); +} + +void AddFeedDialog::useStandardStorageTimeToggled() +{ + bool checked = ui->useStandardStorageTimeCheckBox->isChecked(); + ui->storageTimeSpinBox->setEnabled(!checked); +} + +void AddFeedDialog::useStandardUpdateIntervalToggled() +{ + bool checked = ui->useStandardUpdateInterval->isChecked(); + ui->updateIntervalSpinBox->setEnabled(!checked); +} + +void AddFeedDialog::useStandardProxyToggled() +{ + bool checked = ui->useStandardProxyCheckBox->isChecked(); + ui->proxyAddressLineEdit->setEnabled(!checked); + ui->proxyPortSpinBox->setEnabled(!checked); +} + +void AddFeedDialog::typeForumToggled() +{ + bool checked = ui->typeForumRadio->isChecked(); + ui->forumComboBox->setEnabled(checked); + ui->updateForumInfoCheckBox->setEnabled(checked); +} + +void AddFeedDialog::denyForumToggled() +{ + if (ui->saveCompletePageCheckBox->isChecked() || ui->embedImagesCheckBox->isChecked()) { + ui->typeForumRadio->setEnabled(false); + ui->typeLocalRadio->setChecked(true); + } else { + ui->typeForumRadio->setEnabled(true); + } +} + +void AddFeedDialog::validate() +{ + bool ok = true; + + if (ui->urlLineEdit->text().isEmpty()) { + ok = false; + } + if (ui->nameLineEdit->text().isEmpty() && !ui->useInfoFromFeedCheckBox->isChecked()) { + ok = false; + } + + ui->previewButton->setEnabled(ok); + + if (!ui->typeLocalRadio->isChecked() && !ui->typeForumRadio->isChecked()) { + ok = false; + } + + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); +} + +void AddFeedDialog::setParent(const std::string &parentId) +{ + mParentId = parentId; +} + +bool AddFeedDialog::fillFeed(const std::string &feedId) +{ + mFeedId = feedId; + + if (!mFeedId.empty()) { + FeedInfo feedInfo; + if (!mFeedReader->getFeedInfo(mFeedId, feedInfo)) { + mFeedId.clear(); + return false; + } + + setWindowTitle(tr("Edit feed")); + ui->typeGroupBox->setEnabled(false); + + mParentId = feedInfo.parentId; + + ui->nameLineEdit->setText(QString::fromUtf8(feedInfo.name.c_str())); + ui->urlLineEdit->setText(QString::fromUtf8(feedInfo.url.c_str())); + ui->useInfoFromFeedCheckBox->setChecked(feedInfo.flag.infoFromFeed); + ui->updateForumInfoCheckBox->setChecked(feedInfo.flag.updateForumInfo); + ui->activatedCheckBox->setChecked(!feedInfo.flag.deactivated); + ui->embedImagesCheckBox->setChecked(feedInfo.flag.embedImages); + ui->saveCompletePageCheckBox->setChecked(feedInfo.flag.saveCompletePage); + + ui->descriptionPlainTextEdit->setPlainText(QString::fromUtf8(feedInfo.description.c_str())); + + ui->typeGroupBox->setEnabled(false); + ui->forumComboBox->hide(); + ui->forumNameLabel->clear(); + ui->forumNameLabel->show(); + + if (feedInfo.flag.forum) { + ui->typeForumRadio->setChecked(true); + ui->saveCompletePageCheckBox->setEnabled(false); + ui->embedImagesCheckBox->setEnabled(false); + + if (feedInfo.forumId.empty()) { + ui->forumNameLabel->setText(tr("Not yet created")); + } else { + ForumInfo forumInfo; + if (rsForums->getForumInfo(feedInfo.forumId, forumInfo)) { + ui->forumNameLabel->setText(QString::fromStdWString(forumInfo.forumName)); + } else { + ui->forumNameLabel->setText(tr("Unknown forum")); + } + } + } else { + ui->typeLocalRadio->setChecked(true); + } + + ui->useAuthenticationCheckBox->setChecked(feedInfo.flag.authentication); + ui->userLineEdit->setText(QString::fromUtf8(feedInfo.user.c_str())); + ui->passwordLineEdit->setText(QString::fromUtf8(feedInfo.password.c_str())); + + ui->useStandardProxyCheckBox->setChecked(feedInfo.flag.standardProxy); + ui->proxyAddressLineEdit->setText(QString::fromUtf8(feedInfo.proxyAddress.c_str())); + ui->proxyPortSpinBox->setValue(feedInfo.proxyPort); + + ui->useStandardUpdateInterval->setChecked(feedInfo.flag.standardUpdateInterval); + ui->updateIntervalSpinBox->setValue(feedInfo.updateInterval / 60); + QDateTime dateTime; + dateTime.setTime_t(feedInfo.lastUpdate); + ui->lastUpdate->setText(dateTime.toString()); + + ui->useStandardStorageTimeCheckBox->setChecked(feedInfo.flag.standardStorageTime); + ui->storageTimeSpinBox->setValue(feedInfo.storageTime / (60 * 60 *24)); + + mXPathsToUse = feedInfo.xpathsToUse; + mXPathsToRemove = feedInfo.xpathsToRemove; + } + + return true; +} + +void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo) +{ + feedInfo.parentId = mParentId; + + feedInfo.name = ui->nameLineEdit->text().toUtf8().constData(); + feedInfo.url = ui->urlLineEdit->text().toUtf8().constData(); + feedInfo.flag.infoFromFeed = ui->useInfoFromFeedCheckBox->isChecked(); + feedInfo.flag.updateForumInfo = ui->updateForumInfoCheckBox->isChecked() && ui->updateForumInfoCheckBox->isEnabled(); + feedInfo.flag.deactivated = !ui->activatedCheckBox->isChecked(); + feedInfo.flag.embedImages = ui->embedImagesCheckBox->isChecked(); + feedInfo.flag.saveCompletePage = ui->saveCompletePageCheckBox->isChecked(); + + feedInfo.description = ui->descriptionPlainTextEdit->toPlainText().toUtf8().constData(); + + feedInfo.flag.forum = ui->typeForumRadio->isChecked(); + if (mFeedId.empty()) { + if (feedInfo.flag.forum) { + /* set forum (only when create a new feed) */ + feedInfo.forumId = ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().toStdString(); + } + } + + feedInfo.flag.authentication = ui->useAuthenticationCheckBox->isChecked(); + feedInfo.user = ui->userLineEdit->text().toUtf8().constData(); + feedInfo.password = ui->passwordLineEdit->text().toUtf8().constData(); + + feedInfo.flag.standardProxy = ui->useStandardProxyCheckBox->isChecked(); + feedInfo.proxyAddress = ui->proxyAddressLineEdit->text().toUtf8().constData(); + feedInfo.proxyPort = ui->proxyPortSpinBox->value(); + + feedInfo.flag.standardUpdateInterval = ui->useStandardUpdateInterval->isChecked(); + feedInfo.updateInterval = ui->updateIntervalSpinBox->value() * 60; + + feedInfo.flag.standardStorageTime = ui->useStandardStorageTimeCheckBox->isChecked(); + feedInfo.storageTime = ui->storageTimeSpinBox->value() * 60 *60 * 24; + + feedInfo.xpathsToUse = mXPathsToUse; + feedInfo.xpathsToRemove = mXPathsToRemove; +} + +void AddFeedDialog::createFeed() +{ + FeedInfo feedInfo; + if (!mFeedId.empty()) { + if (!mFeedReader->getFeedInfo(mFeedId, feedInfo)) { + QMessageBox::critical(this, tr("Edit feed"), tr("Can't edit feed. Feed does not exist.")); + return; + } + } + + getFeedInfo(feedInfo); + + if (mFeedId.empty()) { + /* add new feed */ + RsFeedAddResult result = mFeedReader->addFeed(feedInfo, mFeedId); + if (FeedReaderStringDefs::showError(this, result, tr("Create feed"), tr("Cannot create feed."))) { + return; + } + } else { + RsFeedAddResult result = mFeedReader->setFeed(mFeedId, feedInfo); + if (FeedReaderStringDefs::showError(this, result, tr("Edit feed"), tr("Cannot change feed."))) { + return; + } + } + + close(); +} + +void AddFeedDialog::preview() +{ + FeedInfo feedInfo; + getFeedInfo(feedInfo); + + PreviewFeedDialog dialog(mFeedReader, mNotify, feedInfo, this); + if (dialog.exec() == QDialog::Accepted) { + dialog.getXPaths(mXPathsToUse, mXPathsToRemove); + } +} diff --git a/plugins/FeedReader/gui/AddFeedDialog.h b/plugins/FeedReader/gui/AddFeedDialog.h new file mode 100644 index 000000000..44066c522 --- /dev/null +++ b/plugins/FeedReader/gui/AddFeedDialog.h @@ -0,0 +1,72 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef ADDFEEDDIALOG_H +#define ADDFEEDDIALOG_H + +#include +#include "interface/rsFeedReader.h" + +namespace Ui { +class AddFeedDialog; +} + +class RsFeedReader; +class FeedReaderNotify; + +class AddFeedDialog : public QDialog +{ + Q_OBJECT + +public: + AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent); + ~AddFeedDialog(); + + void setParent(const std::string &parentId); + bool fillFeed(const std::string &feedId); + +private slots: + void authenticationToggled(); + void useStandardStorageTimeToggled(); + void useStandardUpdateIntervalToggled(); + void useStandardProxyToggled(); + void typeForumToggled(); + void denyForumToggled(); + void validate(); + void createFeed(); + void preview(); + +private: + void processSettings(bool load); + void getFeedInfo(FeedInfo &feedInfo); + + RsFeedReader *mFeedReader; + FeedReaderNotify *mNotify; + std::string mFeedId; + std::string mParentId; + + std::list mXPathsToUse; + std::list mXPathsToRemove; + + Ui::AddFeedDialog *ui; +}; + +#endif // ADDFEEDDIALOG_H diff --git a/plugins/FeedReader/gui/AddFeedDialog.ui b/plugins/FeedReader/gui/AddFeedDialog.ui new file mode 100644 index 000000000..a6a4cea84 --- /dev/null +++ b/plugins/FeedReader/gui/AddFeedDialog.ui @@ -0,0 +1,462 @@ + + + AddFeedDialog + + + + 0 + 0 + 715 + 605 + + + + Create new feed + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 64 + + + + QFrame#headerFrame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 6 + + + + + + 48 + 48 + + + + + + + + + + :/images/FeedReader.png + + + true + + + + + + + color: rgb(255, 255, 255); + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Feed Details</span></p></body></html> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Authentication (not yet supported) + + + + + + Feed needs authentication + + + + + + + User + + + + + + + Password + + + + + + + + + + QLineEdit::Password + + + + + + + + + + Update interval + + + + + + Use standard update interval + + + + + + + Interval in minutes (0 = manual) + + + + + + + + 50 + 16777215 + + + + + + + + + + Last update + + + + + + + + 0 + 0 + + + + Never + + + + + + + + + + + + Storage time + + + + + + Use standard storage time + + + + + + + Days (0 = off) + + + + + + + + 50 + 16777215 + + + + 999999999 + + + + + + + + + + Proxy + + + + + + Use standard proxy + + + + + + + Server + + + + + + + + + + : + + + + + + + 65535 + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Preview + + + + + + + + + Type + + + + 6 + + + + + + + Forum + + + + + + + + + + + 0 + 0 + + + + Forum name + + + + + + + + + Local Feed + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Misc + + + + + + Activated + + + + + + + Use name and description from feed + + + + + + + Update forum information + + + + + + + Embed images (experimental for local feeds) + + + + + + + Save complete web page (experimental for local feeds) + + + + + + + + + + + + Description: + + + + + + + + + + + + + + RSS-Feed-URL: + + + + + + + + + + Name: + + + + + + + + + + + + + + + urlLineEdit + nameLineEdit + descriptionPlainTextEdit + typeForumRadio + forumComboBox + activatedCheckBox + useInfoFromFeedCheckBox + updateForumInfoCheckBox + useAuthenticationCheckBox + userLineEdit + passwordLineEdit + useStandardStorageTimeCheckBox + storageTimeSpinBox + useStandardUpdateInterval + updateIntervalSpinBox + useStandardProxyCheckBox + proxyAddressLineEdit + proxyPortSpinBox + buttonBox + + + + + + + diff --git a/plugins/FeedReader/gui/FeedReaderConfig.cpp b/plugins/FeedReader/gui/FeedReaderConfig.cpp new file mode 100644 index 000000000..2b9102c9c --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderConfig.cpp @@ -0,0 +1,80 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "FeedReaderConfig.h" +#include "ui_FeedReaderConfig.h" +#include "gui/settings/rsharesettings.h" +#include "interface/rsFeedReader.h" + +/** Constructor */ +FeedReaderConfig::FeedReaderConfig(QWidget *parent, Qt::WFlags flags) + : ConfigPage(parent, flags), ui(new Ui::FeedReaderConfig) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui->setupUi(this); + + connect(ui->useProxyCheckBox, SIGNAL(toggled(bool)), this, SLOT(useProxyToggled())); + + ui->proxyAddressLineEdit->setEnabled(false); + ui->proxyPortSpinBox->setEnabled(false); + + loaded = false; +} + +/** Destructor */ +FeedReaderConfig::~FeedReaderConfig() +{ + delete(ui); +} + +/** Loads the settings for this page */ +void FeedReaderConfig::load() +{ + ui->updateIntervalSpinBox->setValue(rsFeedReader->getStandardUpdateInterval() / 60); + ui->storageTimeSpinBox->setValue(rsFeedReader->getStandardStorageTime() / (60 * 60 *24)); + ui->setMsgToReadOnActivate->setChecked(Settings->valueFromGroup("FeedReaderDialog", "SetMsgToReadOnActivate", true).toBool()); + + std::string proxyAddress; + uint16_t proxyPort; + ui->useProxyCheckBox->setChecked(rsFeedReader->getStandardProxy(proxyAddress, proxyPort)); + ui->proxyAddressLineEdit->setText(QString::fromUtf8(proxyAddress.c_str())); + ui->proxyPortSpinBox->setValue(proxyPort); + + loaded = true; +} + +bool FeedReaderConfig::save(QString &/*errmsg*/) +{ + rsFeedReader->setStandardUpdateInterval(ui->updateIntervalSpinBox->value() * 60); + rsFeedReader->setStandardStorageTime(ui->storageTimeSpinBox->value() * 60 *60 * 24); + rsFeedReader->setStandardProxy(ui->useProxyCheckBox->isChecked(), ui->proxyAddressLineEdit->text().toUtf8().constData(), ui->proxyPortSpinBox->value()); + Settings->setValueToGroup("FeedReaderDialog", "SetMsgToReadOnActivate", ui->setMsgToReadOnActivate->isChecked()); + + return true; +} + +void FeedReaderConfig::useProxyToggled() +{ + bool enabled = ui->useProxyCheckBox->isChecked(); + + ui->proxyAddressLineEdit->setEnabled(enabled); + ui->proxyPortSpinBox->setEnabled(enabled); +} diff --git a/plugins/FeedReader/gui/FeedReaderConfig.h b/plugins/FeedReader/gui/FeedReaderConfig.h new file mode 100644 index 000000000..ed846269a --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderConfig.h @@ -0,0 +1,57 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FEEDREADERCONFIG_H +#define _FEEDREADERCONFIG_H + +#include "retroshare-gui/configpage.h" + +namespace Ui { +class FeedReaderConfig; +} + +class FeedReaderConfig : public ConfigPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + FeedReaderConfig(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + virtual ~FeedReaderConfig(); + + /** Saves the changes on this page */ + virtual bool save(QString &errmsg); + /** Loads the settings for this page */ + virtual void load(); + + virtual QPixmap iconPixmap() const { return QPixmap(":/images/FeedReader.png") ; } + virtual QString pageName() const { return tr("FeedReader") ; } + +private slots: + void useProxyToggled(); + +private: + Ui::FeedReaderConfig *ui; + bool loaded; +}; + +#endif diff --git a/plugins/FeedReader/gui/FeedReaderConfig.ui b/plugins/FeedReader/gui/FeedReaderConfig.ui new file mode 100644 index 000000000..36deae46b --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderConfig.ui @@ -0,0 +1,148 @@ + + + FeedReaderConfig + + + + 0 + 0 + 508 + 378 + + + + Form + + + + + + Update + + + + + + Interval in minutes (0 = manual) + + + + + + + + 50 + 16777215 + + + + 999999999 + + + + + + + + + + Storage time + + + + + + Days (0 = off) + + + + + + + + 50 + 16777215 + + + + 999999999 + + + + + + + + + + Proxy + + + + + + Use proxy + + + + + + + Server + + + + + + + + + + 65535 + + + + + + + : + + + + + + + + + + Misc + + + + + + Set message to read on activate + + + + + + + + + + Qt::Vertical + + + + 20 + 301 + + + + + + + + + diff --git a/plugins/FeedReader/gui/FeedReaderDialog.cpp b/plugins/FeedReader/gui/FeedReaderDialog.cpp new file mode 100644 index 000000000..7d72a6b23 --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderDialog.cpp @@ -0,0 +1,1128 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FeedReaderDialog.h" +#include "ui_FeedReaderDialog.h" +#include "FeedReaderNotify.h" +#include "AddFeedDialog.h" +#include "FeedReaderStringDefs.h" +#include "gui/common/RSTreeWidgetItem.h" +#include "util/HandleRichText.h" +#include "gui/settings/rsharesettings.h" + +#include "interface/rsFeedReader.h" +#include "retroshare/rsiface.h" + +#define COLUMN_FEED_COUNT 1 +#define COLUMN_FEED_NAME 0 +#define COLUMN_FEED_DATA 0 + +#define ROLE_FEED_ID Qt::UserRole +#define ROLE_FEED_SORT Qt::UserRole + 1 +#define ROLE_FEED_FOLDER Qt::UserRole + 2 +#define ROLE_FEED_UNREAD Qt::UserRole + 3 +#define ROLE_FEED_NAME Qt::UserRole + 4 +#define ROLE_FEED_WORKSTATE Qt::UserRole + 5 +#define ROLE_FEED_LOADING Qt::UserRole + 6 +#define ROLE_FEED_ICON Qt::UserRole + 7 +#define ROLE_FEED_ERROR Qt::UserRole + 8 +#define ROLE_FEED_DEACTIVATED Qt::UserRole + 9 + +#define COLUMN_MSG_COUNT 4 +#define COLUMN_MSG_TITLE 0 +#define COLUMN_MSG_READ 1 +#define COLUMN_MSG_PUBDATE 2 +#define COLUMN_MSG_AUTHOR 3 +#define COLUMN_MSG_DATA 0 + +#define ROLE_MSG_ID Qt::UserRole +#define ROLE_MSG_SORT Qt::UserRole + 1 +#define ROLE_MSG_NEW Qt::UserRole + 2 +#define ROLE_MSG_READ Qt::UserRole + 3 +#define ROLE_MSG_LINK Qt::UserRole + 4 + +static int filterColumnToComboBox(int nIndex) +{ + switch (nIndex) { + case COLUMN_MSG_TITLE: + return 0; + case COLUMN_MSG_PUBDATE: + return 1; + case COLUMN_MSG_AUTHOR: + return 2; + } + + return filterColumnToComboBox(COLUMN_MSG_TITLE); +} + +static int filterColumnFromComboBox(int nIndex) +{ + switch (nIndex) { + case 0: + return COLUMN_MSG_TITLE; + case 1: + return COLUMN_MSG_PUBDATE; + case 2: + return COLUMN_MSG_AUTHOR; + } + + return COLUMN_MSG_TITLE; +} + +FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, QWidget *parent) + : MainPage(parent), mFeedReader(feedReader), ui(new Ui::FeedReaderDialog) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui->setupUi(this); + + mNotify = new FeedReaderNotify(); + mFeedReader->setNotify(mNotify); + connect(mNotify, SIGNAL(notifyFeedChanged(QString,int)), this, SLOT(feedChanged(QString,int))); + connect(mNotify, SIGNAL(notifyMsgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,QString,int))); + + mProcessSettings = false; + + /* connect signals */ + connect(ui->feedTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(feedItemChanged(QTreeWidgetItem*))); + connect(ui->msgTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(msgItemChanged())); + connect(ui->msgTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(msgItemClicked(QTreeWidgetItem*,int))); + + connect(ui->feedTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(feedTreeCustomPopupMenu(QPoint))); + connect(ui->msgTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(msgTreeCustomPopupMenu(QPoint))); + + connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString))); + connect(ui->filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged())); + + connect(ui->linkButton, SIGNAL(clicked()), this, SLOT(openLinkMsg())); + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggleMsgText())); + + mFeedCompareRole = new RSTreeWidgetItemCompareRole; + mFeedCompareRole->setRole(COLUMN_FEED_NAME, ROLE_FEED_SORT); + + mMsgCompareRole = new RSTreeWidgetItemCompareRole; + mMsgCompareRole->setRole(COLUMN_MSG_TITLE, ROLE_MSG_SORT); + mMsgCompareRole->setRole(COLUMN_MSG_READ, ROLE_MSG_SORT); + mMsgCompareRole->setRole(COLUMN_MSG_PUBDATE, ROLE_MSG_SORT); + mMsgCompareRole->setRole(COLUMN_MSG_AUTHOR, ROLE_MSG_SORT); + + /* initialize root item */ + mRootItem = new QTreeWidgetItem(ui->feedTreeWidget); + QString name = tr("Message Folders"); + mRootItem->setText(COLUMN_FEED_NAME, name); + mRootItem->setIcon(COLUMN_FEED_NAME, QIcon(":/images/Root.png")); + mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_NAME, name); + mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_FOLDER, true); + mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_ICON, QIcon(":/images/Root.png")); + mRootItem->setExpanded(true); + + /* initialize msg list */ + ui->msgTreeWidget->sortItems(COLUMN_MSG_PUBDATE, Qt::DescendingOrder); + + /* set initial size the splitter */ + QList sizes; + sizes << 300 << width(); // Qt calculates the right sizes + ui->splitter->setSizes(sizes); + + /* set header resize modes and initial section sizes */ + QHeaderView *header = ui->msgTreeWidget->header(); + header->setResizeMode(COLUMN_MSG_TITLE, QHeaderView::Interactive); + header->resizeSection(COLUMN_MSG_TITLE, 350); + header->resizeSection(COLUMN_MSG_PUBDATE, 140); + header->resizeSection(COLUMN_MSG_AUTHOR, 150); + + /* set text of column "Read" to empty - without this the column has a number as header text */ + QTreeWidgetItem *headerItem = ui->msgTreeWidget->headerItem(); + headerItem->setText(COLUMN_MSG_READ, ""); + + /* load settings */ + processSettings(true); + + /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ + header->resizeSection(COLUMN_MSG_READ, 24); + header->setResizeMode(COLUMN_MSG_READ, QHeaderView::Fixed); + + /* initialize feed list */ + ui->feedTreeWidget->sortItems(COLUMN_FEED_NAME, Qt::AscendingOrder); + + /* build menu for link button */ + QMenu *menu = new QMenu(this); + QAction *action = menu->addAction(tr("Open link in browser"), this, SLOT(openLinkMsg())); + menu->addAction(tr("Copy link to clipboard"), this, SLOT(copyLinkMsg())); + + QFont font = action->font(); + font.setBold(true); + action->setFont(font); + + ui->linkButton->setMenu(menu); + ui->linkButton->setEnabled(false); + + ui->msgTreeWidget->installEventFilter(this); +} + +FeedReaderDialog::~FeedReaderDialog() +{ + /* save settings */ + processSettings(false); + + delete(mFeedCompareRole); + delete(mMsgCompareRole); + delete(ui); + + mFeedReader->setNotify(NULL); + delete(mNotify); +} + +void FeedReaderDialog::processSettings(bool load) +{ + mProcessSettings = true; + + QHeaderView *header = ui->msgTreeWidget->header (); + + Settings->beginGroup(QString("FeedReaderDialog")); + + if (load) { + // load settings + + // expandButton + bool value = Settings->value("expandButton", true).toBool(); + ui->expandButton->setChecked(value); + toggleMsgText_internal(); + + // filterColumn + ui->filterColumnComboBox->setCurrentIndex(filterColumnToComboBox(Settings->value("filterColumn", COLUMN_MSG_TITLE).toInt())); + + // state of thread tree + header->restoreState(Settings->value("msgTree").toByteArray()); + + // state of splitter + ui->splitter->restoreState(Settings->value("Splitter").toByteArray()); + ui->msgSplitter->restoreState(Settings->value("msgSplitter").toByteArray()); + } else { + // save settings + + // state of thread tree + Settings->setValue("msgTree", header->saveState()); + + // state of splitter + Settings->setValue("Splitter", ui->splitter->saveState()); + Settings->setValue("msgSplitter", ui->msgSplitter->saveState()); + } + + Settings->endGroup(); + mProcessSettings = false; +} + +void FeedReaderDialog::showEvent(QShowEvent */*event*/) +{ + updateFeeds("", mRootItem); +} + +bool FeedReaderDialog::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui->msgTreeWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent) { + if (keyEvent->key() == Qt::Key_Space) { + /* Space pressed */ + QTreeWidgetItem *item = ui->msgTreeWidget->currentItem(); + msgItemClicked(item, COLUMN_MSG_READ); + return true; // eat event + } + if (keyEvent->key() == Qt::Key_Delete) { + /* Delete pressed */ + removeMsg(); + return true; // eat event + } + } + } + } + if (obj == ui->feedTreeWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent) { + if (keyEvent->key() == Qt::Key_Delete) { + /* Delete pressed */ + removeFeed(); + return true; // eat event + } + } + } + } + /* pass the event on to the parent class */ + return MainPage::eventFilter(obj, event); +} + +std::string FeedReaderDialog::currentFeedId() +{ + QTreeWidgetItem *item = ui->feedTreeWidget->currentItem(); + if (!item) { + return ""; + } + + return item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString(); +} + +std::string FeedReaderDialog::currentMsgId() +{ + QTreeWidgetItem *item = ui->msgTreeWidget->currentItem(); + if (!item) { + return ""; + } + + return item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString(); +} + +void FeedReaderDialog::feedTreeCustomPopupMenu(QPoint /*point*/) +{ + QMenu contextMnu(this); + + bool folder = false; + QTreeWidgetItem *item = ui->feedTreeWidget->currentItem(); + if (item) { + folder = item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool(); + } + + QMenu *menu = contextMnu.addMenu(QIcon(""), tr("New")); + QAction *action = menu->addAction(QIcon(":/images/FeedAdd.png"), tr("Feed"), this, SLOT(newFeed())); + if (!item || !folder) { + action->setEnabled(false); + } + action = menu->addAction(QIcon(":/images/FolderAdd.png"), tr("Folder"), this, SLOT(newFolder())); + if (!item || !folder) { + action->setEnabled(false); + } + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(":/images/edit_16.png"), tr("Edit"), this, SLOT(editFeed())); + if (!item || item == mRootItem) { + action->setEnabled(false); + } + + action = contextMnu.addAction(QIcon(":/images/delete.png"), tr("Delete"), this, SLOT(removeFeed())); + if (!item || item == mRootItem) { + action->setEnabled(false); + } + + contextMnu.addSeparator(); + + bool deactivated = false; + if (!folder && item) { + deactivated = item->data(COLUMN_FEED_DATA, ROLE_FEED_DEACTIVATED).toBool(); + } + + action = contextMnu.addAction(QIcon(":/images/Update.png"), tr("Update"), this, SLOT(processFeed())); + action->setEnabled(!deactivated); + + action = contextMnu.addAction(QIcon(""), deactivated ? tr("Activate") : tr("Deactivate"), this, SLOT(activateFeed())); + if (!item || item == mRootItem || folder) { + action->setEnabled(false); + } + + contextMnu.exec(QCursor::pos()); +} + +void FeedReaderDialog::msgTreeCustomPopupMenu(QPoint /*point*/) +{ + QMenu contextMnu(this); + + QList selectedItems = ui->msgTreeWidget->selectedItems(); + + QAction *action = contextMnu.addAction(QIcon(""), tr("Mark as read"), this, SLOT(markAsReadMsg())); + action->setEnabled(!selectedItems.empty()); + + action = contextMnu.addAction(QIcon(""), tr("Mark as unread"), this, SLOT(markAsUnreadMsg())); + action->setEnabled(!selectedItems.empty()); + + action = contextMnu.addAction(QIcon(""), tr("Mark all as read"), this, SLOT(markAllAsReadMsg())); + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(""), tr("Copy link"), this, SLOT(copyLinskMsg())); + action->setEnabled(!selectedItems.empty()); + + action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg())); + action->setEnabled(!selectedItems.empty()); + + contextMnu.exec(QCursor::pos()); +} + +void FeedReaderDialog::updateFeeds(const std::string &parentId, QTreeWidgetItem *parentItem) +{ + if (!parentItem) { + return; + } + + /* get feed infos */ + std::list feedInfos; + mFeedReader->getFeedList(parentId, feedInfos); + + int index = 0; + QTreeWidgetItem *item; + std::list::iterator feedIt; + + /* update existing and delete not existing feeds */ + while (index < parentItem->childCount()) { + item = parentItem->child(index); + std::string feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString(); + + /* search existing feed */ + int found = -1; + for (feedIt = feedInfos.begin (); feedIt != feedInfos.end (); ++feedIt) { + if (feedIt->feedId == feedId) { + /* found it, update it */ + updateFeedItem(item, *feedIt); + + if (feedIt->flag.folder) { + /* process child feeds */ + updateFeeds(feedIt->feedId, item); + } + + feedInfos.erase(feedIt); + found = index; + break; + } + } + if (found >= 0) { + ++index; + } else { + delete(parentItem->takeChild(index)); + } + } + + /* add new feeds */ + for (feedIt = feedInfos.begin (); feedIt != feedInfos.end (); ++feedIt) { + item = new RSTreeWidgetItem(mFeedCompareRole); + parentItem->addChild(item); + updateFeedItem(item, *feedIt); + + if (feedIt->flag.folder) { + /* process child feeds */ + updateFeeds(feedIt->feedId, item); + } + } + calculateFeedItems(); +} + +void FeedReaderDialog::calculateFeedItem(QTreeWidgetItem *item, uint32_t &unreadCount, bool &loading) +{ + uint32_t unreadCountItem = 0; + bool loadingItem = false; + + if (item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool()) { + int childCount = item->childCount(); + for (int index = 0; index < childCount; ++index) { + calculateFeedItem(item->child(index), unreadCountItem, loadingItem); + } + } else { + unreadCountItem = item->data(COLUMN_FEED_DATA, ROLE_FEED_UNREAD).toUInt(); + loadingItem = item->data(COLUMN_FEED_DATA, ROLE_FEED_LOADING).toBool(); + } + + unreadCount += unreadCountItem; + loading = loading || loadingItem; + + QString name = item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString(); + QString workState = item->data(COLUMN_FEED_DATA, ROLE_FEED_WORKSTATE).toString(); + + if (unreadCountItem) { + name += QString(" (%1)").arg(unreadCountItem); + } + if (!workState.isEmpty()) { + name += QString(" (%1)").arg(workState); + } + + item->setText(COLUMN_FEED_NAME, name); + + bool deactivated = item->data(COLUMN_FEED_DATA, ROLE_FEED_DEACTIVATED).toBool(); + + QColor colorActivated; + QColor colorDeactivated = QColor(Qt::gray); + for (int i = 0; i < COLUMN_FEED_COUNT; i++) { + QFont font = item->font(i); + font.setBold(unreadCountItem != 0); + item->setFont(i, font); + + item->setTextColor(COLUMN_FEED_NAME, deactivated ? colorDeactivated : colorActivated); + } + + QIcon icon = item->data(COLUMN_FEED_DATA, ROLE_FEED_ICON).value(); + + if (deactivated) { + /* create disabled icon */ + icon = icon.pixmap(QSize(16, 16), QIcon::Disabled); + } + + QImage overlayIcon; + if (loadingItem) { + /* overlaying icon */ + overlayIcon = QImage(":/images/FeedProcessOverlay.png"); + } else if (item->data(COLUMN_FEED_DATA, ROLE_FEED_ERROR).toBool()) { + overlayIcon = QImage(":/images/FeedErrorOverlay.png"); + } + if (!overlayIcon.isNull()) { + if (icon.isNull()) { + icon = QPixmap::fromImage(overlayIcon); + } else { + QPixmap pixmap = icon.pixmap(QSize(16, 16)); + QPainter painter(&pixmap); + painter.drawImage(0, 0, overlayIcon.scaled(pixmap.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + painter.end(); + icon = pixmap; + } + } + + item->setIcon(COLUMN_FEED_NAME, icon); +} + +void FeedReaderDialog::calculateFeedItems() +{ + uint32_t unreadCount = 0; + bool loading = false; + + calculateFeedItem(mRootItem, unreadCount, loading); + ui->feedTreeWidget->sortItems(COLUMN_FEED_NAME, Qt::AscendingOrder); +} + +void FeedReaderDialog::updateFeedItem(QTreeWidgetItem *item, FeedInfo &info) +{ + + QIcon icon; + if (info.flag.folder) { + /* use folder icon */ + icon = QIcon(":/images/Folder.png"); + } else { + long todo; // show icon from feed +// if (info.icon.empty()) { + /* use standard icon */ + icon = QIcon(":/images/Feed.png"); +// } else { +// /* use icon from feed */ +// icon = QIcon(QPixmap::fromImage(QImage((uchar*) QByteArray::fromBase64(info.icon.c_str()).constData(), 16, 16, QImage::Format_RGB32))); +// } + } + + item->setData(COLUMN_FEED_DATA, ROLE_FEED_ICON, icon); + + QString name = QString::fromUtf8(info.name.c_str()); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_NAME, name.isEmpty() ? tr("No name") : name); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_WORKSTATE, FeedReaderStringDefs::workState(info.workstate)); + + uint32_t unreadCount; + mFeedReader->getMessageCount(info.feedId, NULL, NULL, &unreadCount); + + item->setData(COLUMN_FEED_NAME, ROLE_FEED_SORT, QString("%1_%2").arg(QString(info.flag.folder ? "0" : "1"), name)); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_UNREAD, unreadCount); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_LOADING, info.workstate != FeedInfo::WAITING); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_ID, QString::fromStdString(info.feedId)); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_FOLDER, info.flag.folder); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_DEACTIVATED, info.flag.deactivated); + item->setData(COLUMN_FEED_DATA, ROLE_FEED_ERROR, (bool) (info.errorState != RS_FEED_ERRORSTATE_OK)); + item->setToolTip(COLUMN_FEED_NAME, (info.errorState != RS_FEED_ERRORSTATE_OK) ? FeedReaderStringDefs::errorString(info) : ""); +} + +void FeedReaderDialog::updateMsgs(const std::string &feedId) +{ + std::list msgInfos; + if (!mFeedReader->getFeedMsgList(feedId, msgInfos)) { + ui->msgTreeWidget->clear(); + return; + } + + int index = 0; + QTreeWidgetItem *item; + std::list::iterator msgIt; + + /* update existing and delete not existing msgs */ + while (index < ui->msgTreeWidget->topLevelItemCount()) { + item = ui->msgTreeWidget->topLevelItem(index); + std::string msgId = item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString(); + + /* search existing msg */ + int found = -1; + for (msgIt = msgInfos.begin (); msgIt != msgInfos.end (); ++msgIt) { + if (msgIt->msgId == msgId) { + /* found it, update it */ + updateMsgItem(item, *msgIt); + + msgInfos.erase(msgIt); + found = index; + break; + } + } + if (found >= 0) { + ++index; + } else { + delete(ui->msgTreeWidget->takeTopLevelItem(index)); + } + } + + /* add new msgs */ + for (msgIt = msgInfos.begin (); msgIt != msgInfos.end (); ++msgIt) { + item = new RSTreeWidgetItem(mMsgCompareRole); + updateMsgItem(item, *msgIt); + ui->msgTreeWidget->addTopLevelItem(item); + } + + filterItems(ui->filterLineEdit->text()); +} + +void FeedReaderDialog::calculateMsgIconsAndFonts(QTreeWidgetItem *item) +{ + if (!item) { + return; + } + + bool isnew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool(); + bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool(); + + if (read) { + item->setIcon(COLUMN_MSG_READ, QIcon(":/images/message-state-read.png")); + } else { + item->setIcon(COLUMN_MSG_READ, QIcon(":/images/message-state-unread.png")); + } + if (isnew) { + item->setIcon(COLUMN_MSG_TITLE, QIcon(":/images/message-state-new.png")); + } else { + item->setIcon(COLUMN_MSG_TITLE, QIcon()); + } + + for (int i = 0; i < COLUMN_FEED_COUNT; i++) { + QFont font = item->font(i); + font.setBold(isnew || !read); + item->setFont(i, font); + } + + item->setData(COLUMN_MSG_READ, ROLE_MSG_SORT, QString("%1_%2_%3").arg(QString(isnew ? "1" : "0"), QString(read ? "0" : "1"), item->data(COLUMN_MSG_TITLE, ROLE_MSG_SORT).toString())); +} + +void FeedReaderDialog::updateMsgItem(QTreeWidgetItem *item, FeedMsgInfo &info) +{ + QString title = QString::fromUtf8(info.title.c_str()); + QDateTime qdatetime; + qdatetime.setTime_t(info.pubDate); + + /* add string to all data */ + QString sort = QString("%1_%2_%2").arg(title, qdatetime.toString("yyyyMMdd_hhmmss"), QString::fromStdString(info.feedId)); + + item->setText(COLUMN_MSG_TITLE, title); + item->setData(COLUMN_MSG_TITLE, ROLE_MSG_SORT, sort); + + QString author = QString::fromUtf8(info.author.c_str()); + item->setText(COLUMN_MSG_AUTHOR, author); + item->setData(COLUMN_MSG_AUTHOR, ROLE_MSG_SORT, author + "_" + sort); + + /* if the message is on same date show only time */ + if (qdatetime.daysTo(QDateTime::currentDateTime()) == 0) { + item->setData(COLUMN_MSG_PUBDATE, Qt::DisplayRole, qdatetime.time()); + } else { + item->setData(COLUMN_MSG_PUBDATE, Qt::DisplayRole, qdatetime); + } + item->setData(COLUMN_MSG_PUBDATE, ROLE_MSG_SORT, QString("%1_%2_%3").arg(qdatetime.toString("yyyyMMdd_hhmmss"), title, QString::fromStdString(info.msgId))); + + item->setData(COLUMN_MSG_DATA, ROLE_MSG_ID, QString::fromStdString(info.msgId)); + item->setData(COLUMN_MSG_DATA, ROLE_MSG_LINK, QString::fromUtf8(info.link.c_str())); + item->setData(COLUMN_MSG_DATA, ROLE_MSG_READ, info.flag.read); + item->setData(COLUMN_MSG_DATA, ROLE_MSG_NEW, info.flag.isnew); + + calculateMsgIconsAndFonts(item); +} + +void FeedReaderDialog::feedChanged(const QString &feedId, int type) +{ + if (!isVisible()) { + /* complete update in showEvent */ + return; + } + + if (feedId.isEmpty()) { + return; + } + + FeedInfo feedInfo; + if (type != NOTIFY_TYPE_DEL) { + if (!mFeedReader->getFeedInfo(feedId.toStdString(), feedInfo)) { + return; + } + + if (feedInfo.flag.preview) { + return; + } + } + + if (type == NOTIFY_TYPE_MOD || type == NOTIFY_TYPE_DEL) { + QTreeWidgetItemIterator it(ui->feedTreeWidget); + QTreeWidgetItem *item; + while ((item = *it) != NULL) { + if (item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString() == feedId) { + if (type == NOTIFY_TYPE_MOD) { + updateFeedItem(item, feedInfo); + } else { + delete(item); + } + break; + } + ++it; + } + } + + if (type == NOTIFY_TYPE_ADD) { + QString id = QString::fromStdString(feedInfo.parentId); + + QTreeWidgetItemIterator it(ui->feedTreeWidget); + QTreeWidgetItem *itemParent; + while ((itemParent = *it) != NULL) { + if (itemParent->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString() == id) { + QTreeWidgetItem *item = new RSTreeWidgetItem(mFeedCompareRole); + itemParent->addChild(item); + updateFeedItem(item, feedInfo); + break; + } + ++it; + } + } + calculateFeedItems(); +} + +void FeedReaderDialog::msgChanged(const QString &feedId, const QString &msgId, int type) +{ + if (!isVisible()) { + /* complete update in showEvent */ + return; + } + + if (feedId.isEmpty() || msgId.isEmpty()) { + return; + } + + if (feedId.toStdString() != currentFeedId()) { + return; + } + + FeedMsgInfo msgInfo; + if (type != NOTIFY_TYPE_DEL) { + if (!mFeedReader->getMsgInfo(feedId.toStdString(), msgId.toStdString(), msgInfo)) { + return; + } + } + + if (type == NOTIFY_TYPE_MOD || type == NOTIFY_TYPE_DEL) { + QTreeWidgetItemIterator it(ui->msgTreeWidget); + QTreeWidgetItem *item; + while ((item = *it) != NULL) { + if (item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString() == msgId) { + if (type == NOTIFY_TYPE_MOD) { + updateMsgItem(item, msgInfo); + filterItem(item); + } else { + delete(item); + } + break; + } + ++it; + } + } + + if (type == NOTIFY_TYPE_ADD) { + QTreeWidgetItem *item = new RSTreeWidgetItem(mMsgCompareRole); + updateMsgItem(item, msgInfo); + ui->msgTreeWidget->addTopLevelItem(item); + filterItem(item); + } +} + +void FeedReaderDialog::feedItemChanged(QTreeWidgetItem *item) +{ + if (!item) { + ui->msgTreeWidget->clear(); + return; + } + + std::string feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toString().toStdString(); + updateMsgs(feedId); +} + +void FeedReaderDialog::msgItemClicked(QTreeWidgetItem *item, int column) +{ + if (item == NULL) { + return; + } + + if (column == COLUMN_MSG_READ) { + QList rows; + rows.append(item); + bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool(); + setMsgAsReadUnread(rows, !read); + return; + } +} + +void FeedReaderDialog::msgItemChanged() +{ + long todo; // show link somewhere + + std::string feedId = currentFeedId(); + std::string msgId = currentMsgId(); + + if (feedId.empty() || msgId.empty()) { + ui->msgTitle->clear(); +// ui->msgLink->clear(); + ui->msgText->clear(); + ui->linkButton->setEnabled(false); + return; + } + + QTreeWidgetItem *item = ui->msgTreeWidget->currentItem(); + if (!item) { + /* there is something wrong */ + ui->msgTitle->clear(); +// ui->msgLink->clear(); + ui->msgText->clear(); + ui->linkButton->setEnabled(false); + return; + } + + /* get msg */ + FeedMsgInfo msgInfo; + if (!mFeedReader->getMsgInfo(feedId, msgId, msgInfo)) { + ui->msgTitle->clear(); +// ui->msgLink->clear(); + ui->msgText->clear(); + ui->linkButton->setEnabled(false); + return; + } + + bool setToReadOnActive = Settings->valueFromGroup("FeedReaderDialog", "SetMsgToReadOnActivate", true).toBool(); + bool isnew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool(); + bool read = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool(); + + QList row; + row.append(item); + if (read) { + if (isnew) { + /* something wrong, but set as read again to clear the new flag */ + setMsgAsReadUnread(row, true); + } + } else { + /* set to read/unread */ + setMsgAsReadUnread(row, setToReadOnActive); + } + + QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(msgInfo.description.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS); + + ui->msgText->setHtml(msgTxt); + ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str())); + + ui->linkButton->setEnabled(!msgInfo.link.empty()); +} + +void FeedReaderDialog::setMsgAsReadUnread(QList &rows, bool read) +{ + QList::iterator rowIt; + + std::string feedId = currentFeedId(); + if (feedId.empty()) { + return; + } + + for (rowIt = rows.begin(); rowIt != rows.end(); rowIt++) { + QTreeWidgetItem *item = *rowIt; + bool rowRead = item->data(COLUMN_MSG_DATA, ROLE_MSG_READ).toBool(); + bool rowNew = item->data(COLUMN_MSG_DATA, ROLE_MSG_NEW).toBool(); + + if (rowNew || read != rowRead) { + std::string msgId = item->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString(); + mFeedReader->setMessageRead(feedId, msgId, read); + } + } +} + +void FeedReaderDialog::filterColumnChanged() +{ + if (mProcessSettings) { + return; + } + + filterItems(ui->filterLineEdit->text()); + + // save index + int filterColumn = filterColumnFromComboBox(ui->filterColumnComboBox->currentIndex()); + Settings->setValueToGroup("FeedReaderDialog", "filterColumn", filterColumn); +} + +void FeedReaderDialog::filterItems(const QString& text) +{ + int filterColumn = filterColumnFromComboBox(ui->filterColumnComboBox->currentIndex()); + + int count = ui->msgTreeWidget->topLevelItemCount(); + for (int index = 0; index < count; ++index) { + filterItem(ui->msgTreeWidget->topLevelItem(index), text, filterColumn); + } +} + +void FeedReaderDialog::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn) +{ + if (text.isEmpty() == false) { + if (item->text(filterColumn).contains(text, Qt::CaseInsensitive)) { + item->setHidden(false); + } else { + item->setHidden(true); + } + } else { + item->setHidden(false); + } +} + +void FeedReaderDialog::filterItem(QTreeWidgetItem *item) +{ + filterItem(item, ui->filterLineEdit->text(), filterColumnFromComboBox(ui->filterColumnComboBox->currentIndex())); +} + +void FeedReaderDialog::toggleMsgText() +{ + // save state of button + Settings->setValueToGroup("FeedReaderDialog", "expandButton", ui->expandButton->isChecked()); + + toggleMsgText_internal(); +} + +void FeedReaderDialog::toggleMsgText_internal() +{ + if (ui->expandButton->isChecked()) { + ui->msgText->setVisible(true); + ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui->expandButton->setToolTip(tr("Hide")); + } else { + ui->msgText->setVisible(false); + ui->expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } +} + +void FeedReaderDialog::newFolder() +{ + QInputDialog dialog; + dialog.setWindowTitle(tr("Add new folder")); + dialog.setLabelText(tr("Please enter a name for the folder")); + dialog.setWindowIcon(QIcon(":/images/FeedReader.png")); + + if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) { + std::string feedId; + RsFeedAddResult result = mFeedReader->addFolder(currentFeedId(), dialog.textValue().toUtf8().constData(), feedId); + FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder.")); + } +} + +void FeedReaderDialog::newFeed() +{ + AddFeedDialog dialog(mFeedReader, mNotify, this); + dialog.setParent(currentFeedId()); + dialog.exec(); +} + +void FeedReaderDialog::removeFeed() +{ + std::string feedId = currentFeedId(); + if (feedId.empty()) { + return; + } + + QTreeWidgetItem *item = ui->feedTreeWidget->currentItem(); + if (!item) { + return; + } + + bool folder = item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool(); + QString name = item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString(); + + if (QMessageBox::question(this, folder ? tr("Remove folder") : tr("Remove feed"), folder ? tr("Do you want to remove the folder %1?").arg(name) : tr("Do you want to remove the feed %1?").arg(name), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { + mFeedReader->removeFeed(feedId); + } +} + +void FeedReaderDialog::editFeed() +{ + std::string feedId = currentFeedId(); + if (feedId.empty()) { + return; + } + + QTreeWidgetItem *item = ui->feedTreeWidget->currentItem(); + if (!item) { + return; + } + + bool folder = item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool(); + if (folder) { + QInputDialog dialog; + dialog.setWindowTitle(tr("Edit folder")); + dialog.setLabelText(tr("Please enter a new name for the folder")); + dialog.setWindowIcon(QIcon(":/images/FeedReader.png")); + dialog.setTextValue(item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString()); + + if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) { + RsFeedAddResult result = mFeedReader->setFolder(feedId, dialog.textValue().toUtf8().constData()); + FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder.")); + } + } else { + AddFeedDialog dialog(mFeedReader, mNotify, this); + if (!dialog.fillFeed(feedId)) { + return; + } + dialog.exec(); + + } +} + +void FeedReaderDialog::activateFeed() +{ + std::string feedId = currentFeedId(); + if (feedId.empty()) { + return; + } + + FeedInfo feedInfo; + if (!mFeedReader->getFeedInfo(feedId, feedInfo)) { + return; + } + + if (feedInfo.flag.folder) { + return; + } + + feedInfo.flag.deactivated = !feedInfo.flag.deactivated; + + mFeedReader->setFeed(feedId, feedInfo); +} + +void FeedReaderDialog::processFeed() +{ + std::string feedId = currentFeedId(); + /* empty feed id process all feeds */ + + mFeedReader->processFeed(feedId); +} + +void FeedReaderDialog::markAsReadMsg() +{ + QList selectedItems = ui->msgTreeWidget->selectedItems(); + setMsgAsReadUnread(selectedItems, true); +} + +void FeedReaderDialog::markAsUnreadMsg() +{ + QList selectedItems = ui->msgTreeWidget->selectedItems(); + setMsgAsReadUnread(selectedItems, false); +} + +void FeedReaderDialog::markAllAsReadMsg() +{ + QList items; + + QTreeWidgetItemIterator it(ui->msgTreeWidget); + QTreeWidgetItem *item; + while ((item = *it) != NULL) { + if (!item->isHidden()) { + items.push_back(item); + } + ++it; + } + setMsgAsReadUnread(items, true); +} + +void FeedReaderDialog::copyLinksMsg() +{ + QString links; + + QTreeWidgetItemIterator it(ui->msgTreeWidget, QTreeWidgetItemIterator::Selected); + QTreeWidgetItem *item; + while ((item = *it) != NULL) { + QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString(); + if (!link.isEmpty()) { + links += link + "\n"; + } + ++it; + } + + if (links.isEmpty()) { + return; + } + + QApplication::clipboard()->setText(links); +} + +void FeedReaderDialog::removeMsg() +{ + std::string feedId = currentFeedId(); + if (feedId.empty()) { + return; + } + + QList selectedItems = ui->msgTreeWidget->selectedItems(); + QList::iterator it; + std::list msgIds; + + for (it = selectedItems.begin(); it != selectedItems.end(); ++it) { + msgIds.push_back((*it)->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString()); + } + mFeedReader->removeMsgs(feedId, msgIds); +} + +void FeedReaderDialog::copyLinkMsg() +{ + QTreeWidgetItem *item = ui->msgTreeWidget->currentItem(); + if (!item) { + return; + } + + QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString(); + if (link.isEmpty()) { + return; + } + + QApplication::clipboard()->setText(link); +} + +void FeedReaderDialog::openLinkMsg() +{ + QTreeWidgetItem *item = ui->msgTreeWidget->currentItem(); + if (!item) { + return; + } + + QString link = item->data(COLUMN_MSG_DATA, ROLE_MSG_LINK).toString(); + if (link.isEmpty()) { + return; + } + + QDesktopServices::openUrl(QUrl(link)); +} diff --git a/plugins/FeedReader/gui/FeedReaderDialog.h b/plugins/FeedReader/gui/FeedReaderDialog.h new file mode 100644 index 000000000..e60f218cb --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderDialog.h @@ -0,0 +1,107 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FEEDREADERDIALOG_H +#define _FEEDREADERDIALOG_H + +#include +#include "interface/rsFeedReader.h" + +namespace Ui { +class FeedReaderDialog; +} + +class QTreeWidgetItem; +class RsFeedReader; +class RSTreeWidgetItemCompareRole; +class FeedReaderNotify; + +class FeedReaderDialog : public MainPage +{ + Q_OBJECT + +public: + FeedReaderDialog(RsFeedReader *feedReader, QWidget *parent = 0); + ~FeedReaderDialog(); + +protected: + virtual void showEvent(QShowEvent *e); + bool eventFilter(QObject *obj, QEvent *ev); + +private slots: + void feedTreeCustomPopupMenu(QPoint point); + void msgTreeCustomPopupMenu(QPoint point); + void feedItemChanged(QTreeWidgetItem *item); + void msgItemChanged(); + void msgItemClicked(QTreeWidgetItem *item, int column); + void filterColumnChanged(); + void filterItems(const QString &text); + void toggleMsgText(); + void newFolder(); + void newFeed(); + void removeFeed(); + void editFeed(); + void activateFeed(); + void processFeed(); + void markAsReadMsg(); + void markAsUnreadMsg(); + void markAllAsReadMsg(); + void copyLinksMsg(); + void removeMsg(); + void openLinkMsg(); + void copyLinkMsg(); + + /* FeedReaderNotify */ + void feedChanged(const QString &feedId, int type); + void msgChanged(const QString &feedId, const QString &msgId, int type); + +private: + std::string currentFeedId(); + std::string currentMsgId(); + void processSettings(bool load); + void updateFeeds(const std::string &parentId, QTreeWidgetItem *parentItem); + void updateFeedItem(QTreeWidgetItem *item, FeedInfo &info); + void updateMsgs(const std::string &feedId); + void calculateMsgIconsAndFonts(QTreeWidgetItem *item); + void updateMsgItem(QTreeWidgetItem *item, FeedMsgInfo &info); + void setMsgAsReadUnread(QList &rows, bool read); + void filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); + void filterItem(QTreeWidgetItem *item); + void toggleMsgText_internal(); + + void calculateFeedItems(); + void calculateFeedItem(QTreeWidgetItem *item, uint32_t &unreadCount, bool &loading); + + bool mProcessSettings; + QTreeWidgetItem *mRootItem; + RSTreeWidgetItemCompareRole *mFeedCompareRole; + RSTreeWidgetItemCompareRole *mMsgCompareRole; + + // gui interface + RsFeedReader *mFeedReader; + FeedReaderNotify *mNotify; + + /** Qt Designer generated object */ + Ui::FeedReaderDialog *ui; +}; + +#endif + diff --git a/plugins/FeedReader/gui/FeedReaderDialog.ui b/plugins/FeedReader/gui/FeedReaderDialog.ui new file mode 100644 index 000000000..7dbaeea91 --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderDialog.ui @@ -0,0 +1,387 @@ + + + FeedReaderDialog + + + + 0 + 0 + 738 + 583 + + + + + + + + + + Qt::Horizontal + + + + + 300 + 300 + + + + QFrame#frame{border: none;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + QFrame#feedsHeaderFrame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + + + :/images/Feed.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Feeds</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + + + + + + + + + + + Qt::Vertical + + + + + + + + 0 + 32 + + + + QFrame#frame_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 2 + + + + + + + + :/images/find-16.png + + + + + + + Search forums + + + + + + + + + + 0 + 0 + + + + + MS Shell Dlg 2 + + + + 0 + + + + Title + + + + + Date + + + + + Author + + + + + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + + Title + + + + + + + + + :/images/message-state-header.png:/images/message-state-header.png + + + + + Date + + + + + Author + + + + + + + + + + + 0 + 0 + + + + + 10 + 75 + true + + + + Message: + + + + + + + QLabel#msgTitle{ +border: 2px solid #CCCCCC; +border-radius: 6px; +background: white;} + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + :/images/Link.png:/images/Link.png + + + QToolButton::MenuButtonPopup + + + true + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + true + + + true + + + + + + + + + + + 0 + 10 + + + + + 9 + + + + + + + + + + + LineEditClear + QLineEdit +
gui/common/LineEditClear.h
+
+ + LinkTextBrowser + QTextBrowser +
gui/common/LinkTextBrowser.h
+
+
+ + + + + +
diff --git a/plugins/FeedReader/gui/FeedReaderNotify.cpp b/plugins/FeedReader/gui/FeedReaderNotify.cpp new file mode 100644 index 000000000..59853c114 --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderNotify.cpp @@ -0,0 +1,36 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "FeedReaderNotify.h" + +FeedReaderNotify::FeedReaderNotify() : QObject() +{ +} + +void FeedReaderNotify::feedChanged(const std::string &feedId, int type) +{ + emit notifyFeedChanged(QString::fromStdString(feedId), type); +} + +void FeedReaderNotify::msgChanged(const std::string &feedId, const std::string &msgId, int type) +{ + emit notifyMsgChanged(QString::fromStdString(feedId), QString::fromStdString(msgId), type); +} diff --git a/plugins/FeedReader/gui/FeedReaderNotify.h b/plugins/FeedReader/gui/FeedReaderNotify.h new file mode 100644 index 000000000..572b540ac --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderNotify.h @@ -0,0 +1,45 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FEEDREADERNOTIFY_H +#define _FEEDREADERNOTIFY_H + +#include +#include "interface/rsFeedReader.h" + +class FeedReaderNotify : public QObject, public RsFeedReaderNotify +{ + Q_OBJECT + +public: + FeedReaderNotify(); + + /* RsFeedReaderNotify */ + virtual void feedChanged(const std::string &feedId, int type); + virtual void msgChanged(const std::string &feedId, const std::string &msgId, int type); + +signals: + void notifyFeedChanged(const QString &feedId, int type); + void notifyMsgChanged(const QString &feedId, const QString &msgId, int type); +}; + +#endif + diff --git a/plugins/FeedReader/gui/FeedReaderStringDefs.cpp b/plugins/FeedReader/gui/FeedReaderStringDefs.cpp new file mode 100644 index 000000000..d7cd8d502 --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderStringDefs.cpp @@ -0,0 +1,148 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "FeedReaderStringDefs.h" + +bool FeedReaderStringDefs::showError(QWidget *parent, RsFeedAddResult result, const QString &title, const QString &text) +{ + QString error; + + switch (result) { + case RS_FEED_ADD_RESULT_SUCCESS: + /* no error */ + return false; + case RS_FEED_ADD_RESULT_FEED_NOT_FOUND: + error = QApplication::translate("FeedReaderStringDefs", "Feed not found."); + break; + case RS_FEED_ADD_RESULT_PARENT_NOT_FOUND: + error = QApplication::translate("FeedReaderStringDefs", "Parent not found."); + break; + case RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER: + error = QApplication::translate("FeedReaderStringDefs", "Parent is no folder."); + break; + case RS_FEED_ADD_RESULT_FEED_IS_FOLDER: + error = QApplication::translate("FeedReaderStringDefs", "Feed is a folder."); + break; + case RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER: + error = QApplication::translate("FeedReaderStringDefs", "Feed is no folder."); + break; + default: + error = QApplication::translate("FeedReaderStringDefs", "Unknown error occured."); + } + + QMessageBox::critical(parent, title, text + "\n" + error); + + return true; +} + +QString FeedReaderStringDefs::workState(FeedInfo::WorkState state) +{ + switch (state) { + case FeedInfo::WAITING: + return ""; + case FeedInfo::WAITING_TO_DOWNLOAD: + return QApplication::translate("FeedReaderStringDefs", "Waiting for download"); + case FeedInfo::DOWNLOADING: + return QApplication::translate("FeedReaderStringDefs", "Downloading"); + case FeedInfo::WAITING_TO_PROCESS: + return QApplication::translate("FeedReaderStringDefs", "Waiting for process"); + case FeedInfo::PROCESSING: + return QApplication::translate("FeedReaderStringDefs", "Processing"); + } + + return ""; +} + +QString FeedReaderStringDefs::errorString(const FeedInfo &feedInfo) +{ + return errorString(feedInfo.errorState, feedInfo.errorString); +} + +QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, const std::string &errorString) +{ + QString errorText; + switch (errorState) { + case RS_FEED_ERRORSTATE_OK: + break; + + /* download */ + case RS_FEED_ERRORSTATE_DOWNLOAD_INTERNAL_ERROR: + errorText = QApplication::translate("FeedReaderStringDefs", "Internal download error"); + break; + case RS_FEED_ERRORSTATE_DOWNLOAD_ERROR: + errorText = QApplication::translate("FeedReaderStringDefs", "Download error"); + break; + case RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE: + errorText = QApplication::translate("FeedReaderStringDefs", "Unknown content type"); + break; + case RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND: + errorText = QApplication::translate("FeedReaderStringDefs", "Download not found"); + break; + case RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE: + errorText = QApplication::translate("FeedReaderStringDefs", "Unknown response code"); + break; + + /* process */ + case RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR: + errorText = QApplication::translate("FeedReaderStringDefs", "Internal process error"); + break; + case RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT: + errorText = QApplication::translate("FeedReaderStringDefs", "Unknown XML format"); + break; + case RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE: + errorText = QApplication::translate("FeedReaderStringDefs", "Can't create forum"); + break; + case RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND: + errorText = QApplication::translate("FeedReaderStringDefs", "Forum not found"); + break; + case RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_ADMIN: + errorText = QApplication::translate("FeedReaderStringDefs", "You are not admin of the forum"); + break; + case RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_ANONYMOUS: + errorText = QApplication::translate("FeedReaderStringDefs", "The forum is no anonymous forum"); + break; + + case RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR: + errorText = QApplication::translate("FeedReaderStringDefs", "Can't read html"); + break; + case RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR: + errorText = QApplication::translate("FeedReaderStringDefs", "Internal XPath error"); + break; + case RS_FEED_ERRORSTATE_PROCESS_XPATH_WRONG_EXPRESSION: + errorText = QApplication::translate("FeedReaderStringDefs", "Wrong XPath expression"); + break; + case RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT: + errorText = QApplication::translate("FeedReaderStringDefs", "Empty XPath result"); + break; + + default: + errorText = QApplication::translate("FeedReaderStringDefs", "Unknown error"); + } + + if (!errorString.empty()) { + errorText += QString(" (%1)").arg(QString::fromUtf8(errorString.c_str())); + } + + return errorText; +} diff --git a/plugins/FeedReader/gui/FeedReaderStringDefs.h b/plugins/FeedReader/gui/FeedReaderStringDefs.h new file mode 100644 index 000000000..13f9afa30 --- /dev/null +++ b/plugins/FeedReader/gui/FeedReaderStringDefs.h @@ -0,0 +1,40 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef FEEDREADER_STRINGDEFS_H +#define FEEDREADER_STRINGDEFS_H + +#include + +#include "interface/rsFeedReader.h" + +class QWidget; + +class FeedReaderStringDefs +{ +public: + static bool showError(QWidget *parent, RsFeedAddResult result, const QString &title, const QString &text); + static QString workState(FeedInfo::WorkState state); + static QString errorString(const FeedInfo &feedInfo); + static QString errorString(RsFeedReaderErrorState errorState, const std::string &errorString); +}; + +#endif diff --git a/plugins/FeedReader/gui/FeedReader_images.qrc b/plugins/FeedReader/gui/FeedReader_images.qrc new file mode 100644 index 000000000..e1a6c5918 --- /dev/null +++ b/plugins/FeedReader/gui/FeedReader_images.qrc @@ -0,0 +1,14 @@ + + + images/FeedReader.png + images/Root.png + images/Folder.png + images/Feed.png + images/FeedProcessOverlay.png + images/FeedErrorOverlay.png + images/FolderAdd.png + images/FeedAdd.png + images/Link.png + images/Update.png + + diff --git a/plugins/FeedReader/gui/PreviewFeedDialog.cpp b/plugins/FeedReader/gui/PreviewFeedDialog.cpp new file mode 100644 index 000000000..947057798 --- /dev/null +++ b/plugins/FeedReader/gui/PreviewFeedDialog.cpp @@ -0,0 +1,766 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +//#include +#include +#include + +#include "PreviewFeedDialog.h" +#include "ui_PreviewFeedDialog.h" +#include "FeedReaderNotify.h" +#include "FeedReaderStringDefs.h" +#include "util/HandleRichText.h" +#include "gui/settings/rsharesettings.h" + +#include "interface/rsFeedReader.h" +#include "retroshare/rsiface.h" +#include "util/HTMLWrapper.h" + +#include + +// not yet functional +//PreviewItemDelegate::PreviewItemDelegate(QTreeWidget *parent) : QItemDelegate(parent) +//{ +// connect(parent->header(), SIGNAL(sectionResized(int,int,int)), SLOT(sectionResized(int,int,int))); +//} + +//void PreviewItemDelegate::sectionResized(int logicalIndex, int /*oldSize*/, int /*newSize*/) +//{ +// QHeaderView *header = dynamic_cast(sender()); +// if (header) { +// QTreeWidget *treeWidget = dynamic_cast(header->parent()); +// if (treeWidget) { +// QModelIndex index = treeWidget->model()->index(0, logicalIndex, QModelIndex()); +// emit sizeHintChanged(index); +// } +// } +//} + +//void PreviewItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const +//{ +// QPen pen(painter->pen()); +// QFont font(painter->font()); +// QPalette::ColorGroup colorgroup(option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled); + +// QTextOption textOption; +// textOption.setWrapMode(QTextOption::WrapAnywhere); +// textOption.setAlignment(option.displayAlignment); + +// QRect textRect = rect.adjusted(5, 0, -5, 0); // remove width padding +// textRect.setTop(qMin(rect.top(), option.rect.top())); +// textRect.setHeight(qMax(rect.height(), option.rect.height())); + +// if (option.state & QStyle::State_Selected) { +// painter->fillRect(rect, option.palette.brush(colorgroup, QPalette::Highlight)); +// painter->setPen(option.palette.color(colorgroup, QPalette::HighlightedText)); +// } else { +// painter->setPen(option.palette.color(colorgroup, QPalette::Text)); +// } + +// if (option.state & QStyle::State_Editing) { +// painter->save(); +// painter->setPen(option.palette.color(colorgroup, QPalette::Text)); +// painter->drawRect(rect.adjusted( 0, 0, -1, -1)); +// painter->restore(); +// } + +// painter->setFont(option.font); +// painter->drawText(textRect, text, textOption); + +// // reset painter +// painter->setFont(font); +// painter->setPen(pen); +//} + +//void PreviewItemDelegate::drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const +//{ +// if (option.state & QStyle::State_HasFocus) { +// QRect textRect(rect); +// textRect.setTop(qMin(rect.top(), option.rect.top())); +// textRect.setHeight(qMax(rect.height(), option.rect.height())); + +// QStyleOptionFocusRect optionFocusRect; +// optionFocusRect.QStyleOption::operator=(option); +// optionFocusRect.rect = textRect; +// optionFocusRect.state |= QStyle::State_KeyboardFocusChange; +// QPalette::ColorGroup colorgroup = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; +// optionFocusRect.backgroundColor = option.palette.color(colorgroup, (option.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Background); +// QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &optionFocusRect, painter); +// } +//} + +//QSize PreviewItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +//{ +//// static bool inSizeHint = false; + +//// if (inSizeHint) { +//// return QSize(); +//// } +//// inSizeHint = true; + +// //d->viewport->width() +// QSize size = QItemDelegate::sizeHint(option, index); +// size.setHeight(50); + +//// QTreeWidget *treeWidget = dynamic_cast(parent()); +//// if (treeWidget) { +//// size.setWidth(treeWidget->header()->sectionSize(index.column())); + +//// QString text = index.data(Qt::DisplayRole).toString(); +//// QRect displayRect = textRectangle(NULL, QRect(0, 0, size.width(), size.height()), option.font, text); +//// QRect displayRect = treeWidget->visualRect(index); +//// int width = treeWidget->columnWidth(index.column()); +//// int height = option.fontMetrics.boundingRect(QRect(0, 0, size.width(), 0), Qt::TextWrapAnywhere | Qt::TextLongestVariant, text).height(); + +//// if (height > size.height()) { +//// size.setHeight(height); +//// } +//// } + +//// inSizeHint = false; + +// return size; +//} + +PreviewFeedDialog::PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, const FeedInfo &feedInfo, QWidget *parent) : + QDialog(parent, Qt::Window), mFeedReader(feedReader), mNotify(notify), ui(new Ui::PreviewFeedDialog) +{ + ui->setupUi(this); + + ui->feedNameLabel->clear(); + ui->useXPathCheckBox->setChecked(true); + + /* connect signals */ + connect(ui->previousPushButton, SIGNAL(clicked()), this, SLOT(previousMsg())); + connect(ui->nextPushButton, SIGNAL(clicked()), this, SLOT(nextMsg())); + connect(ui->closeStructureButton, SIGNAL(clicked()), this, SLOT(showStructureFrame())); + connect(ui->structureButton, SIGNAL(toggled(bool)), this, SLOT(showStructureFrame(bool))); + connect(ui->xpathPushButton, SIGNAL(toggled(bool)), this, SLOT(showXPathFrame(bool))); + connect(ui->useXPathCheckBox, SIGNAL(toggled(bool)), this, SLOT(fillStructureTree())); + connect(ui->xpathUseListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(xpathListCustomPopupMenu(QPoint))); + connect(ui->xpathRemoveListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(xpathListCustomPopupMenu(QPoint))); + connect(ui->xpathUseListWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(xpathCloseEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); + connect(ui->xpathRemoveListWidget->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(xpathCloseEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); + + connect(mNotify, SIGNAL(notifyFeedChanged(QString,int)), this, SLOT(feedChanged(QString,int))); + connect(mNotify, SIGNAL(notifyMsgChanged(QString,QString,int)), this, SLOT(msgChanged(QString,QString,int))); + +// ui->documentTreeWidget->setItemDelegate(new PreviewItemDelegate(ui->documentTreeWidget)); + ui->structureFrame->hide(); + + if (mFeedReader->addPreviewFeed(feedInfo, mFeedId)) { + setFeedInfo(""); + } else { + setFeedInfo(tr("Cannot create preview")); + } + setXPathInfo(""); + showXPathFrame(true); + + /* fill xpath expressions */ + QListWidgetItem *item; + std::string xpath; + foreach(xpath, feedInfo.xpathsToUse){ + item = new QListWidgetItem(QString::fromUtf8(xpath.c_str())); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->xpathUseListWidget->addItem(item); + } + foreach(xpath, feedInfo.xpathsToRemove){ + item = new QListWidgetItem(QString::fromUtf8(xpath.c_str())); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->xpathRemoveListWidget->addItem(item); + } + + updateMsgCount(); + + ui->xpathUseListWidget->installEventFilter(this); + ui->xpathRemoveListWidget->installEventFilter(this); + + /* load settings */ + processSettings(true); +} + +PreviewFeedDialog::~PreviewFeedDialog() +{ + /* save settings */ + processSettings(false); + + disconnect(mNotify); + disconnect(mNotify); + + if (!mFeedId.empty()) { + mFeedReader->removeFeed(mFeedId); + } + + delete ui; +} + +void PreviewFeedDialog::processSettings(bool load) +{ + Settings->beginGroup(QString("PreviewFeedDialog")); + + if (load) { + // load settings + QByteArray geometry = Settings->value("Geometry").toByteArray(); + if (!geometry.isEmpty()) { + restoreGeometry(geometry); + } + } else { + // save settings + Settings->setValue("Geometry", saveGeometry()); + } + + Settings->endGroup(); +} + +bool PreviewFeedDialog::eventFilter(QObject *obj, QEvent *event) +{ + long todo_here; + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent) { + if (keyEvent->key() == Qt::Key_Delete) { + /* Delete pressed */ + if (obj == ui->xpathUseListWidget || obj == ui->xpathRemoveListWidget) { + QListWidget *listWidget = dynamic_cast(obj); + if (listWidget) { + QListWidgetItem *item = listWidget->currentItem(); + if (item) { + delete(item); + processXPath(); + } + return true; // eat event + } + } + } + } + } + /* pass the event on to the parent class */ + return QDialog::eventFilter(obj, event); +} + +void PreviewFeedDialog::feedChanged(const QString &feedId, int type) +{ + if (feedId.isEmpty()) { + return; + } + + if (feedId.toStdString() != mFeedId) { + return; + } + + if (type == NOTIFY_TYPE_DEL) { + /* feed deleted */ + mFeedId.clear(); + return; + } + + if (type == NOTIFY_TYPE_ADD || type == NOTIFY_TYPE_MOD) { + FeedInfo feedInfo; + if (!mFeedReader->getFeedInfo(mFeedId, feedInfo)) { + return; + } + fillFeedInfo(feedInfo); + } +} + +void PreviewFeedDialog::msgChanged(const QString &feedId, const QString &msgId, int type) +{ + if (feedId.isEmpty() || msgId.isEmpty()) { + return; + } + + if (feedId.toStdString() != mFeedId) { + return; + } + + switch (type) { + case NOTIFY_TYPE_ADD: + if (mMsgId.empty()) { + mMsgId = msgId.toStdString(); + updateMsg(); + } + break; + case NOTIFY_TYPE_MOD: + if (mMsgId == msgId.toStdString()) { + updateMsg(); + } + break; + case NOTIFY_TYPE_DEL: + if (mMsgId == msgId.toStdString()) { + std::list::iterator it = std::find(mMsgIds.begin(), mMsgIds.end(), mMsgId); + if (it != mMsgIds.end()) { + ++it; + if (it != mMsgIds.end()) { + mMsgId = *it; + } else { + --it; + if (it != mMsgIds.begin()) { + --it; + mMsgId = *it; + } else { + mMsgId.clear(); + } + } + updateMsg(); + } + } + break; + } + + /* calculate message count */ + mMsgIds.clear(); + mFeedReader->getFeedMsgIdList(mFeedId, mMsgIds); + + updateMsgCount(); +} + +void PreviewFeedDialog::showStructureFrame(bool show) +{ + ui->structureButton->setChecked(show); + ui->structureFrame->setVisible(show); + + if (show) { + fillStructureTree(); + } +} + +void PreviewFeedDialog::showXPathFrame(bool show) +{ + ui->xpathFrame->setVisible(show); + + if (show) { + ui->xpathPushButton->setToolTip(tr("Hide XPath expressions")); + ui->xpathPushButton->setIcon(QIcon(":images/show_toolbox_frame.png")); + } else { + ui->xpathPushButton->setToolTip(tr("Show XPath expressions")); + ui->xpathPushButton->setIcon(QIcon(":images/hide_toolbox_frame.png")); + } +} + +void PreviewFeedDialog::xpathListCustomPopupMenu(QPoint /*point*/) +{ + QListWidgetItem *item = NULL; + + if (sender() == ui->xpathUseListWidget) { + item = ui->xpathUseListWidget->currentItem(); + } else if (sender() == ui->xpathRemoveListWidget) { + item = ui->xpathRemoveListWidget->currentItem(); + } else { + return; + } + + QMenu contextMnu(this); + + QAction *action = contextMnu.addAction(QIcon(), tr("Add"), this, SLOT(addXPath())); + action->setData(QVariant::fromValue(sender())); + + action = contextMnu.addAction(QIcon(), tr("Edit"), this, SLOT(editXPath())); + action->setData(QVariant::fromValue(sender())); + if (!item) { + action->setEnabled(false); + } + + action = contextMnu.addAction(QIcon(), tr("Delete"), this, SLOT(removeXPath())); + action->setData(QVariant::fromValue(sender())); + if (!item) { + action->setEnabled(false); + } + + contextMnu.exec(QCursor::pos()); +} + + +void PreviewFeedDialog::xpathCloseEditor(QWidget */*editor*/, QAbstractItemDelegate::EndEditHint /*hint*/) +{ + processXPath(); +} + +void PreviewFeedDialog::addXPath() +{ + QAction *action = dynamic_cast(sender()); + if (!action) { + return; + } + + QObject *source = action->data().value(); + + QListWidget *listWidget; + if (source == ui->xpathUseListWidget) { + listWidget = ui->xpathUseListWidget; + } else if (source == ui->xpathRemoveListWidget) { + listWidget = ui->xpathRemoveListWidget; + } else { + return; + } + + QListWidgetItem *item = new QListWidgetItem(); + item->setFlags(item->flags() | Qt::ItemIsEditable); + listWidget->addItem(item); + + listWidget->editItem(item); +} + +void PreviewFeedDialog::editXPath() +{ + QAction *action = dynamic_cast(sender()); + if (!action) { + return; + } + + QObject *source = action->data().value(); + + QListWidget *listWidget; + if (source == ui->xpathUseListWidget) { + listWidget = ui->xpathUseListWidget; + } else if (source == ui->xpathRemoveListWidget) { + listWidget = ui->xpathRemoveListWidget; + } else { + return; + } + + listWidget->editItem(listWidget->currentItem()); +} + +void PreviewFeedDialog::removeXPath() +{ + QAction *action = dynamic_cast(sender()); + if (!action) { + return; + } + + QObject *source = action->data().value(); + + QListWidget *listWidget; + if (source == ui->xpathUseListWidget) { + listWidget = ui->xpathUseListWidget; + } else if (source == ui->xpathRemoveListWidget) { + listWidget = ui->xpathRemoveListWidget; + } else { + return; + } + + QListWidgetItem *item = listWidget->currentItem(); + if (item) { + delete(item); + } + + processXPath(); +} + +int PreviewFeedDialog::getMsgPos() +{ + int pos = -1; + std::list::iterator it; + for (it = mMsgIds.begin(); it != mMsgIds.end(); ++it) { + ++pos; + if (*it == mMsgId) { + break; + } + } + + return pos; +} + +void PreviewFeedDialog::setFeedInfo(const QString &info) +{ + ui->feedInfoLabel->setText(info); + ui->feedInfoLabel->setVisible(!info.isEmpty()); +} + +void PreviewFeedDialog::setXPathInfo(const QString &info) +{ + ui->xpathInfoLabel->setText(info); + ui->xpathInfoLabel->setVisible(!info.isEmpty()); +} + +void PreviewFeedDialog::fillFeedInfo(const FeedInfo &feedInfo) +{ + QString name = feedInfo.name.empty() ? tr("No name") : QString::fromUtf8(feedInfo.name.c_str()); + + QString workState = FeedReaderStringDefs::workState(feedInfo.workstate); + if (!workState.isEmpty()) { + name += QString(" (%1)").arg(workState); + } + ui->feedNameLabel->setText(name); + + setFeedInfo(FeedReaderStringDefs::errorString(feedInfo)); +} + +void PreviewFeedDialog::previousMsg() +{ + std::list::iterator it = std::find(mMsgIds.begin(), mMsgIds.end(), mMsgId); + if (it != mMsgIds.end()) { + if (it != mMsgIds.begin()) { + --it; + mMsgId = *it; + updateMsg(); + updateMsgCount(); + } + } +} + +void PreviewFeedDialog::nextMsg() +{ + std::list::iterator it = std::find(mMsgIds.begin(), mMsgIds.end(), mMsgId); + if (it != mMsgIds.end()) { + ++it; + if (it != mMsgIds.end()) { + mMsgId = *it; + updateMsg(); + updateMsgCount(); + } + } +} + +void PreviewFeedDialog::updateMsgCount() +{ + int pos = getMsgPos(); + ui->messageCountLabel->setText(QString("%1/%2").arg(pos + 1).arg(mMsgIds.size())); + + ui->previousPushButton->setEnabled(pos > 0); + ui->nextPushButton->setEnabled(pos + 1 < (int) mMsgIds.size()); +} + +void PreviewFeedDialog::updateMsg() +{ + FeedMsgInfo msgInfo; + if (mMsgId.empty() || !mFeedReader->getMsgInfo(mFeedId, mMsgId, msgInfo)) { + ui->msgTitle->clear(); + ui->msgText->clear(); + mDescription.clear(); + mDescriptionXPath.clear(); + return; + } + + ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str())); + + /* store description */ + mDescription = msgInfo.description; + + /* process xpath */ + processXPath(); +} + +static void buildNodeText(HTMLWrapper &html, xmlNodePtr node, QString &text) +{ + switch (node->type) { + case XML_ELEMENT_NODE: + text = QString("<%1 ").arg(QString::fromUtf8(html.nodeName(node).c_str())); + + for (xmlAttrPtr attr = node->properties; attr; attr = attr->next) { + QString value = QString::fromUtf8(html.getAttr(node, attr).c_str()); + if (value.length() > 100) { + value = value.left(100) + "..."; + } + text += QString("%1=\"%2\" ").arg(QString::fromUtf8(html.attrName(attr).c_str()), value); + } + text = text.trimmed() + ">"; + + if (node->children && !node->children->next && node->children->type == XML_TEXT_NODE) { + /* only one text node as child */ + std::string content; + if (html.getContent(node->children, content)) { + text += QString::fromUtf8(content.c_str()); + } else { + text += QApplication::translate("PreviewFeedDialog", "Error getting content"); + } + text += QString("<%1>").arg(QString::fromUtf8(html.nodeName(node).c_str())); + + xmlUnlinkNode(node->children); + xmlFreeNode(node->children); + } + break; + case XML_TEXT_NODE: + case XML_COMMENT_NODE: + { + if (node->type == XML_COMMENT_NODE) { + text = ""; + } + } + break; + case XML_ATTRIBUTE_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + break; + } +} + +static void examineChildElements(QTreeWidget *treeWidget, HTMLWrapper &html, QList &nodes, QTreeWidgetItem *parentItem) +{ + int childIndex = 0; + int childCount; + + QList > nodeItems; + foreach (xmlNodePtr node, nodes) { + QString text; + buildNodeText(html, node, text); + + QList itemsToDelete; + QTreeWidgetItem *item = NULL; + + childCount = parentItem->childCount(); + for (int index = childIndex; index < childCount; ++index) { + QTreeWidgetItem *childItem = parentItem->child(index); + if (childItem->text(0) == text) { + /* reuse item */ + item = childItem; + break; + } + itemsToDelete.push_back(childItem); + } + + if (item) { + /* delete old items */ + foreach (QTreeWidgetItem *item, itemsToDelete) { + delete(item); + } + ++childIndex; + } else { + item = new QTreeWidgetItem; + item->setText(0, text); + parentItem->insertChild(childIndex, item); + item->setExpanded(true); + + ++childIndex; + } + + nodeItems.push_back(QPair(node, item)); + } + + /* delete not used items */ + while (childIndex < parentItem->childCount()) { + delete(parentItem->child(childIndex)); + } + + QList >::iterator nodeItem; + for (nodeItem = nodeItems.begin(); nodeItem != nodeItems.end(); ++nodeItem) { + QList childNodes; + for (xmlNodePtr childNode = nodeItem->first->children; childNode; childNode = childNode->next) { + childNodes.push_back(childNode); + } + examineChildElements(treeWidget, html, childNodes, nodeItem->second); + } + +// QLabel *label = new QLabel(text); +// label->setTextFormat(Qt::PlainText); +// label->setWordWrap(true); +// treeWidget->setItemWidget(item, 0, label); +} + +void PreviewFeedDialog::fillStructureTree() +{ + if (!ui->structureTreeWidget->isVisible()) { + return; + } + +// if (ui->structureTreeWidget->topLevelItemCount() > 0) { +// return; +// } + + if (mDescriptionXPath.empty()) { + ui->structureTreeWidget->clear(); + return; + } + + bool useXPath = ui->useXPathCheckBox->isChecked(); + + HTMLWrapper html; + if (!html.readHTML(useXPath ? mDescriptionXPath.c_str() : mDescription.c_str(), "")) { + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, tr("Error parsing document")); + ui->structureTreeWidget->addTopLevelItem(item); + + return; + } + + xmlNodePtr root = html.getRootElement(); + if (!root) { + return; + } + + QList nodes; + nodes.push_back(root); + examineChildElements(ui->structureTreeWidget, html, nodes, ui->structureTreeWidget->invisibleRootItem()); + ui->structureTreeWidget->resizeColumnToContents(0); +} + +void PreviewFeedDialog::getXPaths(std::list &xpathsToUse, std::list &xpathsToRemove) +{ + int row; + int rowCount = ui->xpathUseListWidget->count(); + for (row = 0; row < rowCount; ++row) { + xpathsToUse.push_back(ui->xpathUseListWidget->item(row)->text().toUtf8().constData()); + } + + rowCount = ui->xpathRemoveListWidget->count(); + for (row = 0; row < rowCount; ++row) { + xpathsToRemove.push_back(ui->xpathRemoveListWidget->item(row)->text().toUtf8().constData()); + } +} + +void PreviewFeedDialog::processXPath() +{ + std::list xpathsToUse; + std::list xpathsToRemove; + + getXPaths(xpathsToUse, xpathsToRemove); + + mDescriptionXPath = mDescription; + std::string errorString; + RsFeedReaderErrorState result = mFeedReader->processXPath(xpathsToUse, xpathsToRemove, mDescriptionXPath, errorString); + setXPathInfo(FeedReaderStringDefs::errorString(result, errorString)); + + /* fill message */ + QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8(mDescriptionXPath.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS); + ui->msgText->setHtml(msgTxt); + + /* fill structure */ + fillStructureTree(); +} diff --git a/plugins/FeedReader/gui/PreviewFeedDialog.h b/plugins/FeedReader/gui/PreviewFeedDialog.h new file mode 100644 index 000000000..d6c7e3da9 --- /dev/null +++ b/plugins/FeedReader/gui/PreviewFeedDialog.h @@ -0,0 +1,104 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef PREVIEWFEEDDIALOG_H +#define PREVIEWFEEDDIALOG_H + +#include +#include + +namespace Ui { +class PreviewFeedDialog; +} + +class QTreeWidget; +class RsFeedReader; +class FeedReaderNotify; +class FeedInfo; + +// not yet functional +//class PreviewItemDelegate : public QItemDelegate +//{ +// Q_OBJECT + +//public: +// PreviewItemDelegate(QTreeWidget *parent); + +//private slots: +// void sectionResized(int logicalIndex, int oldSize, int newSize); + +//protected: +// virtual void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const; +// virtual void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const; +// virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; +//}; + +class PreviewFeedDialog : public QDialog +{ + Q_OBJECT + +public: + PreviewFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, const FeedInfo &feedInfo, QWidget *parent = 0); + ~PreviewFeedDialog(); + + void getXPaths(std::list &xpathsToUse, std::list &xpathsToRemove); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + +private slots: + void previousMsg(); + void nextMsg(); + void showStructureFrame(bool show = false); + void showXPathFrame(bool show); + void xpathListCustomPopupMenu(QPoint point); + void xpathCloseEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint); + void addXPath(); + void editXPath(); + void removeXPath(); + void fillStructureTree(); + + /* FeedReaderNotify */ + void feedChanged(const QString &feedId, int type); + void msgChanged(const QString &feedId, const QString &msgId, int type); + +private: + void processSettings(bool load); + int getMsgPos(); + void setFeedInfo(const QString &info); + void setXPathInfo(const QString &info); + void fillFeedInfo(const FeedInfo &feedInfo); + void updateMsgCount(); + void updateMsg(); + void processXPath(); + + RsFeedReader *mFeedReader; + FeedReaderNotify *mNotify; + std::string mFeedId; + std::string mMsgId; + std::list mMsgIds; + std::string mDescription; + std::string mDescriptionXPath; + + Ui::PreviewFeedDialog *ui; +}; + +#endif // PREVIEWFEEDDIALOG_H diff --git a/plugins/FeedReader/gui/PreviewFeedDialog.ui b/plugins/FeedReader/gui/PreviewFeedDialog.ui new file mode 100644 index 000000000..21a2a89a5 --- /dev/null +++ b/plugins/FeedReader/gui/PreviewFeedDialog.ui @@ -0,0 +1,547 @@ + + + PreviewFeedDialog + + + + 0 + 0 + 800 + 783 + + + + Preview + + + true + + + + 0 + + + + + + + + 0 + 0 + + + + Name: + + + + + + + Feed name + + + true + + + + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 118 + 116 + 108 + + + + + + + + Feed information + + + true + + + + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 118 + 116 + 108 + + + + + + + + XPath information + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Previous + + + + + + + + 0 + 0 + + + + 0/0 + + + + + + + + 0 + 0 + + + + Next + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Structure + + + true + + + + + + + + + + + + 0 + 0 + + + + Titel: + + + + + + + + 0 + 24 + + + + QLabel#msgTitle{ +border: 2px solid #CCCCCC; +border-radius: 6px; +background: white;} + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + Qt::Vertical + + + false + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 16 + 16 + + + + QToolButton +{ + border-image: url(:/images/closenormal.png) +} + +QToolButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QToolButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + ... + + + true + + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + Qt::Horizontal + + + false + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 0 + + + + + Use XPath + + + + + + + true + + + false + + + false + + + + 1 + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 0 + + + + + XPath use + + + + + + + Qt::CustomContextMenu + + + + + + + XPath remove + + + + + + + Qt::CustomContextMenu + + + + + + + + + + + + + + 14 + 31 + + + + + 14 + 31 + + + + true + + + + + + + Qt::Vertical + + + + 13 + 13 + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + PreviewFeedDialog + accept() + + + 258 + 339 + + + 157 + 274 + + + + + buttonBox + rejected() + PreviewFeedDialog + reject() + + + 326 + 339 + + + 286 + 274 + + + + + diff --git a/plugins/FeedReader/gui/images/Feed.png b/plugins/FeedReader/gui/images/Feed.png new file mode 100644 index 000000000..176ec7d07 Binary files /dev/null and b/plugins/FeedReader/gui/images/Feed.png differ diff --git a/plugins/FeedReader/gui/images/FeedAdd.png b/plugins/FeedReader/gui/images/FeedAdd.png new file mode 100644 index 000000000..19b38d6d5 Binary files /dev/null and b/plugins/FeedReader/gui/images/FeedAdd.png differ diff --git a/plugins/FeedReader/gui/images/FeedErrorOverlay.png b/plugins/FeedReader/gui/images/FeedErrorOverlay.png new file mode 100644 index 000000000..c834333bd Binary files /dev/null and b/plugins/FeedReader/gui/images/FeedErrorOverlay.png differ diff --git a/plugins/FeedReader/gui/images/FeedProcessOverlay.png b/plugins/FeedReader/gui/images/FeedProcessOverlay.png new file mode 100644 index 000000000..95526940c Binary files /dev/null and b/plugins/FeedReader/gui/images/FeedProcessOverlay.png differ diff --git a/plugins/FeedReader/gui/images/FeedReader.png b/plugins/FeedReader/gui/images/FeedReader.png new file mode 100644 index 000000000..47351ffb6 Binary files /dev/null and b/plugins/FeedReader/gui/images/FeedReader.png differ diff --git a/plugins/FeedReader/gui/images/Folder.png b/plugins/FeedReader/gui/images/Folder.png new file mode 100644 index 000000000..0075a86c9 Binary files /dev/null and b/plugins/FeedReader/gui/images/Folder.png differ diff --git a/plugins/FeedReader/gui/images/FolderAdd.png b/plugins/FeedReader/gui/images/FolderAdd.png new file mode 100644 index 000000000..0075a86c9 Binary files /dev/null and b/plugins/FeedReader/gui/images/FolderAdd.png differ diff --git a/plugins/FeedReader/gui/images/Link.png b/plugins/FeedReader/gui/images/Link.png new file mode 100644 index 000000000..8f8fd3bc1 Binary files /dev/null and b/plugins/FeedReader/gui/images/Link.png differ diff --git a/plugins/FeedReader/gui/images/Root.png b/plugins/FeedReader/gui/images/Root.png new file mode 100644 index 000000000..35097f23b Binary files /dev/null and b/plugins/FeedReader/gui/images/Root.png differ diff --git a/plugins/FeedReader/gui/images/Update.png b/plugins/FeedReader/gui/images/Update.png new file mode 100644 index 000000000..cdbd86b4b Binary files /dev/null and b/plugins/FeedReader/gui/images/Update.png differ diff --git a/plugins/FeedReader/interface/rsFeedReader.h b/plugins/FeedReader/interface/rsFeedReader.h new file mode 100644 index 000000000..dc3efd1b3 --- /dev/null +++ b/plugins/FeedReader/interface/rsFeedReader.h @@ -0,0 +1,207 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RETROSHARE_FEEDREADER_GUI_INTERFACE_H +#define RETROSHARE_FEEDREADER_GUI_INTERFACE_H + +#include +#include +#include + +enum RsFeedReaderErrorState { + RS_FEED_ERRORSTATE_OK = 0, + + /* download */ + RS_FEED_ERRORSTATE_DOWNLOAD_INTERNAL_ERROR = 1, + RS_FEED_ERRORSTATE_DOWNLOAD_ERROR = 2, + RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE = 3, + RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND = 4, + RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE = 5, + + /* process */ + RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR = 50, + RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT = 51, + RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE = 100, + RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND = 101, + RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_ADMIN = 102, + RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_ANONYMOUS = 103, + + RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR = 150, + RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR = 151, + RS_FEED_ERRORSTATE_PROCESS_XPATH_WRONG_EXPRESSION = 152, + RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT = 153 +}; + + +class RsFeedReader; +extern RsFeedReader *rsFeedReader; + +enum RsFeedAddResult +{ + RS_FEED_ADD_RESULT_SUCCESS, + RS_FEED_ADD_RESULT_FEED_NOT_FOUND, + RS_FEED_ADD_RESULT_PARENT_NOT_FOUND, + RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER, + RS_FEED_ADD_RESULT_FEED_IS_FOLDER, + RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER +}; + +class FeedInfo +{ +public: + enum WorkState + { + WAITING, + WAITING_TO_DOWNLOAD, + DOWNLOADING, + WAITING_TO_PROCESS, + PROCESSING + }; + +public: + FeedInfo() + { + proxyPort = 0; + updateInterval = 0; + lastUpdate = 0; + storageTime = 0; + errorState = RS_FEED_ERRORSTATE_OK; + flag.folder = false; + flag.infoFromFeed = false; + flag.standardStorageTime = false; + flag.standardUpdateInterval = false; + flag.standardProxy = false; + flag.authentication = false; + flag.deactivated = false; + flag.forum = false; + flag.updateForumInfo = false; + flag.embedImages = false; + flag.saveCompletePage = false; + flag.preview = false; + } + + std::string feedId; + std::string parentId; + std::string url; + std::string name; + std::string description; + std::string icon; + std::string user; + std::string password; + std::string proxyAddress; + uint16_t proxyPort; + uint32_t updateInterval; + time_t lastUpdate; + uint32_t storageTime; + std::string forumId; + WorkState workstate; + RsFeedReaderErrorState errorState; + std::string errorString; + + std::list xpathsToUse; + std::list xpathsToRemove; + + struct { + bool folder : 1; + bool infoFromFeed : 1; + bool standardStorageTime : 1; + bool standardUpdateInterval : 1; + bool standardProxy : 1; + bool authentication : 1; + bool deactivated : 1; + bool forum : 1; + bool updateForumInfo : 1; + bool embedImages : 1; + bool saveCompletePage : 1; + bool preview : 1; + } flag; +}; + +class FeedMsgInfo +{ +public: + FeedMsgInfo() + { + pubDate = 0; + flag.isnew = false; + flag.read = false; + } + + std::string msgId; + std::string feedId; + std::string title; + std::string link; + std::string author; + std::string description; + time_t pubDate; + + struct { + bool isnew : 1; + bool read : 1; + } flag; +}; + +class RsFeedReaderNotify +{ +public: + RsFeedReaderNotify() {} + + virtual void feedChanged(const std::string &/*feedId*/, int /*type*/) {} + virtual void msgChanged(const std::string &/*feedId*/, const std::string &/*msgId*/, int /*type*/) {} +}; + +class RsFeedReader +{ +public: + RsFeedReader() {} + virtual ~RsFeedReader() {} + + virtual void stop() = 0; + virtual void setNotify(RsFeedReaderNotify *notify) = 0; + + virtual uint32_t getStandardStorageTime() = 0; + virtual void setStandardStorageTime(uint32_t storageTime) = 0; + virtual uint32_t getStandardUpdateInterval() = 0; + virtual void setStandardUpdateInterval(uint32_t updateInterval) = 0; + virtual bool getStandardProxy(std::string &proxyAddress, uint16_t &proxyPort) = 0; + virtual void setStandardProxy(bool useProxy, const std::string &proxyAddress, uint16_t proxyPort) = 0; + + virtual RsFeedAddResult addFolder(const std::string parentId, const std::string &name, std::string &feedId) = 0; + virtual RsFeedAddResult setFolder(const std::string &feedId, const std::string &name) = 0; + virtual RsFeedAddResult addFeed(const FeedInfo &feedInfo, std::string &feedId) = 0; + virtual RsFeedAddResult setFeed(const std::string &feedId, const FeedInfo &feedInfo) = 0; + virtual bool removeFeed(const std::string &feedId) = 0; + virtual bool addPreviewFeed(const FeedInfo &feedInfo, std::string &feedId) = 0; + virtual void getFeedList(const std::string &parentId, std::list &feedInfos) = 0; + virtual bool getFeedInfo(const std::string &feedId, FeedInfo &feedInfo) = 0; + virtual bool getMsgInfo(const std::string &feedId, const std::string &msgId, FeedMsgInfo &msgInfo) = 0; + virtual bool removeMsg(const std::string &feedId, const std::string &msgId) = 0; + virtual bool removeMsgs(const std::string &feedId, const std::list &msgIds) = 0; + virtual bool getMessageCount(const std::string &feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount) = 0; + virtual bool getFeedMsgList(const std::string &feedId, std::list &msgInfos) = 0; + virtual bool getFeedMsgIdList(const std::string &feedId, std::list &msgIds) = 0; + virtual bool processFeed(const std::string &feedId) = 0; + virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read) = 0; + + virtual RsFeedReaderErrorState processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString) = 0; +}; + +#endif diff --git a/plugins/FeedReader/lang/FeedReader_de.ts b/plugins/FeedReader/lang/FeedReader_de.ts new file mode 100644 index 000000000..07d48332a --- /dev/null +++ b/plugins/FeedReader/lang/FeedReader_de.ts @@ -0,0 +1,339 @@ + + + + + AddLinksDialog + + + + Add Link + Link hinzufügen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Link zur Wolke hinzufügen</span></p></body></html> + + + + Cancel + Abbrechen + + + + Add a new Link + Neuen Link hinzufügen + + + + Title: + Titel: + + + + Url: + Url: + + + + Add Anonymous Link + Anonym hinzufügen + + + + +2 Great! + +2 Großartig! + + + + +1 Good + +1 Gut + + + + 0 Okay + 0 In Ordnung + + + + -1 Sux + -1 Nervt + + + + -2 Bad Link + -2 Schlechter Link + + + + New Link + Neuer Link + + + + Add Link Failure + Link hinzufügen fehlgeschlagen + + + + Missing Link and/or Title + Titel und/oder Url fehlt + + + + LinksCloudPlugin + + + This plugin provides a set of cached links, and a voting system to promote them. + Das Plugin stellt Links und ein Wahlsystem zur Verfügung, um sie zu verbreiten. + + + + LinksCloud + Verknüpfungswolke + + + + LinksDialog + + + Title / Comment + Titel / Kommentar + + + + Score + Punkte + + + + Peer / Link + Nachbar / Link + + + + Sort by + Sortiere nach + + + + Combo + Kombiniert + + + + Time + Zeit + + + + Ranking + Platzierung + + + + In last + Im letzten + + + + Month + Monat + + + + Week + Woche + + + + Day + Tag + + + + + From + Von + + + + All Peers + Alle Nachbarn + + + + Own Links + Eigene Links + + + + Show + Zeige + + + + Top 100 + Top 100 + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + Letzten 100 + + + + Link: + Link: + + + + Add Anonymous Link + Anonym hinzufügen + + + + Add Link/Comment + Link/Kommentar hinzufügen + + + + Title: + Titel: + + + + Score: + Punkte: + + + + +2 Great! + +2 Großartig! + + + + +1 Good + +1 Gut + + + + 0 Okay + 0 In Ordnung + + + + -1 Sux + -1 Nervt + + + + -2 Bad Link + -2 Schlechter Link + + + + Url: + Url: + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Verknüpfungswolke</span></p></body></html> + + + + Add new link + Neuen Link hinzufügen + + + + Share Link Anonymously + Link anonym verteilen + + + + Vote on Link + Wähle für Link + + + + Download + Herunterladen + + + + Expand + Erweitern + + + + Hide + Verbergen + + + + File Request Confirmation + Bestätigung der Dateianforderung + + + + The file has been added to your download list. + Die Datei wurde zur Downloadliste hinzugefügt. + + + + File Request canceled + Dateianforderung abgebrochen + + + + The file has not been added to your download list, because you already have it. + Die folgende Datei wurde nicht zur Downloadliste hinzugefügt, da Du diese schon hast. + + + + File Request Error + Fehler bei der Dateianforderung + + + + The file link is malformed. + Link ist fehlerhaft. + + + diff --git a/plugins/FeedReader/lang/lang.qrc b/plugins/FeedReader/lang/lang.qrc new file mode 100644 index 000000000..67e313476 --- /dev/null +++ b/plugins/FeedReader/lang/lang.qrc @@ -0,0 +1,5 @@ + + + + + diff --git a/plugins/FeedReader/services/p3FeedReader.cc b/plugins/FeedReader/services/p3FeedReader.cc new file mode 100644 index 000000000..f4940048d --- /dev/null +++ b/plugins/FeedReader/services/p3FeedReader.cc @@ -0,0 +1,1935 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "rsFeedReaderItems.h" +#include "p3FeedReader.h" +#include "p3FeedReaderThread.h" +#include "serialiser/rsconfigitems.h" +#include "retroshare/rsiface.h" +#include "retroshare/rsforums.h" +#include "util/rsstring.h" + +RsFeedReader *rsFeedReader = NULL; + +#define FEEDREADER_CLEAN_INTERVAL 1 * 60 * 60 // check every hour +#define FEEDREADER_FORUM_PREFIX L"RSS: " + +/********* + * #define FEEDREADER_DEBUG + *********/ + +p3FeedReader::p3FeedReader(RsPluginHandler* pgHandler) + : RsPQIService(RS_SERVICE_TYPE_PLUGIN_FEEDREADER, CONFIG_TYPE_FEEDREADER, 5, pgHandler), + mFeedReaderMtx("p3FeedReader"), mDownloadMutex("p3FeedReaderDownload"), mProcessMutex("p3FeedReaderProcess"), mPreviewMutex("p3FeedReaderPreview") +{ + mNextFeedId = 1; + mNextMsgId = 1; + mNextPreviewFeedId = -1; // use negative values + mNextPreviewMsgId = -1; // use negative values + mStandardUpdateInterval = 60 * 60; // 60 minutes + mStandardStorageTime = 30 * 60 * 60 * 24; // 30 days + mStandardUseProxy = false; + mStandardProxyPort = 0; + mLastClean = 0; + mNotify = NULL; + + mPreviewDownloadThread = NULL; + mPreviewProcessThread = NULL; + + /* start download thread */ + p3FeedReaderThread *frt = new p3FeedReaderThread(this, p3FeedReaderThread::DOWNLOAD, ""); + mThreads.push_back(frt); + frt->start(); + + /* start process thread */ + frt = new p3FeedReaderThread(this, p3FeedReaderThread::PROCESS, ""); + mThreads.push_back(frt); + frt->start(); +} + +/***************************************************************************/ +/****************************** RsFeedReader *******************************/ +/***************************************************************************/ + +static void feedToInfo(const RsFeedReaderFeed *feed, FeedInfo &info) +{ + info.feedId = feed->feedId; + info.parentId = feed->parentId; + info.url = feed->url; + info.name = feed->name; + info.description = feed->description; + info.icon = feed->icon; + info.user = feed->user; + info.password = feed->password; + info.proxyAddress = feed->proxyAddress; + info.proxyPort = feed->proxyPort; + info.updateInterval = feed->updateInterval; + info.lastUpdate = feed->lastUpdate; + info.forumId = feed->forumId; + info.storageTime = feed->storageTime; + info.errorState = feed->errorState; + info.errorString = feed->errorString; + + info.xpathsToUse = feed->xpathsToUse.ids; + info.xpathsToRemove = feed->xpathsToRemove.ids; + + info.flag.folder = (feed->flag & RS_FEED_FLAG_FOLDER); + info.flag.infoFromFeed = (feed->flag & RS_FEED_FLAG_INFO_FROM_FEED); + info.flag.standardStorageTime = (feed->flag & RS_FEED_FLAG_STANDARD_STORAGE_TIME); + info.flag.standardUpdateInterval = (feed->flag & RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL); + info.flag.standardProxy = (feed->flag & RS_FEED_FLAG_STANDARD_PROXY); + info.flag.authentication = (feed->flag & RS_FEED_FLAG_AUTHENTICATION); + info.flag.deactivated = (feed->flag & RS_FEED_FLAG_DEACTIVATED); + info.flag.forum = (feed->flag & RS_FEED_FLAG_FORUM); + info.flag.updateForumInfo = (feed->flag & RS_FEED_FLAG_UPDATE_FORUM_INFO); + info.flag.embedImages = (feed->flag & RS_FEED_FLAG_EMBED_IMAGES); + info.flag.saveCompletePage = (feed->flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE); + + info.flag.preview = feed->preview; + + switch (feed->workstate) { + case RsFeedReaderFeed::WAITING: + info.workstate = FeedInfo::WAITING; + break; + case RsFeedReaderFeed::WAITING_TO_DOWNLOAD: + info.workstate = FeedInfo::WAITING_TO_DOWNLOAD; + break; + case RsFeedReaderFeed::DOWNLOADING: + info.workstate = FeedInfo::DOWNLOADING; + break; + case RsFeedReaderFeed::WAITING_TO_PROCESS: + info.workstate = FeedInfo::WAITING_TO_PROCESS; + break; + case RsFeedReaderFeed::PROCESSING: + info.workstate = FeedInfo::PROCESSING; + break; + } +} + +static void infoToFeed(const FeedInfo &info, RsFeedReaderFeed *feed, bool add) +{ +// feed->feedId = info.feedId; + feed->parentId = info.parentId; + feed->url = info.url; + feed->name = info.name; + feed->description = info.description; +// feed->icon = info.icon; + feed->user = info.user; + feed->password = info.password; + feed->proxyAddress = info.proxyAddress; + feed->proxyPort = info.proxyPort; + feed->updateInterval = info.updateInterval; +// feed->lastUpdate = info.lastUpdate; + feed->storageTime = info.storageTime; + if (add) { + /* set forum id only when adding a feed */ + feed->forumId = info.forumId; + } + + feed->xpathsToUse.ids = info.xpathsToUse; + feed->xpathsToRemove.ids = info.xpathsToRemove; + +// feed->preview = info.flag.preview; + + uint32_t oldFlag = feed->flag; + feed->flag = 0; + if (info.flag.infoFromFeed) { + feed->flag |= RS_FEED_FLAG_INFO_FROM_FEED; + } + if (info.flag.standardStorageTime) { + feed->flag |= RS_FEED_FLAG_STANDARD_STORAGE_TIME; + } + if (info.flag.standardUpdateInterval) { + feed->flag |= RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL; + } + if (info.flag.standardProxy) { + feed->flag |= RS_FEED_FLAG_STANDARD_PROXY; + } + if (info.flag.authentication) { + feed->flag |= RS_FEED_FLAG_AUTHENTICATION; + } + if (info.flag.deactivated) { + feed->flag |= RS_FEED_FLAG_DEACTIVATED; + } + if (info.flag.embedImages) { + feed->flag |= RS_FEED_FLAG_EMBED_IMAGES; + } + if (info.flag.saveCompletePage) { + feed->flag |= RS_FEED_FLAG_SAVE_COMPLETE_PAGE; + } + if (add) { + /* only set when adding a new feed */ + if (info.flag.folder) { + feed->flag |= RS_FEED_FLAG_FOLDER; + } + if (info.flag.forum) { + feed->flag |= RS_FEED_FLAG_FORUM; + } + } else { + /* use old bits */ + feed->flag |= (oldFlag & (RS_FEED_FLAG_FOLDER | RS_FEED_FLAG_FORUM)); + } + if (info.flag.updateForumInfo) { + feed->flag |= RS_FEED_FLAG_UPDATE_FORUM_INFO; + } +} + +static void feedMsgToInfo(const RsFeedReaderMsg *msg, FeedMsgInfo &info) +{ + info.msgId = msg->msgId; + info.feedId = msg->feedId; + info.title = msg->title; + info.link = msg->link; + info.author = msg->author; + info.description = msg->description; + info.pubDate = msg->pubDate; + + info.flag.isnew = (msg->flag & RS_FEEDMSG_FLAG_NEW); + info.flag.read = (msg->flag & RS_FEEDMSG_FLAG_READ); +} + +void p3FeedReader::setNotify(RsFeedReaderNotify *notify) +{ + mNotify = notify; +} + +uint32_t p3FeedReader::getStandardStorageTime() +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + return mStandardStorageTime; +} + +void p3FeedReader::setStandardStorageTime(uint32_t storageTime) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + if (mStandardStorageTime != storageTime) { + mStandardStorageTime = storageTime; + IndicateConfigChanged(); + } +} + +uint32_t p3FeedReader::getStandardUpdateInterval() +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + return mStandardUpdateInterval; +} + +void p3FeedReader::setStandardUpdateInterval(uint32_t updateInterval) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + if (mStandardUpdateInterval != updateInterval) { + mStandardUpdateInterval = updateInterval; + IndicateConfigChanged(); + } +} + +bool p3FeedReader::getStandardProxy(std::string &proxyAddress, uint16_t &proxyPort) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + proxyAddress = mStandardProxyAddress; + proxyPort = mStandardProxyPort; + + return mStandardUseProxy; +} + +void p3FeedReader::setStandardProxy(bool useProxy, const std::string &proxyAddress, uint16_t proxyPort) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + if (useProxy != mStandardUseProxy || proxyAddress != mStandardProxyAddress || proxyPort != mStandardProxyPort) { + mStandardProxyAddress = proxyAddress; + mStandardProxyPort = proxyPort; + mStandardUseProxy = useProxy; + IndicateConfigChanged(); + } +} + +void p3FeedReader::stop() +{ + { + RsStackMutex stack(mPreviewMutex); /******* LOCK STACK MUTEX *********/ + + stopPreviewThreads_locked(); + } + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* stop threads */ + std::list::iterator it; + for (it = mThreads.begin(); it != mThreads.end(); ++it) { + (*it)->join(); + delete(*it); + } + mThreads.clear(); + } +} + +void p3FeedReader::stopPreviewThreads_locked() +{ + if (mPreviewDownloadThread) { + mPreviewDownloadThread->join(); + delete mPreviewDownloadThread; + mPreviewDownloadThread = NULL; + } + if (mPreviewProcessThread) { + mPreviewProcessThread->join(); + delete mPreviewProcessThread; + mPreviewProcessThread = NULL; + } +} + +RsFeedAddResult p3FeedReader::addFolder(const std::string parentId, const std::string &name, std::string &feedId) +{ + feedId.clear(); + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + if (!parentId.empty()) { + /* check parent id */ + std::map::iterator parentIt = mFeeds.find(parentId); + if (parentIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::addFolder - parent id " << parentId << " not found" << std::endl; +#endif + return RS_FEED_ADD_RESULT_PARENT_NOT_FOUND; + } + + if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::addFolder - parent " << parentIt->second->name << " is no folder" << std::endl; +#endif + return RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER; + } + } + + RsFeedReaderFeed *fi = new RsFeedReaderFeed; + rs_sprintf(fi->feedId, "%lu", mNextFeedId++); + fi->parentId = parentId; + fi->name = name; + fi->flag = RS_FEED_FLAG_FOLDER; + mFeeds[fi->feedId] = fi; + + feedId = fi->feedId; + } + + IndicateConfigChanged(); + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_ADD); + } + + return RS_FEED_ADD_RESULT_SUCCESS; +} + +RsFeedAddResult p3FeedReader::setFolder(const std::string &feedId, const std::string &name) +{ + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFolder - feed id " << feedId << ", name " << name << std::endl; +#endif + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFolder - feed id " << feedId << " not found" << std::endl; +#endif + return RS_FEED_ADD_RESULT_FEED_NOT_FOUND; + } + + if ((feedIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFolder - feed " << feedIt->second->name << " is no folder" << std::endl; +#endif + return RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER; + } + + RsFeedReaderFeed *fi = feedIt->second; + if (fi->name == name) { + return RS_FEED_ADD_RESULT_SUCCESS; + } + fi->name = name; + } + + IndicateConfigChanged(); + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } + + return RS_FEED_ADD_RESULT_SUCCESS; +} + +RsFeedAddResult p3FeedReader::addFeed(const FeedInfo &feedInfo, std::string &feedId) +{ + feedId.clear(); + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::addFeed - add feed " << feedInfo.name << ", url " << feedInfo.url << std::endl; +#endif + + if (!feedInfo.parentId.empty()) { + /* check parent id */ + std::map::iterator parentIt = mFeeds.find(feedInfo.parentId); + if (parentIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::addFeed - parent id " << feedInfo.parentId << " not found" << std::endl; +#endif + return RS_FEED_ADD_RESULT_PARENT_NOT_FOUND; + } + + if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::addFeed - parent " << parentIt->second->name << " is no folder" << std::endl; +#endif + return RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER; + } + } + + RsFeedReaderFeed *fi = new RsFeedReaderFeed; + infoToFeed(feedInfo, fi, true); + rs_sprintf(fi->feedId, "%lu", mNextFeedId++); + + mFeeds[fi->feedId] = fi; + + feedId = fi->feedId; + } + + IndicateConfigChanged(); + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_ADD); + } + + return RS_FEED_ADD_RESULT_SUCCESS; +} + +RsFeedAddResult p3FeedReader::setFeed(const std::string &feedId, const FeedInfo &feedInfo) +{ + std::string forumId; + ForumInfo forumInfo; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - set feed " << feedInfo.name << ", url " << feedInfo.url << std::endl; +#endif + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - feed id " << feedId << " not found" << std::endl; +#endif + return RS_FEED_ADD_RESULT_FEED_NOT_FOUND; + } + + if (feedIt->second->flag & RS_FEED_FLAG_FOLDER) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - feed " << feedIt->second->name << " is a folder" << std::endl; +#endif + return RS_FEED_ADD_RESULT_FEED_IS_FOLDER; + } + + if (!feedInfo.parentId.empty()) { + /* check parent id */ + std::map::iterator parentIt = mFeeds.find(feedInfo.parentId); + if (parentIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - parent id " << feedInfo.parentId << " not found" << std::endl; +#endif + return RS_FEED_ADD_RESULT_PARENT_NOT_FOUND; + } + + if ((parentIt->second->flag & RS_FEED_FLAG_FOLDER) == 0) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - parent " << parentIt->second->name << " is no folder" << std::endl; +#endif + return RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER; + } + } + + RsFeedReaderFeed *fi = feedIt->second; + std::string oldName = fi->name; + std::string oldDescription = fi->description; + + infoToFeed(feedInfo, fi, false); + + if ((fi->flag & RS_FEED_FLAG_FORUM) && (fi->flag & RS_FEED_FLAG_UPDATE_FORUM_INFO) && !fi->forumId.empty() && + (fi->name != oldName || fi->description != oldDescription)) { + /* name or description changed, update forum */ + forumId = fi->forumId; + librs::util::ConvertUtf8ToUtf16(fi->name, forumInfo.forumName); + librs::util::ConvertUtf8ToUtf16(fi->description, forumInfo.forumDesc); + } + } + + IndicateConfigChanged(); + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } + + if (!forumId.empty()) { + /* name or description changed, update forum */ + if (!rsForums->setForumInfo(forumId, forumInfo)) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - can't change forum " << forumId << std::endl; +#endif + } + } + + return RS_FEED_ADD_RESULT_SUCCESS; +} + +void p3FeedReader::deleteAllMsgs_locked(RsFeedReaderFeed *fi) +{ + if (!fi) { + return; + } + + std::map::iterator msgIt; + for (msgIt = fi->msgs.begin(); msgIt != fi->msgs.end(); ++msgIt) { + delete(msgIt->second); + } + + fi->msgs.clear(); +} + +bool p3FeedReader::removeFeed(const std::string &feedId) +{ + std::list removedFeedIds; + bool changed = false; + bool preview = false; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::removeFeed - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + removedFeedIds.push_back(feedId); + + RsFeedReaderFeed *fi = feedIt->second; + mFeeds.erase(feedIt); + changed = !fi->preview; + preview = fi->preview; + + if (fi->flag & RS_FEED_FLAG_FOLDER) { + std::list feedIds; + feedIds.push_back(fi->feedId); + while (!feedIds.empty()) { + std::string parentId = feedIds.front(); + feedIds.pop_front(); + + std::map::iterator feedIt1; + for (feedIt1 = mFeeds.begin(); feedIt1 != mFeeds.end(); ) { + RsFeedReaderFeed *fi1 = feedIt1->second; + + if (fi1->parentId == parentId) { + removedFeedIds.push_back(fi1->feedId); + + std::map::iterator tempIt = feedIt1; + ++feedIt1; + mFeeds.erase(tempIt); + + if (fi1->flag & RS_FEED_FLAG_FOLDER) { + feedIds.push_back(fi->feedId); + } + + deleteAllMsgs_locked(fi1); + delete(fi1); + + continue; + } + ++feedIt1; + } + } + } + + deleteAllMsgs_locked(fi); + delete(fi); + } + + if (changed) { + IndicateConfigChanged(); + } + + if (preview) { + RsStackMutex stack(mPreviewMutex); /******* LOCK STACK MUTEX *********/ + + /* only check download thread */ + if (mPreviewDownloadThread && mPreviewDownloadThread->getFeedId() == feedId) { + stopPreviewThreads_locked(); + } + } + + if (mNotify) { + /* only notify remove of feed */ + std::list::iterator it; + for (it = removedFeedIds.begin(); it != removedFeedIds.end(); ++it) { + mNotify->feedChanged(*it, NOTIFY_TYPE_DEL); + } + } + + return true; +} + +bool p3FeedReader::addPreviewFeed(const FeedInfo &feedInfo, std::string &feedId) +{ + { + RsStackMutex stack(mPreviewMutex); /******* LOCK STACK MUTEX *********/ + + stopPreviewThreads_locked(); + } + + feedId.clear(); + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::addPreviewFeed - add feed " << feedInfo.name << ", url " << feedInfo.url << std::endl; +#endif + + RsFeedReaderFeed *fi = new RsFeedReaderFeed; + infoToFeed(feedInfo, fi, true); + rs_sprintf(fi->feedId, "preview%d", mNextPreviewFeedId--); + fi->preview = true; + + /* process feed */ + fi->workstate = RsFeedReaderFeed::WAITING_TO_DOWNLOAD; + fi->content.clear(); + + /* clear not needed members */ + fi->parentId.clear(); + fi->updateInterval = 0; + fi->lastUpdate = 0; + fi->forumId.clear(); + fi->storageTime = 0; + + mFeeds[fi->feedId] = fi; + + feedId = fi->feedId; + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_ADD); + } + + { + RsStackMutex stack(mPreviewMutex); /******* LOCK STACK MUTEX *********/ + + /* start download thread for preview */ + mPreviewDownloadThread = new p3FeedReaderThread(this, p3FeedReaderThread::DOWNLOAD, feedId); + mPreviewDownloadThread->start(); + + /* start process thread for preview */ + mPreviewProcessThread = new p3FeedReaderThread(this, p3FeedReaderThread::PROCESS, feedId); + mPreviewProcessThread->start(); + } + + return true; +} + +void p3FeedReader::getFeedList(const std::string &parentId, std::list &feedInfos) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt; + for (feedIt = mFeeds.begin(); feedIt != mFeeds.end(); ++feedIt) { + RsFeedReaderFeed *fi = feedIt->second; + + if (fi->preview) { + continue; + } + + if (fi->parentId == parentId) { + FeedInfo feedInfo; + feedToInfo(fi, feedInfo); + feedInfos.push_back(feedInfo); + } + } +} + +bool p3FeedReader::getFeedInfo(const std::string &feedId, FeedInfo &feedInfo) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedInfo - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + feedToInfo(feedIt->second, feedInfo); + + return true; +} + +bool p3FeedReader::getMsgInfo(const std::string &feedId, const std::string &msgId, FeedMsgInfo &msgInfo) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getMsgInfo - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + + std::map::iterator msgIt; + msgIt = fi->msgs.find(msgId); + if (msgIt == fi->msgs.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getMsgInfo - msg " << msgId << " not found" << std::endl; +#endif + return false; + } + + feedMsgToInfo(msgIt->second, msgInfo); + + return true; +} + +bool p3FeedReader::removeMsg(const std::string &feedId, const std::string &msgId) +{ + bool changed = false; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::removeMsg - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + changed = !fi->preview; + + std::map::iterator msgIt; + msgIt = fi->msgs.find(msgId); + if (msgIt == fi->msgs.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::removeMsg - msg " << msgId << " not found" << std::endl; +#endif + return false; + } + + msgIt->second->flag |= RS_FEEDMSG_FLAG_DELETED; + } + + if (changed) { + IndicateConfigChanged(); + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + mNotify->msgChanged(feedId, msgId, NOTIFY_TYPE_DEL); + } + + return true; +} + +bool p3FeedReader::removeMsgs(const std::string &feedId, const std::list &msgIds) +{ + std::list removedMsgs; + bool changed = false; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::removeMsgs - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + changed = !fi->preview; + + std::list::const_iterator idIt; + for (idIt = msgIds.begin(); idIt != msgIds.end(); ++idIt) { + std::map::iterator msgIt; + msgIt = fi->msgs.find(*idIt); + if (msgIt == fi->msgs.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::removeMsgs - msg " << *idIt << " not found" << std::endl; +#endif + continue; + } + + msgIt->second->flag |= RS_FEEDMSG_FLAG_DELETED; + + removedMsgs.push_back(*idIt); + } + } + + if (changed) { + IndicateConfigChanged(); + } + + if (mNotify && !removedMsgs.empty()) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + + std::list::iterator it; + for (it = removedMsgs.begin(); it != removedMsgs.end(); ++it) { + mNotify->msgChanged(feedId, *it, NOTIFY_TYPE_DEL); + } + } + + return true; +} + +bool p3FeedReader::getMessageCount(const std::string &feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount) +{ + if (msgCount) *msgCount = 0; + if (unreadCount) *unreadCount = 0; + if (newCount) *newCount = 0; + + if (!msgCount && !unreadCount && !newCount) { + return true; + } + + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getMessageCount - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + + std::map::iterator msgIt; + for (msgIt = fi->msgs.begin(); msgIt != fi->msgs.end(); ++msgIt) { + RsFeedReaderMsg *mi = msgIt->second; + + if (mi->flag & RS_FEEDMSG_FLAG_DELETED) { + continue; + } + + if (msgCount) ++(*msgCount); + if (newCount && (mi->flag & RS_FEEDMSG_FLAG_NEW)) ++(*newCount); + if (unreadCount && (mi->flag & RS_FEEDMSG_FLAG_READ) == 0) ++(*unreadCount); + } + + return true; +} + +bool p3FeedReader::getFeedMsgList(const std::string &feedId, std::list &msgInfos) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedMsgList - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + + std::map::iterator msgIt; + for (msgIt = fi->msgs.begin(); msgIt != fi->msgs.end(); ++msgIt) { + RsFeedReaderMsg *mi = msgIt->second; + + if (mi->flag & RS_FEEDMSG_FLAG_DELETED) { + continue; + } + + FeedMsgInfo msgInfo; + feedMsgToInfo(mi, msgInfo); + msgInfos.push_back(msgInfo); + } + + return true; +} + +bool p3FeedReader::getFeedMsgIdList(const std::string &feedId, std::list &msgIds) +{ + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedMsgList - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + + std::map::iterator msgIt; + for (msgIt = fi->msgs.begin(); msgIt != fi->msgs.end(); ++msgIt) { + RsFeedReaderMsg *mi = msgIt->second; + + if (mi->flag & RS_FEEDMSG_FLAG_DELETED) { + continue; + } + + msgIds.push_back(mi->msgId); + } + + return true; +} + +static bool canProcessFeed(RsFeedReaderFeed *fi) +{ + if (fi->preview) { + /* preview feed */ + return false; + } + + if (fi->flag & RS_FEED_FLAG_DEACTIVATED) { + /* deactivated */ + return false; + } + + if (fi->workstate != RsFeedReaderFeed::WAITING) { + /* should be working */ + return false; + } + + if (fi->flag & RS_FEED_FLAG_FOLDER) { + /* folder */ + return false; + } + + return true; +} + +bool p3FeedReader::processFeed(const std::string &feedId) +{ + std::list feedToDownload; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt; + + if (feedId.empty()) { + /* process all feeds */ + for (feedIt = mFeeds.begin(); feedIt != mFeeds.end(); ++feedIt) { + RsFeedReaderFeed *fi = feedIt->second; + + if (!canProcessFeed(fi)) { + continue; + } + + /* add to download list */ + feedToDownload.push_back(fi->feedId); + fi->workstate = RsFeedReaderFeed::WAITING_TO_DOWNLOAD; + fi->content.clear(); + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::processFeed - starting feed " << fi->feedId << " (" << fi->name << ")" << std::endl; +#endif + } + } else { + feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::processFeed - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + if (fi->flag & RS_FEED_FLAG_FOLDER) { + std::list feedIds; + feedIds.push_back(fi->feedId); + while (!feedIds.empty()) { + std::string parentId = feedIds.front(); + feedIds.pop_front(); + + std::map::iterator feedIt1; + for (feedIt1 = mFeeds.begin(); feedIt1 != mFeeds.end(); ++feedIt1) { + RsFeedReaderFeed *fi1 = feedIt1->second; + + if (fi1->parentId == parentId) { + if (fi1->flag & RS_FEED_FLAG_FOLDER) { + feedIds.push_back(fi1->feedId); + } else { + if (canProcessFeed(fi1)) { + fi1->workstate = RsFeedReaderFeed::WAITING_TO_DOWNLOAD; + fi1->content.clear(); + + feedToDownload.push_back(fi1->feedId); +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::processFeed - starting feed " << fi1->feedId << " (" << fi1->name << ")" << std::endl; +#endif + } + } + } + } + } + } else { + if (canProcessFeed(fi)) { + fi->workstate = RsFeedReaderFeed::WAITING_TO_DOWNLOAD; + fi->content.clear(); + + feedToDownload.push_back(fi->feedId); +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::processFeed - starting feed " << fi->feedId << " (" << fi->name << ")" << std::endl; +#endif + } + } + } + } + + std::list notifyIds; + std::list::iterator it; + + if (!feedToDownload.empty()) { + RsStackMutex stack(mDownloadMutex); /******* LOCK STACK MUTEX *********/ + + for (it = feedToDownload.begin(); it != feedToDownload.end(); ++it) { + if (std::find(mDownloadFeeds.begin(), mDownloadFeeds.end(), *it) == mDownloadFeeds.end()) { + mDownloadFeeds.push_back(*it); + notifyIds.push_back(*it); + } + } + } + + if (mNotify) { + for (it = notifyIds.begin(); it != notifyIds.end(); ++it) { + mNotify->feedChanged(*it, NOTIFY_TYPE_MOD); + } + } + + return true; +} + +bool p3FeedReader::setMessageRead(const std::string &feedId, const std::string &msgId, bool read) +{ + bool changed = false; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::map::iterator feedIt = mFeeds.find(feedId); + if (feedIt == mFeeds.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setMessageRead - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = feedIt->second; + + std::map::iterator msgIt; + msgIt = fi->msgs.find(msgId); + if (msgIt == fi->msgs.end()) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setMessageRead - msg " << msgId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderMsg *mi = msgIt->second; + uint32_t oldFlag = mi->flag; + mi->flag &= ~RS_FEEDMSG_FLAG_NEW; + if (read) { + /* remove flag new */ + mi->flag |= RS_FEEDMSG_FLAG_READ; + } else { + mi->flag &= ~RS_FEEDMSG_FLAG_READ; + } + + changed = (mi->flag != oldFlag); + } + + if (changed) { + IndicateConfigChanged(); + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + mNotify->msgChanged(feedId, msgId, NOTIFY_TYPE_MOD); + } + } + + return true; +} + +RsFeedReaderErrorState p3FeedReader::processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString) +{ + return p3FeedReaderThread::processXPath(xpathsToUse, xpathsToRemove, description, errorString); +} + +/***************************************************************************/ +/****************************** p3Service **********************************/ +/***************************************************************************/ + +int p3FeedReader::tick() +{ + /* clean feeds */ + cleanFeeds(); + + /* check feeds for update interval */ + time_t currentTime = time(NULL); + std::list feedToDownload; + std::map::iterator feedIt; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + for (feedIt = mFeeds.begin(); feedIt != mFeeds.end(); ++feedIt) { + RsFeedReaderFeed *fi = feedIt->second; + + if (!canProcessFeed(fi)) { + continue; + } + + uint32_t updateInterval; + if (fi->flag & RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL) { + updateInterval = mStandardUpdateInterval; + } else { + updateInterval = fi->updateInterval; + } + + if (updateInterval == 0) { + continue; + } + + if (fi->lastUpdate == 0 || fi->lastUpdate + (long) updateInterval <= currentTime) { + /* add to download list */ + feedToDownload.push_back(fi->feedId); + fi->workstate = RsFeedReaderFeed::WAITING_TO_DOWNLOAD; + fi->content.clear(); + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::tick - starting feed " << fi->feedId << " (" << fi->name << ")" << std::endl; +#endif + } + } + } + + std::list notifyIds; + std::list::iterator it; + + if (!feedToDownload.empty()) { + RsStackMutex stack(mDownloadMutex); /******* LOCK STACK MUTEX *********/ + + for (it = feedToDownload.begin(); it != feedToDownload.end(); ++it) { + if (std::find(mDownloadFeeds.begin(), mDownloadFeeds.end(), *it) == mDownloadFeeds.end()) { + mDownloadFeeds.push_back(*it); + notifyIds.push_back(*it); + } + } + } + + if (mNotify) { + for (it = notifyIds.begin(); it != notifyIds.end(); ++it) { + mNotify->feedChanged(*it, NOTIFY_TYPE_MOD); + } + } + + return 0; +} + +void p3FeedReader::cleanFeeds() +{ + time_t currentTime = time(NULL); + + if (mLastClean == 0 || mLastClean + FEEDREADER_CLEAN_INTERVAL <= currentTime) { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + std::list > removedMsgIds; + std::map::iterator feedIt; + for (feedIt = mFeeds.begin(); feedIt != mFeeds.end(); ++feedIt) { + RsFeedReaderFeed *fi = feedIt->second; + + uint32_t storageTime = 0; + if (fi->flag & RS_FEED_FLAG_STANDARD_STORAGE_TIME) { + storageTime = mStandardStorageTime; + } else { + storageTime = fi->storageTime; + } + if (storageTime > 0) { + uint32_t removedMsgs = 0; + + std::map::iterator msgIt; + for (msgIt = fi->msgs.begin(); msgIt != fi->msgs.end(); ) { + RsFeedReaderMsg *mi = msgIt->second; + + if (mi->flag & RS_FEEDMSG_FLAG_DELETED) { + if (mi->pubDate < currentTime - (long) storageTime) { + removedMsgIds.push_back(std::pair (fi->feedId, mi->msgId)); + delete(mi); + std::map::iterator deleteIt = msgIt++; + fi->msgs.erase(deleteIt); + ++removedMsgs; + continue; + } + } + ++msgIt; + } +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::tick - feed " << fi->feedId << " (" << fi->name << ") cleaned, " << removedMsgs << " messages removed" << std::endl; +#endif + } + } + mLastClean = currentTime; + + if (removedMsgIds.size()) { + IndicateConfigChanged(); + + std::list >::iterator it; + for (it = removedMsgIds.begin(); it != removedMsgIds.end(); ++it) { + mNotify->msgChanged(it->first, it->second, NOTIFY_TYPE_DEL); + } + } + } +} + +/***************************************************************************/ +/****************************** p3Config ***********************************/ +/***************************************************************************/ + +RsSerialiser *p3FeedReader::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsFeedReaderSerialiser()); + rss->addSerialType(new RsGeneralConfigSerialiser()); + + return rss; +} + +bool p3FeedReader::saveList(bool &cleanup, std::list & saveData) +{ + mFeedReaderMtx.lock(); /*********************** LOCK *******/ + + cleanup = false; + + RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); + + RsTlvKeyValue kv; + kv.key = "StandardStorageTime"; + rs_sprintf(kv.value, "%u", mStandardStorageTime); + rskv->tlvkvs.pairs.push_back(kv); + + kv.key = "StandardUpdateInterval"; + rs_sprintf(kv.value, "%u", mStandardUpdateInterval); + rskv->tlvkvs.pairs.push_back(kv); + + kv.key = "StandardUseProxy"; + rs_sprintf(kv.value, "%hu", mStandardUseProxy ? 1 : 0); + rskv->tlvkvs.pairs.push_back(kv); + + kv.key = "StandardProxyAddress"; + rs_sprintf(kv.value, "%s", mStandardProxyAddress.c_str()); + rskv->tlvkvs.pairs.push_back(kv); + + kv.key = "StandardProxyPort"; + rs_sprintf(kv.value, "%hu", mStandardProxyPort); + rskv->tlvkvs.pairs.push_back(kv); + + /* Add KeyValue to saveList */ + saveData.push_back(rskv); + + std::map::iterator it1; + for (it1 = mFeeds.begin(); it1 != mFeeds.end(); ++it1) { + RsFeedReaderFeed *fi = it1->second; + if (fi->preview) { + continue; + } + saveData.push_back(fi); + + std::map::iterator it2; + for (it2 = fi->msgs.begin(); it2 != fi->msgs.end(); ++it2) { + saveData.push_back(it2->second); + } + } + + /* list completed! */ + return true; +} + +void p3FeedReader::saveDone() +{ + mFeedReaderMtx.unlock(); /*********************** UNLOCK *******/ + return; +} + +bool p3FeedReader::loadList(std::list& load) +{ + std::list::iterator it; + RsFeedReaderFeed *fi; + RsFeedReaderMsg *mi; + RsConfigKeyValueSet *rskv; + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::loadList() Item Count: " << load.size(); + std::cerr << std::endl; +#endif + + mNextFeedId = 1; + mNextMsgId = 1; + + std::map msgs; + + for (it = load.begin(); it != load.end(); ++it) { + /* switch on type */ + if (NULL != (fi = dynamic_cast(*it))) { + uint32_t feedId = 0; + if (sscanf(fi->feedId.c_str(), "%u", &feedId) == 1) { + RsStackMutex stack(mFeedReaderMtx); /********** STACK LOCKED MTX ******/ + if (mFeeds.find(fi->feedId) != mFeeds.end()) { + /* feed with the same id exists */ + delete mFeeds[fi->feedId]; + } + mFeeds[fi->feedId] = fi; + + if (feedId + 1 > mNextFeedId) { + mNextFeedId = feedId + 1; + } + } else { + /* invalid feed id */ + delete(*it); + } + } else if (NULL != (mi = dynamic_cast(*it))) { + if (msgs.find(mi->msgId) != msgs.end()) { + delete msgs[mi->msgId]; + } + msgs[mi->msgId] = mi; + } else if (NULL != (rskv = dynamic_cast(*it))) { + std::list::iterator kit; + for(kit = rskv->tlvkvs.pairs.begin(); kit != rskv->tlvkvs.pairs.end(); kit++) { + if (kit->key == "StandardStorageTime") { + uint32_t value; + if (sscanf(kit->value.c_str(), "%u", &value) == 1) { + mStandardStorageTime = value; + } + } else if (kit->key == "StandardUpdateInterval") { + uint32_t value; + if (sscanf(kit->value.c_str(), "%u", &value) == 1) { + mStandardUpdateInterval = value; + } + } else if (kit->key == "StandardUseProxy") { + uint16_t value; + if (sscanf(kit->value.c_str(), "%hu", &value) == 1) { + mStandardUseProxy = value == 1 ? true : false; + } + } else if (kit->key == "StandardProxyAddress") { + mStandardProxyAddress = kit->value; + } else if (kit->key == "StandardProxyPort") { + uint16_t value; + if (sscanf(kit->value.c_str(), "%hu", &value) == 1) { + mStandardProxyPort = value; + } + } + } + } else { + /* cleanup */ + delete(*it); + } + } + + /* now sort msgs into feeds */ + RsStackMutex stack(mFeedReaderMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it1; + for (it1 = msgs.begin(); it1 != msgs.end(); ++it1) { + uint32_t msgId = 0; + if (sscanf(it1->first.c_str(), "%u", &msgId) == 1) { + std::map::iterator it2 = mFeeds.find(it1->second->feedId); + if (it2 == mFeeds.end()) { + /* feed does not exist exists */ + delete it1->second; + continue; + } + it2->second->msgs[it1->first] = it1->second; + if (msgId + 1 > mNextMsgId) { + mNextMsgId = msgId + 1; + } + } else { + /* invalid msg id */ + delete(it1->second); + } + } + + return true; +} + +/***************************************************************************/ +/****************************** internal ***********************************/ +/***************************************************************************/ + +bool p3FeedReader::getFeedToDownload(RsFeedReaderFeed &feed, const std::string &neededFeedId) +{ + std::string feedId = neededFeedId; + + if (feedId.empty()) { + RsStackMutex stack(mDownloadMutex); /******* LOCK STACK MUTEX *********/ + + if (mDownloadFeeds.empty()) { + /* nothing to download */ + return false; + } + + /* get next feed id to download */ + feedId = mDownloadFeeds.front(); + mDownloadFeeds.pop_front(); + } + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedToDownload - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + /* check state */ + if (it->second->workstate != RsFeedReaderFeed::WAITING_TO_DOWNLOAD) { + std::cerr << "p3FeedReader::getFeedToDownload - feed in wrong work state for download " << it->second->workstate << std::endl; + return false; + } + + /* set state to downloading */ + it->second->workstate = RsFeedReaderFeed::DOWNLOADING; + + /* return a copy of the feed */ + feed = *(it->second); + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedToDownload - feed " << it->second->feedId << " (" << it->second->name << ") is starting to download" << std::endl; +#endif + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } + + return true; +} + +void p3FeedReader::onDownloadSuccess(const std::string &feedId, const std::string &content, std::string &icon) +{ + bool preview; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onDownloadSuccess - feed " << feedId << " not found" << std::endl; +#endif + return; + } + + RsFeedReaderFeed *fi = it->second; + fi->workstate = RsFeedReaderFeed::WAITING_TO_PROCESS; + fi->content = content; + preview = fi->preview; + + if (fi->icon != icon) { + fi->icon = icon; + + if (!preview) { + IndicateConfigChanged(); + } + } + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onDownloadSuccess - feed " << fi->feedId << " (" << fi->name << ") add to process" << std::endl; +#endif + } + + if (!preview) { + RsStackMutex stack(mProcessMutex); /******* LOCK STACK MUTEX *********/ + + if (std::find(mProcessFeeds.begin(), mProcessFeeds.end(), feedId) == mProcessFeeds.end()) { + mProcessFeeds.push_back(feedId); + } + + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } +} + +void p3FeedReader::onDownloadError(const std::string &feedId, RsFeedReaderErrorState result, const std::string &errorString) +{ + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onDownloadError - feed " << feedId << " not found" << std::endl; +#endif + return; + } + + RsFeedReaderFeed *fi = it->second; + fi->workstate = RsFeedReaderFeed::WAITING; + fi->lastUpdate = time(NULL); + fi->content.clear(); + + fi->errorState = result; + fi->errorString = errorString; + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onDownloadError - feed " << fi->feedId << " (" << fi->name << ") error download, result = " << result << ", errorState = " << fi->errorState << ", error = " << errorString << std::endl; +#endif + + if (!fi->preview) { + IndicateConfigChanged(); + } + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } +} + +bool p3FeedReader::getFeedToProcess(RsFeedReaderFeed &feed, const std::string &neededFeedId) +{ + std::string feedId = neededFeedId; + + if (feedId.empty()) { + RsStackMutex stack(mProcessMutex); /******* LOCK STACK MUTEX *********/ + + if (mProcessFeeds.empty()) { + /* nothing to process */ + return false; + } + + /* get next feed id to process */ + feedId = mProcessFeeds.front(); + mProcessFeeds.pop_front(); + } + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedToProcess - feed " << feedId << " not found" << std::endl; +#endif + return false; + } + + RsFeedReaderFeed *fi = it->second; + + if (fi->workstate != RsFeedReaderFeed::WAITING_TO_PROCESS) { + std::cerr << "p3FeedReader::getFeedToProcess - feed in wrong state for process " << fi->workstate << std::endl; + return false; + } + + /* set state to processing */ + fi->workstate = RsFeedReaderFeed::PROCESSING; + fi->errorState = RS_FEED_ERRORSTATE_OK; + fi->errorString.clear(); + + /* return a copy of the feed */ + feed = *fi; + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::getFeedToProcess - feed " << fi->feedId << " (" << fi->name << ") is starting to process" << std::endl; +#endif + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } + + return true; +} + +void p3FeedReader::onProcessSuccess_filterMsg(const std::string &feedId, std::list &msgs) +{ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_filterMsg - feed " << feedId << " got " << msgs.size() << " messages" << std::endl; +#endif + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_filterMsg - feed " << feedId << " not found" << std::endl; +#endif + return; + } + + RsFeedReaderFeed *fi = it->second; + + std::list::iterator newMsgIt; + for (newMsgIt = msgs.begin(); newMsgIt != msgs.end(); ) { + RsFeedReaderMsg *miNew = *newMsgIt; + /* search for existing msg */ + std::map::iterator msgIt; + for (msgIt = fi->msgs.begin(); msgIt != fi->msgs.end(); ++msgIt) { + RsFeedReaderMsg *mi = msgIt->second; + if (mi->title == miNew->title && mi->link == miNew->link && mi->author == miNew->author) { + /* msg exist */ + break; + } + } + if (msgIt != fi->msgs.end()) { + /* msg exists */ + delete(miNew); + newMsgIt = msgs.erase(newMsgIt); + } else { + ++newMsgIt; + } + } + + fi->content.clear(); + fi->errorString.clear(); + + if (!fi->preview) { + IndicateConfigChanged(); + } + } +} + +void p3FeedReader::onProcessSuccess_addMsgs(const std::string &feedId, std::list &msgs, bool single) +{ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - feed " << feedId << " got " << msgs.size() << " messages" << std::endl; +#endif + + std::list addedMsgs; + std::string forumId; + std::list forumMsgs; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - feed " << feedId << " not found" << std::endl; +#endif + return; + } + + RsFeedReaderFeed *fi = it->second; + bool forum = (fi->flag & RS_FEED_FLAG_FORUM) && !fi->preview; + RsFeedReaderErrorState errorState = RS_FEED_ERRORSTATE_OK; + + if (forum && !msgs.empty()) { + if (fi->forumId.empty()) { + /* create new forum */ + std::wstring forumName; + librs::util::ConvertUtf8ToUtf16(fi->name, forumName); + forumName.insert(0, FEEDREADER_FORUM_PREFIX); + + long todo; // search for existing forum? + + /* search for existing own forum */ +// std::list forumList; +// if (rsForums->getForumList(forumList)) { +// std::wstring wName = StringToWString(name); +// for (std::list::iterator it = forumList.begin(); it != forumList.end(); ++it) { +// if (it->forumName == wName) { +// std::cout << "DEBUG_RSS2FORUM: Found existing forum " << it->forumId << " for " << name << std::endl; +// return it->forumId; +// } +// } +// } + + std::wstring forumDescription; + librs::util::ConvertUtf8ToUtf16(fi->description, forumDescription); + /* create anonymous public forum */ + fi->forumId = rsForums->createForum(forumName, forumDescription, RS_DISTRIB_PUBLIC | RS_DISTRIB_AUTHEN_ANON); + forumId = fi->forumId; + + if (fi->forumId.empty()) { + errorState = RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE; + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_filterMsg - can't create forum for feed " << feedId << " (" << fi->name << ") - ignore all messages" << std::endl; + } else { + std::cerr << "p3FeedReader::onProcessSuccess_filterMsg - forum " << fi->forumId << " (" << fi->name << ") created" << std::endl; +#endif + } + } else { + /* check forum */ + ForumInfo forumInfo; + if (rsForums->getForumInfo(fi->forumId, forumInfo)) { + if ((forumInfo.subscribeFlags & RS_DISTRIB_ADMIN) == 0) { + errorState = RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_ADMIN; + } else if ((forumInfo.forumFlags & RS_DISTRIB_AUTHEN_REQ) || (forumInfo.forumFlags & RS_DISTRIB_AUTHEN_ANON) == 0) { + errorState = RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_ANONYMOUS; + } else { + forumId = fi->forumId; + } + } else { + errorState = RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND; + } + } + } + + /* process msgs */ + if (errorState == RS_FEED_ERRORSTATE_OK) { + /* process msgs */ +#ifdef FEEDREADER_DEBUG + uint32_t newMsgs = 0; +#endif + + std::list::iterator newMsgIt; + for (newMsgIt = msgs.begin(); newMsgIt != msgs.end(); ) { + RsFeedReaderMsg *miNew = *newMsgIt; + /* add new msg */ + if (fi->preview) { + rs_sprintf(miNew->msgId, "preview%d", mNextPreviewMsgId--); + } else { + rs_sprintf(miNew->msgId, "%lu", mNextMsgId++); + } + if (forum) { + miNew->flag = RS_FEEDMSG_FLAG_DELETED; + forumMsgs.push_back(*miNew); +// miNew->description.clear(); + } else { + miNew->flag = RS_FEEDMSG_FLAG_NEW; + addedMsgs.push_back(miNew->msgId); + } + fi->msgs[miNew->msgId] = miNew; + newMsgIt = msgs.erase(newMsgIt); + +#ifdef FEEDREADER_DEBUG + ++newMsgs; +#endif + } +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_addMsgs - feed " << fi->feedId << " (" << fi->name << ") added " << newMsgs << "/" << msgs.size() << " messages" << std::endl; +#endif + } + + if (!single) { + fi->workstate = RsFeedReaderFeed::WAITING; + fi->content.clear(); + fi->errorState = errorState; + fi->lastUpdate = time(NULL); + } + + if (!fi->preview) { + IndicateConfigChanged(); + } + } + + if (!forumId.empty() && !forumMsgs.empty()) { + /* add messages as forum messages */ + std::list::iterator msgIt; + for (msgIt = forumMsgs.begin(); msgIt != forumMsgs.end(); ++msgIt) { + RsFeedReaderMsg &mi = *msgIt; + + /* convert to forum messages */ + ForumMsgInfo forumMsgInfo; + forumMsgInfo.forumId = forumId; + librs::util::ConvertUtf8ToUtf16(mi.title, forumMsgInfo.title); + + std::string description = mi.description; + /* add link */ + if (!mi.link.empty()) { + description += "
" + mi.link + ""; + } + librs::util::ConvertUtf8ToUtf16(description, forumMsgInfo.msg); + + if (rsForums->ForumMessageSend(forumMsgInfo)) { + /* set to new */ + rsForums->setMessageStatus(forumMsgInfo.forumId, forumMsgInfo.msgId, 0, FORUM_MSG_STATUS_MASK); + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessSuccess_filterMsg - can't add forum message " << mi.title << " for feed " << forumId << std::endl; +#endif + } + } + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + + std::list::iterator it; + for (it = addedMsgs.begin(); it != addedMsgs.end(); ++it) { + mNotify->msgChanged(feedId, *it, NOTIFY_TYPE_ADD); + } + } +} + +void p3FeedReader::onProcessError(const std::string &feedId, RsFeedReaderErrorState result, const std::string &errorString) +{ + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessError - feed " << feedId << " not found" << std::endl; +#endif + return; + } + + RsFeedReaderFeed *fi = it->second; + fi->workstate = RsFeedReaderFeed::WAITING; + fi->lastUpdate = time(NULL); + fi->content.clear(); + + fi->errorState = result; + fi->errorString = errorString; + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::onProcessError - feed " << fi->feedId << " (" << fi->name << ") error process, result = " << result << ", errorState = " << fi->errorState << std::endl; +#endif + + if (!fi->preview) { + IndicateConfigChanged(); + } + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } +} + +void p3FeedReader::setFeedInfo(const std::string &feedId, const std::string &name, const std::string &description) +{ + bool changed = false; + bool preview; + std::string forumId; + ForumInfo forumInfoNew; + + { + RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/ + + /* find feed */ + std::map::iterator it = mFeeds.find(feedId); + if (it == mFeeds.end()) { + /* feed not found */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeedInfo - feed " << feedId << " not found" << std::endl; +#endif + return; + } + + RsFeedReaderFeed *fi = it->second; + preview = fi->preview; + if (fi->name != name) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeedInfo - feed " << fi->feedId << " changed name from " << fi->name << " to " << name << std::endl; +#endif + fi->name = name; + changed = true; + } + if (fi->description != description) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeedInfo - feed " << fi->feedId << " changed description from " << fi->description << " to " << description << std::endl; +#endif + fi->description = description; + changed = true; + } + + if ((fi->flag & RS_FEED_FLAG_FORUM) && (fi->flag & RS_FEED_FLAG_UPDATE_FORUM_INFO) && !fi->forumId.empty() && !preview) { + /* change forum too */ + forumId = fi->forumId; + librs::util::ConvertUtf8ToUtf16(fi->name, forumInfoNew.forumName); + librs::util::ConvertUtf8ToUtf16(fi->description, forumInfoNew.forumDesc); + forumInfoNew.forumName.insert(0, FEEDREADER_FORUM_PREFIX); + } + } + + if (changed) { + if (!preview) { + IndicateConfigChanged(); + } + + if (mNotify) { + mNotify->feedChanged(feedId, NOTIFY_TYPE_MOD); + } + } + + if (!forumId.empty()) { + ForumInfo forumInfo; + if (rsForums->getForumInfo(forumId, forumInfo)) { + if (forumInfo.forumName != forumInfoNew.forumName || forumInfo.forumDesc != forumInfoNew.forumDesc) { + /* name or description changed, update forum */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - change forum " << forumId << std::endl; +#endif + if (!rsForums->setForumInfo(forumId, forumInfoNew)) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - can't change forum " << forumId << std::endl; +#endif + } + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReader::setFeed - can't get forum info " << forumId << std::endl; +#endif + } + } +} diff --git a/plugins/FeedReader/services/p3FeedReader.h b/plugins/FeedReader/services/p3FeedReader.h new file mode 100644 index 000000000..34901620e --- /dev/null +++ b/plugins/FeedReader/services/p3FeedReader.h @@ -0,0 +1,122 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef P3_FEEDREADER +#define P3_FEEDREADER + +#include "retroshare/rsplugin.h" +#include "plugins/rspqiservice.h" +#include "interface/rsFeedReader.h" + +class RsFeedReaderFeed; +class RsFeedReaderMsg; +class p3FeedReaderThread; + +class p3FeedReader : public RsPQIService, public RsFeedReader +{ +public: + p3FeedReader(RsPluginHandler *pgHandler); + + /****************** FeedReader Interface *************/ + virtual void stop(); + virtual void setNotify(RsFeedReaderNotify *notify); + + virtual uint32_t getStandardStorageTime(); + virtual void setStandardStorageTime(uint32_t storageTime); + virtual uint32_t getStandardUpdateInterval(); + virtual void setStandardUpdateInterval(uint32_t updateInterval); + virtual bool getStandardProxy(std::string &proxyAddress, uint16_t &proxyPort); + virtual void setStandardProxy(bool useProxy, const std::string &proxyAddress, uint16_t proxyPort); + + virtual RsFeedAddResult addFolder(const std::string parentId, const std::string &name, std::string &feedId); + virtual RsFeedAddResult setFolder(const std::string &feedId, const std::string &name); + virtual RsFeedAddResult addFeed(const FeedInfo &feedInfo, std::string &feedId); + virtual RsFeedAddResult setFeed(const std::string &feedId, const FeedInfo &feedInfo); + virtual bool removeFeed(const std::string &feedId); + virtual bool addPreviewFeed(const FeedInfo &feedInfo, std::string &feedId); + virtual void getFeedList(const std::string &parentId, std::list &feedInfos); + virtual bool getFeedInfo(const std::string &feedId, FeedInfo &feedInfo); + virtual bool getMsgInfo(const std::string &feedId, const std::string &msgId, FeedMsgInfo &msgInfo); + virtual bool removeMsg(const std::string &feedId, const std::string &msgId); + virtual bool removeMsgs(const std::string &feedId, const std::list &msgIds); + virtual bool getMessageCount(const std::string &feedId, uint32_t *msgCount, uint32_t *newCount, uint32_t *unreadCount); + virtual bool getFeedMsgList(const std::string &feedId, std::list &msgInfos); + virtual bool getFeedMsgIdList(const std::string &feedId, std::list &msgIds); + virtual bool processFeed(const std::string &feedId); + virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read); + + virtual RsFeedReaderErrorState processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString); + + /****************** p3Service STUFF ******************/ + virtual int tick(); + + /****************** internal STUFF *******************/ + bool getFeedToDownload(RsFeedReaderFeed &feed, const std::string &neededFeedId); + void onDownloadSuccess(const std::string &feedId, const std::string &content, std::string &icon); + void onDownloadError(const std::string &feedId, RsFeedReaderErrorState result, const std::string &errorString); + void onProcessSuccess_filterMsg(const std::string &feedId, std::list &msgs); + void onProcessSuccess_addMsgs(const std::string &feedId, std::list &msgs, bool single); + void onProcessError(const std::string &feedId, RsFeedReaderErrorState result, const std::string &errorString); + + bool getFeedToProcess(RsFeedReaderFeed &feed, const std::string &neededFeedId); + + void setFeedInfo(const std::string &feedId, const std::string &name, const std::string &description); + +protected: + /****************** p3Config STUFF *******************/ + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list&); + virtual bool loadList(std::list& load); + virtual void saveDone(); + +private: + void cleanFeeds(); + void deleteAllMsgs_locked(RsFeedReaderFeed *fi); + void stopPreviewThreads_locked(); + + time_t mLastClean; + RsFeedReaderNotify *mNotify; + + RsMutex mFeedReaderMtx; + std::list mThreads; + uint32_t mNextFeedId; + uint32_t mNextMsgId; + int32_t mNextPreviewFeedId; + int32_t mNextPreviewMsgId; + uint32_t mStandardUpdateInterval; + uint32_t mStandardStorageTime; + bool mStandardUseProxy; + std::string mStandardProxyAddress; + uint16_t mStandardProxyPort; + std::map mFeeds; + + RsMutex mDownloadMutex; + std::list mDownloadFeeds; + + RsMutex mProcessMutex; + std::list mProcessFeeds; + + RsMutex mPreviewMutex; + p3FeedReaderThread *mPreviewDownloadThread; + p3FeedReaderThread *mPreviewProcessThread; +}; + +#endif diff --git a/plugins/FeedReader/services/p3FeedReaderThread.cc b/plugins/FeedReader/services/p3FeedReaderThread.cc new file mode 100644 index 000000000..764491ea1 --- /dev/null +++ b/plugins/FeedReader/services/p3FeedReaderThread.cc @@ -0,0 +1,1360 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "p3FeedReaderThread.h" +#include "rsFeedReaderItems.h" +#include "util/rsstring.h" +#include "util/CURLWrapper.h" +#include "util/XMLWrapper.h" +#include "util/HTMLWrapper.h" +#include "util/XPathWrapper.h" + +#include + +enum FeedFormat { FORMAT_RSS, FORMAT_RDF }; + +/********* + * #define FEEDREADER_DEBUG + *********/ +#define FEEDREADER_DEBUG + +p3FeedReaderThread::p3FeedReaderThread(p3FeedReader *feedReader, Type type, const std::string &feedId) : + RsThread(), mFeedReader(feedReader), mType(type), mFeedId(feedId) +{ +} + +p3FeedReaderThread::~p3FeedReaderThread() +{ +} + +/***************************************************************************/ +/****************************** Thread *************************************/ +/***************************************************************************/ + +void p3FeedReaderThread::run() +{ + while (isRunning()) { +#ifdef WIN32 + Sleep(1000); +#else + usleep(1000000); +#endif + /* every second */ + + switch (mType) { + case DOWNLOAD: + { + RsFeedReaderFeed feed; + if (mFeedReader->getFeedToDownload(feed, mFeedId)) { + std::string content; + std::string icon; + std::string errorString; + + RsFeedReaderErrorState result = download(feed, content, icon, errorString); + if (result == RS_FEED_ERRORSTATE_OK) { + mFeedReader->onDownloadSuccess(feed.feedId, content, icon); + } else { + mFeedReader->onDownloadError(feed.feedId, result, errorString); + } + } + } + break; + case PROCESS: + { + RsFeedReaderFeed feed; + if (mFeedReader->getFeedToProcess(feed, mFeedId)) { + std::list msgs; + std::string errorString; + std::list::iterator it; + + RsFeedReaderErrorState result = process(feed, msgs, errorString); + if (result == RS_FEED_ERRORSTATE_OK) { + /* first, filter the messages */ + mFeedReader->onProcessSuccess_filterMsg(feed.feedId, msgs); + if (isRunning()) { + /* second, process the descriptions */ + for (it = msgs.begin(); it != msgs.end(); ) { + RsFeedReaderMsg *mi = *it; + result = processMsg(feed, mi, errorString); + if (result != RS_FEED_ERRORSTATE_OK) { + break; + } + + if (feed.preview) { + /* add every message */ + it = msgs.erase(it); + + std::list msgSingle; + msgSingle.push_back(mi); + mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgSingle, true); + + /* delete not accepted message */ + std::list::iterator it1; + for (it1 = msgSingle.begin(); it1 != msgSingle.end(); ++it1) { + delete (*it1); + } + } else { + ++it; + } + } + if (result == RS_FEED_ERRORSTATE_OK) { + /* third, add messages */ + mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgs, false); + } else { + mFeedReader->onProcessError(feed.feedId, result, errorString); + } + } + } else { + mFeedReader->onProcessError(feed.feedId, result, errorString); + } + + /* delete not accepted messages */ + for (it = msgs.begin(); it != msgs.end(); ++it) { + delete (*it); + } + msgs.clear(); + } + } + break; + } + } +} + +/***************************************************************************/ +/****************************** Download ***********************************/ +/***************************************************************************/ + +static bool isContentType(const std::string &contentType, const char *type) +{ + return (strncasecmp(contentType.c_str(), type, strlen(type)) == 0); +} + +static bool toBase64(const std::vector &data, std::string &base64) +{ + bool result = false; + + /* Set up a base64 encoding BIO that writes to a memory BIO */ + BIO *b64 = BIO_new(BIO_f_base64()); + if (b64) { + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + BIO *bmem = BIO_new(BIO_s_mem()); + if (bmem) { + BIO_set_flags(bmem, BIO_CLOSE); // probably redundant + b64 = BIO_push(b64, bmem); + /* Send the data */ + BIO_write(b64, data.data(), data.size()); + /* Collect the encoded data */ + BIO_flush(b64); + char* temp; + int count = BIO_get_mem_data(bmem, &temp); + if (count && temp) { + base64.assign(temp, count); + result = true; + } + } + BIO_free_all(b64); + } + + return result; +} + +static std::string getBaseLink(std::string link) +{ + size_t found = link.rfind('/'); + if (found != std::string::npos) { + link.erase(found + 1); + } + + return link; +} + +static std::string calculateLink(const std::string &baseLink, const std::string &link) +{ + if (link.substr(0, 7) == "http://") { + /* absolute link */ + return link; + } + + /* calculate link of base link */ + std::string resultLink = baseLink; + + /* link should begin with "http://" */ + if (resultLink.substr(0, 7) != "http://") { + resultLink.insert(0, "http://"); + } + + if (link.empty()) { + /* no link */ + return resultLink; + } + + if (*link.begin() == '/') { + /* link begins with "/" */ + size_t found = resultLink.find('/', 7); + if (found != std::string::npos) { + resultLink.erase(found); + } + } else { + /* check for "/" at the end */ + std::string::reverse_iterator it = resultLink.rend (); + it--; + if (*it != '/') { + resultLink += "/"; + } + } + + resultLink += link; + + return resultLink; +} + +static bool getFavicon(CURLWrapper &CURL, const std::string &url, std::string &icon) +{ + icon.clear(); + + bool result = false; + + std::vector vicon; + CURLcode code = CURL.downloadBinary(calculateLink(url, "/favicon.ico"), vicon); + if (code == CURLE_OK) { + if (CURL.responseCode() == 200) { + std::string contentType = CURL.contentType(); + if (isContentType(contentType, "image/x-icon") || + isContentType(contentType, "application/octet-stream") || + isContentType(contentType, "text/plain")) { + if (!vicon.empty()) { + long todo; // check it + result = toBase64(vicon, icon); + } + } + } + } + + return result; +} + +RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &error) +{ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << ")" << std::endl; +#endif + + content.clear(); + error.clear(); + + RsFeedReaderErrorState result; + + std::string proxy = getProxyForFeed(feed); + CURLWrapper CURL(proxy); + CURLcode code = CURL.downloadText(feed.url, content); + + if (code == CURLE_OK) { + long responseCode = CURL.responseCode(); + + switch (responseCode) { + case 200: + { + std::string contentType = CURL.contentType(); + + if (isContentType(contentType, "text/xml") || + isContentType(contentType, "application/rss+xml") || + isContentType(contentType, "application/xml") || + isContentType(contentType, "application/xhtml+xml")) { + /* ok */ + result = RS_FEED_ERRORSTATE_OK; + } else { + result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE; + error = contentType; + } + } + break; + case 404: + result = RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND; + break; + default: + result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE; + rs_sprintf(error, "%ld", responseCode); + } + + getFavicon(CURL, feed.url, icon); + } else { + result = RS_FEED_ERRORSTATE_DOWNLOAD_ERROR; + error = curl_easy_strerror(code); + } + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << error << std::endl; +#endif + + return result; +} + +/***************************************************************************/ +/****************************** Process ************************************/ +/***************************************************************************/ + +static xmlNodePtr getNextItem(FeedFormat feedFormat, xmlNodePtr channel, xmlNodePtr item) +{ + if (!channel) { + return NULL; + } + + if (!item) { + switch (feedFormat) { + case FORMAT_RSS: + item = channel->children; + break; + case FORMAT_RDF: + item = channel->next; + break; + default: + return NULL; + } + } else { + item = item->next; + } + for (; item; item = item->next) { + if (item->type == XML_ELEMENT_NODE && xmlStrEqual(item->name, BAD_CAST"item")) { + break; + } + } + + return item; +} + +static void splitString(std::string s, std::vector &v, const char d) +{ + v.clear(); + + std::string::size_type p; + while ((p = s.find_first_of(d)) != std::string::npos) { + v.push_back(s.substr(0, p)); + s.erase(0, p + 1); + } + if (!s.empty()) { + v.push_back(s); + } +} + +static unsigned int ymdhms_to_seconds(int year, int mon, int day, int hour, int minute, int second) +{ + if (sizeof(time_t) == 4) + { + if ((time_t)-1 < 0) + { + if (year >= 2038) + { + year = 2038; + mon = 0; + day = 1; + hour = 0; + minute = 0; + second = 0; + } + } + else + { + if (year >= 2115) + { + year = 2115; + mon = 0; + day = 1; + hour = 0; + minute = 0; + second = 0; + } + } + } + + unsigned int ret = (day - 32075) /* days */ + + 1461L * (year + 4800L + (mon - 14) / 12) / 4 + + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12 + - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4 + - 2440588; + ret = 24*ret + hour; /* hours */ + ret = 60*ret + minute; /* minutes */ + ret = 60*ret + second; /* seconds */ + + return ret; +} + +static const char haystack[37]="janfebmaraprmayjunjulaugsepoctnovdec"; + +// we follow the recommendation of rfc2822 to consider all +// obsolete time zones not listed here equivalent to "-0000" +static const struct { + const char tzName[4]; + int tzOffset; +} known_zones[] = { + { "UT", 0 }, + { "GMT", 0 }, + { "EST", -300 }, + { "EDT", -240 }, + { "CST", -360 }, + { "CDT", -300 }, + { "MST", -420 }, + { "MDT", -360 }, + { "PST", -480 }, + { "PDT", -420 }, + { { 0,0,0,0 }, 0 } +}; + +// copied from KRFCDate::parseDate +static time_t parseRFC822Date(const std::string &pubDate) +{ + if (pubDate.empty()) + return 0; + + // This parse a date in the form: + // Wednesday, 09-Nov-99 23:12:40 GMT + // or + // Sat, 01-Jan-2000 08:00:00 GMT + // or + // Sat, 01 Jan 2000 08:00:00 GMT + // or + // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822) + // + // We ignore the weekday + // + time_t result = 0; + int offset = 0; + char *newPosStr; + const char *dateString = pubDate.c_str(); + int day = 0; + char monthStr[4]; + int month = -1; + int year = 0; + int hour = 0; + int minute = 0; + int second = 0; + + // Strip leading space + while(*dateString && isspace(*dateString)) + dateString++; + + // Strip weekday + while(*dateString && !isdigit(*dateString) && !isspace(*dateString)) + dateString++; + + // Strip trailing space + while(*dateString && isspace(*dateString)) + dateString++; + + if (!*dateString) + return result; // Invalid date + + if (isalpha(*dateString)) + { + // ' Nov 5 1994 18:15:30 GMT' + // Strip leading space + while(*dateString && isspace(*dateString)) + dateString++; + + for(int i=0; i < 3;i++) + { + if (!*dateString || (*dateString == '-') || isspace(*dateString)) + return result; // Invalid date + monthStr[i] = tolower(*dateString++); + } + monthStr[3] = '\0'; + + newPosStr = (char*)strstr(haystack, monthStr); + + if (!newPosStr) + return result; // Invalid date + + month = (newPosStr-haystack)/3; // Jan=00, Feb=01, Mar=02, .. + + if ((month < 0) || (month > 11)) + return result; // Invalid date + + while (*dateString && isalpha(*dateString)) + dateString++; // Skip rest of month-name + } + + // ' 09-Nov-99 23:12:40 GMT' + // ' 5 1994 18:15:30 GMT' + day = strtol(dateString, &newPosStr, 10); + dateString = newPosStr; + + if ((day < 1) || (day > 31)) + return result; // Invalid date; + + if (!*dateString) + return result; // Invalid date + + while(*dateString && (isspace(*dateString) || (*dateString == '-'))) + dateString++; + + if (month == -1) + { + for(int i=0; i < 3;i++) + { + if (!*dateString || (*dateString == '-') || isspace(*dateString)) + return result; // Invalid date + monthStr[i] = tolower(*dateString++); + } + monthStr[3] = '\0'; + + newPosStr = (char*)strstr(haystack, monthStr); + + if (!newPosStr) + return result; // Invalid date + + month = (newPosStr-haystack)/3; // Jan=00, Feb=01, Mar=02, .. + + if ((month < 0) || (month > 11)) + return result; // Invalid date + + while (*dateString && isalpha(*dateString)) + dateString++; // Skip rest of month-name + + } + + // '-99 23:12:40 GMT' + while(*dateString && (isspace(*dateString) || (*dateString == '-'))) + dateString++; + + if (!*dateString || !isdigit(*dateString)) + return result; // Invalid date + + // '99 23:12:40 GMT' + year = strtol(dateString, &newPosStr, 10); + dateString = newPosStr; + + // Y2K: Solve 2 digit years + if ((year >= 0) && (year < 50)) + year += 2000; + + if ((year >= 50) && (year < 100)) + year += 1900; // Y2K + + if ((year < 1900) || (year > 2500)) + return result; // Invalid date + + // Don't fail if the time is missing. + if (*dateString) + { + // ' 23:12:40 GMT' + if (!isspace(*dateString++)) + return result; // Invalid date + + hour = strtol(dateString, &newPosStr, 10); + dateString = newPosStr; + + if ((hour < 0) || (hour > 23)) + return result; // Invalid date + + if (!*dateString) + return result; // Invalid date + + // ':12:40 GMT' + if (*dateString++ != ':') + return result; // Invalid date + + minute = strtol(dateString, &newPosStr, 10); + dateString = newPosStr; + + if ((minute < 0) || (minute > 59)) + return result; // Invalid date + + if (!*dateString) + return result; // Invalid date + + // ':40 GMT' + if (*dateString != ':' && !isspace(*dateString)) + return result; // Invalid date + + // seconds are optional in rfc822 + rfc2822 + if (*dateString ==':') { + dateString++; + + second = strtol(dateString, &newPosStr, 10); + dateString = newPosStr; + + if ((second < 0) || (second > 59)) + return result; // Invalid date + } else { + dateString++; + } + + while(*dateString && isspace(*dateString)) + dateString++; + } + + // don't fail if the time zone is missing, some + // broken mail-/news-clients omit the time zone + if (*dateString) { + if ((strncasecmp(dateString, "gmt", 3) == 0) || + (strncasecmp(dateString, "utc", 3) == 0)) + { + dateString += 3; + while(*dateString && isspace(*dateString)) + dateString++; + } + + if ((*dateString == '+') || (*dateString == '-')) { + offset = strtol(dateString, &newPosStr, 10); + if (abs(offset) < 30) + { + dateString = newPosStr; + + offset = offset * 100; + + if (*dateString && *(dateString+1)) + { + dateString++; + int minutes = strtol(dateString, &newPosStr, 10); + if (offset > 0) + offset += minutes; + else + offset -= minutes; + } + } + + if ((offset < -9959) || (offset > 9959)) + return result; // Invalid date + + int sgn = (offset < 0)? -1:1; + offset = abs(offset); + offset = ((offset / 100)*60 + (offset % 100))*sgn; + } else { + for (int i=0; known_zones[i].tzName != 0; i++) { + if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) { + offset = known_zones[i].tzOffset; + break; + } + } + } + } + + result = ymdhms_to_seconds(year, month+1, day, hour, minute, second); + + // avoid negative time values + if ((offset > 0) && (offset > result)) + offset = 0; + + result -= offset*60; + + // If epoch 0 return epoch +1 which is Thu, 01-Jan-70 00:00:01 GMT + // This is so that parse error and valid epoch 0 return values won't + // be the same for sensitive applications... + if (result < 1) result = 1; + + return result; +} + +// copied and converted to std::string from KRFCDate::parseDateISO8601 +static time_t parseISO8601Date(const std::string &pubDate) +{ + if (pubDate.empty()) { + return 0; + } + + // These dates look like this: + // YYYY-MM-DDTHH:MM:SS + // But they may also have 0, 1 or 2 suffixes. + // Suffix 1: .secfrac (fraction of second) + // Suffix 2: Either 'Z' or +zone or -zone, where zone is HHMM + + unsigned int year = 0; + unsigned int month = 0; + unsigned int mday = 0; + unsigned int hour = 0; + unsigned int min = 0; + unsigned int sec = 0; + + int offset = 0; + + std::string input = pubDate; + + // First find the 'T' separator, if any. + int tPos = input.find('T'); + + // If there is no time, no month or no day specified, fill those missing + // fields so that 'input' matches YYYY-MM-DDTHH:MM:SS + if (-1 == tPos) { + int dashes = 0; + std::string::iterator it; + for (it = input.begin(); it != input.end(); ++it) { + if (*it == '-') { + ++dashes; + } + } + if (0 == dashes) { + input += "-01-01"; + } else if (1 == dashes) { + input += "-01"; + } + tPos = input.length(); + input += "T12:00:00"; + } + + // Now parse the date part. + + std::string dateString = input.substr(0, tPos);//.stripWhiteSpace(); + + std::string timeString = input.substr(tPos + 1);//.stripWhiteSpace(); + + std::vector l; + splitString(dateString, l, '-'); + + if (l.size() < 3) + return 0; + + sscanf(l[0].c_str(), "%u", &year); + sscanf(l[1].c_str(), "%u", &month); + sscanf(l[2].c_str(), "%u", &mday); + + // Z suffix means UTC. + if ('Z' == timeString[timeString.length() - 1]) { + timeString.erase(timeString.length() - 1, 1); + } + + // +zone or -zone suffix (offset from UTC). + + int plusPos = timeString.find_last_of('+'); + + if (-1 != plusPos) { + std::string offsetString = timeString.substr(plusPos + 1); + + unsigned int offsetHour; + unsigned int offsetMinute; + + sscanf(offsetString.substr(0, 1).c_str(), "%u", &offsetHour); + sscanf(offsetString.substr(offsetString.length() - 2).c_str(), "%u", &offsetMinute); + + offset = offsetHour * 60 + offsetMinute; + + timeString = timeString.substr(0, plusPos); + } else { + int minusPos = timeString.find_last_of('-'); + + if (-1 != minusPos) { + std::string offsetString = timeString.substr(minusPos + 1); + + unsigned int offsetHour; + unsigned int offsetMinute; + + sscanf(offsetString.substr(0, 1).c_str(), "%u", &offsetHour); + sscanf(offsetString.substr(offsetString.length() - 2).c_str(), "%u", &offsetMinute); + + timeString = timeString.substr(0, minusPos); + } + } + + // secfrac suffix. + int dotPos = timeString.find_last_of('.'); + + if (-1 != dotPos) { + timeString = timeString.substr(0, dotPos); + } + + // Now parse the time part. + + splitString(timeString, l, ':'); + + if (l.size() < 3) + return 0; + + sscanf(l[0].c_str(), "%u", &hour); + sscanf(l[1].c_str(), "%u", &min); + sscanf(l[2].c_str(), "%u", &sec); + + time_t result = ymdhms_to_seconds(year, month, mday, hour, min, sec); + + // avoid negative time values + if ((offset > 0) && (offset > result)) + offset = 0; + + result -= offset*60; + + // If epoch 0 return epoch +1 which is Thu, 01-Jan-70 00:00:01 GMT + // This is so that parse error and valid epoch 0 return values won't + // be the same for sensitive applications... + if (result < 1) result = 1; + + return result; +} + +RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, std::list &entries, std::string &error) +{ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << ")" << std::endl; +#endif + + RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; + + XMLWrapper xml; + if (xml.readXML(feed.content.c_str())) { + xmlNodePtr root = xml.getRootElement(); + if (root) { + FeedFormat feedFormat; + if (xmlStrEqual(root->name, BAD_CAST"rss")) { + feedFormat = FORMAT_RSS; + } else if (xmlStrEqual (root->name, BAD_CAST"rdf")) { + feedFormat = FORMAT_RDF; + } else { + result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT; + error = "Only RSS or RDF supported"; + } + + if (result == RS_FEED_ERRORSTATE_OK) { + xmlNodePtr channel = xml.findNode(root->children, "channel"); + if (channel) { + /* import header info */ + if (feed.flag & RS_FEED_FLAG_INFO_FROM_FEED) { + std::string title; + if (xml.getChildText(channel, "title", title) && !title.empty()) { + std::string::size_type p; + while ((p = title.find_first_of("\r\n")) != std::string::npos) { + title.erase(p, 1); + } + std::string description; + xml.getChildText(channel, "description", description); + mFeedReader->setFeedInfo(feed.feedId, title, description); + } + } + + /* get item count */ + xmlNodePtr node; + for (node = NULL; (node = getNextItem(feedFormat, channel, node)) != NULL; ) { + if (!isRunning()) { + break; + } + + std::string title; + if (!xml.getChildText(node, "title", title) || title.empty()) { + continue; + } + + /* remove newlines */ + std::string::size_type p; + while ((p = title.find_first_of("\r\n")) != std::string::npos) { + title.erase(p, 1); + } + + RsFeedReaderMsg *item = new RsFeedReaderMsg(); + item->msgId.clear(); // is calculated later + item->feedId = feed.feedId; + item->title = title; + + /* try feedburner:origLink */ + if (!xml.getChildText(node, "origLink", item->link) || item->link.empty()) { + xml.getChildText(node, "link", item->link); + } + + long todo; // remove sid +// // remove sid= +// CString sLinkUpper = sLink; +// sLinkUpper.MakeUpper (); +// int nSIDStart = sLinkUpper.Find (TEXT("SID=")); +// if (nSIDStart != -1) { +// int nSIDEnd1 = sLinkUpper.Find (TEXT(";"), nSIDStart); +// int nSIDEnd2 = sLinkUpper.Find (TEXT("#"), nSIDStart); + +// if (nSIDEnd1 == -1) { +// nSIDEnd1 = sLinkUpper.GetLength (); +// } +// if (nSIDEnd2 == -1) { +// nSIDEnd2 = sLinkUpper.GetLength (); +// } + +// if (nSIDStart > 0 && sLinkUpper [nSIDStart - 1] == '&') { +// nSIDStart--; +// } + +// int nSIDEnd = min (nSIDEnd1, nSIDEnd2); +// sLink.Delete (nSIDStart, nSIDEnd - nSIDStart); +// } + + xml.getChildText(node, "author", item->author); + + xml.getChildText(node, "description", item->description); + + std::string pubDate; + if (xml.getChildText(node, "pubdate", pubDate)) { + item->pubDate = parseRFC822Date(pubDate); + } + if (xml.getChildText(node, "date", pubDate)) { + item->pubDate = parseISO8601Date (pubDate); + } + + if (item->pubDate == 0) { + /* use current time */ + item->pubDate = time(NULL); + } + + entries.push_back(item); + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT; + error = "Channel not found"; + } + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT; + error = "Can't read document"; + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; + } + +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << error << std::endl; +#endif + + return result; +} + +std::string p3FeedReaderThread::getProxyForFeed(const RsFeedReaderFeed &feed) +{ + std::string proxy; + if (feed.flag & RS_FEED_FLAG_STANDARD_PROXY) { + std::string standardProxyAddress; + uint16_t standardProxyPort; + if (mFeedReader->getStandardProxy(standardProxyAddress, standardProxyPort)) { + rs_sprintf(proxy, "%s:%u", standardProxyAddress.c_str(), standardProxyPort); + } + } else { + if (!feed.proxyAddress.empty() && feed.proxyPort) { + rs_sprintf(proxy, "%s:%u", feed.proxyAddress.c_str(), feed.proxyPort); + } + } + return proxy; +} + +RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString) +{ + long todo_fill_errorString; + + if (!msg) { + return RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; + } + + RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; + std::string proxy = getProxyForFeed(feed); + + std::string url; + if (feed.flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl; +#endif + std::string content; + CURLWrapper CURL(proxy); + CURLcode code = CURL.downloadText(msg->link, content); + + if (code == CURLE_OK) { + long responseCode = CURL.responseCode(); + + switch (responseCode) { + case 200: + { + std::string contentType = CURL.contentType(); + + if (isContentType(CURL.contentType(), "text/html")) { + /* ok */ + msg->description = content; + } else { + result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE; + errorString = contentType; + } + } + break; + case 404: + result = RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND; + break; + default: + result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE; + rs_sprintf(errorString, "%ld", responseCode); + } + } else { + result = RS_FEED_ERRORSTATE_DOWNLOAD_ERROR; + errorString = curl_easy_strerror(code); + } + + if (result != RS_FEED_ERRORSTATE_OK) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl; +#endif + return result; + } + + /* get effective url (moved location) */ + std::string effectiveUrl = CURL.effectiveUrl(); + url = getBaseLink(effectiveUrl.empty() ? msg->link : effectiveUrl); + } + + /* check if string contains xml chars (very simple test) */ + if (msg->description.find('<') == std::string::npos) { + return result; + } + + /* process description */ + long todo; // encoding + HTMLWrapper html; + if (html.readHTML(msg->description.c_str(), url.c_str())) { + xmlNodePtr root = html.getRootElement(); + if (root) { + std::list nodesToDelete; + + /* process all children */ + std::list nodes; + nodes.push_back(root); + + while (!nodes.empty()) { + if (!isRunning()) { + break; + } + xmlNodePtr node = nodes.front(); + nodes.pop_front(); + + switch (node->type) { + case XML_ELEMENT_NODE: + if (xmlStrEqual(node->name, BAD_CAST"img")) { + /* process images */ + + if ((feed.flag & RS_FEED_FLAG_EMBED_IMAGES) == 0) { + /* remove image */ + xmlUnlinkNode(node); + nodesToDelete.push_back(node); + continue; + } + } else if (xmlStrEqual(node->name, BAD_CAST"script")) { + /* remove script */ + xmlUnlinkNode(node); + nodesToDelete.push_back(node); + continue; + } + + xmlNodePtr child; + for (child = node->children; child; child = child->next) { + nodes.push_back(child); + } + break; + + case XML_TEXT_NODE: + { + /* check for only space */ + std::string content; + if (html.getContent(node, content)) { + std::string newContent = content; + + /* trim left */ + std::string::size_type find = newContent.find_first_not_of(" \t\r\n"); + if (find != std::string::npos) { + newContent.erase(0, find); + + /* trim right */ + find = newContent.find_last_not_of(" \t\r\n"); + if (find != std::string::npos) { + newContent.erase(find + 1); + } + } else { + newContent.clear(); + } + + if (newContent.empty()) { + xmlUnlinkNode(node); + nodesToDelete.push_back(node); + } else { + if (content != newContent) { + html.setContent(node, newContent.c_str()); + } + } + } + } + break; + + case XML_COMMENT_NODE: +// xmlUnlinkNode(node); +// nodesToDelete.push_back(node); + break; + + case XML_ATTRIBUTE_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + break; + } + } + + std::list::iterator nodeIt; + for (nodeIt = nodesToDelete.begin(); nodeIt != nodesToDelete.end(); ++nodeIt) { + xmlFreeNode(*nodeIt); + } + nodesToDelete.clear(); + + if (!feed.preview) { + result = processXPath(feed.xpathsToUse.ids, feed.xpathsToRemove.ids, html, errorString); + } + + if (result == RS_FEED_ERRORSTATE_OK) { + unsigned int xpathCount; + unsigned int xpathIndex; + XPathWrapper *xpath = html.createXPath(); + if (xpath) { + /* process images */ + if (xpath->compile("//img")) { + xpathCount = xpath->count(); + for (xpathIndex = 0; xpathIndex < xpathCount; ++xpathIndex) { + xmlNodePtr node = xpath->node(xpathIndex); + + if (node->type == XML_ELEMENT_NODE) { + bool removeImage = true; + + if (feed.flag & RS_FEED_FLAG_EMBED_IMAGES) { + /* embed image */ + std::string src = html.getAttr(node, "src"); + if (!src.empty()) { + /* download image */ +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl; +#endif + std::vector data; + CURLWrapper CURL(proxy); + CURLcode code = CURL.downloadBinary(calculateLink(url, src), data); + if (code == CURLE_OK && CURL.responseCode() == 200) { + std::string contentType = CURL.contentType(); + if (isContentType(contentType, "image/")) { + std::string base64; + if (toBase64(data, base64)) { + std::string imageBase64; + rs_sprintf(imageBase64, "data:%s;base64,%s", contentType.c_str(), base64.c_str()); + if (html.setAttr(node, "src", imageBase64.c_str())) { + removeImage = false; + } + } + } + } + } + } + + if (removeImage) { + /* remove image */ + xmlUnlinkNode(node); + nodesToDelete.push_back(node); + continue; + } + } + } + } else { + // unable to compile xpath expression + result = RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR; + } + delete(xpath); + xpath = NULL; + } else { + // unable to create xpath object + result = RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR; + std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << "), unable to create xpath object" << std::endl; + } + } + + for (nodeIt = nodesToDelete.begin(); nodeIt != nodesToDelete.end(); ++nodeIt) { + xmlFreeNode(*nodeIt); + } + nodesToDelete.clear(); + + if (result == RS_FEED_ERRORSTATE_OK) { + if (isRunning()) { + if (!html.saveHTML(msg->description)) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; + } + } + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; + } + + return result; +} + +RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, HTMLWrapper &html, std::string &errorString) +{ + long todo_fill_errorString; + + if (xpathsToUse.empty() && xpathsToRemove.empty()) { + return RS_FEED_ERRORSTATE_OK; + } + + XPathWrapper *xpath = html.createXPath(); + if (xpath == NULL) { + // unable to create xpath object + std::cerr << "p3FeedReaderThread::processXPath - unable to create xpath object" << std::endl; + return RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR; + } + + RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; + + unsigned int xpathCount; + unsigned int xpathIndex; + std::list::const_iterator xpathIt; + + if (!xpathsToUse.empty()) { + HTMLWrapper htmlNew; + if (htmlNew.createHTML()) { + xmlNodePtr body = htmlNew.getBody(); + if (body) { + /* process use list */ + for (xpathIt = xpathsToUse.begin(); xpathIt != xpathsToUse.end(); ++xpathIt) { + if (xpath->compile(xpathIt->c_str())) { + xpathCount = xpath->count(); + if (xpathCount) { + for (xpathIndex = 0; xpathIndex < xpathCount; ++xpathIndex) { + xmlNodePtr node = xpath->node(xpathIndex); + xmlUnlinkNode(node); + xmlAddChild(body, node); + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT; + errorString = *xpathIt; + break; + } + } else { + // unable to process xpath expression +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processXPath - unable to process xpath expression" << std::endl; +#endif + errorString = *xpathIt; + result = RS_FEED_ERRORSTATE_PROCESS_XPATH_WRONG_EXPRESSION; + } + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; + } + + if (result == RS_FEED_ERRORSTATE_OK) { + html = htmlNew; + } + } + + if (result == RS_FEED_ERRORSTATE_OK) { + std::list nodesToDelete; + + /* process remove list */ + for (xpathIt = xpathsToRemove.begin(); xpathIt != xpathsToRemove.end(); ++xpathIt) { + if (xpath->compile(xpathIt->c_str())) { + xpathCount = xpath->count(); + if (xpathCount) { + for (xpathIndex = 0; xpathIndex < xpathCount; ++xpathIndex) { + xmlNodePtr node = xpath->node(xpathIndex); + + xmlUnlinkNode(node); + nodesToDelete.push_back(node); + } + } else { + result = RS_FEED_ERRORSTATE_PROCESS_XPATH_NO_RESULT; + errorString = *xpathIt; + break; + } + } else { + // unable to process xpath expression +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processXPath - unable to process xpath expression" << std::endl; +#endif + errorString = *xpathIt; + return RS_FEED_ERRORSTATE_PROCESS_XPATH_WRONG_EXPRESSION; + } + } + + std::list::iterator nodeIt; + for (nodeIt = nodesToDelete.begin(); nodeIt != nodesToDelete.end(); ++nodeIt) { + xmlFreeNode(*nodeIt); + } + nodesToDelete.clear(); + } + + return result; +} + +RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString) +{ + if (xpathsToUse.empty() && xpathsToRemove.empty()) { + return RS_FEED_ERRORSTATE_OK; + } + + RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; + + long todo_fill_errorString; + + /* process description */ + long todo; // encoding + HTMLWrapper html; + if (html.readHTML(description.c_str(), "")) { + xmlNodePtr root = html.getRootElement(); + if (root) { + result = processXPath(xpathsToUse, xpathsToRemove, html, errorString); + + if (result == RS_FEED_ERRORSTATE_OK) { + if (!html.saveHTML(description)) { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processXPath - cannot dump html" << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; + } + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processXPath - no root element" << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; + } + } else { +#ifdef FEEDREADER_DEBUG + std::cerr << "p3FeedReaderThread::processXPath - cannot read html" << std::endl; +#endif + result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; + } + + return result; +} diff --git a/plugins/FeedReader/services/p3FeedReaderThread.h b/plugins/FeedReader/services/p3FeedReaderThread.h new file mode 100644 index 000000000..9e3e926b9 --- /dev/null +++ b/plugins/FeedReader/services/p3FeedReaderThread.h @@ -0,0 +1,68 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef P3_FEEDREADERTHREAD +#define P3_FEEDREADERTHREAD + +#include "interface/rsFeedReader.h" + +#include "util/rsthreads.h" +#include + +class p3FeedReader; +class RsFeedReaderFeed; +class RsFeedReaderMsg; +class HTMLWrapper; +class RsFeedReaderXPath; + +class p3FeedReaderThread : public RsThread +{ +public: + enum Type + { + DOWNLOAD, + PROCESS + }; + +public: + p3FeedReaderThread(p3FeedReader *feedReader, Type type, const std::string &feedId); + virtual ~p3FeedReaderThread(); + + std::string getFeedId() { return mFeedId; } + + static RsFeedReaderErrorState processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, std::string &description, std::string &errorString); + static RsFeedReaderErrorState processXPath(const std::list &xpathsToUse, const std::list &xpathsToRemove, HTMLWrapper &html, std::string &errorString); + +private: + virtual void run(); + + RsFeedReaderErrorState download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &error); + RsFeedReaderErrorState process(const RsFeedReaderFeed &feed, std::list &entries, std::string &error); + + std::string getProxyForFeed(const RsFeedReaderFeed &feed); + RsFeedReaderErrorState processMsg(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString); + + p3FeedReader *mFeedReader; + Type mType; + std::string mFeedId; +}; + +#endif diff --git a/plugins/FeedReader/services/rsFeedReaderItems.cc b/plugins/FeedReader/services/rsFeedReaderItems.cc new file mode 100644 index 000000000..1d5f60cdd --- /dev/null +++ b/plugins/FeedReader/services/rsFeedReaderItems.cc @@ -0,0 +1,406 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" +#include "rsFeedReaderItems.h" + +/*************************************************************************/ + +RsFeedReaderFeed::RsFeedReaderFeed() + : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PLUGIN_FEEDREADER, RS_PKT_SUBTYPE_FEEDREADER_FEED), + xpathsToUse(TLV_TYPE_STRINGSET), xpathsToRemove(TLV_TYPE_STRINGSET) +{ + clear(); +} + +void RsFeedReaderFeed::clear() +{ + feedId.clear(); + parentId.clear(); + name.clear(); + url.clear(); + user.clear(); + password.clear(); + proxyAddress.clear(); + proxyPort = 0; + updateInterval = 0; + lastUpdate = 0; + storageTime = 0; + flag = 0; + forumId.clear(); + description.clear(); + icon.clear(); + errorState = RS_FEED_ERRORSTATE_OK; + errorString.clear(); + xpathsToUse.ids.clear(); + xpathsToRemove.ids.clear(); + + preview = false; + workstate = WAITING; + content.clear(); +} + +std::ostream &RsFeedReaderFeed::print(std::ostream &out, uint16_t /*indent*/) +{ + return out; +} + +uint32_t RsFeedReaderSerialiser::sizeFeed(RsFeedReaderFeed *item) +{ + uint32_t s = 8; /* header */ + s += 2; /* version */ + s += GetTlvStringSize(item->feedId); + s += GetTlvStringSize(item->parentId); + s += GetTlvStringSize(item->url); + s += GetTlvStringSize(item->name); + s += GetTlvStringSize(item->description); + s += GetTlvStringSize(item->icon); + s += GetTlvStringSize(item->user); + s += GetTlvStringSize(item->password); + s += GetTlvStringSize(item->proxyAddress); + s += sizeof(uint16_t); /* proxyPort */ + s += sizeof(uint32_t); /* updateInterval */ + s += sizeof(time_t); /* lastscan */ + s += sizeof(uint32_t); /* storageTime */ + s += sizeof(uint32_t); /* flag */ + s += GetTlvStringSize(item->forumId); + s += sizeof(uint32_t); /* errorstate */ + s += GetTlvStringSize(item->errorString); + s += item->xpathsToUse.TlvSize(); + s += item->xpathsToRemove.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeFeed(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add values */ + ok &= setRawUInt16(data, tlvsize, &offset, 0); /* version */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->feedId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->parentId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->url); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->name); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->description); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->icon); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->user); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->password); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->proxyAddress); + ok &= setRawUInt16(data, tlvsize, &offset, item->proxyPort); + ok &= setRawUInt32(data, tlvsize, &offset, item->updateInterval); + ok &= setRawUInt32(data, tlvsize, &offset, item->lastUpdate); + ok &= setRawUInt32(data, tlvsize, &offset, item->storageTime); + ok &= setRawUInt32(data, tlvsize, &offset, item->flag); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->forumId); + ok &= setRawUInt32(data, tlvsize, &offset, item->errorState); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->errorString); + ok &= item->xpathsToUse.SetTlv(data, tlvsize, &offset); + ok &= item->xpathsToRemove.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsFeedReaderSerialiser::serialiseFeed() Size Error! " << std::endl; + } + + return ok; +} + +RsFeedReaderFeed *RsFeedReaderSerialiser::deserialiseFeed(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_PLUGIN_FEEDREADER != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_FEEDREADER_FEED != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFeedReaderFeed *item = new RsFeedReaderFeed(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get values */ + uint16_t version = 0; + ok &= getRawUInt16(data, rssize, &offset, &version); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GENID, item->feedId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->parentId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LINK, item->url); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_NAME, item->name); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->description); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->icon); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->user); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->password); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->proxyAddress); + ok &= getRawUInt16(data, rssize, &offset, &(item->proxyPort)); + ok &= getRawUInt32(data, rssize, &offset, &(item->updateInterval)); + ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->lastUpdate)); + ok &= getRawUInt32(data, rssize, &offset, &(item->storageTime)); + ok &= getRawUInt32(data, rssize, &offset, &(item->flag)); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->forumId); + uint32_t errorState = 0; + ok &= getRawUInt32(data, rssize, &offset, &errorState); + item->errorState = (RsFeedReaderErrorState) errorState; + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->errorString); + ok &= item->xpathsToUse.GetTlv(data, rssize, &offset); + ok &= item->xpathsToRemove.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +RsFeedReaderMsg::RsFeedReaderMsg() : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PLUGIN_FEEDREADER, RS_PKT_SUBTYPE_FEEDREADER_MSG) +{ + clear(); +} + +void RsFeedReaderMsg::clear() +{ + msgId.clear(); + feedId.clear(); + title.clear(); + link.clear(); + author.clear(); + description.clear(); + pubDate = 0; + flag = 0; +} + +std::ostream &RsFeedReaderMsg::print(std::ostream &out, uint16_t /*indent*/) +{ + return out; +} + +uint32_t RsFeedReaderSerialiser::sizeMsg(RsFeedReaderMsg *item) +{ + uint32_t s = 8; /* header */ + s += 2; /* version */ + s += GetTlvStringSize(item->msgId); + s += GetTlvStringSize(item->feedId); + s += GetTlvStringSize(item->title); + s += GetTlvStringSize(item->link); + s += GetTlvStringSize(item->author); + s += GetTlvStringSize(item->description); + s += sizeof(time_t); /* pubDate */ + s += sizeof(uint32_t); /* flag */ + + return s; +} + +/* serialise the data to the buffer */ +bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeMsg(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add values */ + ok &= setRawUInt16(data, tlvsize, &offset, 0); /* version */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->msgId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->feedId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->title); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->link); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->author); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->description); + ok &= setRawUInt32(data, tlvsize, &offset, item->pubDate); + ok &= setRawUInt32(data, tlvsize, &offset, item->flag); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsFeedReaderSerialiser::serialiseMsg() Size Error! " << std::endl; + } + + return ok; +} + +RsFeedReaderMsg *RsFeedReaderSerialiser::deserialiseMsg(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_PLUGIN_FEEDREADER != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_FEEDREADER_MSG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFeedReaderMsg *item = new RsFeedReaderMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get values */ + uint16_t version = 0; + ok &= getRawUInt16(data, rssize, &offset, &version); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GENID, item->msgId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->feedId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_NAME, item->title); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LINK, item->link); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->author); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->description); + ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->pubDate)); + ok &= getRawUInt32(data, rssize, &offset, &(item->flag)); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +uint32_t RsFeedReaderSerialiser::size(RsItem *item) +{ + RsFeedReaderFeed *fi; + RsFeedReaderMsg *ei; + + if (NULL != (fi = dynamic_cast(item))) + { + return sizeFeed((RsFeedReaderFeed*) item); + } + if (NULL != (ei = dynamic_cast(item))) + { + return sizeMsg((RsFeedReaderMsg*) item); + } + + return 0; +} + +bool RsFeedReaderSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + RsFeedReaderFeed *fi; + RsFeedReaderMsg *ei; + + if (NULL != (fi = dynamic_cast(item))) + { + return serialiseFeed((RsFeedReaderFeed*) item, data, pktsize); + } + if (NULL != (ei = dynamic_cast(item))) + { + return serialiseMsg((RsFeedReaderMsg*) item, data, pktsize); + } + + return false; +} + +RsItem *RsFeedReaderSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_PLUGIN_FEEDREADER != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch (getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_FEEDREADER_FEED: + return deserialiseFeed(data, pktsize); + case RS_PKT_SUBTYPE_FEEDREADER_MSG: + return deserialiseMsg(data, pktsize); + } + + return NULL; +} diff --git a/plugins/FeedReader/services/rsFeedReaderItems.h b/plugins/FeedReader/services/rsFeedReaderItems.h new file mode 100644 index 000000000..847034456 --- /dev/null +++ b/plugins/FeedReader/services/rsFeedReaderItems.h @@ -0,0 +1,144 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RS_FEEDREADER_ITEMS_H +#define RS_FEEDREADER_ITEMS_H + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "p3FeedReader.h" + +const uint32_t CONFIG_TYPE_FEEDREADER = 0x0001; // is this correct? + +const uint8_t RS_PKT_SUBTYPE_FEEDREADER_FEED = 0x02; +const uint8_t RS_PKT_SUBTYPE_FEEDREADER_MSG = 0x03; + +/**************************************************************************/ + +#define RS_FEED_FLAG_FOLDER 0x001 +#define RS_FEED_FLAG_INFO_FROM_FEED 0x002 +#define RS_FEED_FLAG_STANDARD_STORAGE_TIME 0x004 +#define RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL 0x008 +#define RS_FEED_FLAG_STANDARD_PROXY 0x010 +#define RS_FEED_FLAG_AUTHENTICATION 0x020 +#define RS_FEED_FLAG_DEACTIVATED 0x040 +#define RS_FEED_FLAG_FORUM 0x080 +#define RS_FEED_FLAG_UPDATE_FORUM_INFO 0x100 +#define RS_FEED_FLAG_EMBED_IMAGES 0x200 +#define RS_FEED_FLAG_SAVE_COMPLETE_PAGE 0x400 + +class RsFeedReaderFeed : public RsItem +{ +public: + enum WorkState { + WAITING, + WAITING_TO_DOWNLOAD, + DOWNLOADING, + WAITING_TO_PROCESS, + PROCESSING + }; + +public: + RsFeedReaderFeed(); + virtual ~RsFeedReaderFeed() {} + + virtual void clear(); + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string feedId; + std::string parentId; + std::string name; + std::string url; + std::string user; + std::string password; + std::string proxyAddress; + uint16_t proxyPort; + uint32_t updateInterval; + time_t lastUpdate; + uint32_t flag; // RS_FEED_FLAG_... + std::string forumId; + uint32_t storageTime; + std::string description; + std::string icon; + RsFeedReaderErrorState errorState; + std::string errorString; + + RsTlvStringSet xpathsToUse; + RsTlvStringSet xpathsToRemove; + + /* Not Serialised */ + bool preview; + WorkState workstate; + std::string content; + + std::map msgs; +}; + +#define RS_FEEDMSG_FLAG_DELETED 1 +#define RS_FEEDMSG_FLAG_NEW 2 +#define RS_FEEDMSG_FLAG_READ 4 + +class RsFeedReaderMsg : public RsItem +{ +public: + RsFeedReaderMsg(); + virtual ~RsFeedReaderMsg() {} + + virtual void clear(); + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string msgId; + std::string feedId; + std::string title; + std::string link; + std::string author; + std::string description; + time_t pubDate; + uint32_t flag; // RS_FEEDMSG_FLAG_... +}; + +class RsFeedReaderSerialiser: public RsSerialType +{ +public: + RsFeedReaderSerialiser() : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PLUGIN_FEEDREADER) {} + virtual ~RsFeedReaderSerialiser() {} + + virtual uint32_t size(RsItem *item); + virtual bool serialise(RsItem *item, void *data, uint32_t *size); + virtual RsItem *deserialise(void *data, uint32_t *size); + +private: + /* For RS_PKT_SUBTYPE_FEEDREADER_FEED */ + virtual uint32_t sizeFeed(RsFeedReaderFeed *item); + virtual bool serialiseFeed(RsFeedReaderFeed *item, void *data, uint32_t *size); + virtual RsFeedReaderFeed *deserialiseFeed(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_FEEDREADER_MSG */ + virtual uint32_t sizeMsg(RsFeedReaderMsg *item); + virtual bool serialiseMsg(RsFeedReaderMsg *item, void *data, uint32_t *size); + virtual RsFeedReaderMsg *deserialiseMsg(void *data, uint32_t *size); +}; + +/**************************************************************************/ + +#endif diff --git a/plugins/FeedReader/util/CURLWrapper.cpp b/plugins/FeedReader/util/CURLWrapper.cpp new file mode 100644 index 000000000..db8ccb94f --- /dev/null +++ b/plugins/FeedReader/util/CURLWrapper.cpp @@ -0,0 +1,137 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "CURLWrapper.h" +#include + +//static int progressCallback (void *clientp, double /*dltotal*/, double /*dlnow*/, double /*ultotal*/, double /*ulnow*/) +//{ +// p3FeedReaderThread *thread = (p3FeedReaderThread*) clientp; + +// if (!thread->isRunning()) { +// /* thread was stopped */ +// return 1; +// } + +// long todo; // show progress in gui + +// return 0; +//} + +CURLWrapper::CURLWrapper(const std::string &proxy) +{ + mCurl = curl_easy_init(); + if (mCurl) { + curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, 0); +// curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, progressCallback); +// curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, feedReader); + curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 60); + curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 120); + + if (!proxy.empty()) { + curl_easy_setopt(mCurl, CURLOPT_PROXY, proxy.c_str()); + } + } +} + +CURLWrapper::~CURLWrapper() +{ + if (mCurl) { + curl_easy_cleanup(mCurl); + } +} + +static size_t writeFunctionString (void *ptr, size_t size, size_t nmemb, void *stream) +{ + std::string *s = (std::string*) stream; + s->append ((char*) ptr, size * nmemb); + + return nmemb * size; +} + +CURLcode CURLWrapper::downloadText(const std::string &link, std::string &data) +{ + data.clear(); + + if (!mCurl) { + return CURLE_FAILED_INIT; + } + + curl_easy_setopt(mCurl, CURLOPT_URL, link.c_str()); + curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, writeFunctionString); + curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &data); + + return curl_easy_perform(mCurl); +} + +static size_t writeFunctionBinary (void *ptr, size_t size, size_t nmemb, void *stream) +{ + std::vector *bytes = (std::vector*) stream; + + std::vector newBytes; + newBytes.resize(size * nmemb); + memcpy(newBytes.data(), ptr, newBytes.size()); + + bytes->insert(bytes->end(), newBytes.begin(), newBytes.end()); + + return nmemb * size; +} + +CURLcode CURLWrapper::downloadBinary(const std::string &link, std::vector &data) +{ + data.clear(); + + if (!mCurl) { + return CURLE_FAILED_INIT; + } + + curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(mCurl, CURLOPT_URL, link.c_str()); + curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, writeFunctionBinary); + curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &data); + + return curl_easy_perform(mCurl); +} + +long CURLWrapper::longInfo(CURLINFO info) +{ + if (!mCurl) { + return 0; + } + + long value; + curl_easy_getinfo(mCurl, info, &value); + + return value; +} + +std::string CURLWrapper::stringInfo(CURLINFO info) +{ + if (!mCurl) { + return ""; + } + + char *value; + curl_easy_getinfo(mCurl, info, &value); + + return value ? value : ""; +} diff --git a/plugins/FeedReader/util/CURLWrapper.h b/plugins/FeedReader/util/CURLWrapper.h new file mode 100644 index 000000000..66ac68f53 --- /dev/null +++ b/plugins/FeedReader/util/CURLWrapper.h @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef CURLWRAPPER +#define CURLWRAPPER + +#include +#include +#include + +class CURLWrapper +{ +public: + CURLWrapper(const std::string &proxy); + ~CURLWrapper(); + + CURLcode downloadText(const std::string &link, std::string &data); + CURLcode downloadBinary(const std::string &link, std::vector &data); + + long responseCode() { return longInfo(CURLINFO_RESPONSE_CODE); } + std::string contentType() { return stringInfo(CURLINFO_CONTENT_TYPE); } + std::string effectiveUrl() { return stringInfo(CURLINFO_EFFECTIVE_URL); } + +protected: + long longInfo(CURLINFO info); + std::string stringInfo(CURLINFO info); + +private: + CURL *mCurl; +}; + +#endif diff --git a/plugins/FeedReader/util/HTMLWrapper.cpp b/plugins/FeedReader/util/HTMLWrapper.cpp new file mode 100644 index 000000000..12c7c727a --- /dev/null +++ b/plugins/FeedReader/util/HTMLWrapper.cpp @@ -0,0 +1,75 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "HTMLWrapper.h" +#include + +HTMLWrapper::HTMLWrapper() : XMLWrapper() +{ +} + +bool HTMLWrapper::readHTML(const char *html, const char *url) +{ + cleanup(); + + mDocument = htmlReadMemory(html, strlen(html), url, "", HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_COMPACT | HTML_PARSE_NONET | HTML_PARSE_NOBLANKS); + if (mDocument) { + return true; + } + + return false; +} + +bool HTMLWrapper::saveHTML(std::string &html) +{ + if (!mDocument) { + return false; + } + + xmlChar *newHtml = NULL; + int newHtmlSize = 0; + htmlDocDumpMemoryFormat(mDocument, &newHtml, &newHtmlSize, 0); + if (newHtml) { + convertToString(newHtml, html); + xmlFree(newHtml); + + return true; + } + + return false; +} + +bool HTMLWrapper::createHTML() +{ + /* easy way */ + return readHTML("", ""); +} + +xmlNodePtr HTMLWrapper::getBody() +{ + xmlNodePtr root = getRootElement(); + if (!root) { + return NULL; + } + return findNode(root->children, "body", false); +} diff --git a/plugins/FeedReader/util/HTMLWrapper.h b/plugins/FeedReader/util/HTMLWrapper.h new file mode 100644 index 000000000..a19b8313f --- /dev/null +++ b/plugins/FeedReader/util/HTMLWrapper.h @@ -0,0 +1,40 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef HTMLWRAPPER +#define HTMLWRAPPER + +#include "XMLWrapper.h" + +class HTMLWrapper : public XMLWrapper +{ +public: + HTMLWrapper(); + + bool readHTML(const char *html, const char *url); + bool saveHTML(std::string &html); + + bool createHTML(); + + xmlNodePtr getBody(); +}; + +#endif diff --git a/plugins/FeedReader/util/XMLWrapper.cpp b/plugins/FeedReader/util/XMLWrapper.cpp new file mode 100644 index 000000000..c1a4b2143 --- /dev/null +++ b/plugins/FeedReader/util/XMLWrapper.cpp @@ -0,0 +1,289 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "XMLWrapper.h" +#include "XPathWrapper.h" + +XMLWrapper::XMLWrapper() +{ + mDocument = NULL; + mCharEncodingHandler = xmlFindCharEncodingHandler ("UTF8"); + + if (!mCharEncodingHandler) { + /* no encoding handler found */ + std::cerr << "XMLWrapper::XMLWrapper - no encoding handler found" << std::endl; + } +} + +XMLWrapper::~XMLWrapper() +{ + cleanup(); + xmlCharEncCloseFunc(mCharEncodingHandler); +} + +XMLWrapper &XMLWrapper::operator=(const XMLWrapper &xml) +{ + cleanup(); + + const xmlDocPtr document = xml.getDocument(); + if (document) { + mDocument = xmlCopyDoc(document, 1); + } + + return *this; +} + +void XMLWrapper::cleanup() +{ + if (mDocument) { + xmlFreeDoc(mDocument); + mDocument = NULL; + } +} + +bool XMLWrapper::convertToString(const xmlChar *xmlText, std::string &text) +{ + bool result = false; + + xmlBufferPtr in = xmlBufferCreateStatic((void*) xmlText, xmlStrlen(xmlText)); + xmlBufferPtr out = xmlBufferCreate(); + int ret = xmlCharEncOutFunc(mCharEncodingHandler, out, in); + if (ret >= 0) { + result = true; + text = (char*) xmlBufferContent(out); + } + + xmlBufferFree(in); + xmlBufferFree(out); + + return result; +} + +bool XMLWrapper::convertFromString(const char *text, xmlChar *&xmlText) +{ + bool result = false; + + xmlBufferPtr in = xmlBufferCreateStatic((void*) text, strlen(text)); + xmlBufferPtr out = xmlBufferCreate(); + int ret = xmlCharEncInFunc(mCharEncodingHandler, out, in); + if (ret >= 0) { + result = true; + xmlText = xmlBufferDetach(out); + } + + xmlBufferFree(in); + xmlBufferFree(out); + + return result; +} + +xmlDocPtr XMLWrapper::getDocument() const +{ + return mDocument; +} + +xmlNodePtr XMLWrapper::getRootElement() const +{ + if (mDocument) { + return xmlDocGetRootElement(mDocument); + } + + return NULL; +} + +bool XMLWrapper::readXML(const char *xml) +{ + cleanup(); + + mDocument = xmlReadDoc(BAD_CAST xml, "", NULL, XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_COMPACT | XML_PARSE_NOENT | XML_PARSE_NOCDATA); + if (mDocument) { + return true; + } + + return false; +} + +bool XMLWrapper::getContent(xmlNodePtr node, std::string &content) +{ + content.clear(); + + if (!node) { + return false; + } + + xmlChar *xmlContent = xmlNodeGetContent(node); + if (!xmlContent) { + return true; + } + + bool result = convertToString(xmlContent, content); + xmlFree(xmlContent); + + return result; +} + +bool XMLWrapper::setContent(xmlNodePtr node, const char *content) +{ + if (!node) { + return false; + } + + xmlChar *xmlContent; + if (!convertFromString(content, xmlContent)) { + return false; + } + + xmlNodeSetContent(node, xmlContent); + xmlFree(xmlContent); + + return true; +} + +std::string XMLWrapper::nodeName(xmlNodePtr node) +{ + std::string name; + + if (node) { + convertToString(node->name, name); + } + + return name; +} + +std::string XMLWrapper::attrName(xmlAttrPtr attr) +{ + std::string name; + + if (attr) { + convertToString(attr->name, name); + } + + return name; +} + +xmlNodePtr XMLWrapper::findNode(xmlNodePtr node, const char *name, bool children) +{ + if (node->name) { + if (xmlStrEqual(node->name, BAD_CAST name)) { + return node; + } + } + + xmlNodePtr nodeFound = NULL; + if (children) { + if (node->children) { + nodeFound = findNode(node->children, name, children); + if (nodeFound) { + return nodeFound; + } + } + } + + if (node->next) { + nodeFound = findNode(node->next, name, children); + if (nodeFound) { + return nodeFound; + } + } + + return NULL; +} + +bool XMLWrapper::getChildText(xmlNodePtr node, const char *childName, std::string &text) +{ + if (node == NULL || node->children == NULL) { + return false; + } + + xmlNodePtr child = findNode(node->children, childName, true); + if (!child) { + return false; + } + + if (child->type != XML_ELEMENT_NODE) { + return false; + } + + if (!child->children) { + return false; + } + + if (child->children->type != XML_TEXT_NODE) { + return false; + } + + if (child->children->content) { + return convertToString(child->children->content, text); + } + + return true; +} + +std::string XMLWrapper::getAttr(xmlNodePtr node, xmlAttrPtr attr) +{ + return getAttr(node, (const char*) attr->name); +} + +std::string XMLWrapper::getAttr(xmlNodePtr node, const char *name) +{ + if (!node || !name) { + return ""; + } + + std::string value; + + xmlChar *xmlValue = xmlGetProp(node, BAD_CAST name); + if (xmlValue) { + convertToString(xmlValue, value); + xmlFree(xmlValue); + } + + return value; +} + +bool XMLWrapper::setAttr(xmlNodePtr node, const char *name, const char *value) +{ + if (!node || !name) { + return false; + } + + xmlChar *xmlValue = NULL; + if (!convertFromString(value, xmlValue)) { + return false; + } + + xmlAttrPtr xmlAttr = xmlSetProp (node, BAD_CAST name, xmlValue); + xmlFree(xmlValue); + + return xmlAttr != NULL; +} + +XPathWrapper *XMLWrapper::createXPath() +{ + if (mDocument) { + return new XPathWrapper(*this); + } + + return NULL; +} diff --git a/plugins/FeedReader/util/XMLWrapper.h b/plugins/FeedReader/util/XMLWrapper.h new file mode 100644 index 000000000..6b94ea796 --- /dev/null +++ b/plugins/FeedReader/util/XMLWrapper.h @@ -0,0 +1,68 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef XMLWRAPPER +#define XMLWRAPPER + +#include +#include + +class XPathWrapper; + +class XMLWrapper +{ +public: + XMLWrapper(); + ~XMLWrapper(); + + XMLWrapper &operator=(const XMLWrapper &xml); + + void cleanup(); + + bool readXML(const char *xml); + + xmlDocPtr getDocument() const; + xmlNodePtr getRootElement() const; + + std::string nodeName(xmlNodePtr node); + std::string attrName(xmlAttrPtr attr); + + xmlNodePtr findNode(xmlNodePtr node, const char *name, bool children = false); + bool getChildText(xmlNodePtr node, const char *childName, std::string &text); + + bool getContent(xmlNodePtr node, std::string &content); + bool setContent(xmlNodePtr node, const char *content); + + std::string getAttr(xmlNodePtr node, xmlAttrPtr attr); + std::string getAttr(xmlNodePtr node, const char *name); + bool setAttr(xmlNodePtr node, const char *name, const char *value); + + XPathWrapper *createXPath(); + + bool convertToString(const xmlChar *xmlText, std::string &text); + bool convertFromString(const char *text, xmlChar *&xmlText); + +protected: + xmlDocPtr mDocument; + xmlCharEncodingHandlerPtr mCharEncodingHandler; +}; + +#endif diff --git a/plugins/FeedReader/util/XPathWrapper.cpp b/plugins/FeedReader/util/XPathWrapper.cpp new file mode 100644 index 000000000..103790493 --- /dev/null +++ b/plugins/FeedReader/util/XPathWrapper.cpp @@ -0,0 +1,102 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "XPathWrapper.h" +#include "XMLWrapper.h" + +XPathWrapper::XPathWrapper(XMLWrapper &xmlWrapper) : mXMLWrapper(xmlWrapper) +{ + mContext = NULL; + mResult = NULL; +} + +XPathWrapper::~XPathWrapper() +{ + cleanup(); +} + +void XPathWrapper::cleanup() +{ + if (mResult) { + xmlXPathFreeObject(mResult); + mResult = NULL; + } + if (mContext) { + xmlXPathFreeContext(mContext); + mContext = NULL; + } +} + +bool XPathWrapper::compile(const char *expression) +{ + cleanup(); + + xmlDocPtr document = mXMLWrapper.getDocument(); + if (!document) { + return false; + } + + mContext = xmlXPathNewContext(document); + if (!mContext) { + cleanup(); + return false; + } + + xmlChar *xmlExpression = NULL; + if (!mXMLWrapper.convertFromString(expression, xmlExpression)) { + cleanup(); + return false; + } + mResult = xmlXPathEvalExpression(xmlExpression, mContext); + xmlFree(xmlExpression); + + return true; +} + +unsigned int XPathWrapper::count() +{ + if (!mResult) { + return 0; + } + + if (xmlXPathNodeSetIsEmpty(mResult->nodesetval)) { + return 0; + } + + return mResult->nodesetval->nodeNr; +} + +xmlNodePtr XPathWrapper::node(unsigned int index) +{ + if (!mResult) { + return NULL; + } + + if (xmlXPathNodeSetIsEmpty(mResult->nodesetval)) { + return NULL; + } + + if (index >= (unsigned int) mResult->nodesetval->nodeNr) { + return NULL; + } + + return mResult->nodesetval->nodeTab[index]; +} diff --git a/plugins/FeedReader/util/XPathWrapper.h b/plugins/FeedReader/util/XPathWrapper.h new file mode 100644 index 000000000..1c30df1aa --- /dev/null +++ b/plugins/FeedReader/util/XPathWrapper.h @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2012 by Thunder + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef XPATHWRAPPER +#define XPATHWRAPPER + +#include + +class XMLWrapper; + +class XPathWrapper +{ + friend class XMLWrapper; + +public: + ~XPathWrapper(); + + void cleanup(); + + bool compile(const char *expression); + + unsigned int count(); + xmlNodePtr node(unsigned int index); + +protected: + XPathWrapper(XMLWrapper &xmlWrapper); + + XMLWrapper &mXMLWrapper; + xmlXPathContextPtr mContext; + xmlXPathObjectPtr mResult; +}; + +#endif diff --git a/plugins/plugins.pro b/plugins/plugins.pro index 37b804d8c..a8840da6e 100644 --- a/plugins/plugins.pro +++ b/plugins/plugins.pro @@ -2,4 +2,5 @@ TEMPLATE = subdirs SUBDIRS += \ LinksCloud \ - VOIP + VOIP \ + FeedReader diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp new file mode 100644 index 000000000..0932e3378 --- /dev/null +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp @@ -0,0 +1,627 @@ +/* + * Retroshare Circle Plugin. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include + +#include "gui/Circles/CirclesDialog.h" + +#include +#include + +#include +#include + +#include + +/****** + * #define CIRCLE_DEBUG 1 + *****/ + + +#define CIRCLESDIALOG_GROUPMETA 1 + +/** Constructor */ +CirclesDialog::CirclesDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.pushButton_refresh, SIGNAL(clicked()), this, SLOT(reloadAll())); + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000); + + /* setup TokenQueue */ + mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); + + connect( ui.treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected())); + connect( ui.treeWidget_friends, SIGNAL(itemSelectionChanged()), this, SLOT(friend_selected())); + connect( ui.treeWidget_category, SIGNAL(itemSelectionChanged()), this, SLOT(category_selected())); +} + + +void CirclesDialog::checkUpdate() +{ + + /* update */ + if (!rsGxsCircles) + return; + + if (rsGxsCircles->updated()) + { + reloadAll(); + } + + return; +} + +#define CIRCLEGROUP_CIRCLE_COL_GROUPNAME 0 +#define CIRCLEGROUP_CIRCLE_COL_GROUPID 1 + +#define CIRCLEGROUP_FRIEND_COL_NAME 0 +#define CIRCLEGROUP_FRIEND_COL_ID 1 + +void CirclesDialog::reloadAll() +{ + requestGroupMeta(); + /* grab all ids */ + //std::list + + std::list friend_pgpIds; + std::list all_pgpIds; + std::list::iterator it; + + std::set friend_set; + + rsPeers->getGPGAcceptedList(friend_pgpIds); + rsPeers->getGPGAllList(all_pgpIds); + + /* clear tree */ + ui.treeWidget_friends->clear(); + + /* add the top level item */ + QTreeWidgetItem *friendsItem = new QTreeWidgetItem(); + friendsItem->setText(0, "Friends"); + ui.treeWidget_friends->addTopLevelItem(friendsItem); + + QTreeWidgetItem *fofItem = new QTreeWidgetItem(); + fofItem->setText(0, "Friends Of Friends"); + ui.treeWidget_friends->addTopLevelItem(fofItem); + + for(it = friend_pgpIds.begin(); it != friend_pgpIds.end(); it++) + { + RsPeerDetails details; + if (rsPeers->getGPGDetails(*it, details)) + { + friend_set.insert(*it); + QTreeWidgetItem *item = new QTreeWidgetItem(); + + item->setText(CIRCLEGROUP_FRIEND_COL_NAME, QString::fromStdString(details.name)); + item->setText(CIRCLEGROUP_FRIEND_COL_ID, QString::fromStdString(*it)); + friendsItem->addChild(item); + } + } + + + for(it = all_pgpIds.begin(); it != all_pgpIds.end(); it++) + { + if (friend_set.end() != friend_set.find(*it)) + { + // already added as a friend. + continue; + } + + RsPeerDetails details; + if (rsPeers->getGPGDetails(*it, details)) + { + QTreeWidgetItem *item = new QTreeWidgetItem(); + + item->setText(CIRCLEGROUP_FRIEND_COL_NAME, QString::fromStdString(details.name)); + item->setText(CIRCLEGROUP_FRIEND_COL_ID, QString::fromStdString(*it)); + fofItem->addChild(item); + } + } +} +#define CLEAR_BACKGROUND 0 +#define GREEN_BACKGROUND 1 +#define BLUE_BACKGROUND 2 +#define RED_BACKGROUND 3 +#define GRAY_BACKGROUND 4 + + +void set_item_background(QTreeWidgetItem *item, uint32_t type) +{ + QBrush brush; + switch(type) + { + default: + case CLEAR_BACKGROUND: + brush = QBrush(Qt::white); + break; + case GREEN_BACKGROUND: + brush = QBrush(Qt::green); + break; + case BLUE_BACKGROUND: + brush = QBrush(Qt::blue); + break; + case RED_BACKGROUND: + brush = QBrush(Qt::red); + break; + case GRAY_BACKGROUND: + brush = QBrush(Qt::gray); + break; + } + item->setBackground (0, brush); +} + +void update_children_background(QTreeWidgetItem *item, uint32_t type) +{ + int count = item->childCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *child = item->child(i); + + if (child->childCount() > 0) + { + update_children_background(child, type); + } + set_item_background(child, type); + } +} + + +void set_tree_background(QTreeWidget *tree, uint32_t type) +{ + std::cerr << "CirclesDialog set_tree_background()"; + std::cerr << std::endl; + + /* grab all toplevel */ + int count = tree->topLevelItemCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *item = tree->topLevelItem(i); + /* resursively clear child backgrounds */ + update_children_background(item, type); + set_item_background(item, type); + } +} + + +void check_mark_item(QTreeWidgetItem *item, const std::set &names, uint32_t col, uint32_t type) +{ + QString coltext = item->text(col); + std::string colstr = coltext.toStdString(); + if (names.end() != names.find(colstr)) + { + set_item_background(item, type); + std::cerr << "CirclesDialog check_mark_item: found match: " << colstr; + std::cerr << std::endl; + } +} + +void update_mark_children(QTreeWidgetItem *item, const std::set &names, uint32_t col, uint32_t type) +{ + int count = item->childCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *child = item->child(i); + + if (child->childCount() > 0) + { + update_mark_children(child, names, col, type); + } + check_mark_item(child, names, col, type); + } +} + +void mark_matching_tree(QTreeWidget *tree, const std::set &names, uint32_t col, uint32_t type) +{ + std::cerr << "CirclesDialog mark_matching_tree()"; + std::cerr << std::endl; + + /* grab all toplevel */ + int count = tree->topLevelItemCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *item = tree->topLevelItem(i); + /* resursively clear child backgrounds */ + update_mark_children(item, names, col, type); + check_mark_item(item, names, col, type); + } +} + + + +/**** Circles checks - v expensive ***/ + +void mark_circle_item(QTreeWidgetItem *item, const std::set &names) +{ + std::string id = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID).toStdString(); + RsGxsCircleDetails details; + if (rsGxsCircles->getCircleDetails(id, details)) + { + std::set::iterator it; + for(it = names.begin(); it != names.end(); it++) + { + if (details.mAllowedPeers.end() != details.mAllowedPeers.find(*it)) + { + set_item_background(item, GREEN_BACKGROUND); + std::cerr << "CirclesDialog mark_circle_item: found match: " << id; + std::cerr << std::endl; + } + } + } + else + { + set_item_background(item, GRAY_BACKGROUND); + std::cerr << "CirclesDialog mark_circle_item: no details: " << id; + std::cerr << std::endl; + } +} + +void mark_circle_children(QTreeWidgetItem *item, const std::set &names) +{ + int count = item->childCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *child = item->child(i); + + if (child->childCount() > 0) + { + mark_circle_children(child, names); + } + mark_circle_item(child, names); + } +} + + +void mark_circle_tree(QTreeWidget *tree, const std::set &names) +{ + std::cerr << "CirclesDialog mark_circle_tree()"; + std::cerr << std::endl; + + /* grab all toplevel */ + int count = tree->topLevelItemCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *item = tree->topLevelItem(i); + mark_circle_children(item, names); + } +} + + + +void CirclesDialog::circle_selected() +{ + QTreeWidgetItem *item = ui.treeWidget_membership->currentItem(); + + std::cerr << "CirclesDialog::circle_selected() valid circle chosen"; + std::cerr << std::endl; + + set_tree_background(ui.treeWidget_membership, CLEAR_BACKGROUND); + set_tree_background(ui.treeWidget_friends, CLEAR_BACKGROUND); + set_tree_background(ui.treeWidget_category, CLEAR_BACKGROUND); + + if ((!item) || (!item->parent())) + { + return; + } + + set_item_background(item, BLUE_BACKGROUND); + + QString coltext = item->text(CIRCLEGROUP_CIRCLE_COL_GROUPID); + std::string id = coltext.toStdString(); + + /* update friend lists */ + RsGxsCircleDetails details; + if (rsGxsCircles->getCircleDetails(id, details)) + { + /* now mark all the members */ + std::set members; + std::map >::iterator it; + for(it = details.mAllowedPeers.begin(); it != details.mAllowedPeers.end(); it++) + { + members.insert(it->first); + std::cerr << "Circle member: " << it->first; + std::cerr << std::endl; + } + + mark_matching_tree(ui.treeWidget_friends, members, + CIRCLEGROUP_FRIEND_COL_ID, GREEN_BACKGROUND); + } + else + { + set_tree_background(ui.treeWidget_friends, GRAY_BACKGROUND); + } + +} + + +void CirclesDialog::friend_selected() +{ + /* update circle lists */ + QTreeWidgetItem *item = ui.treeWidget_friends->currentItem(); + + if ((!item) || (!item->parent())) + { + return; + } + + + set_tree_background(ui.treeWidget_membership, CLEAR_BACKGROUND); + set_tree_background(ui.treeWidget_friends, CLEAR_BACKGROUND); + set_tree_background(ui.treeWidget_category, CLEAR_BACKGROUND); + + set_item_background(item, BLUE_BACKGROUND); + + std::string id = item->text(CIRCLEGROUP_FRIEND_COL_ID).toStdString(); + + /* update permission lists */ + std::set names; + names.insert(id); + mark_circle_tree(ui.treeWidget_membership, names); +} + +void CirclesDialog::category_selected() +{ + + + +} + + + + +#if 0 +void CirclesDialog::groupTreeChanged() +{ + /* */ + std::string groupId; + std::string pageId; + std::string origPageId; + + getSelectedPage(groupId, pageId, origPageId); + if (pageId == mPageSelected) + { + return; /* nothing changed */ + } + + if (pageId == "") + { + /* clear Mods */ + clearGroupTree(); + return; + } + + RsGxsGrpMsgIdPair origPagePair = std::make_pair(groupId, origPageId); + RsGxsGrpMsgIdPair pagepair = std::make_pair(groupId, pageId); + requestWikiPage(pagepair); +} + +void CirclesDialog::updateWikiPage(const RsWikiSnapshot &page) +{ +#ifdef USE_PEGMMD_RENDERER + /* render as HTML */ + int extensions = 0; + char *answer = markdown_to_string((char *) page.mPage.c_str(), extensions, HTML_FORMAT); + + QString renderedText = QString::fromUtf8(answer); + ui.textBrowser->setHtml(renderedText); + + // free answer. + free(answer); +#else + /* render as HTML */ + QString renderedText = "IN (dummy) RENDERED TEXT MODE:\n"; + renderedText += QString::fromStdString(page.mPage); + ui.textBrowser->setPlainText(renderedText); +#endif +} + + +void CirclesDialog::clearWikiPage() +{ + ui.textBrowser->setPlainText(""); +} + + +void CirclesDialog::clearGroupTree() +{ + ui.treeWidget_Pages->clear(); +} + + +#define WIKI_GROUP_COL_GROUPNAME 0 +#define WIKI_GROUP_COL_GROUPID 1 + +#define WIKI_GROUP_COL_PAGENAME 0 +#define WIKI_GROUP_COL_PAGEID 1 +#define WIKI_GROUP_COL_ORIGPAGEID 2 + + +bool CirclesDialog::getSelectedPage(std::string &groupId, std::string &pageId, std::string &origPageId) +{ +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedPage()" << std::endl; +#endif + + /* get current item */ + QTreeWidgetItem *item = ui.treeWidget_Pages->currentItem(); + + if (!item) + { + /* leave current list */ +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedPage() Nothing selected" << std::endl; +#endif + return false; + } + + QTreeWidgetItem *parent = item->parent(); + + if (!parent) + { +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedPage() No Parent -> Group Selected" << std::endl; +#endif + return false; + } + + + /* check if it has changed */ + groupId = parent->text(WIKI_GROUP_COL_GROUPID).toStdString(); + pageId = item->text(WIKI_GROUP_COL_PAGEID).toStdString(); + origPageId = item->text(WIKI_GROUP_COL_ORIGPAGEID).toStdString(); + +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedPage() PageId: " << pageId << std::endl; +#endif + return true; +} + + +std::string CirclesDialog::getSelectedGroup() +{ + std::string groupId; +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedGroup()" << std::endl; +#endif + + /* get current item */ + QTreeWidgetItem *item = ui.treeWidget_Pages->currentItem(); + + if (!item) + { + /* leave current list */ +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedGroup() Nothing selected" << std::endl; +#endif + return groupId; + } + + QTreeWidgetItem *parent = item->parent(); + + if (parent) + { + groupId = parent->text(WIKI_GROUP_COL_GROUPID).toStdString(); +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedGroup() Page -> GroupId: " << groupId << std::endl; +#endif + return groupId; + } + + /* otherwise, we are on the group already */ + groupId = item->text(WIKI_GROUP_COL_GROUPID).toStdString(); +#ifdef WIKI_DEBUG + std::cerr << "CirclesDialog::getSelectedGroup() GroupId: " << groupId << std::endl; +#endif + return groupId; +} + +#endif + +/************************** Request / Response *************************/ +/*** Loading Main Index ***/ + +void CirclesDialog::requestGroupMeta() +{ + std::cerr << "CirclesDialog::requestGroupMeta()"; + std::cerr << std::endl; + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + uint32_t token; + mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, CIRCLESDIALOG_GROUPMETA); +} + + +void CirclesDialog::loadGroupMeta(const uint32_t &token) +{ + std::cerr << "CirclesDialog::loadGroupMeta()"; + std::cerr << std::endl; + + ui.treeWidget_membership->clear(); + + std::list groupInfo; + std::list::iterator vit; + + if (!rsGxsCircles->getGroupSummary(token,groupInfo)) + { + std::cerr << "CirclesDialog::loadGroupMeta() Error getting GroupMeta"; + std::cerr << std::endl; + return; + } + + /* add the top level item */ + QTreeWidgetItem *circlesItem = new QTreeWidgetItem(); + circlesItem->setText(0, "Circles"); + ui.treeWidget_membership->addTopLevelItem(circlesItem); + + for(vit = groupInfo.begin(); vit != groupInfo.end(); vit++) + { + /* Add Widget, and request Pages */ + std::cerr << "CirclesDialog::loadGroupMeta() GroupId: " << vit->mGroupId; + std::cerr << " Group: " << vit->mGroupName; + std::cerr << std::endl; + + QTreeWidgetItem *groupItem = new QTreeWidgetItem(); + groupItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromStdString(vit->mGroupName)); + groupItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPID, QString::fromStdString(vit->mGroupId)); + circlesItem->addChild(groupItem); + } +} + + + +void CirclesDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + + std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; + + if (queue == mCircleQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case CIRCLESDIALOG_GROUPMETA: + loadGroupMeta(req.mToken); + break; + + default: + std::cerr << "CirclesDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} + + + + + + diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.h b/retroshare-gui/src/gui/Circles/CirclesDialog.h new file mode 100644 index 000000000..6fe5ce7a8 --- /dev/null +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.h @@ -0,0 +1,96 @@ +/* + * Retroshare Circle. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_CIRCLE_DIALOG_H +#define MRK_CIRCLE_DIALOG_H + +#include "retroshare-gui/mainpage.h" +#include "ui_CirclesDialog.h" + +//#include + +#include "util/TokenQueue.h" + +#include + +class CirclesDialog : public MainPage, public TokenResponse +{ + Q_OBJECT + +public: + CirclesDialog(QWidget *parent = 0); + +void loadRequest(const TokenQueue *queue, const TokenRequest &req); + +private slots: + +void checkUpdate(); + +void reloadAll(); + +void circle_selected(); +void friend_selected(); +void category_selected(); + +#if 0 + void OpenOrShowAddPageDialog(); + void OpenOrShowAddGroupDialog(); + void OpenOrShowEditDialog(); + void OpenOrShowRepublishDialog(); + + void groupTreeChanged(); + + void newGroup(); + void showGroupDetails(); + void editGroupDetails(); + + void insertWikiGroups(); +#endif + +private: + +#if 0 +void clearWikiPage(); +void clearGroupTree(); + +void updateWikiPage(const RsWikiSnapshot &page); + +bool getSelectedPage(std::string &groupId, std::string &pageId, std::string &origPageId); +std::string getSelectedPage(); +std::string getSelectedGroup(); + +#endif + +void requestGroupMeta(); +void loadGroupMeta(const uint32_t &token); + + + TokenQueue *mCircleQueue; + + /* UI - from Designer */ + Ui::CirclesDialog ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.ui b/retroshare-gui/src/gui/Circles/CirclesDialog.ui new file mode 100644 index 000000000..8bac2a020 --- /dev/null +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.ui @@ -0,0 +1,198 @@ + + + CirclesDialog + + + + 0 + 0 + 746 + 568 + + + + + + + + + + + + Create Personal Group + + + + + + + Create Public Group + + + + + + + Refresh + + + + + + + Qt::Horizontal + + + + 378 + 20 + + + + + + + + + + + 75 + true + + + + Showing details: + + + + + + + + + Membership + + + + + + + Name + + + + + IDs + + + + + Personal Circles + + + + + Public Circles + + + + + + + + + + + true + + + Peers + + + + + + + Name + + + + + Status + + + + + ID + + + + + Friends + + + + + + + + Friends of Friends + + + + + + + + Others + + + + + + + + + + + + + + Permissions + + + + + + Anon Transfers + + + + + + + Discovery + + + + + + + + Share Category + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/Circles/Circles_images.qrc b/retroshare-gui/src/gui/Circles/Circles_images.qrc new file mode 100644 index 000000000..1ea8313ef --- /dev/null +++ b/retroshare-gui/src/gui/Circles/Circles_images.qrc @@ -0,0 +1,16 @@ + + + images/arrow-left.png + images/arrow-right.png + images/resource-group-new.png + images/appointment-new.png + images/book2_32.png + images/story-editor.png + images/story-editor_48.png + images/republish.png + images/resource-group-new_48.png + images/wikibook_32.png + images/resource-group_64.png + images/appointment-new_64.png + + diff --git a/retroshare-gui/src/gui/ForumsV2Dialog.cpp b/retroshare-gui/src/gui/ForumsV2Dialog.cpp deleted file mode 100644 index cc45cb33a..000000000 --- a/retroshare-gui/src/gui/ForumsV2Dialog.cpp +++ /dev/null @@ -1,2412 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2008 Robert Fernie - * - * 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 (at your option) 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. - * - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "ForumsV2Dialog.h" - -#include "forumsv2/CreateForumV2.h" -#include "forumsv2/CreateForumV2Msg.h" -#include "forumsv2/ForumV2Details.h" -#include "forumsv2/EditForumV2Details.h" - -#include "msgs/MessageComposer.h" -#include "settings/rsharesettings.h" -#include "common/Emoticons.h" -#include "common/RSItemDelegate.h" -#include "common/PopularityDefs.h" -#include "RetroShareLink.h" -#include "channels/ShareKey.h" -#include "notifyqt.h" -#include "util/HandleRichText.h" - -#include -#include - -#include - -//#define DEBUG_FORUMS - -/* Images for context menu icons */ -#define IMAGE_MESSAGE ":/images/folder-draft.png" -#define IMAGE_MESSAGEREPLY ":/images/mail_reply.png" -#define IMAGE_MESSAGEREMOVE ":/images/mail_delete.png" -#define IMAGE_DOWNLOAD ":/images/start.png" -#define IMAGE_DOWNLOADALL ":/images/startall.png" - -/* Images for TreeWidget */ -#define IMAGE_FOLDER ":/images/folder16.png" -#define IMAGE_FOLDERGREEN ":/images/folder_green.png" -#define IMAGE_FOLDERRED ":/images/folder_red.png" -#define IMAGE_FOLDERYELLOW ":/images/folder_yellow.png" -#define IMAGE_FORUM ":/images/konversation.png" -#define IMAGE_SUBSCRIBE ":/images/edit_add24.png" -#define IMAGE_UNSUBSCRIBE ":/images/cancel.png" -#define IMAGE_INFO ":/images/info16.png" -#define IMAGE_NEWFORUM ":/images/new_forum16.png" -#define IMAGE_FORUMAUTHD ":/images/konv_message2.png" -#define IMAGE_COPYLINK ":/images/copyrslink.png" - -#define VIEW_LAST_POST 0 -#define VIEW_THREADED 1 -#define VIEW_FLAT 2 - -/* Thread constants */ -#define COLUMN_THREAD_COUNT 6 -#define COLUMN_THREAD_TITLE 0 -#define COLUMN_THREAD_READ 1 -#define COLUMN_THREAD_DATE 2 -#define COLUMN_THREAD_AUTHOR 3 -#define COLUMN_THREAD_SIGNED 4 -#define COLUMN_THREAD_CONTENT 5 - -#define COLUMN_THREAD_DATA 0 // column for storing the userdata like msgid and parentid - -#define ROLE_THREAD_MSGID Qt::UserRole -#define ROLE_THREAD_STATUS Qt::UserRole + 1 -#define ROLE_THREAD_MISSING Qt::UserRole + 2 -// no need to copy, don't count in ROLE_THREAD_COUNT -#define ROLE_THREAD_READCHILDREN Qt::UserRole + 3 -#define ROLE_THREAD_UNREADCHILDREN Qt::UserRole + 4 - -#define ROLE_THREAD_COUNT 3 - - -static int FilterColumnFromComboBox(int nIndex) -{ - switch (nIndex) { - case 0: - return COLUMN_THREAD_DATE; - case 1: - return COLUMN_THREAD_TITLE; - case 2: - return COLUMN_THREAD_AUTHOR; - case 3: - return COLUMN_THREAD_CONTENT; - } - - return COLUMN_THREAD_TITLE; -} - -static int FilterColumnToComboBox(int nIndex) -{ - switch (nIndex) { - case COLUMN_THREAD_DATE: - return 0; - case COLUMN_THREAD_TITLE: - return 1; - case COLUMN_THREAD_AUTHOR: - return 2; - case COLUMN_THREAD_CONTENT: - return 3; - } - - return FilterColumnToComboBox(COLUMN_THREAD_TITLE); -} - - -/* - * Transformation Notes: - * there are still a couple of things that the new forums differ from Old version. - * these will need to be addressed in the future. - * -> Missing Messages are not handled yet. - * -> Child TS (for sorting) is not handled by GXS, this will probably have to be done in the GUI. - * -> Need to handle IDs properly. - * -> Popularity not handled in GXS yet. - * -> Much more to do. - */ - -/** Constructor */ -ForumsV2Dialog::ForumsV2Dialog(QWidget *parent) -: RsAutoUpdatePage(1000,parent) -{ - /* Invoke the Qt Designer generated object setup routine */ - ui.setupUi(this); - - m_bProcessSettings = false; - subscribeFlags = 0; - inMsgAsReadUnread = false; - - - /* Setup Queue */ - mForumQueue = new TokenQueue(rsForumsV2, this); - - - - connect( ui.forumTreeWidget, SIGNAL( treeCustomContextMenuRequested( QPoint ) ), this, SLOT( forumListCustomPopupMenu( QPoint ) ) ); - connect( ui.threadTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( threadListCustomPopupMenu( QPoint ) ) ); - - connect(ui.newForumButton, SIGNAL(clicked()), this, SLOT(newforum())); - connect(ui.newmessageButton, SIGNAL(clicked()), this, SLOT(createmessage())); - connect(ui.newthreadButton, SIGNAL(clicked()), this, SLOT(createthread())); - - connect( ui.forumTreeWidget, SIGNAL( treeCurrentItemChanged(QString) ), this, SLOT( changedForum(QString) ) ); - - connect( ui.threadTreeWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( changedThread () ) ); - connect( ui.threadTreeWidget, SIGNAL( itemClicked(QTreeWidgetItem*,int)), this, SLOT( clickedThread (QTreeWidgetItem*,int) ) ); - connect( ui.viewBox, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( changedViewBox () ) ); - - connect(ui.expandButton, SIGNAL(clicked()), this, SLOT(togglethreadview())); - connect(ui.previousButton, SIGNAL(clicked()), this, SLOT(previousMessage())); - connect(ui.nextButton, SIGNAL(clicked()), this, SLOT(nextMessage())); - connect(ui.nextUnreadButton, SIGNAL(clicked()), this, SLOT(nextUnreadMessage())); - - connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadAllFiles())); - - connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString))); - connect(ui.filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged())); - - connect(NotifyQt::getInstance(), SIGNAL(forumMsgReadSatusChanged(QString,QString,int)), this, SLOT(forumMsgReadSatusChanged(QString,QString,int))); - - /* Set initial size the splitter */ - QList sizes; - sizes << 300 << width(); // Qt calculates the right sizes - //ui.splitter->setSizes(sizes); - - /* Set own item delegate */ - RSItemDelegate *itemDelegate = new RSItemDelegate(this); - itemDelegate->setSpacing(QSize(0, 2)); - ui.threadTreeWidget->setItemDelegate(itemDelegate); - - /* Set header resize modes and initial section sizes */ - QHeaderView * ttheader = ui.threadTreeWidget->header () ; - ttheader->setResizeMode (COLUMN_THREAD_TITLE, QHeaderView::Interactive); - ttheader->resizeSection (COLUMN_THREAD_DATE, 140); - ttheader->resizeSection (COLUMN_THREAD_TITLE, 290); - - ui.threadTreeWidget->sortItems( COLUMN_THREAD_DATE, Qt::DescendingOrder ); - - /* Set text of column "Read" to empty - without this the column has a number as header text */ - QTreeWidgetItem *headerItem = ui.threadTreeWidget->headerItem(); - headerItem->setText(COLUMN_THREAD_READ, ""); - - /* Initialize group tree */ - ui.forumTreeWidget->initDisplayMenu(ui.displayButton); - - /* create forum tree */ - yourForums = ui.forumTreeWidget->addCategoryItem(tr("My Forums"), QIcon(IMAGE_FOLDER), true); - subscribedForums = ui.forumTreeWidget->addCategoryItem(tr("Subscribed Forums"), QIcon(IMAGE_FOLDERRED), true); - popularForums = ui.forumTreeWidget->addCategoryItem(tr("Popular Forums"), QIcon(IMAGE_FOLDERGREEN), false); - otherForums = ui.forumTreeWidget->addCategoryItem(tr("Other Forums"), QIcon(IMAGE_FOLDERYELLOW), false); - - lastViewType = -1; - - // load settings - processSettings(true); - - /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ - ttheader->resizeSection (COLUMN_THREAD_READ, 24); - ttheader->setResizeMode (COLUMN_THREAD_READ, QHeaderView::Fixed); - ttheader->hideSection (COLUMN_THREAD_CONTENT); - - ui.progressBar->hide(); - ui.progLayOutTxt->hide(); - ui.progressBarLayOut->setEnabled(false); - - mThreadLoading = false; - - insertThreads(); - - ui.threadTreeWidget->installEventFilter(this); - - /* Hide platform specific features */ -#ifdef Q_WS_WIN - -#endif -} - -ForumsV2Dialog::~ForumsV2Dialog() -{ - // save settings - processSettings(false); -} - -void ForumsV2Dialog::processSettings(bool bLoad) -{ - m_bProcessSettings = true; - - QHeaderView *pHeader = ui.threadTreeWidget->header () ; - - Settings->beginGroup(QString("ForumsV2Dialog")); - - if (bLoad) { - // load settings - - // expandFiles - bool bValue = Settings->value("expandButton", true).toBool(); - ui.expandButton->setChecked(bValue); - togglethreadview_internal(); - - // filterColumn - int nValue = FilterColumnToComboBox(Settings->value("filterColumn", true).toInt()); - ui.filterColumnComboBox->setCurrentIndex(nValue); - - // index of viewBox - ui.viewBox->setCurrentIndex(Settings->value("viewBox", VIEW_THREADED).toInt()); - - // state of thread tree - pHeader->restoreState(Settings->value("ThreadTree").toByteArray()); - - // state of splitter - ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); - ui.threadSplitter->restoreState(Settings->value("threadSplitter").toByteArray()); - } else { - // save settings - - // state of thread tree - Settings->setValue("ThreadTree", pHeader->saveState()); - - // state of splitter - Settings->setValue("Splitter", ui.splitter->saveState()); - Settings->setValue("threadSplitter", ui.threadSplitter->saveState()); - } - - ui.forumTreeWidget->processSettings(Settings, bLoad); - - Settings->endGroup(); - m_bProcessSettings = false; -} - -void ForumsV2Dialog::forumListCustomPopupMenu( QPoint /*point*/ ) -{ - QMenu contextMnu( this ); - - QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum())); - action->setDisabled (mCurrForumId.empty() || IS_GROUP_SUBSCRIBED(subscribeFlags)); - - action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum())); - action->setEnabled (!mCurrForumId.empty() && IS_GROUP_SUBSCRIBED(subscribeFlags)); - - contextMnu.addSeparator(); - - contextMnu.addAction(QIcon(IMAGE_NEWFORUM), tr("New Forum"), this, SLOT(newforum())); - - action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Forum Details"), this, SLOT(showForumDetails())); - action->setEnabled (!mCurrForumId.empty ()); - - action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails())); - action->setEnabled (!mCurrForumId.empty () && IS_GROUP_ADMIN(subscribeFlags)); - - QAction *shareKeyAct = new QAction(QIcon(":/images/gpgp_key_generate.png"), tr("Share Forum"), &contextMnu); - connect( shareKeyAct, SIGNAL( triggered() ), this, SLOT( shareKey() ) ); - shareKeyAct->setEnabled(!mCurrForumId.empty() && IS_GROUP_ADMIN(subscribeFlags)); - contextMnu.addAction( shareKeyAct); - - QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu); - connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) ); - restoreKeysAct->setEnabled(!mCurrForumId.empty() && !IS_GROUP_ADMIN(subscribeFlags)); - contextMnu.addAction( restoreKeysAct); - - action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink())); - action->setEnabled(!mCurrForumId.empty()); - - contextMnu.addSeparator(); - - action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsReadAll())); - action->setEnabled (!mCurrForumId.empty () && IS_GROUP_SUBSCRIBED(subscribeFlags)); - - action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnreadAll())); - action->setEnabled (!mCurrForumId.empty () && IS_GROUP_SUBSCRIBED(subscribeFlags)); - -#ifdef DEBUG_FORUMS - contextMnu.addSeparator(); - action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData())); - action->setEnabled (!mCurrForumId.empty() && IS_GROUP_SUBSCRIBED(subscribeFlags)); -#endif - - contextMnu.exec(QCursor::pos()); -} - -void ForumsV2Dialog::threadListCustomPopupMenu( QPoint /*point*/ ) -{ - if (mThreadLoading) { - return; - } - - QMenu contextMnu( this ); - - QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply" ), &contextMnu ); - connect( replyAct , SIGNAL( triggered() ), this, SLOT( createmessage() ) ); - - QAction *newthreadAct = new QAction(QIcon(IMAGE_DOWNLOADALL), tr( "Start New Thread" ), &contextMnu ); - newthreadAct->setEnabled (IS_GROUP_SUBSCRIBED(subscribeFlags)); - connect( newthreadAct , SIGNAL( triggered() ), this, SLOT( createthread() ) ); - - QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply to Author" ), &contextMnu ); - connect( replyauthorAct , SIGNAL( triggered() ), this, SLOT( replytomessage() ) ); - - QAction* expandAll = new QAction(tr( "Expand all" ), &contextMnu ); - connect( expandAll , SIGNAL( triggered() ), ui.threadTreeWidget, SLOT (expandAll()) ); - - QAction* collapseAll = new QAction(tr( "Collapse all" ), &contextMnu ); - connect( collapseAll , SIGNAL( triggered() ), ui.threadTreeWidget, SLOT(collapseAll()) ); - - QAction *markMsgAsRead = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read"), &contextMnu); - connect(markMsgAsRead , SIGNAL(triggered()), this, SLOT(markMsgAsRead())); - - QAction *markMsgAsReadChildren = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read") + " (" + tr ("with children") + ")", &contextMnu); - connect(markMsgAsReadChildren, SIGNAL(triggered()), this, SLOT(markMsgAsReadChildren())); - - QAction *markMsgAsUnread = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread"), &contextMnu); - connect(markMsgAsUnread , SIGNAL(triggered()), this, SLOT(markMsgAsUnread())); - - QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu); - connect(markMsgAsUnreadChildren , SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren())); - - if (IS_GROUP_SUBSCRIBED(subscribeFlags)) { - QList Rows; - QList RowsRead; - QList RowsUnread; - int nCount = getSelectedMsgCount (&Rows, &RowsRead, &RowsUnread); - - if (RowsUnread.size() == 0) { - - markMsgAsRead->setDisabled(true); - } - if (RowsRead.size() == 0) { - markMsgAsUnread->setDisabled(true); - } - - bool bHasUnreadChildren = false; - bool bHasReadChildren = false; - int nRowCount = Rows.count(); - for (int i = 0; i < nRowCount; i++) { - if (bHasUnreadChildren || Rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN).toBool()) { - bHasUnreadChildren = true; - } - if (bHasReadChildren || Rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN).toBool()) { - bHasReadChildren = true; - } - } - markMsgAsReadChildren->setEnabled(bHasUnreadChildren); - markMsgAsUnreadChildren->setEnabled(bHasReadChildren); - - if (nCount == 1) { - replyAct->setEnabled (true); - replyauthorAct->setEnabled (true); - } else { - replyAct->setDisabled (true); - replyauthorAct->setDisabled (true); - } - } else { - markMsgAsRead->setDisabled(true); - markMsgAsReadChildren->setDisabled(true); - markMsgAsUnread->setDisabled(true); - markMsgAsUnreadChildren->setDisabled(true); - replyAct->setDisabled (true); - replyauthorAct->setDisabled (true); - } - - contextMnu.addAction( replyAct); - contextMnu.addAction( newthreadAct); - contextMnu.addAction( replyauthorAct); - QAction* action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr( "Copy RetroShare Link"), this, SLOT(copyMessageLink())); - action->setEnabled(!mCurrForumId.empty() && !mCurrThreadId.empty()); - contextMnu.addSeparator(); - contextMnu.addAction(markMsgAsRead); - contextMnu.addAction(markMsgAsReadChildren); - contextMnu.addAction(markMsgAsUnread); - contextMnu.addAction(markMsgAsUnreadChildren); - contextMnu.addSeparator(); - contextMnu.addAction( expandAll); - contextMnu.addAction( collapseAll); - - contextMnu.exec(QCursor::pos()); -} - -bool ForumsV2Dialog::eventFilter(QObject *obj, QEvent *event) -{ - if (obj == ui.threadTreeWidget) { - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent && keyEvent->key() == Qt::Key_Space) { - // Space pressed - QTreeWidgetItem *item = ui.threadTreeWidget->currentItem (); - clickedThread (item, COLUMN_THREAD_READ); - return true; // eat event - } - } - } - // pass the event on to the parent class - return RsAutoUpdatePage::eventFilter(obj, event); -} - -void ForumsV2Dialog::restoreForumKeys(void) -{ - rsForumsV2->groupRestoreKeys(mCurrForumId); -} - -void ForumsV2Dialog::togglethreadview() -{ - // save state of button - Settings->setValueToGroup("ForumsV2Dialog", "expandButton", ui.expandButton->isChecked()); - - togglethreadview_internal(); -} - -void ForumsV2Dialog::togglethreadview_internal() -{ - if (ui.expandButton->isChecked()) { - ui.postText->setVisible(true); - ui.expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); - ui.expandButton->setToolTip(tr("Hide")); - } else { - ui.postText->setVisible(false); - ui.expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); - ui.expandButton->setToolTip(tr("Expand")); - } -} - -void ForumsV2Dialog::updateDisplay() -{ - std::list forumIds; - std::list::iterator it; - if (!rsForumsV2) - return; - -#if 0 - // TODO groupsChanged... HACK XXX. - if ((rsForumsV2->groupsChanged(forumIds)) || (rsForumsV2->updated())) - { - /* update Forums List */ - insertForums(); - - it = std::find(forumIds.begin(), forumIds.end(), mCurrForumId); - if (it != forumIds.end()) - { - /* update threads as well */ - insertThreads(); - } - } -#endif - - /* The proper version (above) can be done with a data request -> TODO */ - if (rsForumsV2->updated()) - { - /* update Forums List */ - insertForums(); - /* update threads as well */ - insertThreads(); - } -} - -static void CleanupItems (QList &items) -{ - QList::iterator item; - for (item = items.begin (); item != items.end (); item++) { - if (*item) { - delete (*item); - } - } - items.clear(); -} - -void ForumsV2Dialog::forumInfoToGroupItemInfo(const RsGroupMetaData &forumInfo, GroupItemInfo &groupItemInfo) -//void ForumsV2Dialog::forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo) -{ - - groupItemInfo.id = QString::fromStdString(forumInfo.mGroupId); - groupItemInfo.name = QString::fromUtf8(forumInfo.mGroupName.c_str()); - //groupItemInfo.description = QString::fromUtf8(forumInfo.forumDesc); - groupItemInfo.popularity = forumInfo.mPop; - groupItemInfo.lastpost = QDateTime::fromTime_t(forumInfo.mLastPost); - - if (forumInfo.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) { - groupItemInfo.name += " (" + tr("AUTHD") + ")"; - groupItemInfo.icon = QIcon(IMAGE_FORUMAUTHD); - } else { - groupItemInfo.icon = QIcon(IMAGE_FORUM); - } - -// groupItemInfo.id = QString::fromStdString(forumInfo.forumId); -// groupItemInfo.name = QString::fromStdWString(forumInfo.forumName); -// groupItemInfo.description = QString::fromStdWString(forumInfo.forumDesc); -// groupItemInfo.popularity = forumInfo.pop; -// groupItemInfo.lastpost = QDateTime::fromTime_t(forumInfo.lastPost); -// -// if (forumInfo.forumFlags & RS_DISTRIB_AUTHEN_REQ) { -// groupItemInfo.name += " (" + tr("AUTHD") + ")"; -// groupItemInfo.icon = QIcon(IMAGE_FORUMAUTHD); -// } else { -// groupItemInfo.icon = QIcon(IMAGE_FORUM); -// } -} - - -/***** INSERT FORUM LISTS *****/ -void ForumsV2Dialog::insertForumsData(const std::list &forumList) -{ - std::list::const_iterator it; - - QList adminList; - QList subList; - QList popList; - QList otherList; - std::multimap popMap; - - for (it = forumList.begin(); it != forumList.end(); it++) { - /* sort it into Publish (Own), Subscribed, Popular and Other */ - uint32_t flags = it->mSubscribeFlags; - - GroupItemInfo groupItemInfo; - forumInfoToGroupItemInfo(*it, groupItemInfo); - - if (flags & RSGXS_GROUP_SUBSCRIBE_ADMIN) { - adminList.push_back(groupItemInfo); - } else if (flags & RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED) { - /* subscribed forum */ - subList.push_back(groupItemInfo); - } else { - /* rate the others by popularity */ - popMap.insert(std::make_pair(it->mPop, groupItemInfo)); - } - } - - /* iterate backwards through popMap - take the top 5 or 10% of list */ - uint32_t popCount = 5; - if (popCount < popMap.size() / 10) - { - popCount = popMap.size() / 10; - } - - uint32_t i = 0; - uint32_t popLimit = 0; - std::multimap::reverse_iterator rit; - for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++) ; - if (rit != popMap.rend()) { - popLimit = rit->first; - } - - for (rit = popMap.rbegin(); rit != popMap.rend(); rit++) { - if (rit->second.popularity < (int) popLimit) { - otherList.append(rit->second); - } else { - popList.append(rit->second); - } - } - - /* now we can add them in as a tree! */ - ui.forumTreeWidget->fillGroupItems(yourForums, adminList); - ui.forumTreeWidget->fillGroupItems(subscribedForums, subList); - ui.forumTreeWidget->fillGroupItems(popularForums, popList); - ui.forumTreeWidget->fillGroupItems(otherForums, otherList); - - updateMessageSummaryList(""); -} - -void ForumsV2Dialog::changedForum(const QString &id) -{ - mCurrForumId = id.toStdString(); - - insertThreads(); -} - -void ForumsV2Dialog::changedThread () -{ - if (mThreadLoading) { - return; - } - - /* just grab the ids of the current item */ - QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem(); - - if ((!curr) || (!curr->isSelected())) { - mCurrThreadId = ""; - } else { - mCurrThreadId = curr->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); - } - insertPost(); -} - -void ForumsV2Dialog::clickedThread (QTreeWidgetItem *item, int column) -{ - if (mCurrForumId.empty() || !IS_GROUP_SUBSCRIBED(subscribeFlags)) { - return; - } - - if (item == NULL) { - return; - } - - if (column == COLUMN_THREAD_READ) { - QList Rows; - Rows.append(item); - uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - setMsgAsReadUnread(Rows, IS_MSG_UNREAD(status)); - return; - } -} - -void ForumsV2Dialog::forumMsgReadStatusChanged(const QString &forumId, const QString &msgId, int status) -{ - if (inMsgAsReadUnread) { - return; - } - - if (forumId.toStdString() == mCurrForumId) { - /* Search exisiting item */ - QTreeWidgetItemIterator itemIterator(ui.threadTreeWidget); - QTreeWidgetItem *item = NULL; - while ((item = *itemIterator) != NULL) { - itemIterator++; - - if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString() == msgId) { - // update status - item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status); - - QTreeWidgetItem *parentItem = item; - while (parentItem->parent()) { - parentItem = parentItem->parent(); - } - CalculateIconsAndFonts(parentItem); - break; - } - } - } - updateMessageSummaryList(forumId.toStdString()); -} - -void ForumsV2Dialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem, bool &bHasReadChilddren, bool &bHasUnreadChilddren) -{ - uint32_t status = pItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - - bool bUnread = IS_MSG_UNREAD(status); - bool missing = pItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool(); - - // set icon - if (missing) { - pItem->setIcon(COLUMN_THREAD_READ, QIcon()); - pItem->setIcon(COLUMN_THREAD_TITLE, QIcon()); - } else { - if (bUnread) { - pItem->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-unread.png")); - } else { - pItem->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-read.png")); - } - if (status & RSGXS_MSG_STATUS_READ) { - pItem->setIcon(COLUMN_THREAD_TITLE, QIcon()); - } else { - pItem->setIcon(COLUMN_THREAD_TITLE, QIcon(":/images/message-state-new.png")); - } - } - - int nItem; - int nItemCount = pItem->childCount(); - - bool bMyReadChilddren = false; - bool bMyUnreadChilddren = false; - - for (nItem = 0; nItem < nItemCount; nItem++) { - CalculateIconsAndFonts(pItem->child(nItem), bMyReadChilddren, bMyUnreadChilddren); - } - - // set font - for (int i = 0; i < COLUMN_THREAD_COUNT; i++) { - QFont qf = pItem->font(i); - - if (!IS_GROUP_SUBSCRIBED(subscribeFlags)) { - qf.setBold(false); - pItem->setTextColor(i, Qt::black); - } else if (bUnread) { - qf.setBold(true); - pItem->setTextColor(i, Qt::black); - } else if (bMyUnreadChilddren) { - qf.setBold(true); - pItem->setTextColor(i, Qt::gray); - } else { - qf.setBold(false); - pItem->setTextColor(i, Qt::gray); - } - if (missing) { - /* Missing message */ - pItem->setTextColor(i, Qt::darkRed); - } - pItem->setFont(i, qf); - } - - pItem->setData(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN, bHasReadChilddren || bMyReadChilddren); - pItem->setData(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN, bHasUnreadChilddren || bMyUnreadChilddren); - - bHasReadChilddren = bHasReadChilddren || bMyReadChilddren || !bUnread; - bHasUnreadChilddren = bHasUnreadChilddren || bMyUnreadChilddren || bUnread; -} - -void ForumsV2Dialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem /*= NULL*/) -{ - bool bDummy1 = false; - bool bDummy2 = false; - - if (pItem) { - CalculateIconsAndFonts(pItem, bDummy1, bDummy2); - return; - } - - int nItem; - int nItemCount = ui.threadTreeWidget->topLevelItemCount(); - - for (nItem = 0; nItem < nItemCount; nItem++) { - bDummy1 = false; - bDummy2 = false; - CalculateIconsAndFonts(ui.threadTreeWidget->topLevelItem(nItem), bDummy1, bDummy2); - } -} - -void ForumsV2Dialog::fillThreadFinished() -{ -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::fillThreadFinished" << std::endl; -#endif - - // This is now only called with a successful Load. - // cleanup of incomplete is handled elsewhere. - - // current thread has finished, hide progressbar and release thread - ui.progressBar->hide(); - ui.progLayOutTxt->hide(); - ui.progressBarLayOut->setEnabled(false); - -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::fillThreadFinished Add messages" << std::endl; -#endif - ui.threadTreeWidget->setSortingEnabled(false); - - /* add all messages in! */ - if (lastViewType != mThreadLoad.ViewType || lastForumID != mCurrForumId) - { - ui.threadTreeWidget->clear(); - lastViewType = mThreadLoad.ViewType; - lastForumID = mCurrForumId; - ui.threadTreeWidget->insertTopLevelItems(0, mThreadLoad.Items); - - // clear list - mThreadLoad.Items.clear(); - } - else - { - FillThreads (mThreadLoad.Items, mThreadLoad.ExpandNewMessages, mThreadLoad.ItemToExpand); - - // cleanup list - CleanupItems (mThreadLoad.Items); - } - - ui.threadTreeWidget->setSortingEnabled(true); - - if (mThreadLoad.FocusMsgId.empty() == false) - { - /* Search exisiting item */ - QTreeWidgetItemIterator itemIterator(ui.threadTreeWidget); - QTreeWidgetItem *item = NULL; - while ((item = *itemIterator) != NULL) - { - itemIterator++; - - if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == mThreadLoad.FocusMsgId) - { - ui.threadTreeWidget->setCurrentItem(item); - ui.threadTreeWidget->setFocus(); - break; - } - } - } - - QList::iterator Item; - for (Item = mThreadLoad.ItemToExpand.begin(); Item != mThreadLoad.ItemToExpand.end(); Item++) - { - if ((*Item)->isHidden() == false) - { - (*Item)->setExpanded(true); - } - } - mThreadLoad.ItemToExpand.clear(); - - if (ui.filterLineEdit->text().isEmpty() == false) { - filterItems(ui.filterLineEdit->text()); - } - - insertPost (); - CalculateIconsAndFonts(); - - ui.newthreadButton->setEnabled (IS_GROUP_SUBSCRIBED(subscribeFlags)); - - mThreadLoading = false; - -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::fillThreadFinished done" << std::endl; -#endif -} - -void ForumsV2Dialog::fillThreadProgress(int current, int count) -{ - // show fill progress - if (count) { - ui.progressBar->setValue(current * ui.progressBar->maximum() / count); - } - -} - -void ForumsV2Dialog::insertThreads() -{ -#ifdef DEBUG_FORUMS - /* get the current Forum */ - std::cerr << "ForumsV2Dialog::insertThreads()" << std::endl; -#endif - - subscribeFlags = 0; - - ui.newmessageButton->setEnabled (false); - ui.newthreadButton->setEnabled (false); - - ui.postText->clear(); - ui.threadTitle->clear(); - - if (mCurrForumId.empty()) - { - /* not an actual forum - clear */ - ui.threadTreeWidget->clear(); - /* when no Thread selected - clear */ - ui.forumName->clear(); - /* clear last stored forumID */ - mCurrForumId.erase(); - lastForumID.erase(); - -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::insertThreads() Current Thread Invalid" << std::endl; -#endif - - return; - } - - // Get Current Forum Info... then complete insertForumThreads(). - requestGroupSummary_CurrentForum(mCurrForumId); -} - - -void ForumsV2Dialog::insertForumThreads(const RsGroupMetaData &fi) -{ - subscribeFlags = fi.mSubscribeFlags; - ui.forumName->setText(QString::fromUtf8(fi.mGroupName.c_str())); - - ui.progressBarLayOut->setEnabled(true); - - ui.progLayOutTxt->show(); - ui.progressBar->reset(); - ui.progressBar->show(); - -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::insertThreads() Start filling Forum threads" << std::endl; -#endif - - loadCurrentForumThreads(fi.mGroupId); -} - - - - -void ForumsV2Dialog::FillThreads(QList &ThreadList, bool expandNewMessages, QList &itemToExpand) -{ -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::FillThreads()" << std::endl; -#endif - - int Index = 0; - QTreeWidgetItem *Thread; - QList::iterator NewThread; - - // delete not existing - while (Index < ui.threadTreeWidget->topLevelItemCount ()) { - Thread = ui.threadTreeWidget->topLevelItem (Index); - - // search existing new thread - int Found = -1; - for (NewThread = ThreadList.begin (); NewThread != ThreadList.end (); NewThread++) { - if (Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*NewThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { - // found it - Found = Index; - break; - } - } - if (Found >= 0) { - Index++; - } else { - delete (ui.threadTreeWidget->takeTopLevelItem (Index)); - } - } - - // iterate all new threads - for (NewThread = ThreadList.begin (); NewThread != ThreadList.end (); NewThread++) { - // search existing thread - int Found = -1; - int Count = ui.threadTreeWidget->topLevelItemCount (); - for (Index = 0; Index < Count; Index++) { - Thread = ui.threadTreeWidget->topLevelItem (Index); - if (Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*NewThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { - // found it - Found = Index; - break; - } - } - - if (Found >= 0) { - // set child data - int i; - for (i = 0; i < COLUMN_THREAD_COUNT; i++) { - Thread->setText (i, (*NewThread)->text (i)); - } - for (i = 0; i < ROLE_THREAD_COUNT; i++) { - Thread->setData (COLUMN_THREAD_DATA, Qt::UserRole + i, (*NewThread)->data (COLUMN_THREAD_DATA, Qt::UserRole + i)); - } - - // fill recursive - FillChildren (Thread, *NewThread, expandNewMessages, itemToExpand); - } else { - // add new thread - ui.threadTreeWidget->addTopLevelItem (*NewThread); - Thread = *NewThread; - *NewThread = NULL; - } - - uint32_t status = Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - if (expandNewMessages && IS_MSG_UNREAD(status)) { - QTreeWidgetItem *pParent = Thread; - while ((pParent = pParent->parent()) != NULL) { - if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) { - itemToExpand.push_back(pParent); - } - } - } - } - -#ifdef DEBUG_FORUMS - std::cerr << "ForumsV2Dialog::FillThreads() done" << std::endl; -#endif -} - -void ForumsV2Dialog::FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool expandNewMessages, QList &itemToExpand) -{ - int Index = 0; - int NewIndex; - int NewCount = NewParent->childCount(); - - QTreeWidgetItem *Child; - QTreeWidgetItem *NewChild; - - // delete not existing - while (Index < Parent->childCount ()) { - Child = Parent->child (Index); - - // search existing new child - int Found = -1; - int Count = NewParent->childCount(); - for (NewIndex = 0; NewIndex < Count; NewIndex++) { - NewChild = NewParent->child (NewIndex); - if (NewChild->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { - // found it - Found = Index; - break; - } - } - if (Found >= 0) { - Index++; - } else { - delete (Parent->takeChild (Index)); - } - } - - // iterate all new children - for (NewIndex = 0; NewIndex < NewCount; NewIndex++) { - NewChild = NewParent->child (NewIndex); - - // search existing child - int Found = -1; - int Count = Parent->childCount(); - for (Index = 0; Index < Count; Index++) { - Child = Parent->child (Index); - if (Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == NewChild->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { - // found it - Found = Index; - break; - } - } - - if (Found >= 0) { - // set child data - int i; - for (i = 0; i < COLUMN_THREAD_COUNT; i++) { - Child->setText (i, NewChild->text (i)); - } - for (i = 0; i < ROLE_THREAD_COUNT; i++) { - Child->setData (COLUMN_THREAD_DATA, Qt::UserRole + i, NewChild->data (COLUMN_THREAD_DATA, Qt::UserRole + i)); - } - - // fill recursive - FillChildren (Child, NewChild, expandNewMessages, itemToExpand); - } else { - // add new child - Child = NewParent->takeChild(NewIndex); - Parent->addChild (Child); - NewIndex--; - NewCount--; - } - - uint32_t status = Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - if (expandNewMessages && IS_MSG_UNREAD(status)) { - QTreeWidgetItem *pParent = Child; - while ((pParent = pParent->parent()) != NULL) { - if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) { - itemToExpand.push_back(pParent); - } - } - } - } -} - -QString ForumsV2Dialog::titleFromInfo(const RsMsgMetaData &meta) -{ - // NOTE - NOTE SURE HOW THIS WILL WORK! - if (meta.mMsgStatus & RS_DISTRIB_MISSING_MSG) { - return QApplication::translate("ForumsV2Dialog", "[ ... Missing Message ... ]"); - } - - return QString::fromUtf8(meta.mMsgName.c_str()); -} - -QString ForumsV2Dialog::messageFromInfo(const RsForumV2Msg &msg) -{ - if (msg.mMeta.mMsgStatus & RS_DISTRIB_MISSING_MSG) { - return QApplication::translate("ForumsV2Dialog", "Placeholder for missing Message"); - } - - return QString::fromUtf8(msg.mMsg.c_str()); -} - -void ForumsV2Dialog::insertPost() -{ - if ((mCurrForumId == "") || (mCurrThreadId == "")) - { - ui.postText->setText(""); - ui.threadTitle->setText(""); - ui.previousButton->setEnabled(false); - ui.nextButton->setEnabled(false); - ui.newmessageButton->setEnabled (false); - return; - } - - QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem(); - if (curr) { - QTreeWidgetItem *Parent = curr->parent (); - int Index = Parent ? Parent->indexOfChild (curr) : ui.threadTreeWidget->indexOfTopLevelItem (curr); - int Count = Parent ? Parent->childCount () : ui.threadTreeWidget->topLevelItemCount (); - ui.previousButton->setEnabled (Index > 0); - ui.nextButton->setEnabled (Index < Count - 1); - } else { - // there is something wrong - ui.previousButton->setEnabled(false); - ui.nextButton->setEnabled(false); - return; - } - - ui.newmessageButton->setEnabled (IS_GROUP_SUBSCRIBED(subscribeFlags) && mCurrThreadId.empty() == false); - - /* blank text, incase we get nothing */ - ui.postText->setText(""); - /* request Post */ - - requestMsgData_InsertPost(mCurrThreadId); - -} - - - -void ForumsV2Dialog::insertPostData(const RsForumV2Msg &msg) -{ - /* As some time has elapsed since request - check that this is still the current msg. - * otherwise, another request will fill the data - */ - - if ((msg.mMeta.mGroupId != mCurrForumId) || (msg.mMeta.mMsgId != mCurrThreadId)) - { - std::cerr << "ForumsV2Dialog::insertPostData() Ignoring Invalid Data...."; - std::cerr << std::endl; - std::cerr << "\t CurrForumId: " << mCurrForumId << " != msg.GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - std::cerr << "\t or CurrThdId: " << mCurrThreadId << " != msg.MsgId: " << msg.mMeta.mMsgId; - std::cerr << std::endl; - std::cerr << std::endl; - return; - } - - QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem(); - - bool bSetToReadOnActive = Settings->getForumMsgSetToReadOnActivate(); - uint32_t status = curr->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - - QList Row; - Row.append(curr); - if (status & RSGXS_MSG_STATUS_READ) { - if (bSetToReadOnActive && (status & RSGXS_MSG_STATUS_UNREAD_BY_USER)) { - /* set to read */ - setMsgAsReadUnread(Row, true); - } - } else { - /* set to read */ - if (bSetToReadOnActive) { - setMsgAsReadUnread(Row, true); - } else { - /* set to unread by user */ - setMsgAsReadUnread(Row, false); - } - } - - QString extraTxt = RsHtml().formatText(ui.postText->document(), messageFromInfo(msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); - - ui.postText->setHtml(extraTxt); - ui.threadTitle->setText(titleFromInfo(msg.mMeta)); -} - - -void ForumsV2Dialog::previousMessage () -{ - QTreeWidgetItem *Item = ui.threadTreeWidget->currentItem (); - if (Item == NULL) { - return; - } - - QTreeWidgetItem *Parent = Item->parent (); - int Index = Parent ? Parent->indexOfChild (Item) : ui.threadTreeWidget->indexOfTopLevelItem (Item); - if (Index > 0) { - QTreeWidgetItem *Previous = Parent ? Parent->child (Index - 1) : ui.threadTreeWidget->topLevelItem (Index - 1); - if (Previous) { - ui.threadTreeWidget->setCurrentItem (Previous); - } - } -} - -void ForumsV2Dialog::nextMessage () -{ - QTreeWidgetItem *Item = ui.threadTreeWidget->currentItem (); - if (Item == NULL) { - return; - } - - QTreeWidgetItem *Parent = Item->parent (); - int Index = Parent ? Parent->indexOfChild (Item) : ui.threadTreeWidget->indexOfTopLevelItem (Item); - int Count = Parent ? Parent->childCount () : ui.threadTreeWidget->topLevelItemCount (); - if (Index < Count - 1) { - QTreeWidgetItem *Next = Parent ? Parent->child (Index + 1) : ui.threadTreeWidget->topLevelItem (Index + 1); - if (Next) { - ui.threadTreeWidget->setCurrentItem (Next); - } - } -} - -void ForumsV2Dialog::downloadAllFiles() -{ - QStringList urls; - if (RsHtml::findAnchors(ui.postText->toHtml(), urls) == false) { - return; - } - - if (urls.count() == 0) { - return; - } - - RetroShareLink::process(urls, RetroShareLink::TYPE_FILE/*, true*/); -} - -void ForumsV2Dialog::nextUnreadMessage() -{ - QTreeWidgetItem *currentItem = ui.threadTreeWidget->currentItem(); - - while (TRUE) { - QTreeWidgetItemIterator itemIterator = currentItem ? QTreeWidgetItemIterator(currentItem, QTreeWidgetItemIterator::NotHidden) : QTreeWidgetItemIterator(ui.threadTreeWidget, QTreeWidgetItemIterator::NotHidden); - - QTreeWidgetItem *item; - while ((item = *itemIterator) != NULL) { - itemIterator++; - - if (item == currentItem) { - continue; - } - - uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - if (IS_UNREAD(status)) { - ui.threadTreeWidget->setCurrentItem(item); - ui.threadTreeWidget->scrollToItem(item, QAbstractItemView::EnsureVisible); - return; - } - } - - if (currentItem == NULL) { - break; - } - - /* start from top */ - currentItem = NULL; - } -} - -// TODO -#if 0 -void ForumsV2Dialog::removemessage() -{ - //std::cerr << "ForumsV2Dialog::removemessage()" << std::endl; - std::string cid, mid; - if (!getCurrentMsg(cid, mid)) - { - //std::cerr << "ForumsV2Dialog::removemessage()"; - //std::cerr << " No Message selected" << std::endl; - return; - } - - rsMsgs -> MessageDelete(mid); -} -#endif - -/* get selected messages - the messages tree is single selected, but who knows ... */ -int ForumsV2Dialog::getSelectedMsgCount(QList *pRows, QList *pRowsRead, QList *pRowsUnread) -{ - if (pRowsRead) pRowsRead->clear(); - if (pRowsUnread) pRowsUnread->clear(); - - QList selectedItems = ui.threadTreeWidget->selectedItems(); - for(QList::iterator it = selectedItems.begin(); it != selectedItems.end(); it++) { - if (pRows) pRows->append(*it); - if (pRowsRead || pRowsUnread) { - uint32_t status = (*it)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - if (IS_MSG_UNREAD(status)) { - if (pRowsUnread) pRowsUnread->append(*it); - } else { - if (pRowsRead) pRowsRead->append(*it); - } - } - } - - return selectedItems.size(); -} - -void ForumsV2Dialog::setMsgAsReadUnread(QList &Rows, bool bRead) -{ - QList::iterator Row; - std::list changedItems; - - inMsgAsReadUnread = true; - - for (Row = Rows.begin(); Row != Rows.end(); Row++) { - if ((*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool()) { - /* Missing message */ - continue; - } - - uint32_t status = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - - /* set always as read ... */ - uint32_t statusNew = status | RSGXS_MSG_STATUS_READ; - if (bRead) { - /* ... and as read by user */ - statusNew &= ~RSGXS_MSG_STATUS_UNREAD_BY_USER; - } else { - /* ... and as unread by user */ - statusNew |= RSGXS_MSG_STATUS_UNREAD_BY_USER; - } - if (status != statusNew) { - std::string msgId = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); - rsForumsV2->setMessageStatus(msgId, statusNew, RSGXS_MSG_STATUS_READ | RSGXS_MSG_STATUS_UNREAD_BY_USER); - - (*Row)->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, statusNew); - - QTreeWidgetItem *parentItem = *Row; - while (parentItem->parent()) { - parentItem = parentItem->parent(); - } - if (std::find(changedItems.begin(), changedItems.end(), parentItem) == changedItems.end()) { - changedItems.push_back(parentItem); - } - } - } - - inMsgAsReadUnread = false; - - if (changedItems.size()) { - for (std::list::iterator it = changedItems.begin(); it != changedItems.end(); it++) { - CalculateIconsAndFonts(*it); - } - updateMessageSummaryList(mCurrForumId); - } -} - -void ForumsV2Dialog::markMsgAsReadUnread (bool bRead, bool bChildren, bool bForum) -{ - if (mCurrForumId.empty() || !IS_GROUP_SUBSCRIBED(subscribeFlags)) { - return; - } - - /* get selected messages */ - QList Rows; - if (bForum) { - int itemCount = ui.threadTreeWidget->topLevelItemCount(); - for (int item = 0; item < itemCount; item++) { - Rows.push_back(ui.threadTreeWidget->topLevelItem(item)); - } - } else { - getSelectedMsgCount (&Rows, NULL, NULL); - } - - if (bChildren) { - /* add children */ - QList AllRows; - - while (Rows.isEmpty() == false) { - QTreeWidgetItem *pRow = Rows.takeFirst(); - - /* add only items with the right state or with not RSGXS_MSG_STATUS_READ */ - uint32_t status = pRow->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); - if (IS_MSG_UNREAD(status) == bRead || (status & RSGXS_MSG_STATUS_READ) == 0) { - AllRows.append(pRow); - } - - for (int i = 0; i < pRow->childCount(); i++) { - /* add child to main list and let the main loop do the work */ - Rows.append(pRow->child(i)); - } - } - - if (AllRows.isEmpty()) { - /* nothing to do */ - return; - } - - setMsgAsReadUnread (AllRows, bRead); - - return; - } - - setMsgAsReadUnread (Rows, bRead); -} - -void ForumsV2Dialog::markMsgAsRead() -{ - markMsgAsReadUnread(true, false, false); -} - -void ForumsV2Dialog::markMsgAsReadChildren() -{ - markMsgAsReadUnread(true, true, false); -} - -void ForumsV2Dialog::markMsgAsReadAll() -{ - markMsgAsReadUnread(true, true, true); -} - -void ForumsV2Dialog::markMsgAsUnread() -{ - markMsgAsReadUnread(false, false, false); -} - -void ForumsV2Dialog::markMsgAsUnreadChildren() -{ - markMsgAsReadUnread(false, true, false); -} - -void ForumsV2Dialog::markMsgAsUnreadAll() -{ - markMsgAsReadUnread(false, true, true); -} - -void ForumsV2Dialog::copyForumLink() -{ - if (mCurrForumId.empty()) { - return; - } - -// THIS CODE CALLS getForumInfo() to verify that the Ids are valid. -// As we are switching to Request/Response this is now harder to do... -// So not bothering any more - shouldn't be necessary. -// IF we get errors - fix them, rather than patching here. -#if 0 - ForumInfo fi; - if (rsForumsV2->getForumInfo(mCurrForumId, fi)) { - RetroShareLink link; - if (link.createForum(fi.forumId, "")) { - QList urls; - urls.push_back(link); - RSLinkClipboard::copyLinks(urls); - } - } -#endif - - { - RetroShareLink link; - if (link.createForum(mCurrForumId, "")) - { - QList urls; - urls.push_back(link); - RSLinkClipboard::copyLinks(urls); - } - } -} - - - - -void ForumsV2Dialog::copyMessageLink() -{ - if (mCurrForumId.empty() || mCurrThreadId.empty()) { - return; - } - -// SEE NOTE In fn above. -#if 0 - ForumInfo fi; - if (rsForumsV2->getForumInfo(mCurrForumId, fi)) { - RetroShareLink link; - if (link.createForum(mCurrForumId, mCurrThreadId)) { - QList urls; - urls.push_back(link); - RSLinkClipboard::copyLinks(urls); - } - } -#endif - - { - RetroShareLink link; - if (link.createForum(mCurrForumId, mCurrThreadId)) - { - QList urls; - urls.push_back(link); - RSLinkClipboard::copyLinks(urls); - } - } -} - - -void ForumsV2Dialog::newforum() -{ - CreateForumV2 cf (this); - cf.exec (); -} - -void ForumsV2Dialog::createmessage() -{ - if (mCurrForumId.empty () || !IS_GROUP_SUBSCRIBED(subscribeFlags)) { - return; - } - - CreateForumV2Msg *cfm = new CreateForumV2Msg(mCurrForumId, mCurrThreadId); - cfm->show(); - - /* window will destroy itself! */ -} - -void ForumsV2Dialog::createthread() -{ - if (mCurrForumId.empty ()) { - QMessageBox::information(this, tr("RetroShare"), tr("No Forum Selected!")); - return; - } - - CreateForumV2Msg *cfm = new CreateForumV2Msg(mCurrForumId, ""); - cfm->setWindowTitle(tr("Start New Thread")); - cfm->show(); - - /* window will destroy itself! */ -} - -void ForumsV2Dialog::subscribeToForum() -{ - forumSubscribe(true); -} - -void ForumsV2Dialog::unsubscribeToForum() -{ - forumSubscribe(false); -} - -void ForumsV2Dialog::forumSubscribe(bool subscribe) -{ - if (mCurrForumId.empty()) { - return; - } - - uint32_t flags = RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED; - if (!subscribe) - { - flags = 0; - } - - rsForumsV2->setGroupSubscribeFlags(mCurrForumId, flags, RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED); - -} - -void ForumsV2Dialog::showForumDetails() -{ - if (mCurrForumId.empty()) { - return; - } - -#ifndef DISABLE_OTHERCLASSES - ForumV2Details fui; - - fui.showDetails (mCurrForumId); - fui.exec (); -#endif -} - -void ForumsV2Dialog::editForumDetails() -{ - if (mCurrForumId.empty()) { - return; - } - -#ifndef DISABLE_OTHERCLASSES - EditForumV2Details editUi(mCurrForumId, this); - editUi.exec(); -#endif -} - -static QString buildReplyHeader(const RsMsgMetaData &meta) -{ - RetroShareLink link; - link.createMessage(meta.mAuthorId, ""); - QString from = link.toHtml(); - - QDateTime qtime; - qtime.setTime_t(meta.mPublishTs); - - QString header = QString("-----%1-----").arg(QApplication::translate("ForumsV2Dialog", "Original Message")); - header += QString("
%1: %2
").arg(QApplication::translate("ForumsV2Dialog", "From"), from); - - header += QString("
%1: %2
").arg(QApplication::translate("ForumsV2Dialog", "Sent"), qtime.toString(Qt::SystemLocaleLongDate)); - header += QString("%1: %2

").arg(QApplication::translate("ForumsV2Dialog", "Subject"), QString::fromUtf8(meta.mMsgName.c_str())); - header += "
"; - - header += QApplication::translate("ForumsV2Dialog", "On %1, %2 wrote:").arg(qtime.toString(Qt::SystemLocaleShortDate), from); - - return header; -} - -void ForumsV2Dialog::replytomessage() -{ - if (mCurrForumId.empty() || mCurrThreadId.empty()) { - QMessageBox::information(this, tr("RetroShare"),tr("You can't reply to a non-existant Message")); - return; - } - - - requestMsgData_ReplyMessage(mCurrThreadId); -} - -void ForumsV2Dialog::replyMessageData(const RsForumV2Msg &msg) -{ - if ((msg.mMeta.mGroupId != mCurrForumId) || (msg.mMeta.mMsgId != mCurrThreadId)) - { - std::cerr << "ForumsV2Dialog::replyMessageData() ERROR Message Ids have changed!"; - std::cerr << std::endl; - return; - } - - // NB: TODO REMOVE rsPeers references. - if (rsPeers->getPeerName(msg.mMeta.mAuthorId) !="") - { - MessageComposer *nMsgDialog = MessageComposer::newMsg(); - nMsgDialog->setTitleText(QString::fromUtf8(msg.mMeta.mMsgName.c_str()), MessageComposer::REPLY); - - nMsgDialog->setQuotedMsg(QString::fromUtf8(msg.mMsg.c_str()), buildReplyHeader(msg.mMeta)); - - nMsgDialog->addRecipient(MessageComposer::TO, msg.mMeta.mAuthorId, false); - nMsgDialog->show(); - nMsgDialog->activateWindow(); - - /* window will destroy itself! */ - } - else - { - QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to an Anonymous Author")); - } -} - -void ForumsV2Dialog::changedViewBox() -{ - if (m_bProcessSettings) { - return; - } - - // save index - Settings->setValueToGroup("ForumsV2Dialog", "viewBox", ui.viewBox->currentIndex()); - - insertThreads(); -} - -void ForumsV2Dialog::filterColumnChanged() -{ - if (m_bProcessSettings) { - return; - } - - int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); - if (filterColumn == COLUMN_THREAD_CONTENT) { - // need content ... refill - insertThreads(); - } else { - filterItems(ui.filterLineEdit->text()); - } - - // save index - Settings->setValueToGroup("ForumsV2Dialog", "filterColumn", filterColumn); -} - -void ForumsV2Dialog::filterItems(const QString& text) -{ - int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); - - int nCount = ui.threadTreeWidget->topLevelItemCount (); - for (int nIndex = 0; nIndex < nCount; nIndex++) { - filterItem(ui.threadTreeWidget->topLevelItem(nIndex), text, filterColumn); - } -} - -void ForumsV2Dialog::shareKey() -{ - ShareKey shareUi(this, 0, mCurrForumId, FORUM_KEY_SHARE); - shareUi.exec(); -} - -bool ForumsV2Dialog::filterItem(QTreeWidgetItem *pItem, const QString &text, int filterColumn) -{ - bool bVisible = true; - - if (text.isEmpty() == false) { - if (pItem->text(filterColumn).contains(text, Qt::CaseInsensitive) == false) { - bVisible = false; - } - } - - int nVisibleChildCount = 0; - int nCount = pItem->childCount(); - for (int nIndex = 0; nIndex < nCount; nIndex++) { - if (filterItem(pItem->child(nIndex), text, filterColumn)) { - nVisibleChildCount++; - } - } - - if (bVisible || nVisibleChildCount) { - pItem->setHidden(false); - } else { - pItem->setHidden(true); - } - - return (bVisible || nVisibleChildCount); -} - -void ForumsV2Dialog::updateMessageSummaryList(std::string forumId) -{ - QTreeWidgetItem *items[2] = { yourForums, subscribedForums }; - - for (int item = 0; item < 2; item++) { - int child; - int childCount = items[item]->childCount(); - for (child = 0; child < childCount; child++) { - QTreeWidgetItem *childItem = items[item]->child(child); - std::string childId = ui.forumTreeWidget->itemId(childItem).toStdString(); - if (childId.empty()) { - continue; - } - - if (forumId.empty() || childId == forumId) { - /* calculate unread messages */ - unsigned int newMessageCount = 0; - unsigned int unreadMessageCount = 0; - //rsForumsV2->getMessageCount(childId, newMessageCount, unreadMessageCount); - std::cerr << "IMPLEMENT rsForumsV2->getMessageCount()"; - std::cerr << std::endl; - - ui.forumTreeWidget->setUnreadCount(childItem, unreadMessageCount); - - if (forumId.empty() == false) { - /* Calculate only this forum */ - break; - } - } - } - } -} - -bool ForumsV2Dialog::navigate(const std::string& forumId, const std::string& msgId) -{ - if (forumId.empty()) { - return false; - } - - if (ui.forumTreeWidget->activateId(QString::fromStdString(forumId), msgId.empty()) == NULL) { - return false; - } - - /* Threads are filled in changedForum */ - if (mCurrForumId != forumId) { - return false; - } - - if (msgId.empty()) { - return true; - } - - if (mThreadLoading) { - mThreadLoad.FocusMsgId = msgId; - return true; - } - - /* Search exisiting item */ - QTreeWidgetItemIterator itemIterator(ui.threadTreeWidget); - QTreeWidgetItem *item = NULL; - while ((item = *itemIterator) != NULL) { - itemIterator++; - - if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == msgId) { - ui.threadTreeWidget->setCurrentItem(item); - ui.threadTreeWidget->setFocus(); - return true; - } - } - - return false; -} - -void ForumsV2Dialog::generateMassData() -{ -#ifdef DEBUG_FORUMS - if (mCurrForumId.empty ()) { - return; - } - - if (QMessageBox::question(this, "Generate mass data", "Do you really want to generate mass data ?", QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No) { - return; - } - - for (int thread = 1; thread < 1000; thread++) { - ForumMsgInfo threadInfo; - threadInfo.forumId = mCurrForumId; - threadInfo.title = QString("Test %1").arg(thread, 3, 10, QChar('0')).toStdWString(); - threadInfo.msg = QString("That is only a test").toStdWString(); - - if (rsForumsV2->ForumMessageSend(threadInfo) == false) { - return; - } - - for (int msg = 1; msg < 3; msg++) { - ForumMsgInfo msgInfo; - msgInfo.forumId = mCurrForumId; - msgInfo.threadId = threadInfo.msgId; - msgInfo.parentId = threadInfo.msgId; - msgInfo.title = threadInfo.title; - msgInfo.msg = threadInfo.msg; - - if (rsForumsV2->ForumMessageSend(msgInfo) == false) { - return; - } - } - } -#endif -} - - - -/*********************** **** **** **** ***********************/ -/** Request / Response of Data ********************************/ -/*********************** **** **** **** ***********************/ - -#define FORUMSV2DIALOG_LISTING 1 -#define FORUMSV2DIALOG_CURRENTFORUM 2 -#define FORUMSV2DIALOG_INSERTTHREADS 3 -#define FORUMSV2DIALOG_INSERTCHILD 4 -#define FORUMV2DIALOG_INSERT_POST 5 -#define FORUMV2DIALOG_REPLY_MESSAGE 6 - - -void ForumsV2Dialog::insertForums() -{ - requestGroupSummary(); -} - -void ForumsV2Dialog::requestGroupSummary() -{ - std::cerr << "ForumsV2Dialog::requestGroupSummary()"; - std::cerr << std::endl; - - std::list ids; - RsTokReqOptions opts; - uint32_t token; - mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, ids, FORUMSV2DIALOG_LISTING); -} - -void ForumsV2Dialog::loadGroupSummary(const uint32_t &token) -{ - std::cerr << "ForumsV2Dialog::loadGroupSummary()"; - std::cerr << std::endl; - - std::list groupInfo; - rsForumsV2->getGroupSummary(token, groupInfo); - - if (groupInfo.size() > 0) - { - insertForumsData(groupInfo); - } - else - { - std::cerr << "ForumsV2Dialog::loadGroupSummary() ERROR No Groups..."; - std::cerr << std::endl; - } -} - -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ - - - -void ForumsV2Dialog::requestGroupSummary_CurrentForum(const std::string &forumId) -{ - RsTokReqOptions opts; - - std::list grpIds; - grpIds.push_back(forumId); - - std::cerr << "ForumsV2Dialog::requestGroupSummary_CurrentForum(" << forumId << ")"; - std::cerr << std::endl; - - uint32_t token; - mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds, FORUMSV2DIALOG_CURRENTFORUM); -} - -void ForumsV2Dialog::loadGroupSummary_CurrentForum(const uint32_t &token) -{ - std::cerr << "ForumsV2Dialog::loadGroupSummary_CurrentForum()"; - std::cerr << std::endl; - - std::list groupInfo; - rsForumsV2->getGroupSummary(token, groupInfo); - - if (groupInfo.size() == 1) - { - RsGroupMetaData fi = groupInfo.front(); - insertForumThreads(fi); - } - else - { - std::cerr << "ForumsV2Dialog::loadGroupSummary_CurrentForum() ERROR Invalid Number of Groups..."; - std::cerr << std::endl; - } -} - -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ - - - -void ForumsV2Dialog::loadCurrentForumThreads(const std::string &forumId) -{ - - std::cerr << "ForumsV2Dialog::loadCurrentForumThreads(" << forumId << ")"; - std::cerr << std::endl; - - /* if already active -> kill current loading */ - if (mThreadLoading) - { - /* Cleanup */ - std::cerr << "ForumsV2Dialog::loadCurrentForumThreads() Cleanup old Threads"; - std::cerr << std::endl; - - /* Wipe Widget Tree */ - mThreadLoad.Items.clear(); - - /* Stop all active requests */ - std::map::iterator it; - for(it = mThreadLoad.MsgTokens.begin(); it != mThreadLoad.MsgTokens.end(); it++) - { - std::cerr << "ForumsV2Dialog::loadCurrentForumThreads() Canceling Request: " << it->first; - std::cerr << std::endl; - - mForumQueue->cancelRequest(it->first); - } - - mThreadLoad.MsgTokens.clear(); - mThreadLoad.ItemToExpand.clear(); - } - - /* initiate loading */ - std::cerr << "ForumsV2Dialog::loadCurrentForumThreads() Initiating Loading"; - std::cerr << std::endl; - - mThreadLoading = true; - - mThreadLoad.ForumId = mCurrForumId; - mThreadLoad.FilterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); - mThreadLoad.ViewType = ui.viewBox->currentIndex(); - mThreadLoad.FillComplete = false; - - if (lastViewType != mThreadLoad.ViewType || lastForumID != mCurrForumId) { - mThreadLoad.FillComplete = true; - } - - mThreadLoad.FlatView = false; - mThreadLoad.UseChildTS = false; - mThreadLoad.ExpandNewMessages = Settings->getExpandNewMessages(); - mThreadLoad.SubscribeFlags = subscribeFlags; - - if (mThreadLoad.ViewType == VIEW_FLAT) { - ui.threadTreeWidget->setRootIsDecorated(false); - } else { - ui.threadTreeWidget->setRootIsDecorated(true); - } - - switch(mThreadLoad.ViewType) - { - case VIEW_LAST_POST: - mThreadLoad.UseChildTS = true; - break; - case VIEW_FLAT: - mThreadLoad.FlatView = true; - break; - case VIEW_THREADED: - break; - } - - requestGroupThreadData_InsertThreads(forumId); -} - - - -void ForumsV2Dialog::requestGroupThreadData_InsertThreads(const std::string &forumId) -{ - RsTokReqOptions opts; - - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; - - std::list grpIds; - grpIds.push_back(forumId); - - std::cerr << "ForumsV2Dialog::requestGroupThreadData_InsertThreads(" << forumId << ")"; - std::cerr << std::endl; - - uint32_t token; - mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, FORUMSV2DIALOG_INSERTTHREADS); -} - - -void ForumsV2Dialog::loadGroupThreadData_InsertThreads(const uint32_t &token) -{ - std::cerr << "ForumsV2Dialog::loadGroupThreadData_InsertThreads()"; - std::cerr << std::endl; - - bool moreData = true; - bool someData = false; - while(moreData) - { - RsForumV2Msg msg; - if (rsForumsV2->getMsgData(token, msg)) - { - std::cerr << "ForumsV2Dialog::loadGroupThreadData_InsertThreads() MsgId: " << msg.mMeta.mMsgId; - std::cerr << std::endl; - - loadForumBaseThread(msg); - someData = true; - } - else - { - moreData = false; - } - } - - /* completed with no data */ - if (!someData) - { - fillThreadFinished(); - } -} - -bool ForumsV2Dialog::convertMsgToThreadWidget(const RsForumV2Msg &msgInfo, std::string authorName, - bool useChildTS, uint32_t filterColumn, QTreeWidgetItem *item) -{ - QString text; - - { - QDateTime qtime; - if (useChildTS) - qtime.setTime_t(msgInfo.mMeta.mChildTs); - else - qtime.setTime_t(msgInfo.mMeta.mPublishTs); - - text = qtime.toString("yyyy-MM-dd hh:mm:ss"); - if (useChildTS) - { - QDateTime qtime2; - qtime2.setTime_t(msgInfo.mMeta.mPublishTs); - QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss"); - text += " / "; - text += timestamp2; - } - item->setText(COLUMN_THREAD_DATE, text); - } - - item->setText(COLUMN_THREAD_TITLE, ForumsV2Dialog::titleFromInfo(msgInfo.mMeta)); - - text = QString::fromUtf8(authorName.c_str()); - - if (text.isEmpty()) - { - item->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous")); - } - else - { - item->setText(COLUMN_THREAD_AUTHOR, text); - } - - if (msgInfo.mMeta.mMsgFlags & RS_DISTRIB_AUTHEN_REQ) - { - item->setText(COLUMN_THREAD_SIGNED, tr("signed")); - item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signed.png")); - } - else - { - item->setText(COLUMN_THREAD_SIGNED, tr("none")); - item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signature-unknown.png")); - } - - if (filterColumn == COLUMN_THREAD_CONTENT) { - // need content for filter - QTextDocument doc; - doc.setHtml(QString::fromUtf8(msgInfo.mMsg.c_str())); - item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" "))); - } - - item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msgInfo.mMeta.mMsgId)); - -#if 0 - if (IS_GROUP_SUBSCRIBED(subscribeFlags) && !(msginfo.mMsgFlags & RS_DISTRIB_MISSING_MSG)) { - rsForumsV2->getMessageStatus(msginfo.forumId, msginfo.msgId, status); - } else { - // show message as read - status = RSGXS_MSG_STATUS_READ; - } -#endif - item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, msgInfo.mMeta.mMsgStatus); - - item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msgInfo.mMeta.mMsgFlags & RS_DISTRIB_MISSING_MSG) ? true : false); - - return true; -} - - -void ForumsV2Dialog::loadForumBaseThread(const RsForumV2Msg &msg) -{ - std::string authorName = rsPeers->getPeerName(msg.mMeta.mAuthorId); - - QTreeWidgetItem *item = new QTreeWidgetItem(); // no Parent. - - convertMsgToThreadWidget(msg, authorName, mThreadLoad.UseChildTS, mThreadLoad.FilterColumn, item); - - /* request Children Data */ - uint32_t token; - requestChildData_InsertThreads(token, msg.mMeta.mMsgId); - - /* store pair of (token, item) */ - mThreadLoad.MsgTokens[token] = item; - - /* add item to final tree */ - mThreadLoad.Items.append(item); -} - - - -/*********************** **** **** **** ***********************/ - -void ForumsV2Dialog::requestChildData_InsertThreads(uint32_t &token, const std::string &parentId) -{ - RsTokReqOptions opts; - - opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; - - std::list msgIds; - msgIds.push_back(parentId); - - std::cerr << "ForumsV2Dialog::requestChildData_InsertThreads(" << parentId << ")"; - std::cerr << std::endl; - - mForumQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, FORUMSV2DIALOG_INSERTCHILD); -} - - -void ForumsV2Dialog::loadChildData_InsertThreads(const uint32_t &token) -{ - std::cerr << "ForumsV2Dialog::loadChildData_InsertThreads()"; - std::cerr << std::endl; - - /* find the matching *item */ - std::map::iterator it; - it = mThreadLoad.MsgTokens.find(token); - if (it == mThreadLoad.MsgTokens.end()) - { - std::cerr << "ForumsV2Dialog::loadGroupThreadData_InsertThreads() ERROR Missing Token->Parent in Map"; - std::cerr << std::endl; - /* finished with this one */ - return; - } - - QTreeWidgetItem *parent = it->second; - // cleanup map. - mThreadLoad.MsgTokens.erase(it); - - std::cerr << "ForumsV2Dialog::loadGroupThreadData_InsertThreads()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsForumV2Msg msg; - if (rsForumsV2->getMsgData(token, msg)) - { - std::cerr << "ForumsV2Dialog::loadGroupThreadData_InsertThreads() MsgId: " << msg.mMeta.mMsgId; - std::cerr << std::endl; - - loadForumChildMsg(msg, parent); - } - else - { - moreData = false; - } - } - - - /* check for completion */ - if (mThreadLoad.MsgTokens.size() == 0) - { - /* finished */ - /* push data into GUI */ - fillThreadFinished(); - } -} - -void ForumsV2Dialog::loadForumChildMsg(const RsForumV2Msg &msg, QTreeWidgetItem *parent) -{ - std::string authorName = rsPeers->getPeerName(msg.mMeta.mAuthorId); - - QTreeWidgetItem *child = NULL; - - if (mThreadLoad.FlatView) - { - child = new QTreeWidgetItem(); // no Parent. - } - else - { - child = new QTreeWidgetItem(parent); - } - - - convertMsgToThreadWidget(msg, authorName, mThreadLoad.UseChildTS, mThreadLoad.FilterColumn, child); - - /* request Children Data */ - uint32_t token; - requestChildData_InsertThreads(token, msg.mMeta.mMsgId); - - /* store pair of (token, item) */ - mThreadLoad.MsgTokens[token] = child; - - // Leave this here... BUT IT WILL NEED TO BE FIXED. - if (mThreadLoad.FillComplete && mThreadLoad.ExpandNewMessages && IS_MSG_UNREAD(msg.mMeta.mMsgStatus)) - { - QTreeWidgetItem *pParent = child; - while ((pParent = pParent->parent()) != NULL) - { - if (std::find(mThreadLoad.ItemToExpand.begin(), mThreadLoad.ItemToExpand.end(), pParent) == mThreadLoad.ItemToExpand.end()) - { - mThreadLoad.ItemToExpand.push_back(pParent); - } - } - } - - if (mThreadLoad.FlatView) - { - /* add item to final tree */ - mThreadLoad.Items.append(child); - } -} - - - -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ - -void ForumsV2Dialog::requestMsgData_InsertPost(const std::string &msgId) -{ - RsTokReqOptions opts; - - std::list msgIds; - msgIds.push_back(msgId); - - std::cerr << "ForumsV2Dialog::requestMsgData_InsertPost(" << msgId << ")"; - std::cerr << std::endl; - - - uint32_t token; - mForumQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, FORUMV2DIALOG_INSERT_POST); -} - - -void ForumsV2Dialog::loadMsgData_InsertPost(const uint32_t &token) -{ - std::cerr << "ForumsV2Dialog::loadMsgData_InsertPost()"; - std::cerr << std::endl; - - RsForumV2Msg msg; - if (rsForumsV2->getMsgData(token, msg)) - { - insertPostData(msg); - } - else - { - std::cerr << "ForumsV2Dialog::loadMsgData_InsertPost() ERROR Missing Message Data..."; - std::cerr << std::endl; - } -} - - -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ - -void ForumsV2Dialog::requestMsgData_ReplyMessage(const std::string &msgId) -{ - RsTokReqOptions opts; - - std::list msgIds; - msgIds.push_back(msgId); - - std::cerr << "ForumsV2Dialog::requestMsgData_ReplyMessage(" << msgId << ")"; - std::cerr << std::endl; - - uint32_t token; - mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, FORUMV2DIALOG_REPLY_MESSAGE); -} - - -void ForumsV2Dialog::loadMsgData_ReplyMessage(const uint32_t &token) -{ - std::cerr << "ForumsV2Dialog::loadMsgData_ReplyMessage()"; - std::cerr << std::endl; - - RsForumV2Msg msg; - if (rsForumsV2->getMsgData(token, msg)) - { - replyMessageData(msg); - } - else - { - std::cerr << "ForumsV2Dialog::loadMsgData_ReplyMessage() ERROR Missing Message Data..."; - std::cerr << std::endl; - } -} - - -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ - - - -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ -/*********************** **** **** **** ***********************/ - -void ForumsV2Dialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "ForumsV2Dialog::loadRequest() UserType: " << req.mUserType; - std::cerr << std::endl; - - if (queue == mForumQueue) - { - /* now switch on req */ - switch(req.mUserType) - { - case FORUMSV2DIALOG_LISTING: - loadGroupSummary(req.mToken); - break; - - case FORUMSV2DIALOG_CURRENTFORUM: - loadGroupSummary_CurrentForum(req.mToken); - break; - - case FORUMSV2DIALOG_INSERTTHREADS: - loadGroupThreadData_InsertThreads(req.mToken); - break; - - case FORUMSV2DIALOG_INSERTCHILD: - loadChildData_InsertThreads(req.mToken); - break; - - case FORUMV2DIALOG_INSERT_POST: - loadMsgData_InsertPost(req.mToken); - break; - - case FORUMV2DIALOG_REPLY_MESSAGE: - loadMsgData_ReplyMessage(req.mToken); - break; - - default: - std::cerr << "ForumsV2Dialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/ForumsV2Dialog.h b/retroshare-gui/src/gui/ForumsV2Dialog.h deleted file mode 100644 index c4651a40c..000000000 --- a/retroshare-gui/src/gui/ForumsV2Dialog.h +++ /dev/null @@ -1,270 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2008 Robert Fernie - * - * 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 (at your option) 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. - * - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#ifndef _FORUMSV2DIALOG_H -#define _FORUMSV2DIALOG_H - -#include - -#include "mainpage.h" -#include "RsAutoUpdatePage.h" -#include "ui_ForumsV2Dialog.h" - -#include - -#include "util/TokenQueue.h" - -#include - -class ForumInfo; - - -/* These are all the parameters that are required for thread loading. - * They are kept static for the load duration. - */ - -class ForumsV2ThreadLoadParameters -{ - public: - - std::string ForumId; - std::string FocusMsgId; - - uint32_t SubscribeFlags; - int ViewType; - uint32_t FilterColumn; - - std::map MsgTokens; - QList Items; - QList ItemToExpand; - - bool FillComplete; - bool FlatView; - bool UseChildTS; - bool ExpandNewMessages; -}; - - - - - - -class ForumsV2Dialog : public RsAutoUpdatePage, public TokenResponse -{ - Q_OBJECT - -public: - ForumsV2Dialog(QWidget *parent = 0); - ~ForumsV2Dialog(); - - bool navigate(const std::string& forumId, const std::string& msgId); - - /* overloaded from RsAuthUpdatePage */ - virtual void updateDisplay(); - - // Callback for all Loads. -virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); - -protected: - bool eventFilter(QObject *obj, QEvent *ev); - -private slots: - /** Create the context popup menu and it's submenus */ - void forumListCustomPopupMenu( QPoint point ); - void threadListCustomPopupMenu( QPoint point ); - void restoreForumKeys(); - void newforum(); - - void changedForum(const QString &id); - void changedThread(); - void clickedThread (QTreeWidgetItem *item, int column); - - void replytomessage(); - void replyMessageData(const RsForumV2Msg &msg); - - //void print(); - //void printpreview(); - - //void removemessage(); - void markMsgAsRead(); - void markMsgAsReadChildren(); - void markMsgAsReadAll(); - void markMsgAsUnread(); - void markMsgAsUnreadAll(); - void markMsgAsUnreadChildren(); - void copyForumLink(); - void copyMessageLink(); - - /* handle splitter */ - void togglethreadview(); - - void createthread(); - void createmessage(); - - void subscribeToForum(); - void unsubscribeToForum(); - - void showForumDetails(); - void editForumDetails(); - - void previousMessage (); - void nextMessage (); - void nextUnreadMessage(); - void downloadAllFiles(); - - void changedViewBox(); - - void filterColumnChanged(); - //void filterRegExpChanged(); - ///void clearFilter(); - - void generateMassData(); - - void fillThreadFinished(); - void fillThreadProgress(int current, int count); - - void shareKey(); - -private: - void insertForums(); - void insertThreads(); - void insertPost(); - void insertPostData(const RsForumV2Msg &msg); // Second Half. - - // Utility Fns. - QString titleFromInfo(const RsMsgMetaData &meta); - QString messageFromInfo(const RsForumV2Msg &msg); - - void forumMsgReadStatusChanged(const QString &forumId, const QString &msgId, int status); - - void updateMessageSummaryList(std::string forumId); - //void forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo); - void forumInfoToGroupItemInfo(const RsGroupMetaData &forumInfo, GroupItemInfo &groupItemInfo); - - void forumSubscribe(bool subscribe); - void FillThreads(QList &ThreadList, bool bExpandNewMessages, QList &itemToExpand); - void FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool bExpandNewMessages, QList &itemToExpand); - - int getSelectedMsgCount(QList *pRows, QList *pRowsRead, QList *pRowsUnread); - void setMsgAsReadUnread(QList &Rows, bool bRead); - void markMsgAsReadUnread(bool bRead, bool bChildren, bool bForum); - void CalculateIconsAndFonts(QTreeWidgetItem *pItem = NULL); - void CalculateIconsAndFonts(QTreeWidgetItem *pItem, bool &bHasReadChilddren, bool &bHasUnreadChilddren); - - void processSettings(bool bLoad); - void togglethreadview_internal(); - - void filterItems(const QString& text); - bool filterItem(QTreeWidgetItem *pItem, const QString &text, int filterColumn); - - // New Request/Response Loading Functions. - void insertForumsData(const std::list &forumList); - void insertForumThreads(const RsGroupMetaData &fi); - - void requestGroupSummary(); - void loadGroupSummary(const uint32_t &token); - - void requestGroupSummary_CurrentForum(const std::string &forumId); - void loadGroupSummary_CurrentForum(const uint32_t &token); - - void loadCurrentForumThreads(const std::string &forumId); - void requestGroupThreadData_InsertThreads(const std::string &forumId); - void loadGroupThreadData_InsertThreads(const uint32_t &token); - void loadForumBaseThread(const RsForumV2Msg &msg); - - void requestChildData_InsertThreads(uint32_t &token, const std::string &parentId); - void loadChildData_InsertThreads(const uint32_t &token); - void loadForumChildMsg(const RsForumV2Msg &msg, QTreeWidgetItem *parent); - - void requestMsgData_InsertPost(const std::string &msgId); - void loadMsgData_InsertPost(const uint32_t &token); - void requestMsgData_ReplyMessage(const std::string &msgId); - void loadMsgData_ReplyMessage(const uint32_t &token); - - bool convertMsgToThreadWidget(const RsForumV2Msg &msgInfo, std::string authorName, - bool useChildTS, uint32_t filterColumn, QTreeWidgetItem *item); - - TokenQueue *mForumQueue; - - - bool m_bProcessSettings; - - QTreeWidgetItem *yourForums; - QTreeWidgetItem *subscribedForums; - QTreeWidgetItem *popularForums; - QTreeWidgetItem *otherForums; - - std::string mCurrForumId; - std::string mCurrThreadId; - int subscribeFlags; - - int lastViewType; - std::string lastForumID; - - bool inMsgAsReadUnread; - //ForumsV2FillThread *fillThread; - - // New Datatypes to replace the FillThread. - bool mThreadLoading; - ForumsV2ThreadLoadParameters mThreadLoad; - - - /** Qt Designer generated object */ - Ui::ForumsV2Dialog ui; -}; - -#if 0 -class ForumsV2FillThread : public QThread -{ - Q_OBJECT - -public: - ForumsV2FillThread(ForumsV2Dialog *parent); - ~ForumsV2FillThread(); - - void run(); - void stop(); - bool wasStopped() { return stopped; } - -signals: - void progress(int current, int count); - -public: - std::string forumId; - int filterColumn; - int subscribeFlags; - bool fillComplete; - int viewType; - bool expandNewMessages; - std::string focusMsgId; - - QList Items; - QList ItemToExpand; - -private: - volatile bool stopped; -}; - -#endif - - -#endif - diff --git a/retroshare-gui/src/gui/ForumsV2Dialog.ui b/retroshare-gui/src/gui/ForumsV2Dialog.ui deleted file mode 100644 index af9688232..000000000 --- a/retroshare-gui/src/gui/ForumsV2Dialog.ui +++ /dev/null @@ -1,714 +0,0 @@ - - - ForumsV2Dialog - - - - 0 - 0 - 732 - 420 - - - - Qt::DefaultContextMenu - - - - 9 - - - 9 - - - - - Qt::Horizontal - - - - - 300 - 300 - - - - QFrame::NoFrame - - - - 0 - - - 0 - - - - - QFrame::Box - - - QFrame::Sunken - - - - 2 - - - - - - 24 - 24 - - - - - - - :/images/konversation.png - - - true - - - - - - - - 10 - 75 - true - - - - Forums - - - - - - - Qt::Horizontal - - - - 123 - 13 - - - - - - - - Qt::NoFocus - - - Display - - - - :/images/looknfeel.png:/images/looknfeel.png - - - - 32 - 16 - - - - QToolButton::InstantPopup - - - true - - - - - - - Qt::NoFocus - - - Create Forum - - - - :/images/new_forum16.png:/images/new_forum16.png - - - - 32 - 16 - - - - true - - - - - - - - - - - 0 - 0 - - - - - 9 - - - - - -1 - -1 - - - - - - - - - Qt::Vertical - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 10 - 75 - true - - - - Forum: - - - - - - - - 0 - 0 - - - - - 10 - 75 - true - - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - Last Post - - - - - Threaded View - - - - - Flat View - - - - - - - - - - - 9 - - - - Qt::CustomContextMenu - - - true - - - true - - - - Title - - - - - - - - - :/images/message-state-header.png:/images/message-state-header.png - - - - - Date - - - - - Author - - - - - Signed - - - - - - - - - - - 0 - 0 - - - - - 10 - 75 - true - - - - Thread: - - - - - - - - 10 - 75 - true - - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - false - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - Qt::NoFocus - - - Previous Thread - - - - - - - :/images/back.png:/images/back.png - - - - - - - false - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - Qt::NoFocus - - - Next Thread - - - - - - - :/images/forward.png:/images/forward.png - - - - - - - - 24 - 24 - - - - Qt::NoFocus - - - - - - - :/images/edit_remove24.png:/images/edit_remove24.png - - - true - - - true - - - - - - - - 24 - 24 - - - - Qt::NoFocus - - - Download all files - - - - :/images/down.png:/images/down.png - - - - - - - - 0 - 0 - - - - Next unread - - - - - - - - - - 0 - 32 - - - - QFrame::Box - - - QFrame::Sunken - - - - 2 - - - - - Qt::NoFocus - - - Start new Thread for Selected Forum - - - - :/images/mail_new.png:/images/mail_new.png - - - - 24 - 16 - - - - true - - - - - - - Qt::NoFocus - - - Reply Message - - - - :/images/mail_reply.png:/images/mail_reply.png - - - - 24 - 16 - - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 40 - 20 - - - - - - - - 2 - - - - - - - - :/images/find-16.png - - - - - - - Search forums - - - - - - - - - - 0 - 0 - - - - - - - - 1 - - - - Date - - - - - Title - - - - - Author - - - - - Content - - - - - - - - - - - - - - 75 - true - - - - Loading - - - - - - - - 16777215 - 25 - - - - 1000 - - - 0 - - - - - - - - - - - 0 - 10 - - - - - 9 - - - - - - - - - - Print - - - - - PrintPreview - - - - - - LinkTextBrowser - QTextBrowser -
gui/common/LinkTextBrowser.h
-
- - GroupTreeWidget - QWidget -
gui/common/GroupTreeWidget.h
- 1 -
- - LineEditClear - QLineEdit -
gui/common/LineEditClear.h
-
-
- - - - -
diff --git a/retroshare-gui/src/gui/GxsForumsDialog.cpp b/retroshare-gui/src/gui/GxsForumsDialog.cpp new file mode 100644 index 000000000..714eb300e --- /dev/null +++ b/retroshare-gui/src/gui/GxsForumsDialog.cpp @@ -0,0 +1,716 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "GxsForumsDialog.h" +#include "gxs/GxsForumGroupDialog.h" +#include "gxsforums/GxsForumThreadWidget.h" + +#include "settings/rsharesettings.h" +#include "RetroShareLink.h" +#include "channels/ShareKey.h" +#include "notifyqt.h" + +// These should be in retroshare/ folder. +#include "gxs/rsgxsflags.h" + +//#define DEBUG_FORUMS + +/* Images for TreeWidget */ +#define IMAGE_FOLDER ":/images/folder16.png" +#define IMAGE_FOLDERGREEN ":/images/folder_green.png" +#define IMAGE_FOLDERRED ":/images/folder_red.png" +#define IMAGE_FOLDERYELLOW ":/images/folder_yellow.png" +#define IMAGE_FORUM ":/images/konversation.png" +#define IMAGE_SUBSCRIBE ":/images/edit_add24.png" +#define IMAGE_UNSUBSCRIBE ":/images/cancel.png" +#define IMAGE_INFO ":/images/info16.png" +#define IMAGE_NEWFORUM ":/images/new_forum16.png" +#define IMAGE_FORUMAUTHD ":/images/konv_message2.png" +#define IMAGE_COPYLINK ":/images/copyrslink.png" + +/* + * Transformation Notes: + * there are still a couple of things that the new forums differ from Old version. + * these will need to be addressed in the future. + * -> Missing Messages are not handled yet. + * -> Child TS (for sorting) is not handled by GXS, this will probably have to be done in the GUI. + * -> Need to handle IDs properly. + * -> Popularity not handled in GXS yet. + * -> Much more to do. + */ + +/** Constructor */ +GxsForumsDialog::GxsForumsDialog(QWidget *parent) +: RsAutoUpdatePage(1000,parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* Setup Queue */ + mForumQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + + connect(ui.forumTreeWidget, SIGNAL(treeCustomContextMenuRequested(QPoint)), this, SLOT(forumListCustomPopupMenu(QPoint))); + connect(ui.newForumButton, SIGNAL(clicked()), this, SLOT(newforum())); + connect(ui.forumTreeWidget, SIGNAL(treeItemClicked(QString)), this, SLOT(changedForum(QString))); + connect(ui.threadTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(threadTabCloseRequested(int))); + connect(NotifyQt::getInstance(), SIGNAL(forumMsgReadSatusChanged(QString,QString,int)), this, SLOT(forumMsgReadSatusChanged(QString,QString,int))); + + // HACK - TEMPORARY HIJACKING THIS BUTTON FOR REFRESH. + connect(ui.refreshButton, SIGNAL(clicked()), this, SLOT(forceUpdateDisplay())); + + /* Set initial size the splitter */ + QList sizes; + sizes << 300 << width(); // Qt calculates the right sizes + ui.splitter->setSizes(sizes); + + /* create forum tree */ + yourForums = ui.forumTreeWidget->addCategoryItem(tr("Your Forums"), QIcon(IMAGE_FOLDER), true); + subscribedForums = ui.forumTreeWidget->addCategoryItem(tr("Subscribed Forums"), QIcon(IMAGE_FOLDERRED), true); + popularForums = ui.forumTreeWidget->addCategoryItem(tr("Popular Forums"), QIcon(IMAGE_FOLDERGREEN), false); + otherForums = ui.forumTreeWidget->addCategoryItem(tr("Other Forums"), QIcon(IMAGE_FOLDERYELLOW), false); + + // load settings + processSettings(true); + +/* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +GxsForumsDialog::~GxsForumsDialog() +{ + // save settings + processSettings(false); + + delete(mForumQueue); +} + +//#AFTER MERGE UserNotify *GxsForumsDialog::getUserNotify(QObject *parent) +//{ +// return new GxsForumUserNotify(parent); +//} + +void GxsForumsDialog::processSettings(bool bLoad) +{ + Settings->beginGroup(QString("GxsForumsDialog")); + + if (bLoad) { + // load settings + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + } else { + // save settings + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + } + + ui.forumTreeWidget->processSettings(Settings, bLoad); + + Settings->endGroup(); +} + +void GxsForumsDialog::forumListCustomPopupMenu(QPoint /*point*/) +{ + int subscribeFlags = ui.forumTreeWidget->subscribeFlags(QString::fromStdString(mForumId)); + + QMenu contextMnu(this); + + QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum())); + action->setDisabled (mForumId.empty() || IS_GROUP_SUBSCRIBED(subscribeFlags)); + + action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum())); + action->setEnabled (!mForumId.empty() && IS_GROUP_SUBSCRIBED(subscribeFlags)); + + contextMnu.addSeparator(); + + contextMnu.addAction(QIcon(IMAGE_NEWFORUM), tr("New Forum"), this, SLOT(newforum())); + + action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Forum Details"), this, SLOT(showForumDetails())); + action->setEnabled (!mForumId.empty ()); + + action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails())); + action->setEnabled (!mForumId.empty () && IS_GROUP_ADMIN(subscribeFlags)); + + QAction *shareKeyAct = new QAction(QIcon(":/images/gpgp_key_generate.png"), tr("Share Forum"), &contextMnu); + connect( shareKeyAct, SIGNAL( triggered() ), this, SLOT( shareKey() ) ); + shareKeyAct->setEnabled(!mForumId.empty() && IS_GROUP_ADMIN(subscribeFlags)); + contextMnu.addAction( shareKeyAct); + + QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu); + connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) ); + restoreKeysAct->setEnabled(!mForumId.empty() && !IS_GROUP_ADMIN(subscribeFlags)); + contextMnu.addAction( restoreKeysAct); + + action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink())); + action->setEnabled(!mForumId.empty()); + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsRead())); + action->setEnabled (!mForumId.empty () && IS_GROUP_SUBSCRIBED(subscribeFlags)); + + action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnread())); + action->setEnabled (!mForumId.empty () && IS_GROUP_SUBSCRIBED(subscribeFlags)); + +#ifdef DEBUG_FORUMS + contextMnu.addSeparator(); + action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData())); + action->setEnabled (!mCurrForumId.empty() && IS_GROUP_SUBSCRIBED(mSubscribeFlags)); +#endif + + contextMnu.exec(QCursor::pos()); +} + +void GxsForumsDialog::restoreForumKeys(void) +{ + QMessageBox::warning(this, "RetroShare", "ToDo"); + +#ifdef TOGXS + rsGxsForums->groupRestoreKeys(mCurrForumId); +#endif +} + +void GxsForumsDialog::updateDisplay() +{ + std::list forumIds; + std::list::iterator it; + if (!rsGxsForums) + return; + +#if 0 + // TODO groupsChanged... HACK XXX. + if ((rsGxsForums->groupsChanged(forumIds)) || (rsGxsForums->updated())) + { + /* update Forums List */ + insertForums(); + + it = std::find(forumIds.begin(), forumIds.end(), mCurrForumId); + if (it != forumIds.end()) + { + /* update threads as well */ + insertThreads(); + } + } +#endif + + /* The proper version (above) can be done with a data request -> TODO */ + if (rsGxsForums->updated()) + { + /* update Forums List */ + insertForums(); + } +} + +// HACK until update works. +void GxsForumsDialog::forceUpdateDisplay() +{ + std::cerr << "GxsForumsDialog::forceUpdateDisplay()"; + std::cerr << std::endl; + + /* update Forums List */ + insertForums(); +} + +void GxsForumsDialog::forumInfoToGroupItemInfo(const RsGroupMetaData &forumInfo, GroupItemInfo &groupItemInfo) +{ + groupItemInfo.id = QString::fromStdString(forumInfo.mGroupId); + groupItemInfo.name = QString::fromUtf8(forumInfo.mGroupName.c_str()); + //groupItemInfo.description = QString::fromUtf8(forumInfo.forumDesc); + groupItemInfo.popularity = forumInfo.mPop; + groupItemInfo.lastpost = QDateTime::fromTime_t(forumInfo.mLastPost); + groupItemInfo.subscribeFlags = forumInfo.mSubscribeFlags; + +#if TOGXS + if (forumInfo.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) { + groupItemInfo.name += " (" + tr("AUTHD") + ")"; + groupItemInfo.icon = QIcon(IMAGE_FORUMAUTHD); + } + else +#endif + { + groupItemInfo.icon = QIcon(IMAGE_FORUM); + } +} + +/***** INSERT FORUM LISTS *****/ +void GxsForumsDialog::insertForumsData(const std::list &forumList) +{ + std::list::const_iterator it; + + QList adminList; + QList subList; + QList popList; + QList otherList; + std::multimap popMap; + + for (it = forumList.begin(); it != forumList.end(); it++) { + /* sort it into Publish (Own), Subscribed, Popular and Other */ + uint32_t flags = it->mSubscribeFlags; + + GroupItemInfo groupItemInfo; + forumInfoToGroupItemInfo(*it, groupItemInfo); + + if (IS_GROUP_ADMIN(flags)) { + adminList.push_back(groupItemInfo); + } else if (IS_GROUP_SUBSCRIBED(flags)) { + /* subscribed forum */ + subList.push_back(groupItemInfo); + } else { + /* rate the others by popularity */ + popMap.insert(std::make_pair(it->mPop, groupItemInfo)); + } + } + + /* iterate backwards through popMap - take the top 5 or 10% of list */ + uint32_t popCount = 5; + if (popCount < popMap.size() / 10) + { + popCount = popMap.size() / 10; + } + + uint32_t i = 0; + uint32_t popLimit = 0; + std::multimap::reverse_iterator rit; + for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++) ; + if (rit != popMap.rend()) { + popLimit = rit->first; + } + + for (rit = popMap.rbegin(); rit != popMap.rend(); rit++) { + if (rit->second.popularity < (int) popLimit) { + otherList.append(rit->second); + } else { + popList.append(rit->second); + } + } + + /* now we can add them in as a tree! */ + ui.forumTreeWidget->fillGroupItems(yourForums, adminList); + ui.forumTreeWidget->fillGroupItems(subscribedForums, subList); + ui.forumTreeWidget->fillGroupItems(popularForums, popList); + ui.forumTreeWidget->fillGroupItems(otherForums, otherList); + + updateMessageSummaryList(""); +} + +GxsForumThreadWidget *GxsForumsDialog::forumThreadWidget(const std::string &id) +{ + int tabCount = ui.threadTabWidget->count(); + for (int index = 0; index < tabCount; ++index) { + GxsForumThreadWidget *childWidget = dynamic_cast(ui.threadTabWidget->widget(index)); + if (childWidget && childWidget->forumId() == id) { + return childWidget; + break; + } + } + + return NULL; +} + +void GxsForumsDialog::changedForum(const QString &id) +{ + mForumId = id.toStdString(); + if (mForumId.empty()) { + return; + } + +// requestGroupSummary_CurrentForum(mForumId); + + /* search exisiting tab */ + GxsForumThreadWidget *threadWidget = forumThreadWidget(id.toStdString()); + + if (!threadWidget) { + /* create a thread widget */ + threadWidget = new GxsForumThreadWidget(id.toStdString()); + int index = ui.threadTabWidget->addTab(threadWidget, threadWidget->forumName(true)); + ui.threadTabWidget->setTabIcon(index, threadWidget->forumIcon()); + connect(threadWidget, SIGNAL(forumChanged(QWidget*)), this, SLOT(threadTabChanged(QWidget*))); + } + + ui.threadTabWidget->setCurrentWidget(threadWidget); +} + +void GxsForumsDialog::threadTabCloseRequested(int index) +{ + GxsForumThreadWidget *threadWidget = dynamic_cast(ui.threadTabWidget->widget(index)); + if (threadWidget) { + delete(threadWidget); + } +} + +void GxsForumsDialog::threadTabChanged(QWidget *widget) +{ + int index = ui.threadTabWidget->indexOf(widget); + if (index < 0) { + return; + } + + GxsForumThreadWidget *threadWidget = dynamic_cast(ui.threadTabWidget->widget(index)); + if (!threadWidget) { + return; + } + + ui.threadTabWidget->setTabText(index, threadWidget->forumName(true)); + ui.threadTabWidget->setTabIcon(index, threadWidget->forumIcon()); +} + +void GxsForumsDialog::copyForumLink() +{ + if (mForumId.empty()) { + return; + } + +// THIS CODE CALLS getForumInfo() to verify that the Ids are valid. +// As we are switching to Request/Response this is now harder to do... +// So not bothering any more - shouldn't be necessary. +// IF we get errors - fix them, rather than patching here. +#if 0 + ForumInfo fi; + if (rsGxsForums->getForumInfo(mCurrForumId, fi)) { + RetroShareLink link; + if (link.createForum(fi.forumId, "")) { + QList urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } + } +#endif + + QMessageBox::warning(this, "RetroShare", "ToDo"); +} + +void GxsForumsDialog::markMsgAsRead() +{ + GxsForumThreadWidget *threadWidget = forumThreadWidget(mForumId); + if (threadWidget) { + threadWidget->setAllMsgReadStatus(true); + } +} + +void GxsForumsDialog::markMsgAsUnread() +{ + GxsForumThreadWidget *threadWidget = forumThreadWidget(mForumId); + if (threadWidget) { + threadWidget->setAllMsgReadStatus(false); + } +} + +void GxsForumsDialog::newforum() +{ + GxsForumGroupDialog cf(mForumQueue, this); + cf.exec (); +} + +void GxsForumsDialog::subscribeToForum() +{ + forumSubscribe(true); +} + +void GxsForumsDialog::unsubscribeToForum() +{ + forumSubscribe(false); +} + +void GxsForumsDialog::forumSubscribe(bool subscribe) +{ + if (mForumId.empty()) { + return; + } + + uint32_t token; + rsGxsForums->subscribeToGroup(token, mForumId, subscribe); +} + +void GxsForumsDialog::showForumDetails() +{ + if (mForumId.empty()) { + return; + } + + RsGxsForumGroup grp; + grp.mMeta.mGroupId = mForumId; + + GxsForumGroupDialog cf(grp, GxsGroupDialog::MODE_SHOW, this); + cf.exec (); +} + +void GxsForumsDialog::editForumDetails() +{ + if (mForumId.empty()) { + return; + } + + RsGxsForumGroup grp; + grp.mMeta.mGroupId = mForumId; + + GxsForumGroupDialog cf(grp, GxsGroupDialog::MODE_EDIT, this); + cf.exec (); +} + +void GxsForumsDialog::shareKey() +{ + ShareKey shareUi(this, mForumId, FORUM_KEY_SHARE); + shareUi.exec(); +} + +void GxsForumsDialog::updateMessageSummaryList(std::string forumId) +{ + QTreeWidgetItem *items[2] = { yourForums, subscribedForums }; + + for (int item = 0; item < 2; item++) { + int child; + int childCount = items[item]->childCount(); + for (child = 0; child < childCount; child++) { + QTreeWidgetItem *childItem = items[item]->child(child); + std::string childId = ui.forumTreeWidget->itemId(childItem).toStdString(); + if (childId.empty()) { + continue; + } + + if (forumId.empty() || childId == forumId) { + /* calculate unread messages */ + unsigned int newMessageCount = 0; + unsigned int unreadMessageCount = 0; + +//#TODO rsGxsForums->getMessageCount(childId, newMessageCount, unreadMessageCount); + + std::cerr << "IMPLEMENT rsGxsForums->getMessageCount()"; + std::cerr << std::endl; + + ui.forumTreeWidget->setUnreadCount(childItem, unreadMessageCount); + + if (forumId.empty() == false) { + /* Calculate only this forum */ + break; + } + } + } + } +} + +bool GxsForumsDialog::navigate(const std::string& forumId, const std::string& msgId) +{ + if (forumId.empty()) { + return false; + } + + if (ui.forumTreeWidget->activateId(QString::fromStdString(forumId), msgId.empty()) == NULL) { + return false; + } + + /* Threads are filled in changedForum */ + if (mForumId != forumId) { + return false; + } + + if (msgId.empty()) { + return true; + } + +//#TODO +// if (mThreadLoading) { +// mThreadLoad.FocusMsgId = msgId; +// return true; +// } + + /* Search exisiting item */ +// QTreeWidgetItemIterator itemIterator(ui.threadTreeWidget); +// QTreeWidgetItem *item = NULL; +// while ((item = *itemIterator) != NULL) { +// itemIterator++; + +// if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == msgId) { +// ui.threadTreeWidget->setCurrentItem(item); +// ui.threadTreeWidget->setFocus(); +// return true; +// } +// } + + return false; +} + +void GxsForumsDialog::generateMassData() +{ +#ifdef DEBUG_FORUMS + if (mCurrForumId.empty ()) { + return; + } + + if (QMessageBox::question(this, "Generate mass data", "Do you really want to generate mass data ?", QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No) { + return; + } + + for (int thread = 1; thread < 1000; thread++) { + ForumMsgInfo threadInfo; + threadInfo.forumId = mCurrForumId; + threadInfo.title = QString("Test %1").arg(thread, 3, 10, QChar('0')).toStdWString(); + threadInfo.msg = QString("That is only a test").toStdWString(); + + if (rsGxsForums->ForumMessageSend(threadInfo) == false) { + return; + } + + for (int msg = 1; msg < 3; msg++) { + ForumMsgInfo msgInfo; + msgInfo.forumId = mCurrForumId; + msgInfo.threadId = threadInfo.msgId; + msgInfo.parentId = threadInfo.msgId; + msgInfo.title = threadInfo.title; + msgInfo.msg = threadInfo.msg; + + if (rsGxsForums->ForumMessageSend(msgInfo) == false) { + return; + } + } + } +#endif +} + +/*********************** **** **** **** ***********************/ +/** Request / Response of Data ********************************/ +/*********************** **** **** **** ***********************/ + +#define TOKEN_TYPE_LISTING 1 +//#define TOKEN_TYPE_CURRENTFORUM 2 + +void GxsForumsDialog::insertForums() +{ + requestGroupSummary(); +} + +void GxsForumsDialog::requestGroupSummary() +{ + std::cerr << "GxsForumsDialog::requestGroupSummary()"; + std::cerr << std::endl; + + std::list tokens; + mForumQueue->activeRequestTokens(TOKEN_TYPE_LISTING, tokens); + if (!tokens.empty()) { + std::list::iterator tokenIt; + for (tokenIt = tokens.begin(); tokenIt != tokens.end(); ++tokenIt) { + std::cerr << "GxsForumsDialog::requestGroupSummary() Canceling Request: " << *tokenIt; + std::cerr << std::endl; + + mForumQueue->cancelRequest(*tokenIt); + } + } + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + uint32_t token; + mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_TYPE_LISTING); +} + +void GxsForumsDialog::loadGroupSummary(const uint32_t &token) +{ + std::cerr << "GxsForumsDialog::loadGroupSummary()"; + std::cerr << std::endl; + + std::list groupInfo; + rsGxsForums->getGroupSummary(token, groupInfo); + + if (groupInfo.size() > 0) + { + insertForumsData(groupInfo); + } + else + { + std::cerr << "GxsForumsDialog::loadGroupSummary() ERROR No Groups..."; + std::cerr << std::endl; + } +} + +/*********************** **** **** **** ***********************/ +/*********************** **** **** **** ***********************/ + +//void GxsForumsDialog::requestGroupSummary_CurrentForum(const std::string &forumId) +//{ +// RsTokReqOptions opts; +// opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + +// std::list grpIds; +// grpIds.push_back(forumId); + +// std::cerr << "GxsForumsDialog::requestGroupSummary_CurrentForum(" << forumId << ")"; +// std::cerr << std::endl; + +// uint32_t token; +// mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds, TOKEN_TYPE_CURRENTFORUM); +//} + +//void GxsForumsDialog::loadGroupSummary_CurrentForum(const uint32_t &token) +//{ +// std::cerr << "GxsForumsDialog::loadGroupSummary_CurrentForum()"; +// std::cerr << std::endl; + +// std::list groupInfo; +// rsGxsForums->getGroupSummary(token, groupInfo); + +// if (groupInfo.size() == 1) +// { +// RsGroupMetaData fi = groupInfo.front(); +// mSubscribeFlags = fi.mSubscribeFlags; +// } +// else +// { +// resetData(); +// std::cerr << "GxsForumsDialog::loadGroupSummary_CurrentForum() ERROR Invalid Number of Groups..."; +// std::cerr << std::endl; +// } + +// setValid(true); +//} + +/*********************** **** **** **** ***********************/ +/*********************** **** **** **** ***********************/ + +void GxsForumsDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "GxsForumsDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; + + if (queue == mForumQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case TOKEN_TYPE_LISTING: + loadGroupSummary(req.mToken); + break; + +// case TOKEN_TYPE_CURRENTFORUM: +// loadGroupSummary_CurrentForum(req.mToken); +// break; + + default: + std::cerr << "GxsForumsDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} diff --git a/retroshare-gui/src/gui/GxsForumsDialog.h b/retroshare-gui/src/gui/GxsForumsDialog.h new file mode 100644 index 000000000..aead3f0f5 --- /dev/null +++ b/retroshare-gui/src/gui/GxsForumsDialog.h @@ -0,0 +1,121 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _GXSFORUMSDIALOG_H +#define _GXSFORUMSDIALOG_H + +#include + +#include "mainpage.h" +#include "RsAutoUpdatePage.h" +#include "ui_GxsForumsDialog.h" + +#include + +#include "util/TokenQueue.h" + +#include "gui/gxs/GxsIdTreeWidgetItem.h" + +class ForumInfo; +class RsGxsForumMsg; +class GxsForumThreadWidget; + +class GxsForumsDialog : public RsAutoUpdatePage, public TokenResponse +{ + Q_OBJECT + +public: + GxsForumsDialog(QWidget *parent = 0); + ~GxsForumsDialog(); + +//#AFTER MERGE virtual UserNotify *getUserNotify(QObject *parent); + + bool navigate(const std::string& forumId, const std::string& msgId); + + /* overloaded from RsAuthUpdatePage */ + virtual void updateDisplay(); + + // Callback for all Loads. + virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); + +private slots: + void forceUpdateDisplay(); // TEMP HACK FN. + + /** Create the context popup menu and it's submenus */ + void forumListCustomPopupMenu( QPoint point ); + + void restoreForumKeys(); + void newforum(); + + void changedForum(const QString &id); + void threadTabCloseRequested(int index); + void threadTabChanged(QWidget *widget); + + void copyForumLink(); + + void subscribeToForum(); + void unsubscribeToForum(); + + void showForumDetails(); + void editForumDetails(); + + void markMsgAsRead(); + void markMsgAsUnread(); + + void generateMassData(); + + void shareKey(); + +private: + void insertForums(); + + void updateMessageSummaryList(std::string forumId); +// void forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo); + void forumInfoToGroupItemInfo(const RsGroupMetaData &forumInfo, GroupItemInfo &groupItemInfo); + + void forumSubscribe(bool subscribe); + + void processSettings(bool load); + + // New Request/Response Loading Functions. + void insertForumsData(const std::list &forumList); + + void requestGroupSummary(); + void loadGroupSummary(const uint32_t &token); + + GxsForumThreadWidget *forumThreadWidget(const std::string &id); + +// void requestGroupSummary_CurrentForum(const std::string &forumId); +// void loadGroupSummary_CurrentForum(const uint32_t &token); + + std::string mForumId; + TokenQueue *mForumQueue; + + QTreeWidgetItem *yourForums; + QTreeWidgetItem *subscribedForums; + QTreeWidgetItem *popularForums; + QTreeWidgetItem *otherForums; + + /** Qt Designer generated object */ + Ui::GxsForumsDialog ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/GxsForumsDialog.ui b/retroshare-gui/src/gui/GxsForumsDialog.ui new file mode 100644 index 000000000..9420b701e --- /dev/null +++ b/retroshare-gui/src/gui/GxsForumsDialog.ui @@ -0,0 +1,208 @@ + + + GxsForumsDialog + + + + 0 + 0 + 732 + 420 + + + + + 9 + + + 9 + + + + + Qt::Horizontal + + + + + 300 + 300 + + + + QFrame::NoFrame + + + + 0 + + + 0 + + + + + QFrame::Box + + + QFrame::Sunken + + + + 2 + + + + + + 24 + 24 + + + + + + + :/images/konversation.png + + + true + + + + + + + + 10 + 75 + true + + + + Forums + + + + + + + Qt::Horizontal + + + + 123 + 13 + + + + + + + + Refresh + + + + + + + Qt::NoFocus + + + Display + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + 32 + 16 + + + + QToolButton::InstantPopup + + + true + + + + + + + Qt::NoFocus + + + Create Forum + + + + :/images/new_forum16.png:/images/new_forum16.png + + + + 32 + 16 + + + + true + + + + + + + + + + + 0 + 0 + + + + + + + + + -1 + + + true + + + true + + + + + + + + Print + + + + + PrintPreview + + + + + + GroupTreeWidget + QWidget +
gui/common/GroupTreeWidget.h
+ 1 +
+
+ + + + +
diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 048ffd39e..a3a4a69a9 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -25,6 +25,7 @@ #include #include +#include "gxs/rsgxsflags.h" #include #include @@ -78,10 +79,7 @@ IdDialog::IdDialog(QWidget *parent) timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); - rsIdentity->generateDummyData(); - - mIdQueue = new TokenQueue(rsIdentity, this); - + mIdQueue = new TokenQueue(rsIdentity->getTokenService(), this); } void IdDialog::ListTypeToggled(bool checked) @@ -133,6 +131,7 @@ void IdDialog::blankSelection() void IdDialog::requestIdDetails(std::string &id) { RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token; std::list groupIds; @@ -145,54 +144,90 @@ void IdDialog::requestIdDetails(std::string &id) void IdDialog::insertIdDetails(uint32_t token) { /* get details from libretroshare */ - RsIdGroup data; - if (!rsIdentity->getGroupData(token, data)) + RsGxsIdGroup data; + std::vector datavector; + if (!rsIdentity->getGroupData(token, datavector)) { ui.lineEdit_KeyId->setText("ERROR GETTING KEY!"); return; } + if (datavector.size() != 1) + { + std::cerr << "IdDialog::insertIdDetails() Invalid datavector size"; + ui.lineEdit_KeyId->setText("INVALID DV SIZE"); + return; + } + + data = datavector[0]; + /* get GPG Details from rsPeers */ - std::string gpgid = rsPeers->getGPGOwnId(); - RsPeerDetails details; - rsPeers->getPeerDetails(gpgid, details); + std::string ownPgpId = rsPeers->getGPGOwnId(); - //ui.lineEdit_Nickname->setText(QString::fromStdString(data.mNickname)); ui.lineEdit_Nickname->setText(QString::fromStdString(data.mMeta.mGroupName)); - //ui.lineEdit_KeyId->setText(QString::fromStdString(data.mKeyId)); ui.lineEdit_KeyId->setText(QString::fromStdString(data.mMeta.mGroupId)); - ui.lineEdit_GpgHash->setText(QString::fromStdString(data.mGpgIdHash)); - ui.lineEdit_GpgId->setText(QString::fromStdString(data.mGpgId)); - ui.lineEdit_GpgName->setText(QString::fromStdString(data.mGpgName)); - ui.lineEdit_GpgEmail->setText(QString::fromStdString(data.mGpgEmail)); - - if (data.mIdType & RSID_RELATION_YOURSELF) + ui.lineEdit_GpgHash->setText(QString::fromStdString(data.mPgpIdHash)); + ui.lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId)); + + if (data.mPgpKnown) + { + RsPeerDetails details; + rsPeers->getGPGDetails(data.mPgpId, details); + ui.lineEdit_GpgName->setText(QString::fromStdString(details.name)); + ui.lineEdit_GpgEmail->setText(QString::fromStdString(details.email)); + } + else + { + if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + ui.lineEdit_GpgName->setText("Unknown Real Name"); + ui.lineEdit_GpgEmail->setText("Unknown Email"); + } + else + { + ui.lineEdit_GpgName->setText("Anonymous Id"); + ui.lineEdit_GpgEmail->setText("-- N/A --"); + } + } + + bool isOwnId = (data.mPgpKnown && (data.mPgpId == ownPgpId)) || + (data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); + + if (isOwnId) { ui.radioButton_IdYourself->setChecked(true); } - else if (data.mIdType & RSID_TYPE_PSEUDONYM) + else if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + if (data.mPgpKnown) + { + if (rsPeers->isGPGAccepted(data.mPgpId)) + { + ui.radioButton_IdFriend->setChecked(true); + } + else + { + ui.radioButton_IdFOF->setChecked(true); + } + } + else + { + ui.radioButton_IdOther->setChecked(true); + } + } + else { ui.radioButton_IdPseudo->setChecked(true); } - else if (data.mIdType & RSID_RELATION_FRIEND) - { - ui.radioButton_IdFriend->setChecked(true); - } - else if (data.mIdType & RSID_RELATION_FOF) - { - ui.radioButton_IdFOF->setChecked(true); - } - else - { - ui.radioButton_IdOther->setChecked(true); - } - + ui.pushButton_NewId->setEnabled(true); - if (data.mIdType & RSID_RELATION_YOURSELF) + + if (isOwnId) { ui.pushButton_Reputation->setEnabled(false); ui.pushButton_Delete->setEnabled(true); - ui.pushButton_EditId->setEnabled(true); + // No Editing Ids yet! + //ui.pushButton_EditId->setEnabled(true); } else { @@ -260,11 +295,13 @@ void IdDialog::OpenOrShowEditDialog() void IdDialog::requestIdList() { RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token; std::list groupIds; - mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, IDDIALOG_IDLIST); + //mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, IDDIALOG_IDLIST); + mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, IDDIALOG_IDLIST); } @@ -283,13 +320,24 @@ void IdDialog::insertIdList(uint32_t token) bool acceptFriends = ui.radioButton_ListFriends->isChecked(); bool acceptOthers = ui.radioButton_ListOthers->isChecked(); - //rsIdentity->getIdentityList(ids); - - //for(it = ids.begin(); it != ids.end(); it++) - //{ - RsIdGroup data; - while(rsIdentity->getGroupData(token, data)) + RsGxsIdGroup data; + std::vector datavector; + std::vector::iterator vit; + if (!rsIdentity->getGroupData(token, datavector)) { + std::cerr << "IdDialog::insertIdList() Error getting GroupData"; + std::cerr << std::endl; + return; + } + + std::string ownPgpId = rsPeers->getGPGOwnId(); + + for(vit = datavector.begin(); vit != datavector.end(); vit++) + { + data = (*vit); + + bool isOwnId = (data.mPgpKnown && (data.mPgpId == ownPgpId)) || + (data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); /* do filtering */ bool ok = false; @@ -297,55 +345,68 @@ void IdDialog::insertIdList(uint32_t token) { ok = true; } - else if (data.mIdType & RSID_TYPE_PSEUDONYM) + else if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + if (isOwnId && acceptYourself) + { + ok = true; + } + else + { + if (data.mPgpKnown) + { + if (acceptFriends) + { + ok = true; + } + } + else + { + if (acceptOthers) + { + ok = true; + } + } + } + } + else { if (acceptPseudo) { ok = true; } - if ((data.mIdType & RSID_RELATION_YOURSELF) && (acceptYourself)) + if (isOwnId && acceptYourself) { ok = true; } } - else - { - if (data.mIdType & RSID_RELATION_YOURSELF) - { - if (acceptYourself) - { - ok = true; - } - } - else if (data.mIdType & (RSID_RELATION_FRIEND | RSID_RELATION_FOF)) - { - if (acceptFriends) - { - ok = true; - } - } - else - { - if (acceptOthers) - { - ok = true; - } - } - } if (!ok) { continue; } - QTreeWidgetItem *item = new QTreeWidgetItem(); - //item->setText(RSID_COL_NICKNAME, QString::fromStdString(data.mNickname)); - //item->setText(RSID_COL_KEYID, QString::fromStdString(data.mKeyId)); item->setText(RSID_COL_NICKNAME, QString::fromStdString(data.mMeta.mGroupName)); item->setText(RSID_COL_KEYID, QString::fromStdString(data.mMeta.mGroupId)); - item->setText(RSID_COL_IDTYPE, QString::fromStdString(rsIdTypeToString(data.mIdType))); + if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + if (data.mPgpKnown) + { + RsPeerDetails details; + rsPeers->getGPGDetails(data.mPgpId, details); + item->setText(RSID_COL_IDTYPE, QString::fromStdString(details.name)); + } + else + { + item->setText(RSID_COL_IDTYPE, "PGP Linked Id"); + } + } + else + { + item->setText(RSID_COL_IDTYPE, "Anon Id"); + } tree->addTopLevelItem(item); } diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 52f3b6246..a124df4ca 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -10,10 +10,76 @@ 647 - - - - + + + + + + + + 6 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + + + + + + :/images/groupchat.png + + + + + + + + 11 + + + + Identities + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + New ID + + + + + + + Showing: @@ -81,7 +147,7 @@ - + @@ -103,258 +169,278 @@ - - - - - Delete ID - - - - - - - Edit Reputation - - - - - - - Edit ID - - - - - - - New ID - - - - - - - - - Identity Type + + + 0 - - - - - Nickname + + + + + 3 - - - - - - true - - - true - - - - - - - - false - + - Yourself - - - true + Delete ID - - - false - + - Friend - - - true + Edit Reputation - - - false - + - Friend of Friend - - - true + Edit ID - - - false - - - Other - - - true - - - - - + Qt::Horizontal + + + 40 + 20 + + + + + + + + + + + Identity Type + + + + + + Nickname + - - + + - false - - - Pseudonym - - true + + true + + + + + + + + + false + + + Yourself + + + true + + + + + + + false + + + Friend + + + true + + + + + + + false + + + Friend of Friend + + + true + + + + + + + false + + + Other + + + true + + + + + + + Qt::Horizontal + + + + + + + false + + + Pseudonym + + + true + + + + + + + + + Key ID + + + + + + + true + + + true + + + + + + + GPG Name + + + + + + + true + + + true + + + + + + + GPG Email + + + + + + + true + + + true + + + + + + + true + + + true + + + + + + + true + + + true + + + + + + + GPG Id + + + + + + + GPG Hash + - - - - - Key ID - - - - - - - true - - - true - - - - - - - PGP Name - - - - - - - true - - - true - - - - - - - PGP Email - - - - - - - true - - - true - - - - - - - true - - - true - - - - - - - true - - - true - - - - - - - PGP Id - - - - - - - PGP Hash - - - - - - - - - - Reputation - - - - - - Your Rating - - - - - - - - - - Overall Rating - - - - - - - - - - - + + + + + + Reputation + + + + + + Your Rating + + + + + + + + + + Overall Rating + + + + + + + + + + + + + - + + + diff --git a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp index ca3a9fa90..3bad7dead 100644 --- a/retroshare-gui/src/gui/Identity/IdEditDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdEditDialog.cpp @@ -41,8 +41,7 @@ IdEditDialog::IdEditDialog(QWidget *parent) connect(ui.radioButton_Pseudo, SIGNAL( toggled( bool ) ), this, SLOT( IdTypeToggled( bool ) ) ); connect(ui.pushButton_Update, SIGNAL( clicked( void ) ), this, SLOT( updateId( void ) ) ); connect(ui.pushButton_Cancel, SIGNAL( clicked( void ) ), this, SLOT( cancelId( void ) ) ); - - mIdQueue = new TokenQueue(rsIdentity, this); + mIdQueue = new TokenQueue(rsIdentity->getTokenService(), this); } void IdEditDialog::setupNewId(bool pseudo) @@ -122,9 +121,19 @@ void IdEditDialog::loadExistingId(uint32_t token) ui.radioButton_Pseudo->setEnabled(false); /* get details from libretroshare */ - RsIdGroup data; - if (!rsIdentity->getGroupData(token, data)) - { + RsGxsIdGroup data; + std::vector datavector; + if (!rsIdentity->getGroupData(token, datavector)) + { + ui.lineEdit_KeyId->setText("ERROR GETTING KEY!"); + return; + } + + if (datavector.size() != 1) + { + std::cerr << "IdDialog::insertIdDetails() Invalid datavector size"; + std::cerr << std::endl; + ui.lineEdit_KeyId->setText("ERROR KEYID INVALID"); ui.lineEdit_Nickname->setText(""); @@ -134,59 +143,64 @@ void IdEditDialog::loadExistingId(uint32_t token) ui.lineEdit_GpgEmail->setText("N/A"); return; } - bool pseudo = (data.mIdType & RSID_TYPE_PSEUDONYM); - if (pseudo) + data = datavector[0]; + + bool realid = (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID); + + if (realid) { - ui.radioButton_Pseudo->setChecked(true); + ui.radioButton_GpgId->setChecked(true); } else { - ui.radioButton_GpgId->setChecked(true); + ui.radioButton_Pseudo->setChecked(true); } // DOES THIS TRIGGER ALREADY??? // force - incase it wasn't triggered. IdTypeToggled(true); - //ui.lineEdit_Nickname->setText(QString::fromStdString(data.mNickname)); - //ui.lineEdit_KeyId->setText(QString::fromStdString(data.mKeyId)); ui.lineEdit_Nickname->setText(QString::fromStdString(data.mMeta.mGroupName)); ui.lineEdit_KeyId->setText(QString::fromStdString(data.mMeta.mGroupId)); - if (pseudo) + if (realid) + { + ui.lineEdit_GpgHash->setText(QString::fromStdString(data.mPgpIdHash)); + + if (data.mPgpKnown) + { + RsPeerDetails details; + rsPeers->getGPGDetails(data.mPgpId, details); + ui.lineEdit_GpgName->setText(QString::fromStdString(details.name)); + ui.lineEdit_GpgEmail->setText(QString::fromStdString(details.email)); + + ui.lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId)); + } + else + { + ui.lineEdit_GpgId->setText("Unknown PgpId"); + ui.lineEdit_GpgName->setText("Unknown Real Name"); + ui.lineEdit_GpgEmail->setText("Unknown Email"); + } + } + else { ui.lineEdit_GpgHash->setText("N/A"); ui.lineEdit_GpgId->setText("N/A"); ui.lineEdit_GpgName->setText("N/A"); ui.lineEdit_GpgEmail->setText("N/A"); } - else - { - ui.lineEdit_GpgHash->setText(QString::fromStdString(data.mGpgIdHash)); - - if (data.mGpgIdKnown) - { - ui.lineEdit_GpgId->setText(QString::fromStdString(data.mGpgId)); - ui.lineEdit_GpgName->setText(QString::fromStdString(data.mGpgName)); - ui.lineEdit_GpgEmail->setText(QString::fromStdString(data.mGpgEmail)); - } - else - { - ui.lineEdit_GpgId->setText("EXIST Unknown"); - ui.lineEdit_GpgName->setText("Unknown"); - ui.lineEdit_GpgEmail->setText("Unknown"); - } - } return; } void IdEditDialog::updateId() { - RsIdGroup rid; + RsGxsIdGroup rid; // Must set, Nickname, KeyId(if existing), mIdType, GpgId. + rid.mMeta.mGroupName = ui.lineEdit_Nickname->text().toStdString(); if (rid.mMeta.mGroupName.size() < 2) @@ -196,7 +210,7 @@ void IdEditDialog::updateId() return; } - rid.mIdType = RSID_RELATION_YOURSELF; + //rid.mIdType = RSID_RELATION_YOURSELF; if (ui.checkBox_NewId->isChecked()) { rid.mMeta.mGroupId = ""; @@ -208,25 +222,31 @@ void IdEditDialog::updateId() if (ui.radioButton_GpgId->isChecked()) { - rid.mIdType |= RSID_TYPE_REALID; + //rid.mIdType |= RSID_TYPE_REALID; - rid.mGpgId = ui.lineEdit_GpgId->text().toStdString(); - rid.mGpgIdHash = ui.lineEdit_GpgHash->text().toStdString(); - rid.mGpgName = ui.lineEdit_GpgName->text().toStdString(); - rid.mGpgEmail = ui.lineEdit_GpgEmail->text().toStdString(); + //rid.mGpgId = ui.lineEdit_GpgId->text().toStdString(); + rid.mPgpIdHash = ui.lineEdit_GpgHash->text().toStdString(); + //rid.mGpgName = ui.lineEdit_GpgName->text().toStdString(); + //rid.mGpgEmail = ui.lineEdit_GpgEmail->text().toStdString(); } else { - rid.mIdType |= RSID_TYPE_PSEUDONYM; + //rid.mIdType |= RSID_TYPE_PSEUDONYM; - rid.mGpgId = ""; - rid.mGpgIdHash = ""; - rid.mGpgName = ""; - rid.mGpgEmail = ""; + //rid.mGpgId = ""; + rid.mPgpIdHash = ""; + //rid.mGpgName = ""; + //rid.mGpgEmail = ""; } - // TODO. - //rsIdentity->updateIdentity(rid); + + // Can only create Identities for the moment! + RsIdentityParameters params; + params.nickname = rid.mMeta.mGroupName; + params.isPgpLinked = (ui.radioButton_GpgId->isChecked()); + + uint32_t dummyToken = 0; + rsIdentity->createIdentity(dummyToken, params); hide(); return; diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 4779cbc82..1aa42bc0b 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -322,10 +322,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WFlags flags) addAction(new QAction(QIcon(IMAGE_UNFINISHED), tr("Unfinished"), ui.toolBar), SLOT(showApplWindow())); #endif - if (activatePage((Page) Settings->getLastPageInMainWindow()) == false) { - /* Select the first action */ - grp->actions()[0]->setChecked(true); - } + ui.stackPages->setCurrentIndex(Settings->getLastPageInMainWindow()); /** StatusBar section ********/ /* initialize combobox in status bar */ @@ -401,7 +398,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WFlags flags) /** Destructor. */ MainWindow::~MainWindow() { - Settings->setLastPageInMainWindow(getActivatePage()); + Settings->setLastPageInMainWindow(ui.stackPages->currentIndex()); delete peerstatus; delete natstatus; diff --git a/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.cpp b/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.cpp new file mode 100644 index 000000000..d77cd20b6 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.cpp @@ -0,0 +1,19 @@ +#include "AddCommentDialog.h" +#include "ui_AddCommentDialog.h" + +AddCommentDialog::AddCommentDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AddCommentDialog) +{ + ui->setupUi(this); +} + +AddCommentDialog::~AddCommentDialog() +{ + delete ui; +} + +QString AddCommentDialog::getComment() const +{ + return ui->textEditAddComment->document()->toPlainText(); +} diff --git a/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.h b/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.h new file mode 100644 index 000000000..f08aa65ca --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.h @@ -0,0 +1,23 @@ +#ifndef ADDCOMMENTDIALOG_H +#define ADDCOMMENTDIALOG_H + +#include + +namespace Ui { + class AddCommentDialog; +} + +class AddCommentDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AddCommentDialog(QWidget *parent = 0); + ~AddCommentDialog(); + QString getComment() const; + +private: + Ui::AddCommentDialog *ui; +}; + +#endif // ADDCOMMENTDIALOG_H diff --git a/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.ui b/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.ui new file mode 100644 index 000000000..d07b9f6dd --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AddCommentDialog.ui @@ -0,0 +1,67 @@ + + + AddCommentDialog + + + + 0 + 0 + 370 + 118 + + + + Add Comment + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AddCommentDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AddCommentDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.cpp b/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.cpp new file mode 100644 index 000000000..746f748ac --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.cpp @@ -0,0 +1,190 @@ +#include + +#include "AlbumCreateDialog.h" +#include "ui_AlbumCreateDialog.h" + +#include "util/misc.h" +#include "gxs/rsgxsflags.h" + +AlbumCreateDialog::AlbumCreateDialog(TokenQueue *photoQueue, RsPhoto *rs_photo, QWidget *parent): + QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), + ui(new Ui::AlbumCreateDialog), mPhotoQueue(photoQueue), mRsPhoto(rs_photo), mPhotoSelected(NULL) +{ + ui->setupUi(this); + + ui->headerFrame->setHeaderImage(QPixmap(":/images/album_create_64.png")); + ui->headerFrame->setHeaderText(tr("Create Album")); + + +#if QT_VERSION >= 0x040700 + ui->lineEdit_Title_2->setPlaceholderText(tr("Untitle Album")); + ui->lineEdit_Caption_2->setPlaceholderText(tr("Say something about this album...")); + //ui->textEdit_Description->setPlaceholderText(tr("Say something about this album...")) ; + ui->lineEdit_Where->setPlaceholderText(tr("Where were this taken?")); +#endif + + ui->backButton->hide(); + + connect(ui->publishButton, SIGNAL(clicked()), this, SLOT(publishAlbum())); + connect(ui->AlbumThumbNail, SIGNAL(clicked()), this, SLOT(addAlbumThumbnail())); + + connect(ui->addphotosButton, SIGNAL(clicked()),this, SLOT(changePage())); + connect(ui->backButton, SIGNAL(clicked()),this, SLOT(backPage())); + + + mPhotoDrop = ui->scrollAreaWidgetContents; + mPhotoDrop->setPhotoItemHolder(this); + + +} + +AlbumCreateDialog::~AlbumCreateDialog() +{ + delete ui; +} + +#define PUBLIC_INDEX 0 +#define RESTRICTED_INDEX 1 +#define PRIVATE_INDEX 2 + +void AlbumCreateDialog::publishAlbum() +{ + // get fields for album to publish, publish and then exit dialog + RsPhotoAlbum album; + + album.mCaption = ui->lineEdit_Caption_2->text().toStdString(); + album.mPhotographer = ui->lineEdit_Photographer->text().toStdString(); + album.mMeta.mGroupName = ui->lineEdit_Title_2->text().toStdString(); + album.mDescription = ui->textEdit_Description->toPlainText().toStdString(); + album.mWhere = ui->lineEdit_Where->text().toStdString(); + album.mPhotographer = ui->lineEdit_Photographer->text().toStdString(); + getAlbumThumbnail(album.mThumbnail); + + + int currIndex = ui->privacyComboBox->currentIndex(); + + switch(currIndex) + { + case PUBLIC_INDEX: + album.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; + break; + case RESTRICTED_INDEX: + album.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_RESTRICTED; + break; + case PRIVATE_INDEX: + album.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PRIVATE; + break; + } + + uint32_t token; + mRsPhoto->submitAlbumDetails(token, album); + mPhotoQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, 0); + + publishPhotos(); + + close(); +} + +void AlbumCreateDialog::publishPhotos() +{ + // get fields for album to publish, publish and then exit dialog + RsPhotoAlbum album; + + QSet photos; + + mPhotoDrop->getPhotos(photos); + + QSetIterator sit(photos); + + while(sit.hasNext()) + { + PhotoItem* item = sit.next(); + uint32_t token; + RsPhotoPhoto photo = item->getPhotoDetails(); + photo.mMeta.mGroupId = album.mMeta.mGroupId; + mRsPhoto->submitPhoto(token, photo); + mPhotoQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0); + } + +} + +bool AlbumCreateDialog::getAlbumThumbnail(RsPhotoThumbnail &nail) +{ + const QPixmap *tmppix = &mThumbNail; + + QByteArray ba; + QBuffer buffer(&ba); + + if(!tmppix->isNull()) + { + // send chan image + + buffer.open(QIODevice::WriteOnly); + tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format + + RsPhotoThumbnail tmpnail; + tmpnail.data = (uint8_t *) ba.data(); + tmpnail.size = ba.size(); + + nail.copyFrom(tmpnail); + + return true; + } + + nail.data = NULL; + nail.size = 0; + return false; +} + +void AlbumCreateDialog::addAlbumThumbnail() +{ + QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Album Thumbnail"), 128, 128); + + if (img.isNull()) + return; + + mThumbNail = img; + + // to show the selected + ui->AlbumThumbNail->setIcon(mThumbNail); +} + +void AlbumCreateDialog::changePage() +{ + int nextPage = ui->stackedWidget->currentIndex() + 1; + if (nextPage >= ui->stackedWidget->count()) + nextPage = 0; + ui->stackedWidget->setCurrentIndex(nextPage); + + ui->backButton->show(); + ui->addphotosButton->hide(); +} + +void AlbumCreateDialog::backPage() +{ + int nextPage = ui->stackedWidget->currentIndex() - 1; + if (nextPage >= ui->stackedWidget->count()) + nextPage = 0; + ui->stackedWidget->setCurrentIndex(nextPage); + + ui->backButton->hide(); + ui->addphotosButton->show(); +} + +void AlbumCreateDialog::notifySelection(PhotoShareItem *selection) +{ + + PhotoItem* pItem = dynamic_cast(selection); + + if(mPhotoSelected == NULL) + { + return; + } + else + { + mPhotoSelected->setSelected(false); + mPhotoSelected = pItem; + } + + mPhotoSelected->setSelected(true); +} diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.h b/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.h new file mode 100644 index 000000000..79af02c2d --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.h @@ -0,0 +1,51 @@ +#ifndef ALBUMCREATEDIALOG_H +#define ALBUMCREATEDIALOG_H + +#include +#include "util/TokenQueue.h" +#include "retroshare/rsphoto.h" +#include "retroshare/rsphoto.h" +#include "PhotoShareItemHolder.h" +#include "PhotoItem.h" +#include "PhotoDrop.h" + +namespace Ui { + class AlbumCreateDialog; +} + + +class AlbumCreateDialog : public QDialog, public PhotoShareItemHolder +{ + Q_OBJECT + +public: + explicit AlbumCreateDialog(TokenQueue* photoQueue, RsPhoto* rs_photo, QWidget *parent = 0); + ~AlbumCreateDialog(); + + void notifySelection(PhotoShareItem* selection); + + +private slots: + void publishAlbum(); + void publishPhotos(); + void addAlbumThumbnail(); + void changePage(); + void backPage(); + + +private: + + bool getAlbumThumbnail(RsPhotoThumbnail &nail); +private: + Ui::AlbumCreateDialog *ui; + + TokenQueue* mPhotoQueue; + RsPhoto* mRsPhoto; + QPixmap mThumbNail; + PhotoDrop* mPhotoDrop; + PhotoItem* mPhotoSelected; +}; + + + +#endif // ALBUMCREATEDIALOG_H diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.ui b/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.ui new file mode 100644 index 000000000..e95cca12f --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumCreateDialog.ui @@ -0,0 +1,539 @@ + + + AlbumCreateDialog + + + + 0 + 0 + 643 + 550 + + + + Create Album + + + true + + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + + + + + + + QFrame::NoFrame + + + + 0 + + + 6 + + + + + 3 + + + + + Album Name: + + + + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + +border: 2px solid white; +border-radius: 10px; + + + + + + + + :/images/album_64.png:/images/album_64.png + + + + 64 + 64 + + + + + + + + Category: + + + + + + + + Animals + + + + + Family + + + + + Friends + + + + + Flowers + + + + + Holiday + + + + + Landcapes + + + + + Pets + + + + + Portraits + + + + + Travel + + + + + Work + + + + + Random + + + + + + + + Caption: + + + + + + + + + + Where: + + + + + + + + + + Photographer: + + + + + + + + + + Description: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + + + + + + 1 + 0 + + + + Share Options + + + + + + + + Policy: + + + + + + + Quality: + + + + + + + Comments: + + + + + + + Identity: + + + + + + + + + + + + 0 + 0 + + + + + Public + + + + + Restricted + + + + + + + + + 0 + 0 + + + + + Resize Images (< 1Mb) + + + + + Resize Images (< 10Mb) + + + + + Send Original Images + + + + + + + + + 0 + 0 + + + + + No Comments Allowed + + + + + Authenticated Comments + + + + + Any Comments Allowed + + + + + + + + + 0 + 0 + + + + + Publish with Identity + + + + + + + + + + Qt::Horizontal + + + + 168 + 20 + + + + + + + + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> + + + + + + + + 0 + 10 + + + + true + + + Qt::ScrollBarAsNeeded + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 621 + 458 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + + + + + + + + + + + + + 9 + + + + + Qt::Horizontal + + + + 419 + 18 + + + + + + + + QDialogButtonBox::Cancel + + + + + + + Back + + + + + + + Add Photos + + + + + + + Publish Album + + + + + + + + + + + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1 +
+ + PhotoDrop + QWidget +
gui/PhotoShare/PhotoDrop.h
+ 1 +
+
+ + + + + + + buttonBox + rejected() + AlbumCreateDialog + close() + + + 353 + 529 + + + 321 + 274 + + + + +
diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumDialog.cpp b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.cpp new file mode 100644 index 000000000..7d20fffeb --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.cpp @@ -0,0 +1,112 @@ +#include + +#include "AlbumDialog.h" +#include "ui_AlbumDialog.h" +#include "gxs/rsgxsflags.h" + +AlbumDialog::AlbumDialog(const RsPhotoAlbum& album, TokenQueue* photoQueue, RsPhoto* rs_Photo, QWidget *parent) : + QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), + ui(new Ui::AlbumDialog), mRsPhoto(rs_Photo), mPhotoQueue(photoQueue), mAlbum(album), mPhotoSelected(NULL) +{ + ui->setupUi(this); + + ui->headerFrame->setHeaderImage(QPixmap(":/images/kview_64.png")); + ui->headerFrame->setHeaderText(tr("Album")); + + connect(ui->pushButton_PublishPhotos, SIGNAL(clicked()), this, SLOT(updateAlbumPhotos())); + connect(ui->pushButton_DeletePhoto, SIGNAL(clicked()), this, SLOT(deletePhoto())); + + mPhotoDrop = ui->scrollAreaWidgetContents; + + if(!(mAlbum.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) + { + ui->scrollAreaPhotos->setEnabled(false); + ui->pushButton_DeletePhoto->setEnabled(false); + } + mPhotoDrop->setPhotoItemHolder(this); + + setUp(); +} + + +void AlbumDialog::setUp() +{ + ui->lineEdit_Title->setText(QString::fromStdString(mAlbum.mMeta.mGroupName)); + ui->lineEdit_Caption->setText(QString::fromStdString(mAlbum.mCaption)); + ui->lineEdit_Category->setText(QString::fromStdString(mAlbum.mCategory)); + ui->lineEdit_Identity->setText(QString::fromStdString(mAlbum.mMeta.mAuthorId)); + ui->lineEdit_Where->setText(QString::fromStdString(mAlbum.mWhere)); + ui->textEdit_description->setText(QString::fromStdString(mAlbum.mDescription)); + + + QPixmap qtn; + qtn.loadFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str()); + + if(mAlbum.mThumbnail.size != 0) + { + ui->label_thumbNail->setPixmap(qtn); + } + else + { + // display a default Album icon when album has no Thumbnail + ui->label_thumbNail->setPixmap(QPixmap(":/images/album_default_128.png")); + } +} + +void AlbumDialog::updateAlbumPhotos(){ + + QSet photos; + + mPhotoDrop->getPhotos(photos); + + QSetIterator sit(photos); + + while(sit.hasNext()) + { + PhotoItem* item = sit.next(); + uint32_t token; + RsPhotoPhoto photo = item->getPhotoDetails(); + photo.mMeta.mGroupId = mAlbum.mMeta.mGroupId; + mRsPhoto->submitPhoto(token, photo); + mPhotoQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0); + } + close(); +} + +void AlbumDialog::deletePhoto(){ + + if(mPhotoSelected) + { + mPhotoSelected->setSelected(false); + mPhotoDrop->deletePhoto(mPhotoSelected); + } + +} + +void AlbumDialog::editPhoto() +{ + +} + +AlbumDialog::~AlbumDialog() +{ + delete ui; +} + +void AlbumDialog::notifySelection(PhotoShareItem *selection) +{ + + PhotoItem* pItem = dynamic_cast(selection); + + if(mPhotoSelected == NULL) + { + return; + } + else + { + mPhotoSelected->setSelected(false); + mPhotoSelected = pItem; + } + + mPhotoSelected->setSelected(true); +} diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumDialog.h b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.h new file mode 100644 index 000000000..a33ea2ded --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.h @@ -0,0 +1,43 @@ +#ifndef ALBUMDIALOG_H +#define ALBUMDIALOG_H + +#include +#include "retroshare/rsphoto.h" +#include "util/TokenQueue.h" +#include "PhotoShareItemHolder.h" +#include "PhotoItem.h" +#include "PhotoDrop.h" + +namespace Ui { + class AlbumDialog; +} + +class AlbumDialog : public QDialog, public PhotoShareItemHolder +{ + Q_OBJECT + +public: + explicit AlbumDialog(const RsPhotoAlbum& album, TokenQueue* photoQueue, RsPhoto* rs_Photo, QWidget *parent = 0); + ~AlbumDialog(); + + void notifySelection(PhotoShareItem* selection); + +private: + + void setUp(); + +private slots: + + void updateAlbumPhotos(); + void deletePhoto(); + void editPhoto(); +private: + Ui::AlbumDialog *ui; + RsPhoto* mRsPhoto; + TokenQueue* mPhotoQueue; + RsPhotoAlbum mAlbum; + PhotoDrop* mPhotoDrop; + PhotoItem* mPhotoSelected; +}; + +#endif // ALBUMDIALOG_H diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui new file mode 100644 index 000000000..d3d02fe27 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumDialog.ui @@ -0,0 +1,472 @@ + + + AlbumDialog + + + + 0 + 0 + 725 + 427 + + + + Album + + + + :/images/rstray3.png:/images/rstray3.png + + + true + + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Qt::Vertical + + + + + + + + 0 + 1 + + + + Album Thumbnail + + + + + + TextLabel + + + + + + + + + + + 10 + 1 + + + + Summary + + + + + + Album Title: + + + + + + + false + + + + 0 + 0 + + + + + + + + Category: + + + + + + + false + + + + 0 + 0 + + + + + + + + Caption + + + + + + + false + + + + 0 + 0 + + + + + + + + Where: + + + + + + + false + + + + 0 + 0 + + + + + + + + When + + + + + + + false + + + + 0 + 0 + + + + + + + + Description: + + + + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 10 + 1 + + + + Share Options + + + + + + false + + + + 0 + 0 + + + + + + + + Comments + + + + + + + Publish Identity + + + + + + + false + + + + 0 + 0 + + + + + + + + Visibility + + + + + + + false + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"> Drag &amp; Drop to insert pictures. Click on a picture to edit details below.</span></p></body></html> + + + + + + + + 0 + 10 + + + + true + + + Qt::ScrollBarAsNeeded + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 701 + 69 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + + + + + + + + + + + + Add Photo + + + + + + + Edit Photo + + + + + + + Delete Photo + + + + + + + Qt::Horizontal + + + + 68 + 17 + + + + + + + + QDialogButtonBox::Cancel + + + + + + + Publish Photos + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + PhotoDrop + QWidget +
gui/PhotoShare/PhotoDrop.h
+ 1 +
+ + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1 +
+
+ + + + + + buttonBox + rejected() + AlbumDialog + close() + + + 481 + 413 + + + 324 + 217 + + + + +
diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp b/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp new file mode 100644 index 000000000..ad74bdabb --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumItem.cpp @@ -0,0 +1,70 @@ +#include "AlbumItem.h" +#include "ui_AlbumItem.h" +#include + +#include + +AlbumItem::AlbumItem(const RsPhotoAlbum &album, PhotoShareItemHolder *albumHolder, QWidget *parent) : + QWidget(NULL), + ui(new Ui::AlbumItem), mAlbum(album), mAlbumHolder(albumHolder) +{ + ui->setupUi(this); + setUp(); +} + +AlbumItem::~AlbumItem() +{ + delete ui; +} + +void AlbumItem::setUp() +{ + ui->label_AlbumTitle->setText(QString::fromStdString(mAlbum.mMeta.mGroupName)); + ui->label_Photographer->setText(QString::fromStdString(mAlbum.mPhotographer)); + QPixmap qtn; + qtn.loadFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str()); + + if(mAlbum.mThumbnail.size != 0) + { + ui->label_Thumbnail->setPixmap(qtn); + } + else + { + // display a default Album icon when album has no Thumbnail + ui->label_Thumbnail->setPixmap(QPixmap(":/images/album_default_128.png")); + } +} + +void AlbumItem::mousePressEvent(QMouseEvent *event) +{ + QPoint pos = event->pos(); + + std::cerr << "AlbumItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; + std::cerr << std::endl; + + if(mAlbumHolder) + mAlbumHolder->notifySelection(this); + else + setSelected(true); + + QWidget::mousePressEvent(event); +} + +void AlbumItem::setSelected(bool on) +{ + mSelected = on; + if (mSelected) + { + ui->albumFrame->setStyleSheet("QFrame#albumFrame{border: 2px solid #55CC55;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #55EE55, stop: 1 #CCCCCC);\nborder-radius: 10px}"); + } + else + { + ui->albumFrame->setStyleSheet("QFrame#albumFrame{border: 2px solid #CCCCCC;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC);\nborder-radius: 10px}"); + } + update(); +} + +const RsPhotoAlbum& AlbumItem::getAlbum() +{ + return mAlbum; +} diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumItem.h b/retroshare-gui/src/gui/PhotoShare/AlbumItem.h new file mode 100644 index 000000000..b7e7cd0ce --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumItem.h @@ -0,0 +1,38 @@ +#ifndef ALBUMITEM_H +#define ALBUMITEM_H + +#include +#include "string.h" +#include "retroshare/rsphoto.h" +#include "PhotoShareItemHolder.h" + +namespace Ui { + class AlbumItem; +} + +class AlbumItem : public QWidget, public PhotoShareItem +{ + Q_OBJECT + +public: + explicit AlbumItem(const RsPhotoAlbum& album, PhotoShareItemHolder* albumHolder, QWidget *parent = 0); + virtual ~AlbumItem(); + + const RsPhotoAlbum& getAlbum(); + + bool isSelected() { return mSelected ;} + void setSelected(bool selected); + +protected: + void mousePressEvent(QMouseEvent *event); + +private: + void setUp(); +private: + Ui::AlbumItem *ui; + RsPhotoAlbum mAlbum; + PhotoShareItemHolder* mAlbumHolder; + bool mSelected; +}; + +#endif // ALBUMITEM_H diff --git a/retroshare-gui/src/gui/PhotoShare/AlbumItem.ui b/retroshare-gui/src/gui/PhotoShare/AlbumItem.ui new file mode 100644 index 000000000..88ef3770d --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/AlbumItem.ui @@ -0,0 +1,114 @@ + + + AlbumItem + + + + 0 + 0 + 229 + 234 + + + + Form + + + + + + QFrame#albumFrame{border: 2px solid #CCCCCC; +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #EEEEEE, stop: 1 #CCCCCC); +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + TextLabel + + + + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Album Title :</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photographer :</span></p></body></html> + + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.cpp deleted file mode 100644 index 027f0ca37..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.cpp +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "gui/PhotoShare/PhotoAddDialog.h" -#include "gui/PhotoShare/PhotoDetailsDialog.h" -#include "gui/PhotoShare/PhotoDrop.h" - -#include - -/** Constructor */ -PhotoAddDialog::PhotoAddDialog(QWidget *parent) -: QWidget(parent) -{ - ui.setupUi(this); - - connect(ui.scrollAreaWidgetContents, SIGNAL( buttonStatus( uint32_t ) ), this, SLOT( updateMoveButtons( uint32_t ) ) ); - connect(ui.pushButton_ShiftLeft, SIGNAL( clicked( void ) ), ui.scrollAreaWidgetContents, SLOT( moveLeft( void ) ) ); - connect(ui.pushButton_ShiftRight, SIGNAL( clicked( void ) ), ui.scrollAreaWidgetContents, SLOT( moveRight( void ) ) ); - connect(ui.pushButton_EditPhotoDetails, SIGNAL( clicked( void ) ), this, SLOT( showPhotoDetails( void ) ) ); - connect(ui.pushButton_EditAlbumDetails, SIGNAL( clicked( void ) ), this, SLOT( showAlbumDetails( void ) ) ); - connect(ui.pushButton_DeleteAlbum, SIGNAL( clicked( void ) ), this, SLOT( deleteAlbum( void ) ) ); - connect(ui.pushButton_DeletePhoto, SIGNAL( clicked( void ) ), this, SLOT( deletePhoto( void ) ) ); - - connect(ui.pushButton_Publish, SIGNAL( clicked( void ) ), this, SLOT( publishAlbum( void ) ) ); - - mPhotoDetails = NULL; - - mPhotoQueue = new TokenQueue(rsPhoto, this); - - ui.AlbumDrop->setSingleImage(); - connect(ui.AlbumDrop, SIGNAL( photosChanged( void ) ), this, SLOT( albumImageChanged( void ) ) ); - connect(ui.scrollAreaWidgetContents, SIGNAL( photosChanged( void ) ), this, SLOT( photoImageChanged( void ) ) ); - -} - - -void PhotoAddDialog::updateMoveButtons(uint32_t status) -{ - std::cerr << "PhotoAddDialog::updateMoveButtons(" << status << ")"; - std::cerr << std::endl; - - switch(status) - { - case PHOTO_SHIFT_NO_BUTTONS: - ui.pushButton_ShiftLeft->setEnabled(false); - ui.pushButton_ShiftRight->setEnabled(false); - break; - case PHOTO_SHIFT_LEFT_ONLY: - ui.pushButton_ShiftLeft->setEnabled(true); - ui.pushButton_ShiftRight->setEnabled(false); - break; - case PHOTO_SHIFT_RIGHT_ONLY: - ui.pushButton_ShiftLeft->setEnabled(false); - ui.pushButton_ShiftRight->setEnabled(true); - break; - case PHOTO_SHIFT_BOTH: - ui.pushButton_ShiftLeft->setEnabled(true); - ui.pushButton_ShiftRight->setEnabled(true); - break; - } -} - - -bool PhotoAddDialog::updateAlbumDetails(const RsPhotoAlbum &album) -{ - std::cerr << "PhotoAddDialog::updateAlbumDetails()"; - std::cerr << " (Copy data to mAlbumData + Add PhotoItem)"; - std::cerr << std::endl; - // cleanup old image first. - mAlbumData.mThumbnail.deleteImage(); - mAlbumData = album; - - // copy photo too. - mAlbumData.mThumbnail.data = 0; - mAlbumData.mThumbnail.copyFrom(album.mThumbnail); - - /* show iterate through all the photos and update them too - except normally they haven't arrived yet */ - - ui.lineEdit_Title->setText(QString::fromUtf8(album.mMeta.mGroupName.c_str())); - ui.lineEdit_Caption->setText(QString::fromUtf8(album.mCaption.c_str())); - ui.lineEdit_Where->setText(QString::fromUtf8(album.mWhere.c_str())); - ui.lineEdit_When->setText(QString::fromUtf8(album.mWhen.c_str())); - - PhotoItem *item = new PhotoItem(NULL, mAlbumData); - ui.AlbumDrop->addPhotoItem(item); - - // called via callback AlbumChanged. - //setAlbumDataToPhotos(); - return true; -} - - -bool PhotoAddDialog::setAlbumDataToPhotos() -{ - std::cerr << "PhotoAddDialog::setAlbumDataToPhotos()"; - std::cerr << std::endl; - - int photoCount = ui.scrollAreaWidgetContents->getPhotoCount(); - - for(int i = 0; i < photoCount; i++) - { - PhotoItem *item = ui.scrollAreaWidgetContents->getPhotoIdx(i); - item->updateAlbumText(mAlbumData); - } - return true; -} - - -void PhotoAddDialog::showPhotoDetails() -{ - std::cerr << "PhotoAddDialog::showPhotoDetails()"; - std::cerr << std::endl; - - PhotoItem *item = ui.scrollAreaWidgetContents->getSelectedPhotoItem(); - if (item) - { - if (!mPhotoDetails) - { - mPhotoDetails = new PhotoDetailsDialog(NULL); - connect(mPhotoDetails, SIGNAL( editingDone( void ) ), this, SLOT( editingStageDone( void ) ) ); - } - mPhotoDetails->setPhotoItem(item); - mPhotoDetails->show(); - mEditingModeAlbum = false; - } -} - - -void PhotoAddDialog::showAlbumDetails() -{ - std::cerr << "PhotoAddDialog::showAlbumDetails()"; - std::cerr << std::endl; - - - /* grab the image from the AlbumDrop */ - PhotoItem *item = NULL; - if (ui.AlbumDrop->getPhotoCount() > 0) - { - item = ui.AlbumDrop->getPhotoIdx(0); - } - - if (item) - { - if (!mPhotoDetails) - { - mPhotoDetails = new PhotoDetailsDialog(NULL); - connect(mPhotoDetails, SIGNAL( editingDone( void ) ), this, SLOT( editingStageDone( void ) ) ); - } - mPhotoDetails->setPhotoItem(item); - mPhotoDetails->show(); - mEditingModeAlbum = true; - } - else - { - std::cerr << "PhotoAddDialog::showAlbumDetails() PhotoItem Invalid"; - std::cerr << std::endl; - } -} - -/* Callback when AlbumDrop gets new image */ -void PhotoAddDialog::albumImageChanged() -{ - std::cerr << "PhotoAddDialog::albumImageChanged()"; - std::cerr << std::endl; - - /* must update the data from the reference stuff */ - PhotoItem *item = NULL; - if (ui.AlbumDrop->getPhotoCount() > 0) - { - item = ui.AlbumDrop->getPhotoIdx(0); - } - - if (!item) - { - std::cerr << "PhotoAddDialog::albumImageChanged() ERROR no Album PhotoItem"; - std::cerr << std::endl; - return; - } - - std::cerr << "PhotoAddDialog::albumImageChanged() PRE: AlbumDrop: " << item->mAlbumDetails; - std::cerr << std::endl; - std::cerr << "PhotoAddDialog::albumImageChanged() PRE: mAlbumData: " << mAlbumData; - std::cerr << std::endl; - - - item->mIsPhoto = false; // Force to Album mode. - - /* now AlbumDrop has the image, but AlbumData has the other stuff */ - - item->getPhotoThumbnail(mAlbumData.mThumbnail); - item->updateAlbumText(mAlbumData); - - - - /* if we are in editing mode -> update it */ - if ((mEditingModeAlbum) && (mPhotoDetails)) - { - std::cerr << "PhotoAddDialog::albumImageChanged() Updating PhotoDetails -> PhotoItem"; - std::cerr << std::endl; - mPhotoDetails->setPhotoItem(item); - } - - std::cerr << "PhotoAddDialog::albumImageChanged() POST: AlbumDrop: " << item->mAlbumDetails; - std::cerr << std::endl; - std::cerr << "PhotoAddDialog::albumImageChanged() POST: mAlbumData: " << mAlbumData; - std::cerr << std::endl; - -} - - -/* This is called back once PhotoDetailsDialog Finishes */ -void PhotoAddDialog::editingStageDone() -{ - std::cerr << "PhotoAddDialog::editingStageDone()"; - std::cerr << std::endl; - - if (mEditingModeAlbum) - { - /* need to resolve Album Data, repopulate entries - */ - - /* grab the image from the AlbumDrop (This is where PhotoDetailsDialog stores the data) */ - PhotoItem *item = NULL; - if (ui.AlbumDrop->getPhotoCount() > 0) - { - item = ui.AlbumDrop->getPhotoIdx(0); - } - - if (!item) - { - std::cerr << "PhotoAddDialog::editingStageDone() ERROR no Album PhotoItem"; - std::cerr << std::endl; - } - - /* Total Hack here Copy from AlbumDrop to Reference Data */ - - // cleanup old image first. - mAlbumData.mThumbnail.deleteImage(); - mAlbumData = item->mAlbumDetails; - item->getPhotoThumbnail(mAlbumData.mThumbnail); - - // Push Back data -> to trigger Text Update. - item->updateAlbumText(mAlbumData); - mEditingModeAlbum = false; - - // Update GUI too. - ui.lineEdit_Title->setText(QString::fromUtf8(mAlbumData.mMeta.mGroupName.c_str())); - ui.lineEdit_Caption->setText(QString::fromUtf8(mAlbumData.mCaption.c_str())); - ui.lineEdit_Where->setText(QString::fromUtf8(mAlbumData.mWhere.c_str())); - ui.lineEdit_When->setText(QString::fromUtf8(mAlbumData.mWhen.c_str())); - - } - else - { - std::cerr << "PhotoAddDialog::editingStageDone() ERROR not EditingModeAlbum"; - std::cerr << std::endl; - } - - // This forces item update -> though the AlbumUpdate is only needed if we edited Album. - setAlbumDataToPhotos(); -} - - -/* Callback when PhotoDrop gets new image */ -void PhotoAddDialog::photoImageChanged() -{ - setAlbumDataToPhotos(); -} - - - -void PhotoAddDialog::publishAlbum() -{ - std::cerr << "PhotoAddDialog::publishAlbum()"; - std::cerr << std::endl; - - /* we need to iterate through each photoItem, and extract the details */ - - RsPhotoAlbum album = mAlbumData; - album.mThumbnail.data = 0; - - album.mShareOptions.mShareType = 0; - album.mShareOptions.mShareGroupId = "unknown"; - album.mShareOptions.mPublishKey = "unknown"; - album.mShareOptions.mCommentMode = 0; - album.mShareOptions.mResizeMode = 0; - - //album.mMeta.mGroupName = ui.lineEdit_Title->text().toStdString(); - //album.mCategory = "Unknown"; - //album.mCaption = ui.lineEdit_Caption->text().toStdString(); - //album.mWhere = ui.lineEdit_Where->text().toStdString(); - //album.mWhen = ui.lineEdit_When->text().toStdString(); - - /* grab the image from the AlbumDrop */ - if (ui.AlbumDrop->getPhotoCount() > 0) - { - PhotoItem *item = ui.AlbumDrop->getPhotoIdx(0); - item->getPhotoThumbnail(album.mThumbnail); - } - - // For the moment, only submit albums Once. - if (mAlbumEdit) - { - std::cerr << "PhotoAddDialog::publishAlbum() AlbumEdit Mode"; - std::cerr << std::endl; - - /* call publishPhotos directly */ - publishPhotos(album.mMeta.mGroupId); - } - - - std::cerr << "PhotoAddDialog::publishAlbum() New Album Mode Submitting....."; - std::cerr << std::endl; - - uint32_t token; - rsPhoto->submitAlbumDetails(token, album, true); - - // tell tokenQueue to expect results from submission. - mPhotoQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_SUMMARY, 0); - -} - - - - -void PhotoAddDialog::publishPhotos(std::string albumId) -{ - /* now have path and album id */ - int photoCount = ui.scrollAreaWidgetContents->getPhotoCount(); - - for(int i = 0; i < photoCount; i++) - { - RsPhotoPhoto photo; - PhotoItem *item = ui.scrollAreaWidgetContents->getPhotoIdx(i); - - if (!item->mIsPhoto) - { - std::cerr << "PhotoAddDialog::publishAlbum() MAJOR ERROR!"; - std::cerr << std::endl; - } - - photo = item->mPhotoDetails; - photo.mThumbnail.data = 0; // do proper data copy. - item->getPhotoThumbnail(photo.mThumbnail); - - bool isNewPhoto = false; - bool isModifiedPhoto = false; - - if (mAlbumEdit) - { - // can have modFlags and be New... so the order is important. - if (photo.mMeta.mGroupId.length() < 1) - { - /* new photo - flag in mods */ - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_PHOTO; - photo.mMeta.mGroupId = albumId; - isNewPhoto = true; - } - else if (photo.mModFlags) - { - isModifiedPhoto = true; - } - } - else - { - /* new album - update GroupId, all photos are new */ - photo.mMeta.mGroupId = albumId; - isNewPhoto = true; - } - - photo.mOrder = i; - - std::cerr << "PhotoAddDialog::publishAlbum() Photo(" << i << ")"; - std::cerr << " mSetFlags: " << photo.mSetFlags; - std::cerr << " mModFlags: " << photo.mModFlags; - std::cerr << std::endl; - -#if 0 - /* scale photo if needed */ - if (album.mShareOptions.mResizeMode) - { - /* */ - - } -#endif - - /* save image to album path */ - photo.path = "unknown"; - - std::cerr << "PhotoAddDialog::publishAlbum() Photo(" << i << ") "; - - uint32_t token; - if (isNewPhoto) - { - std::cerr << "Is a New Photo"; - rsPhoto->submitPhoto(token, photo, true); - } - else if (isModifiedPhoto) - { - std::cerr << "Is Updated"; - rsPhoto->submitPhoto(token, photo, false); - } - else - { - std::cerr << "Is Unchanged"; - } - std::cerr << std::endl; - } - - clearDialog(); - - hide(); -} - - -void PhotoAddDialog::deleteAlbum() -{ - std::cerr << "PhotoAddDialog::deleteAlbum() Not Implemented Yet"; - std::cerr << std::endl; -} - - -void PhotoAddDialog::deletePhoto() -{ - std::cerr << "PhotoAddDialog::deletePhoto() Not Implemented Yet"; - std::cerr << std::endl; -} - - -void PhotoAddDialog::clearDialog() -{ - ui.lineEdit_Title->setText(QString("title")); - ui.lineEdit_Caption->setText(QString("Caption")); - ui.lineEdit_Where->setText(QString("Where")); - ui.lineEdit_When->setText(QString("When")); - - ui.scrollAreaWidgetContents->clearPhotos(); - ui.AlbumDrop->clearPhotos(); - - /* clean up album image */ - mAlbumData.mThumbnail.deleteImage(); - - RsPhotoAlbum emptyAlbum; - mAlbumData = emptyAlbum; - - /* add empty image */ - PhotoItem *item = new PhotoItem(NULL, mAlbumData); - ui.AlbumDrop->addPhotoItem(item); - - mAlbumEdit = false; -} - - -void PhotoAddDialog::loadAlbum(const std::string &albumId) -{ - /* much like main load fns */ - clearDialog(); - mAlbumEdit = true; - - RsTokReqOptions opts; - uint32_t token; - std::list albumIds; - albumIds.push_back(albumId); - - // We need both Album and Photo Data. - - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, albumIds, 0); - -} - - -bool PhotoAddDialog::loadPhotoData(const uint32_t &token) -{ - std::cerr << "PhotoAddDialog::loadPhotoData()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPhotoPhoto photo; - - if (rsPhoto->getPhoto(token, photo)) - { - std::cerr << "PhotoDialog::addAddPhoto() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - PhotoItem *item = new PhotoItem(NULL, photo, mAlbumData); - ui.scrollAreaWidgetContents->addPhotoItem(item); - - } - else - { - moreData = false; - } - } - return true; -} - -bool PhotoAddDialog::loadAlbumData(const uint32_t &token) -{ - std::cerr << "PhotoAddDialog::loadAlbumData()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPhotoAlbum album; - if (rsPhoto->getAlbum(token, album)) - { - std::cerr << " PhotoAddDialog::loadAlbumData() AlbumId: " << album.mMeta.mGroupId << std::endl; - updateAlbumDetails(album); - - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - uint32_t token; - std::list albumIds; - albumIds.push_back(album.mMeta.mGroupId); - mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, albumIds, 0); - } - else - { - moreData = false; - } - } - return true; -} - -bool PhotoAddDialog::loadCreatedAlbum(const uint32_t &token) -{ - std::cerr << "PhotoAddDialog::loadCreatedAlbum()"; - std::cerr << std::endl; - - std::list groupInfo; - if (!rsPhoto->getGroupSummary(token, groupInfo)) - { - std::cerr << "PhotoAddDialog::loadCreatedAlbum() ERROR Getting MetaData"; - std::cerr << std::endl; - return false; - } - - if (groupInfo.size() != 1) - { - std::cerr << "PhotoAddDialog::loadCreatedAlbum() ERROR Too much Info"; - std::cerr << std::endl; - return false; - } - - std::cerr << "PhotoAddDialog::loadCreatedAlbum() publishing Photos"; - std::cerr << std::endl; - - publishPhotos(groupInfo.front().mGroupId); - - return true; -} - - -void PhotoAddDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "PhotoDialog::loadRequest()"; - std::cerr << std::endl; - - if (queue == mPhotoQueue) - { - /* now switch on req */ - switch(req.mType) - { - case TOKENREQ_GROUPINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_DATA: - loadAlbumData(req.mToken); - break; - case RS_TOKREQ_ANSTYPE_SUMMARY: - loadCreatedAlbum(req.mToken); - break; - default: - std::cerr << "PhotoAddDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; - std::cerr << std::endl; - } - break; - case TOKENREQ_MSGINFO: - loadPhotoData(req.mToken); - break; - default: - std::cerr << "PhotoAddDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } -} - - - - diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.h b/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.h deleted file mode 100644 index 5c1a06121..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef MRK_PHOTO_ADD_DIALOG_H -#define MRK_PHOTO_ADD_DIALOG_H - -#include "ui_PhotoAddDialog.h" - -#include -#include "util/TokenQueue.h" - -class PhotoDetailsDialog; - -class PhotoAddDialog : public QWidget, public TokenResponse -{ - Q_OBJECT - -public: - PhotoAddDialog(QWidget *parent = 0); - - void loadAlbum(const std::string &albumId); -virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); - - void clearDialog(); - -private slots: - void showPhotoDetails(); - void showAlbumDetails(); - void editingStageDone(); - - // From PhotoDrops... - void albumImageChanged(); - void photoImageChanged(); - void updateMoveButtons(uint32_t status); - - void publishAlbum(); - - void deleteAlbum(); - void deletePhoto(); -private: - - void publishPhotos(std::string albumId); - - bool updateAlbumDetails(const RsPhotoAlbum &album); - bool setAlbumDataToPhotos(); - bool loadPhotoData(const uint32_t &token); - bool loadAlbumData(const uint32_t &token); - bool loadCreatedAlbum(const uint32_t &token); - - TokenQueue *mPhotoQueue; -protected: - - bool mAlbumEdit; // Editing or New. - bool mEditingModeAlbum; // Changing Album or Photo Details. - RsPhotoAlbum mAlbumData; - PhotoDetailsDialog *mPhotoDetails; - Ui::PhotoAddDialog ui; - -}; - -#endif - diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.ui b/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.ui deleted file mode 100644 index bfb09f45e..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoAddDialog.ui +++ /dev/null @@ -1,493 +0,0 @@ - - - PhotoAddDialog - - - - 0 - 0 - 852 - 383 - - - - - - - - - - Qt::Vertical - - - - - - - - 1 - 0 - - - - Share Options - - - - - - - 0 - 0 - - - - - Public - - - - - All Friends - - - - - Restricted - - - - - - - - - 0 - 0 - - - - - N/A - - - - - University Friends - - - - - Family - - - - - This List Contains - - - - - All your Groups - - - - - - - - - 0 - 0 - - - - - Resize Images (< 1Mb) - - - - - Resize Images (< 10Mb) - - - - - Send Original Images - - - - - - - - - 0 - 0 - - - - - No Comments Allowed - - - - - Authenticated Comments - - - - - Any Comments Allowed - - - - - - - - - 0 - 0 - - - - - Publish with XXX Key - - - - - - - - - - - - 0 - 1 - - - - Album Thumbnail - - - - - - - - - - - - - - - 10 - 1 - - - - Summary - - - - - - false - - - - 0 - 0 - - - - - - - - Category: - - - - - - - false - - - - Travel - - - - - Holiday - - - - - Friends - - - - - Family - - - - - Work - - - - - Random - - - - - - - - Caption - - - - - - - false - - - - 0 - 0 - - - - - - - - Where: - - - - - - - false - - - - 0 - 0 - - - - - - - - false - - - - 0 - 0 - - - - - - - - Album Title: - - - - - - - When - - - - - - - - - - Delete Album - - - - - - - Qt::Horizontal - - - - 78 - 20 - - - - - - - - Edit Album Details - - - - - - - - - - - HELP: Drag & Drop to insert, and re-order pictures. Click on a picture to edit details below. - - - - - - - - 0 - 10 - - - - true - - - Qt::ScrollBarAsNeeded - - - true - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - 0 - 0 - 830 - 83 - - - - QWidget#scrollAreaWidgetContents{border: none;} - - - - - - - - - - - - - - - Delete Photo - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Edit Photo Details - - - - - - - Qt::Horizontal - - - - 68 - 17 - - - - - - - - << - - - - - - - >> - - - - - - - Qt::Horizontal - - - - 68 - 17 - - - - - - - - Publish Album - - - - - - - - - - PhotoDrop - QWidget -
gui/PhotoShare/PhotoDrop.h
- 1 -
-
- - - - -
diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.cpp new file mode 100644 index 000000000..8d757122e --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.cpp @@ -0,0 +1,32 @@ +#include + +#include "PhotoCommentItem.h" +#include "ui_PhotoCommentItem.h" + + +PhotoCommentItem::PhotoCommentItem(const RsPhotoComment& comment, QWidget *parent): + QWidget(parent), + ui(new Ui::PhotoCommentItem), mComment(comment) +{ + ui->setupUi(this); + setUp(); +} + +PhotoCommentItem::~PhotoCommentItem() +{ + delete ui; +} + +const RsPhotoComment& PhotoCommentItem::getComment() +{ + return mComment; +} + +void PhotoCommentItem::setUp() +{ + ui->labelComment->setText(QString::fromUtf8(mComment.mComment.c_str())); + QDateTime qtime; + qtime.setTime_t(mComment.mMeta.mPublishTs); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm"); + ui->datetimelabel->setText(timestamp); +} diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.h b/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.h new file mode 100644 index 000000000..85fd2887d --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.h @@ -0,0 +1,29 @@ +#ifndef PHOTOCOMMENTITEM_H +#define PHOTOCOMMENTITEM_H + +#include +#include "retroshare/rsphoto.h" + +namespace Ui { + class PhotoCommentItem; +} + +class PhotoCommentItem : public QWidget +{ + Q_OBJECT + +public: + explicit PhotoCommentItem(const RsPhotoComment& comment, QWidget *parent = 0); + ~PhotoCommentItem(); + + const RsPhotoComment& getComment(); + +private: + + void setUp(); +private: + Ui::PhotoCommentItem *ui; + RsPhotoComment mComment; +}; + +#endif // PHOTOCOMMENTITEM_H diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.ui b/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.ui new file mode 100644 index 000000000..e43693241 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoCommentItem.ui @@ -0,0 +1,208 @@ + + + PhotoCommentItem + + + + 0 + 0 + 338 + 60 + + + + Form + + + + 0 + + + + + + 0 + 0 + + + + + 400 + 71 + + + + + + + + + 255 + 255 + 255 + + + + + + + 237 + 239 + 244 + + + + + + + + + 255 + 255 + 255 + + + + + + + 237 + 239 + 244 + + + + + + + + + 237 + 239 + 244 + + + + + + + 237 + 239 + 244 + + + + + + + + true + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + :/images/no_avatar_70.png + + + true + + + + + + + + 0 + 0 + + + + + PreferAntialias + + + + true + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Vertical + + + + 29 + 13 + + + + + + + + + 75 + true + PreferAntialias + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.cpp deleted file mode 100644 index 87f74184a..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "gui/PhotoShare/PhotoDetailsDialog.h" -#include "gui/PhotoShare/PhotoItem.h" - -#include - -/** Constructor */ -PhotoDetailsDialog::PhotoDetailsDialog(QWidget *parent) -: QWidget(parent) -{ - ui.setupUi(this); - connect( ui.pushButton_Update, SIGNAL( clicked() ), this, SLOT( updateDetails () ) ); - -} - - -void PhotoDetailsDialog::setPhotoItem(PhotoItem *item) -{ - if (mPhotoItem == item) - { - return; - } - - mPhotoItem = item; - - /* update fields from the edit fields */ - refreshDetails(); -} - - -void PhotoDetailsDialog::refreshDetails() -{ - blankDetails(); - if (!mPhotoItem) - { - return; - } - - ui.label_Headline->setText(QString("Photo Description")); - - //ui.comboBox_Category= mPhotoItem->mDetails.mCaption; - - if (mPhotoItem->mIsPhoto) - { - // THIS is tedious! - - RsPhotoPhoto &photo = mPhotoItem->mPhotoDetails; - RsPhotoAlbum &album = mPhotoItem->mAlbumDetails; - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - ui.lineEdit_Title->setText(QString::fromUtf8(photo.mMeta.mMsgName.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - ui.lineEdit_Title->setText(QString::fromUtf8(album.mMeta.mGroupName.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_CAPTION) - { - ui.lineEdit_Caption->setText(QString::fromUtf8(photo.mCaption.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_CAPTION) - { - ui.lineEdit_Caption->setText(QString::fromUtf8(album.mCaption.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_DESC) - { - ui.textEdit_Description->setText(QString::fromUtf8(photo.mDescription.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_DESC) - { - ui.textEdit_Description->setText(QString::fromUtf8(album.mDescription.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER) - { - ui.lineEdit_Photographer->setText(QString::fromUtf8(photo.mPhotographer.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER) - { - ui.lineEdit_Photographer->setText(QString::fromUtf8(album.mPhotographer.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - ui.lineEdit_Where->setText(QString::fromUtf8(photo.mWhere.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - ui.lineEdit_Where->setText(QString::fromUtf8(album.mWhere.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - ui.lineEdit_When->setText(QString::fromUtf8(photo.mWhen.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - ui.lineEdit_When->setText(QString::fromUtf8(album.mWhen.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_OTHER) - { - ui.lineEdit_Other->setText(QString::fromUtf8(photo.mOther.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_OTHER) - { - ui.lineEdit_Other->setText(QString::fromUtf8(album.mOther.c_str())); - } - - if (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_HASHTAGS) - { - ui.lineEdit_HashTags->setText(QString::fromUtf8(photo.mHashTags.c_str())); - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_HASHTAGS) - { - ui.lineEdit_HashTags->setText(QString::fromUtf8(album.mHashTags.c_str())); - } - } - else - { - RsPhotoAlbum &album = mPhotoItem->mAlbumDetails; - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - ui.lineEdit_Title->setText(QString::fromUtf8(album.mMeta.mGroupName.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_CAPTION) - { - ui.lineEdit_Caption->setText(QString::fromUtf8(album.mCaption.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_DESC) - { - ui.textEdit_Description->setText(QString::fromUtf8(album.mDescription.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER) - { - ui.lineEdit_Photographer->setText(QString::fromUtf8(album.mPhotographer.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - ui.lineEdit_Where->setText(QString::fromUtf8(album.mWhere.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - ui.lineEdit_When->setText(QString::fromUtf8(album.mWhen.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_OTHER) - { - ui.lineEdit_Other->setText(QString::fromUtf8(album.mOther.c_str())); - } - - if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_HASHTAGS) - { - ui.lineEdit_HashTags->setText(QString::fromUtf8(album.mHashTags.c_str())); - } - } - - const QPixmap *qtn = mPhotoItem->getPixmap(); - QPixmap cpy(*qtn); - ui.label_Photo->setPixmap(cpy); -} - -void PhotoDetailsDialog::blankDetails() -{ - ui.label_Headline->setText(QString("Nothing")); - - //ui.comboBox_Category= mPhotoItem->mDetails.mCaption; - - ui.lineEdit_Title->setText(QString("")); - ui.lineEdit_Caption->setText(QString("")); - ui.textEdit_Description->setText(QString("")); - ui.lineEdit_Photographer->setText(QString("")); - ui.lineEdit_Where->setText(QString("")); - ui.lineEdit_When->setText(QString("")); - ui.lineEdit_Other->setText(QString("")); - ui.lineEdit_HashTags->setText(QString("")); - - //QPixmap qtn = mPhotoItem->getPixmap(); - //ui.label_Photo->setPixmap(qtn); -} - - -void PhotoDetailsDialog::updateDetails() -{ - saveDetails(); - - // Notify Listeners. - editingDone(); - - hide(); -} - -void PhotoDetailsDialog::saveDetails() -{ - - if(!mPhotoItem) - { - return; - } - - RsPhotoPhoto &photo = mPhotoItem->mPhotoDetails; - RsPhotoAlbum &album = mPhotoItem->mAlbumDetails; - - std::string txt = ui.lineEdit_Title->text().toUtf8().constData(); - bool setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE)) - { - if (txt != photo.mMeta.mMsgName) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - if (txt != album.mMeta.mGroupName) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_TITLE; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_TITLE; - photo.mMeta.mMsgName = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_TITLE; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_TITLE; - album.mMeta.mGroupName = txt; - } - } - - - txt = ui.lineEdit_Caption->text().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_CAPTION)) - { - if (txt != photo.mCaption) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_CAPTION) - { - if (txt != album.mCaption) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_CAPTION; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_CAPTION; - photo.mCaption = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_CAPTION; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_CAPTION; - album.mCaption = txt; - } - } - - - txt = ui.textEdit_Description->toPlainText().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_DESC)) - { - if (txt != photo.mDescription) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_DESC) - { - if (txt != album.mDescription) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_DESC; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_DESC; - photo.mDescription = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_DESC; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_DESC; - album.mDescription = txt; - } - } - - - txt = ui.lineEdit_Photographer->text().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER)) - { - if (txt != photo.mPhotographer) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER) - { - if (txt != album.mPhotographer) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER; - photo.mPhotographer = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_PHOTOGRAPHER; - album.mPhotographer = txt; - } - } - - - txt = ui.lineEdit_Where->text().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE)) - { - if (txt != photo.mWhere) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - if (txt != album.mWhere) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_WHERE; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_WHERE; - photo.mWhere = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_WHERE; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_WHERE; - album.mWhere = txt; - } - } - - txt = ui.lineEdit_When->text().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN)) - { - if (txt != photo.mWhen) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - if (txt != album.mWhen) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_WHEN; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_WHEN; - photo.mWhen = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_WHEN; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_WHEN; - album.mWhen = txt; - } - } - - - txt = ui.lineEdit_HashTags->text().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_HASHTAGS)) - { - if (txt != photo.mHashTags) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_HASHTAGS) - { - if (txt != album.mHashTags) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_HASHTAGS; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_HASHTAGS; - photo.mHashTags = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_HASHTAGS; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_HASHTAGS; - album.mHashTags = txt; - } - } - - - txt = ui.lineEdit_Other->text().toUtf8().constData(); - setName = false; - if ((mPhotoItem->mIsPhoto) && (photo.mSetFlags & RSPHOTO_FLAGS_ATTRIB_OTHER)) - { - if (txt != photo.mOther) - setName = true; - } - else if (album.mSetFlags & RSPHOTO_FLAGS_ATTRIB_OTHER) - { - if (txt != album.mOther) - setName = true; - } - else if (txt.length() != 0) - { - setName = true; - } - - if (setName) - { - if (mPhotoItem->mIsPhoto) - { - photo.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_OTHER; - photo.mModFlags |= RSPHOTO_FLAGS_ATTRIB_OTHER; - photo.mOther = txt; - } - else - { - album.mSetFlags |= RSPHOTO_FLAGS_ATTRIB_OTHER; - album.mModFlags |= RSPHOTO_FLAGS_ATTRIB_OTHER; - album.mOther = txt; - } - } - - - - std::cerr << "PhotoDetailsDialog::saveDetails() "; - if (mPhotoItem->mIsPhoto) - { - std::cerr << " photo.mSetFlags: " << mPhotoItem->mPhotoDetails.mSetFlags; - std::cerr << " photo.mModFlags: " << mPhotoItem->mPhotoDetails.mModFlags; - } - std::cerr << " album.mSetFlags: " << mPhotoItem->mAlbumDetails.mSetFlags; - std::cerr << " album.mModFlags: " << mPhotoItem->mAlbumDetails.mModFlags; - std::cerr << std::endl; - - //QPixmap qtn = mPhotoItem->getPixmap(); - //ui.label_Photo->setPixmap(qtn); -} - - diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.ui b/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.ui deleted file mode 100644 index 45bc80d3f..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.ui +++ /dev/null @@ -1,221 +0,0 @@ - - - PhotoDetailsDialog - - - - 0 - 0 - 683 - 415 - - - - - - - - - - - - - - - 18 - 75 - true - - - - Album Description - - - - - - - Album Name: - - - - - - - - - - Category: - - - - - - - - Travel - - - - - Holiday - - - - - Friends - - - - - Family - - - - - Work - - - - - Random - - - - - - - - - - Thumbnail -Here -Dummy -Text -1 -2 -3 -................................... - - - - - - - - - - - Caption: - - - - - - - - - - Photographer: - - - - - - - - - - Description - - - - - - - - - - Where: - - - - - - - - - - When - - - - - - - - - - Other 1: - - - - - - - - - - HashTags: - - - - - - - - - - Qt::Vertical - - - - 20 - 18 - - - - - - - - - - - - Qt::Horizontal - - - - 598 - 20 - - - - - - - - Update Details - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.cpp index 405e7e397..fbec92ef5 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.cpp +++ b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.cpp @@ -1,766 +1,237 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "PhotoDialog.h" - -#include -#include - #include -#include +#include +#include "PhotoDialog.h" +#include "ui_PhotoDialog.h" +#include "retroshare/rsidentity.h" +#include "AddCommentDialog.h" -#include -#include - -/****** - * #define PHOTO_DEBUG 1 - *****/ - - -/**************************************************************** - * New Photo Display Widget. - * - * This has two 'lists'. - * Top list shows Albums. - * Lower list is photos from the selected Album. - * - * Notes: - * Each Item will be an AlbumItem, which contains a thumbnail & random details. - * We will limit Items to < 100. With a 'Filter to see more message. - * - * Thumbnails will come from Service. - * Option to Share albums / pictures onward (if permissions allow). - * Option to Download the albums to a specified directory. (is this required if sharing an album?) - * - * Will introduce a FullScreen SlideShow later... first get basics happening. - */ - - - - -/** Constructor */ -PhotoDialog::PhotoDialog(QWidget *parent) -: MainPage(parent) +PhotoDialog::PhotoDialog(RsPhoto *rs_photo, const RsPhotoPhoto &photo, QWidget *parent) : + QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), + ui(new Ui::PhotoDialog), mRsPhoto(rs_photo), mPhotoQueue(new TokenQueue(mRsPhoto->getTokenService(), this)), + mPhotoDetails(photo) { - ui.setupUi(this); + ui->setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); - mAddDialog = NULL; - mAlbumSelected = NULL; - mPhotoSelected = NULL; - mSlideShow = NULL; + connect(ui->pushButton_AddComment, SIGNAL(clicked()), this, SLOT(createComment())); + connect(ui->pushButton_AddCommentDlg, SIGNAL(clicked()), this, SLOT(addComment())); + connect(ui->fullscreenButton, SIGNAL(clicked()),this, SLOT(setFullScreen())); - connect( ui.toolButton_NewAlbum, SIGNAL(clicked()), this, SLOT(OpenOrShowPhotoAddDialog())); - connect( ui.toolButton_EditAlbum, SIGNAL(clicked()), this, SLOT(OpenPhotoEditDialog())); - connect( ui.toolButton_SlideShow, SIGNAL(clicked()), this, SLOT(OpenSlideShow())); - - QTimer *timer = new QTimer(this); - timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); - timer->start(1000); - - - /* setup TokenQueue */ - mPhotoQueue = new TokenQueue(rsPhoto, this); - -} - - -void PhotoDialog::notifySelection(PhotoItem *item, int ptype) -{ - std::cerr << "PhotoDialog::notifySelection() from : " << ptype << " " << item; - std::cerr << std::endl; - - switch(ptype) - { - default: - case PHOTO_ITEM_TYPE_ALBUM: - notifyAlbumSelection(item); - break; - case PHOTO_ITEM_TYPE_PHOTO: - notifyPhotoSelection(item); - break; - } -} - -void PhotoDialog::notifyAlbumSelection(PhotoItem *item) -{ - std::cerr << "PhotoDialog::notifyAlbumSelection() from : " << item; - std::cerr << std::endl; - - if (mAlbumSelected) - { - std::cerr << "PhotoDialog::notifyAlbumSelection() unselecting old one : " << mAlbumSelected; - std::cerr << std::endl; - - mAlbumSelected->setSelected(false); - } - - mAlbumSelected = item; - insertPhotosForSelectedAlbum(); -} - - -void PhotoDialog::notifyPhotoSelection(PhotoItem *item) -{ - std::cerr << "PhotoDialog::notifyPhotoSelection() from : " << item; - std::cerr << std::endl; - - if (mPhotoSelected) - { - std::cerr << "PhotoDialog::notifyPhotoSelection() unselecting old one : " << mPhotoSelected; - std::cerr << std::endl; - - mPhotoSelected->setSelected(false); - } - - mPhotoSelected = item; -} - - -void PhotoDialog::checkUpdate() -{ - /* update */ - if (!rsPhoto) - return; - - if (rsPhoto->updated()) - { - //insertAlbums(); - requestAlbumList(); - } - - return; -} - - -/*************** New Photo Dialog ***************/ - -void PhotoDialog::OpenSlideShow() -{ - - // TODO. - if (!mAlbumSelected) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Please select an album before\n" - "requesting to edit it!"), - QMessageBox::Ok); - return; - } - - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::OpenPhotoEditDialog() MAJOR ERROR!"; - std::cerr << std::endl; - return; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; - - if (mSlideShow) - { - mSlideShow->show(); - } - else - { - mSlideShow = new PhotoSlideShow(NULL); - mSlideShow->show(); - } - mSlideShow->loadAlbum(albumId); - -} - - -/*************** New Photo Dialog ***************/ - -void PhotoDialog::OpenOrShowPhotoAddDialog() -{ - if (mAddDialog) - { - mAddDialog->show(); - } - else - { - mAddDialog = new PhotoAddDialog(NULL); - mAddDialog->show(); - } - mAddDialog->clearDialog(); -} - - -/*************** Edit Photo Dialog ***************/ - -void PhotoDialog::OpenPhotoEditDialog() -{ - /* check if we have an album selected */ - // THE TWO MessageBoxes - should be handled by disabling the Button!. - // TODO. - if (!mAlbumSelected) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Please select an album before\n" - "requesting to edit it!"), - QMessageBox::Ok); - return; - } - - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::OpenPhotoEditDialog() MAJOR ERROR!"; - std::cerr << std::endl; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; -#if 0 - uint32_t flags = mAlbumSelected->mAlbumDetails.mMeta.mGroupFlags; - - if (!(flags & OWN)) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Cannot Edit Someone Else's Album"), - QMessageBox::Ok); - return; - } +#if QT_VERSION >= 0x040700 + ui->lineEdit->setPlaceholderText(tr("Write a comment...")) ; #endif - - OpenOrShowPhotoAddDialog(); - mAddDialog->loadAlbum(albumId); + setUp(); } - -bool PhotoDialog::matchesAlbumFilter(const RsPhotoAlbum &album) +PhotoDialog::~PhotoDialog() { - - return true; + delete ui; + delete mPhotoQueue; } -double PhotoDialog::AlbumScore(const RsPhotoAlbum &album) +void PhotoDialog::setUp() { - return 1; + QPixmap qtn; + qtn.loadFromData(mPhotoDetails.mThumbnail.data, mPhotoDetails.mThumbnail.size, mPhotoDetails.mThumbnail.type.c_str()); + ui->label_Photo->setPixmap(qtn); + ui->lineEdit_Title->setText(QString::fromStdString(mPhotoDetails.mMeta.mMsgName)); + + requestComments(); } - -bool PhotoDialog::matchesPhotoFilter(const RsPhotoPhoto &photo) +void PhotoDialog::addComment() { + AddCommentDialog dlg(this); + if (dlg.exec() == QDialog::Accepted) { + RsPhotoComment comment; + comment.mComment = dlg.getComment().toUtf8().constData(); - return true; + uint32_t token; + comment.mMeta.mGroupId = mPhotoDetails.mMeta.mGroupId; + comment.mMeta.mParentId = mPhotoDetails.mMeta.mOrigMsgId; + mRsPhoto->submitComment(token, comment); + mPhotoQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0); + } } -double PhotoDialog::PhotoScore(const RsPhotoPhoto &photo) +void PhotoDialog::clearComments() { - return 1; + //QLayout* l = ui->scrollAreaWidgetContents->layout(); + QSetIterator sit(mComments); + while(sit.hasNext()) + { + PhotoCommentItem* item = sit.next(); + ui->verticalLayout->removeWidget(item); + item->setParent(NULL); + delete item; + } + + mComments.clear(); } -void PhotoDialog::insertPhotosForSelectedAlbum() +void PhotoDialog::resetComments() { - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum()"; - std::cerr << std::endl; - - clearPhotos(); - - //std::list albumIds; - if (mAlbumSelected) - { - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() MAJOR ERROR!"; - std::cerr << std::endl; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; - //albumIds.push_back(albumId); - - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() AlbumId: " << albumId; - std::cerr << std::endl; - requestPhotoList(albumId); - } - //requestPhotoList(albumIds); + QSetIterator sit(mComments); + //QLayout* l = ui->scrollAreaWidgetContents->layout(); + while(sit.hasNext()) + { + PhotoCommentItem* item = sit.next(); + ui->verticalLayout->insertWidget(0,item); + } } - -void PhotoDialog::clearAlbums() +void PhotoDialog::requestComments() { - std::cerr << "PhotoDialog::clearAlbums()" << std::endl; - - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PhotoDialog::clearAlbums() missing litem"; - std::cerr << std::endl; - continue; - } - - PhotoItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PhotoDialog::clearAlbums() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "PhotoDialog::clearAlbums() Found Child, which is not a PhotoItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); pit++) - { - PhotoItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - mAlbumSelected = NULL; + RsTokReqOptions opts; + opts.mMsgFlagMask = RsPhoto::FLAG_MSG_TYPE_MASK; + opts.mMsgFlagFilter = RsPhoto::FLAG_MSG_TYPE_PHOTO_COMMENT; + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; + RsGxsGrpMsgIdPair msgId; + uint32_t token; + msgId.first = mPhotoDetails.mMeta.mGroupId; + msgId.second = mPhotoDetails.mMeta.mMsgId; + std::vector msgIdV; + msgIdV.push_back(msgId); + mPhotoQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIdV, 0); } -void PhotoDialog::clearPhotos() +void PhotoDialog::createComment() { - std::cerr << "PhotoDialog::clearPhotos()" << std::endl; + RsPhotoComment comment; + QString commentString = ui->lineEdit->text(); - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PhotoDialog::clearPhotos() missing litem"; - std::cerr << std::endl; - continue; - } - - PhotoItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PhotoDialog::clearPhotos() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "PhotoDialog::clearPhotos() Found Child, which is not a PhotoItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); pit++) - { - PhotoItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - - mPhotoSelected = NULL; - - -} + comment.mComment = commentString.toUtf8().constData(); -void PhotoDialog::addAlbum(const RsPhotoAlbum &album) -{ - std::cerr << " PhotoDialog::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; + uint32_t token; + comment.mMeta.mGroupId = mPhotoDetails.mMeta.mGroupId; + comment.mMeta.mParentId = mPhotoDetails.mMeta.mOrigMsgId; + mRsPhoto->submitComment(token, comment); + mPhotoQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0); - PhotoItem *item = new PhotoItem(this, album); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); + ui->lineEdit->clear(); } -void PhotoDialog::addPhoto(const RsPhotoPhoto &photo) -{ - std::cerr << "PhotoDialog::addPhoto() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - RsPhotoAlbum dummyAlbum; - dummyAlbum.mSetFlags = 0; - - PhotoItem *item = new PhotoItem(this, photo, dummyAlbum); - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - alayout->addWidget(item); - -} - -void PhotoDialog::deletePhotoItem(PhotoItem *item, uint32_t type) -{ - - - return; -} - - -/**************************** Request / Response Filling of Data ************************/ - - -void PhotoDialog::requestAlbumList() -{ - - std::list ids; - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); -} - - -void PhotoDialog::loadAlbumList(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadAlbumList()"; - std::cerr << std::endl; - - std::list albumIds; - rsPhoto->getGroupList(token, albumIds); - - requestAlbumData(albumIds); - - clearPhotos(); - - std::list::iterator it; - for(it = albumIds.begin(); it != albumIds.end(); it++) - { - requestPhotoList(*it); - } - -} - - -void PhotoDialog::requestAlbumData(const std::list &ids) -{ - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, 0); -} - - -bool PhotoDialog::loadAlbumData(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadAlbumData()"; - std::cerr << std::endl; - - clearAlbums(); - - bool moreData = true; - while(moreData) - { - RsPhotoAlbum album; - if (rsPhoto->getAlbum(token, album)) - { - std::cerr << " PhotoDialog::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; - - PhotoItem *item = new PhotoItem(this, album); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); - } - else - { - moreData = false; - } - } - - return true; -} - - -void PhotoDialog::requestPhotoList(const std::string &albumId) -{ - - std::list ids; - ids.push_back(albumId); - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - uint32_t token; - mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); -} - - - - -void PhotoDialog::loadPhotoList(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadPhotoList()"; - std::cerr << std::endl; - - - std::list photoIds; - - rsPhoto->getMsgList(token, photoIds); - requestPhotoData(photoIds); -} - - -void PhotoDialog::requestPhotoData(const std::list &photoIds) -{ - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, photoIds, 0); -} - - -void PhotoDialog::loadPhotoData(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadPhotoData()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPhotoPhoto photo; - - if (rsPhoto->getPhoto(token, photo)) - { - - std::cerr << "PhotoDialog::loadPhotoData() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - addPhoto(photo); - } - else - { - moreData = false; - } - } -} - - -/********************************/ +/*************** message loading **********************/ void PhotoDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) { - std::cerr << "PhotoDialog::loadRequest()"; - std::cerr << std::endl; + std::cerr << "PhotoShare::loadRequest()"; + std::cerr << std::endl; + + if (queue == mPhotoQueue) + { + /* now switch on req */ + switch(req.mType) + { + case TOKENREQ_MSGINFO: + { + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_DATA: + loadComment(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_LIST: + loadList(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeComment(req.mToken); + break; + default: + std::cerr << "PhotoShare::loadRequest() ERROR: MSG INVALID TYPE"; + std::cerr << std::endl; + break; + } + break; + } + + default: + { + std::cerr << "PhotoShare::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } + } - if (queue == mPhotoQueue) - { - /* now switch on req */ - switch(req.mType) - { - case TOKENREQ_GROUPINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_LIST: - loadAlbumList(req.mToken); - break; - case RS_TOKREQ_ANSTYPE_DATA: - loadAlbumData(req.mToken); - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - case TOKENREQ_MSGINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_LIST: - loadPhotoList(req.mToken); - break; - //case RS_TOKREQ_ANSTYPE_DATA: - // loadPhotoData(req.mToken); - // break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - case TOKENREQ_MSGRELATEDINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_DATA: - loadPhotoData(req.mToken); - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } } - -/**************************** Request / Response Filling of Data ************************/ - - -// OLD STUFF THAT CANNOT BE USED WITH NEW REQ/RESP -#if 0 - - -void PhotoDialog::insertAlbums() +void PhotoDialog::loadComment(uint32_t token) { - /* clear it all */ - clearAlbums(); - //ui.albumLayout->clear(); - /* create a list of albums */ + clearComments(); + PhotoRelatedCommentResult results; + mRsPhoto->getPhotoRelatedComment(token, results); - std::list albumIds; - std::list filteredAlbumIds; - std::list::iterator it; + PhotoRelatedCommentResult::iterator mit = results.begin(); - rsPhoto->getAlbumList(albumIds); + for(; mit != results.end(); mit++) + { + const std::vector& commentV = mit->second; + std::vector::const_iterator vit = commentV.begin(); - /* Filter Albums */ /* Sort Albums */ -#define MAX_ALBUMS 50 + for(; vit != commentV.end(); vit++) + { + addComment(*vit); + } + } - int count = MAX_ALBUMS; - FilterNSortAlbums(albumIds, filteredAlbumIds, count); - - for(it = filteredAlbumIds.begin(); it != filteredAlbumIds.end(); it++) - { - addAlbum(*it); - } - - insertPhotosForAlbum(filteredAlbumIds); + resetComments(); } -void PhotoDialog::insertPhotosForAlbum(const std::list &albumIds) +void PhotoDialog::loadList(uint32_t token) { - /* clear it all */ - clearPhotos(); - //ui.photoLayout->clear(); + GxsMsgReq msgIds; + mRsPhoto->getMsgList(token, msgIds); + RsTokReqOptions opts; - /* create a list of albums */ - - std::list ids; - std::list photoIds; - std::list filteredPhotoIds; - std::list::const_iterator it; - - for(it = albumIds.begin(); it != albumIds.end(); it++) - { - rsPhoto->getPhotoList(*it, photoIds); - } - - /* Filter Albums */ /* Sort Albums */ -#define MAX_PHOTOS 50 - - int count = MAX_PHOTOS; - - FilterNSortPhotos(photoIds, filteredPhotoIds, MAX_PHOTOS); - - for(it = filteredPhotoIds.begin(); it != filteredPhotoIds.end(); it++) - { - addPhoto(*it); - } + // just use data as no need to worry about getting comments + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + uint32_t reqToken; + mPhotoQueue->requestMsgInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, 0); } - -void PhotoDialog::insertPhotosForSelectedAlbum() +void PhotoDialog::addComment(const RsPhotoComment &comment) { - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum()"; - std::cerr << std::endl; - - clearPhotos(); - - std::list albumIds; - if (mAlbumSelected) - { - albumIds.push_back(mAlbumSelected->mDetails.mAlbumId); - - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() AlbumId: " << mAlbumSelected->mDetails.mAlbumId; - std::cerr << std::endl; - } - - insertPhotosForAlbum(albumIds); + PhotoCommentItem* item = new PhotoCommentItem(comment); + mComments.insert(item); } -bool PhotoDialog::FilterNSortAlbums(const std::list &albumIds, std::list &filteredAlbumIds, int count) +void PhotoDialog::acknowledgeComment(uint32_t token) { - std::multimap sortedAlbums; - std::multimap::iterator sit; - std::list::const_iterator it; - - for(it = albumIds.begin(); it != albumIds.end(); it++) - { - RsPhotoAlbum album; - rsPhoto->getAlbum(*it, album); + RsGxsGrpMsgIdPair msgId; + mRsPhoto->acknowledgeMsg(token, msgId); - if (matchesAlbumFilter(album)) - { - double score = AlbumScore(album); + if(msgId.first.empty() || msgId.second.empty()){ - sortedAlbums.insert(std::make_pair(score, *it)); - } - } - - int i; - for (sit = sortedAlbums.begin(), i = 0; (sit != sortedAlbums.end()) && (i < count); sit++, i++) - { - filteredAlbumIds.push_back(sit->second); - } - - return true; + }else + { + requestComments(); + } } - -bool PhotoDialog::FilterNSortPhotos(const std::list &photoIds, std::list &filteredPhotoIds, int count) +void PhotoDialog::setFullScreen() { - std::multimap sortedPhotos; - std::multimap::iterator sit; - std::list::const_iterator it; - - int i = 0; - for(it = photoIds.begin(); it != photoIds.end(); it++, i++) - { - RsPhotoPhoto photo; - rsPhoto->getPhoto(*it, photo); - - if (matchesPhotoFilter(photo)) - { - double score = i; //PhotoScore(album); - sortedPhotos.insert(std::make_pair(score, *it)); - } - } - - for (sit = sortedPhotos.begin(), i = 0; (sit != sortedPhotos.end()) && (i < count); sit++, i++) - { - filteredPhotoIds.push_back(sit->second); - } - return true; -} + if (!isFullScreen()) { + // hide menu & toolbars +#ifdef Q_WS_X11 + show(); + raise(); + setWindowState( windowState() | Qt::WindowFullScreen ); +#else + setWindowState( windowState() | Qt::WindowFullScreen ); + show(); + raise(); #endif + } else { + setWindowState( windowState() ^ Qt::WindowFullScreen ); + show(); + } +} diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.h b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.h index c99094b2b..15cf6bf5f 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.h +++ b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.h @@ -1,112 +1,62 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ +#ifndef PHOTODIALOG_H +#define PHOTODIALOG_H -#ifndef MRK_PHOTO_DIALOG_H -#define MRK_PHOTO_DIALOG_H - -#include "retroshare-gui/mainpage.h" -#include "ui_PhotoDialog.h" - -#include - -#include - -#include "gui/PhotoShare/PhotoItem.h" -#include "gui/PhotoShare/PhotoAddDialog.h" -#include "gui/PhotoShare/PhotoSlideShow.h" +#include +#include +#include "retroshare/rsphoto.h" #include "util/TokenQueue.h" +#include "PhotoCommentItem.h" -class PhotoDialog : public MainPage, public PhotoHolder, public TokenResponse +namespace Ui { + class PhotoDialog; +} + +class PhotoDialog : public QDialog, public TokenResponse { - Q_OBJECT + Q_OBJECT public: - PhotoDialog(QWidget *parent = 0); - -virtual void deletePhotoItem(PhotoItem *, uint32_t type); -virtual void notifySelection(PhotoItem *item, int ptype); - - void notifyAlbumSelection(PhotoItem *item); - void notifyPhotoSelection(PhotoItem *item); + explicit PhotoDialog(RsPhoto* rs_photo, const RsPhotoPhoto& photo, QWidget *parent = 0); + ~PhotoDialog(); private slots: - void checkUpdate(); - void OpenOrShowPhotoAddDialog(); - void OpenPhotoEditDialog(); - void OpenSlideShow(); + void addComment(); + void createComment(); + void setFullScreen(); + +public: + void loadRequest(const TokenQueue *queue, const TokenRequest &req); private: + void setUp(); - /* Request Response Functions for loading data */ - void requestAlbumList(); - void requestAlbumData(const std::list &ids); - void requestPhotoList(const std::string &albumId); - void requestPhotoData(const std::list &photoIds); - - void loadAlbumList(const uint32_t &token); - bool loadAlbumData(const uint32_t &token); - void loadPhotoList(const uint32_t &token); - void loadPhotoData(const uint32_t &token); - - void loadRequest(const TokenQueue *queue, const TokenRequest &req); + /*! + * clears comments + * and places them back in dialog + */ + void resetComments(); + /*! + * Request comments + */ + void requestComments(); - /* TODO: These functions must be filled in for proper filtering to work - * and tied to the GUI input - */ + /*! + * Simply removes comments but doesn't place them back in dialog + */ + void clearComments(); - bool matchesAlbumFilter(const RsPhotoAlbum &album); - double AlbumScore(const RsPhotoAlbum &album); - bool matchesPhotoFilter(const RsPhotoPhoto &photo); - double PhotoScore(const RsPhotoPhoto &photo); - - /* Grunt work of setting up the GUI */ - - //bool FilterNSortAlbums(const std::list &albumIds, std::list &filteredAlbumIds, int count); - //bool FilterNSortPhotos(const std::list &photoIds, std::list &filteredPhotoIds, int count); - //void insertAlbums(); - //void insertPhotosForAlbum(const std::list &albumIds); - - void insertPhotosForSelectedAlbum(); - - void addAlbum(const RsPhotoAlbum &album); - void addPhoto(const RsPhotoPhoto &photo); - - void clearAlbums(); - void clearPhotos(); - - PhotoAddDialog *mAddDialog; - PhotoSlideShow *mSlideShow; - - PhotoItem *mAlbumSelected; - PhotoItem *mPhotoSelected; - - TokenQueue *mPhotoQueue; - - /* UI - from Designer */ - Ui::PhotoDialog ui; + void acknowledgeComment(uint32_t token); + void loadComment(uint32_t token); + void loadList(uint32_t token); + void addComment(const RsPhotoComment& comment); +private: + Ui::PhotoDialog *ui; + RsPhoto* mRsPhoto; + TokenQueue* mPhotoQueue; + RsPhotoPhoto mPhotoDetails; + QSet mComments; }; -#endif - +#endif // PHOTODIALOG_H diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui index 30217f6c8..d61266bf0 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui +++ b/retroshare-gui/src/gui/PhotoShare/PhotoDialog.ui @@ -1,225 +1,338 @@ PhotoDialog - + 0 0 - 774 - 608 + 594 + 572 - + PhotoShare - - - - - - - Filter - - - - - - - - - - Source - - - - - Category - - - - - Rating - - - - - - - - - - - [ - ] - - - - - - - [ + ] - - - - - - - - - - - - Source - - - - - Category - - - - - Rating - - - - - - - - - - - [ - ] - - - - - - - [ + ] - - - - - - - - - - - Qt::Vertical + + + :/images/rstray3.png:/images/rstray3.png + + + true + + + + + + + 0 + 1 + - - - true - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - 0 - 0 - 754 - 234 - - - - QWidget#scrollAreaWidgetContents{border: none;} - - - - - - - - - - - - - Qt::Horizontal - - - - 139 - 20 - - - - - - - - - - true - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - 0 - 0 - 754 - 233 - - - - QWidget#scrollAreaWidgetContents{border: none;} - - - - - - Qt::Horizontal - - - - 426 - 20 - - - - - - - + + Photo + + + + + + + 0 + 0 + + + + + 200 + 300 + + + + TextLabel + + + + - - - - - - Slide Show - - - - - - - Edit Album - - - - - - - New Album - - - - + + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + true + + + + + 0 + 0 + 328 + 20 + + + + + 0 + 0 + + + + + + + 1 + + + + + + + + + + + + + + Comment + + + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Summary + + + + + + false + + + + 0 + 0 + + + + + + + + Caption + + + + + + + false + + + + 0 + 0 + + + + + + + + Where: + + + + + + + false + + + + 0 + 0 + + + + + + + + false + + + + 0 + 0 + + + + + + + + Photo Title: + + + + + + + When + + + + + + + + + + ... + + + + :/images/window_fullscreen.png:/images/window_fullscreen.png + + + true + + + + + + + Qt::Horizontal + + + + 238 + 20 + + + + + + + + Add Comment + + - + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDialog_v1.ui b/retroshare-gui/src/gui/PhotoShare/PhotoDialog_v1.ui deleted file mode 100644 index 3e44e7d1f..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDialog_v1.ui +++ /dev/null @@ -1,273 +0,0 @@ - - - PhotoDialog - - - - 0 - 0 - 774 - 608 - - - - - - - - - - - - Filter - - - - - - - - - - Source - - - - - Category - - - - - Rating - - - - - - - - - - - [ - ] - - - - - - - [ + ] - - - - - - - - - - - - Source - - - - - Category - - - - - Rating - - - - - - - - - - - [ - ] - - - - - - - [ + ] - - - - - - - - - - - Qt::Vertical - - - - true - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - 0 - 0 - 746 - 227 - - - - QWidget#scrollAreaWidgetContents{border: none;} - - - - - - - - - Album 1 - - - - - - - Album 2 - - - - - - - Album 3 - - - - - - - Album 4 - - - - - - - Qt::Horizontal - - - - 139 - 20 - - - - - - - - - - true - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - 0 - 0 - 746 - 227 - - - - QWidget#scrollAreaWidgetContents{border: none;} - - - - - - - - - PICTURE 1 - - - - - - - Qt::Horizontal - - - - 426 - 20 - - - - - - - - - - - - - - - Remove Picture - - - - - - - Slide Show - - - - - - - Edit Album - - - - - - - Edit Picture Details - - - - - - - New Album - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDrop.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoDrop.cpp index 49a316963..94f0fc31d 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDrop.cpp +++ b/retroshare-gui/src/gui/PhotoShare/PhotoDrop.cpp @@ -57,40 +57,17 @@ PhotoDrop::PhotoDrop(QWidget *parent) : QWidget(parent) { setAcceptDrops(true); - mIsSingleImageDrop = false; mSelected = NULL; checkMoveButtons(); reorderPhotos(); } -void PhotoDrop::notifySelection(PhotoItem *item, int ptype) -{ - std::cerr << "PhotoDrop::notifySelection() from : " << ptype << " " << item; - std::cerr << std::endl; - - if (mSelected) - { - std::cerr << "PhotoDrop::notifySelection() unselecting old one : " << mSelected; - std::cerr << std::endl; - - mSelected->setSelected(false); - } - - mSelected = item; - checkMoveButtons(); -} - void PhotoDrop::clear() { } -void PhotoDrop::setSingleImage() -{ - mIsSingleImageDrop = true; -} - PhotoItem *PhotoDrop::getSelectedPhotoItem() { @@ -98,11 +75,6 @@ PhotoItem *PhotoDrop::getSelectedPhotoItem() } -void PhotoDrop::deletePhotoItem(PhotoItem *, uint32_t type) -{ - return; -} - void PhotoDrop::resizeEvent ( QResizeEvent * event ) { @@ -175,6 +147,10 @@ PhotoItem *PhotoDrop::getPhotoIdx(int idx) return NULL; } +void PhotoDrop::getPhotos(QSet &photos) +{ + photos = mPhotos; +} void PhotoDrop::reorderPhotos() @@ -637,11 +613,8 @@ void PhotoDrop::dropEvent(QDropEvent *event) std::cerr << "Whole URL: " << uit->toString().toStdString() << std::endl; std::cerr << "or As Local File: " << localpath.toStdString() << std::endl; - PhotoItem *item = new PhotoItem(this, localpath.toStdString()); - - addPhotoItem(item); - //mPhotos.push_back(item); - //layout()->addWidget(item); + PhotoItem* item = new PhotoItem(mHolder, localpath); + addPhotoItem(item); } event->setDropAction(Qt::CopyAction); event->accept(); @@ -671,22 +644,30 @@ void PhotoDrop::mousePressEvent(QMouseEvent *event) QWidget::mousePressEvent(event); } - +void PhotoDrop::setPhotoItemHolder(PhotoShareItemHolder *holder) +{ + mHolder = holder; +} void PhotoDrop::addPhotoItem(PhotoItem *item) { std::cerr << "PhotoDrop::addPhotoItem()"; std::cerr << std::endl; - if (mIsSingleImageDrop) - { - clearPhotos(); - } - - item->updateParent(this); + mPhotos.insert(item); layout()->addWidget(item); //checkMoveButtons(); } +bool PhotoDrop::deletePhoto(PhotoItem *item) +{ + if(mPhotos.contains(item)){ + mPhotos.remove(item); + layout()->removeWidget(item); + delete item; + } + else + return false; +} diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDrop.h b/retroshare-gui/src/gui/PhotoShare/PhotoDrop.h index 881cf9ccd..7bba5979b 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDrop.h +++ b/retroshare-gui/src/gui/PhotoShare/PhotoDrop.h @@ -28,6 +28,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class QDragEnterEvent; @@ -36,6 +37,7 @@ class QMouseEvent; QT_END_NAMESPACE #include "gui/PhotoShare/PhotoItem.h" +#include "PhotoShareItemHolder.h" #define PHOTO_SHIFT_NO_BUTTONS 0 #define PHOTO_SHIFT_LEFT_ONLY 1 @@ -43,22 +45,28 @@ QT_END_NAMESPACE #define PHOTO_SHIFT_BOTH 3 -class PhotoDrop : public QWidget, public PhotoHolder +class PhotoDrop : public QWidget { Q_OBJECT public: + PhotoDrop(QWidget *parent = 0); void clear(); - void setSingleImage(); + PhotoItem *getSelectedPhotoItem(); + int getPhotoCount(); + PhotoItem *getPhotoIdx(int idx); + void getPhotos(QSet& photos); -virtual void deletePhotoItem(PhotoItem *, uint32_t type); -virtual void notifySelection(PhotoItem *item, int ptype); + void addPhotoItem(PhotoItem *item); + void setPhotoItemHolder(PhotoShareItemHolder* holder); -PhotoItem *getSelectedPhotoItem(); -int getPhotoCount(); -PhotoItem *getPhotoIdx(int idx); -void addPhotoItem(PhotoItem *item); + /*! + * delete photo item held by photo drop + * @param item photo item to delete + * @return false if item could not be found + */ + bool deletePhoto(PhotoItem* item); public slots: void moveLeft(); @@ -86,7 +94,8 @@ private: PhotoItem *mSelected; int mColumns; - bool mIsSingleImageDrop; + PhotoShareItemHolder* mHolder; + QSet mPhotos; }; #endif diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoItem.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoItem.cpp index 26611d9d0..c17034aad 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoItem.cpp +++ b/retroshare-gui/src/gui/PhotoShare/PhotoItem.cpp @@ -1,282 +1,153 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include -#include -#include - -#include "PhotoItem.h" - -#include - -#include -#include - -/**** - * #define DEBUG_ITEM 1 - ****/ - -/** Constructor */ -PhotoItem::PhotoItem(PhotoHolder *parent, const RsPhotoAlbum &album) -:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_ALBUM) -{ - setupUi(this); - - setAttribute ( Qt::WA_DeleteOnClose, true ); - - mIsPhoto = false; - setDummyText(); - updateAlbumText(album); // saves: mAlbumDetails = album; - updateImage(album.mThumbnail); - - setSelected(false); -} - - -PhotoItem::PhotoItem(PhotoHolder *parent, const RsPhotoPhoto &photo, const RsPhotoAlbum &album) -:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_PHOTO) -{ - setupUi(this); - - setAttribute ( Qt::WA_DeleteOnClose, true ); - - mIsPhoto = true; - - setDummyText(); - updatePhotoText(photo); // saves: mPhotoDetails = photo; - updateAlbumText(album); // saves: mAlbumDetails = album; - - updateImage(photo.mThumbnail); - - setSelected(false); -} - - -PhotoItem::PhotoItem(PhotoHolder *parent, std::string path) // for new photos. -:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_NEW) -{ - setupUi(this); - - setAttribute ( Qt::WA_DeleteOnClose, true ); - - setDummyText(); - mIsPhoto = true; - - int width = 120; - int height = 120; - - //QPixmap qtn = QPixmap(QString::fromStdString(path)).scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - QPixmap qtn = QPixmap(QString::fromStdString(path)).scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); - imgLabel->setPixmap(qtn); - setSelected(false); -} - -void PhotoItem::updateParent(PhotoHolder *parent) // for external construction. -{ - mParent = parent; -} - - -void PhotoItem::setDummyText() -{ - titleLabel->setText(QString("Unknown")); - fromBoldLabel->setText(QString("By:")); - fromLabel->setText(QString("Unknown")); - statusBoldLabel->setText(QString("Where:")); - statusLabel->setText(QString("Unknown")); - dateBoldLabel->setText(QString("When:")); - dateLabel->setText(QString("Unknown")); -} - - -void PhotoItem::updateAlbumText(const RsPhotoAlbum &album) -{ - mAlbumDetails = album; - mAlbumDetails.mThumbnail.data = 0; - updateText(); -} - -void PhotoItem::updatePhotoText(const RsPhotoPhoto &photo) -{ - // Save new Photo details. - mPhotoDetails = photo; - mPhotoDetails.mThumbnail.data = 0; - updateText(); -} - - - -void PhotoItem::updateText() -{ - // SET Album Values first -> then overwrite with Photo Values. - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - titleLabel->setText(QString::fromUtf8(mAlbumDetails.mMeta.mGroupName.c_str())); - } - - // This needs to be fixed!! TODO - fromLabel->setText(QString::fromStdString(mAlbumDetails.mMeta.mGroupId)); - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_AUTHOR) - { - // This needs to be fixed!! TODO - fromLabel->setText(QString::fromStdString(mAlbumDetails.mMeta.mGroupId)); - } - - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - statusLabel->setText(QString::fromUtf8(mAlbumDetails.mWhere.c_str())); - } - - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - dateLabel->setText(QString::fromUtf8(mAlbumDetails.mWhen.c_str())); - } - - // NOW Photo Bits. - if (mIsPhoto) - { - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - titleLabel->setText(QString::fromUtf8(mPhotoDetails.mMeta.mMsgName.c_str())); - } - - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_AUTHOR) - { - // This needs to be fixed!! TODO - fromLabel->setText(QString::fromStdString(mPhotoDetails.mMeta.mAuthorId)); - } - - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - statusLabel->setText(QString::fromUtf8(mPhotoDetails.mWhere.c_str())); - } - - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - dateLabel->setText(QString::fromUtf8(mPhotoDetails.mWhen.c_str())); - } - } - -} - -void PhotoItem::updateImage(const RsPhotoThumbnail &thumbnail) -{ - if (thumbnail.data != NULL) - { - QPixmap qtn; - qtn.loadFromData(thumbnail.data, thumbnail.size, thumbnail.type.c_str()); - imgLabel->setPixmap(qtn); - } -} - -bool PhotoItem::getPhotoThumbnail(RsPhotoThumbnail &nail) -{ - const QPixmap *tmppix = imgLabel->pixmap(); - - QByteArray ba; - QBuffer buffer(&ba); - - if(!tmppix->isNull()) - { - // send chan image - - buffer.open(QIODevice::WriteOnly); - tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format - - RsPhotoThumbnail tmpnail; - tmpnail.data = (uint8_t *) ba.data(); - tmpnail.size = ba.size(); - - nail.copyFrom(tmpnail); - - return true; - } - - nail.data = NULL; - nail.size = 0; - return false; -} - - -void PhotoItem::removeItem() -{ -#ifdef DEBUG_ITEM - std::cerr << "PhotoItem::removeItem()"; - std::cerr << std::endl; -#endif - hide(); - if (mParent) - { - mParent->deletePhotoItem(this, mType); - } -} - - -void PhotoItem::setSelected(bool on) -{ - mSelected = on; - if (mSelected) - { - mParent->notifySelection(this, mType); - frame->setStyleSheet("QFrame#frame{border: 2px solid #55CC55;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #55EE55, stop: 1 #CCCCCC);\nborder-radius: 10px}"); - } - else - { - frame->setStyleSheet("QFrame#frame{border: 2px solid #CCCCCC;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC);\nborder-radius: 10px}"); - } - update(); -} - -bool PhotoItem::isSelected() -{ - return mSelected; -} - - -void PhotoItem::mousePressEvent(QMouseEvent *event) -{ - /* We can be very cunning here? - * grab out position. - * flag ourselves as selected. - * then pass the mousePressEvent up for handling by the parent - */ - - QPoint pos = event->pos(); - - std::cerr << "PhotoItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; - std::cerr << std::endl; - - setSelected(true); - - QWidget::mousePressEvent(event); -} - - -const QPixmap *PhotoItem::getPixmap() -{ - return imgLabel->pixmap(); -} - - +#include +#include +#include +#include + +#include "PhotoItem.h" +#include "ui_PhotoItem.h" + +PhotoItem::PhotoItem(PhotoShareItemHolder *holder, const RsPhotoPhoto &photo, QWidget *parent): + QWidget(parent), + ui(new Ui::PhotoItem), mHolder(holder), mPhotoDetails(photo) +{ + + ui->setupUi(this); + setSelected(false); + + ui->lineEdit_PhotoGrapher->setEnabled(false); + ui->lineEdit_Title->setEnabled(false); + + ui->editLayOut->removeWidget(ui->lineEdit_Title); + ui->editLayOut->removeWidget(ui->lineEdit_PhotoGrapher); + + ui->lineEdit_Title->setVisible(false); + ui->lineEdit_PhotoGrapher->setVisible(false); + + setUp(); +} + +PhotoItem::PhotoItem(PhotoShareItemHolder *holder, const QString& path, QWidget *parent) : + QWidget(parent), + ui(new Ui::PhotoItem), mHolder(holder) +{ + ui->setupUi(this); + + + QPixmap qtn = QPixmap(path); + mThumbNail = qtn; + ui->label_Thumbnail->setPixmap(mThumbNail.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + setSelected(false); + + getPhotoThumbnail(mPhotoDetails.mThumbnail); + + connect(ui->lineEdit_Title, SIGNAL(editingFinished()), this, SLOT(setTitle())); + connect(ui->lineEdit_PhotoGrapher, SIGNAL(editingFinished()), this, SLOT(setPhotoGrapher())); + +} + +void PhotoItem::setSelected(bool selected) +{ + mSelected = selected; + if (mSelected) + { + ui->photoFrame->setStyleSheet("QFrame#photoFrame{border: 2px solid #9562B8;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #55EE55, stop: 1 #CCCCCC);\nborder-radius: 10px}"); + } + else + { + ui->photoFrame->setStyleSheet("QFrame#photoFrame{border: 2px solid #CCCCCC;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC);\nborder-radius: 10px}"); + } + update(); +} + +bool PhotoItem::getPhotoThumbnail(RsPhotoThumbnail &nail) +{ + const QPixmap *tmppix = &mThumbNail; + + QByteArray ba; + QBuffer buffer(&ba); + + if(!tmppix->isNull()) + { + // send chan image + + buffer.open(QIODevice::WriteOnly); + tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format + + RsPhotoThumbnail tmpnail; + tmpnail.data = (uint8_t *) ba.data(); + tmpnail.size = ba.size(); + + nail.copyFrom(tmpnail); + + return true; + } + + nail.data = NULL; + nail.size = 0; + return false; +} + + + +void PhotoItem::setTitle(){ + + mPhotoDetails.mMeta.mMsgName = ui->lineEdit_Title->text().toStdString(); +} + +void PhotoItem::setPhotoGrapher() +{ + mPhotoDetails.mPhotographer = ui->lineEdit_PhotoGrapher->text().toStdString(); +} + +const RsPhotoPhoto& PhotoItem::getPhotoDetails() +{ + return mPhotoDetails; +} + +PhotoItem::~PhotoItem() +{ + delete ui; +} + +void PhotoItem::setUp() +{ + + mTitleLabel = new QLabel(); + mPhotoGrapherLabel = new QLabel(); + + mTitleLabel->setText(QString::fromStdString(mPhotoDetails.mMeta.mMsgName)); + mPhotoGrapherLabel->setText(QString::fromStdString(mPhotoDetails.mPhotographer)); + + + ui->editLayOut->addWidget(mPhotoGrapherLabel); + ui->editLayOut->addWidget(mTitleLabel); + + updateImage(mPhotoDetails.mThumbnail); +} + +void PhotoItem::updateImage(const RsPhotoThumbnail &thumbnail) +{ + if (thumbnail.data != NULL) + { + QPixmap qtn; + qtn.loadFromData(thumbnail.data, thumbnail.size, thumbnail.type.c_str()); + ui->label_Thumbnail->setPixmap(qtn.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + mThumbNail = qtn; + } +} + +void PhotoItem::mousePressEvent(QMouseEvent *event) +{ + + QPoint pos = event->pos(); + + std::cerr << "PhotoItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; + std::cerr << std::endl; + + if(mHolder) + mHolder->notifySelection(this); + else + setSelected(true); + + QWidget::mousePressEvent(event); +} diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoItem.h b/retroshare-gui/src/gui/PhotoShare/PhotoItem.h index 2e32b3de2..45160d443 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoItem.h +++ b/retroshare-gui/src/gui/PhotoShare/PhotoItem.h @@ -1,92 +1,52 @@ -/* - * Retroshare Photo Plugin. - * - * Copyright 2012-2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2.1 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ +#ifndef PHOTOITEM_H +#define PHOTOITEM_H -#ifndef MRK_PHOTO_PHOTO_ITEM_H -#define MRK_PHOTO_PHOTO_ITEM_H +#include +#include +#include "PhotoShareItemHolder.h" +#include "retroshare/rsphoto.h" -#include "ui_PhotoItem.h" +namespace Ui { + class PhotoItem; +} -#include - -class PhotoItem; - -class PhotoHolder +class PhotoItem : public QWidget, public PhotoShareItem { - public: -virtual void deletePhotoItem(PhotoItem *, uint32_t ptype) = 0; -virtual void notifySelection(PhotoItem *item, int ptype) = 0; -}; - - -#define PHOTO_ITEM_TYPE_ALBUM 0x0001 -#define PHOTO_ITEM_TYPE_PHOTO 0x0002 -#define PHOTO_ITEM_TYPE_NEW 0x0003 - -class PhotoItem : public QWidget, private Ui::PhotoItem -{ - Q_OBJECT + Q_OBJECT public: - PhotoItem(PhotoHolder *parent, const RsPhotoAlbum &album); - PhotoItem(PhotoHolder *parent, const RsPhotoPhoto &photo, const RsPhotoAlbum &album); - PhotoItem(PhotoHolder *parent, std::string url); // for new photos. - - void setDummyText(); - void updateParent(PhotoHolder *parent); // for external construction. - void updateAlbumText(const RsPhotoAlbum &album); - void updatePhotoText(const RsPhotoPhoto &photo); - void updateText(); - bool getPhotoThumbnail(RsPhotoThumbnail &nail); - - void removeItem(); - - void setSelected(bool on); - bool isSelected(); - - const QPixmap *getPixmap(); - - // details are public - so that can be easily edited. - bool mIsPhoto; - bool mWasModified; - RsPhotoPhoto mPhotoDetails; - RsPhotoAlbum mAlbumDetails; - -//private slots: + PhotoItem(PhotoShareItemHolder *holder, const RsPhotoPhoto& photo, QWidget* parent = 0); + PhotoItem(PhotoShareItemHolder *holder, const QString& path, QWidget* parent = 0); // for new photos. + ~PhotoItem(); + void setSelected(bool selected); + bool isSelected(){ return mSelected; } + const RsPhotoPhoto& getPhotoDetails(); + bool getPhotoThumbnail(RsPhotoThumbnail &nail); protected: - void mousePressEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); private: - void updateImage(const RsPhotoThumbnail &thumbnail); + void updateImage(const RsPhotoThumbnail &thumbnail); + void setUp(); - PhotoHolder *mParent; - uint32_t mType; + private slots: + void setTitle(); + void setPhotoGrapher(); +private: + Ui::PhotoItem *ui; - bool mSelected; + QPixmap mThumbNail; + + QPixmap getPixmap() { return mThumbNail; } + + bool mSelected; + RsPhotoPhoto mPhotoDetails; + PhotoShareItemHolder* mHolder; + + QLabel *mTitleLabel, *mPhotoGrapherLabel; }; - -#endif - +#endif // PHOTOITEM_H diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoItem.ui b/retroshare-gui/src/gui/PhotoShare/PhotoItem.ui index 8b7e990d9..7162fd137 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoItem.ui +++ b/retroshare-gui/src/gui/PhotoShare/PhotoItem.ui @@ -6,32 +6,18 @@ 0 0 - 166 - 216 + 253 + 233 - - - 9 - - - + Form - - - 6 - - - - - - 0 - 0 - - + + + - QFrame#frame{border: 2px solid #CCCCCC; + QFrame#photoFrame{border: 2px solid #CCCCCC; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC); border-radius: 10px} @@ -42,206 +28,83 @@ border-radius: 10px} QFrame::Raised - - - 0 - - - 0 - + - - - - 150 - 150 - - - - - 150 - 150 - - - - QLabel#label{border: 2px solid black; -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #EEEEEE, stop: 1 #CCCCCC); -border-radius: 10px} - + - - - - :/images/konversation.png - - - Qt::AlignCenter + TextLabel - - - - 0 - 0 - - - - - 9 - 75 - true - - - - Album: - - - - - + - - - - 0 - 0 - - - - - 9 - 75 - true - - - - From - - - - - - - - 0 - 0 - - - - - 9 - - - - Signed by - - - true - - + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo Title :</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photographer :</span></p></body></html> + + + + + + + + + + + + + + + + + + + + - - - - - - 0 - 0 - - - - - 9 - 75 - true - - - - Status - - - - - - - - 0 - 0 - - - - - 9 - - - - You eyes only - - - true - - - - - - - - - - - - 0 - 0 - - - - - 9 - 75 - true - - - - Date - - - - - - - - 0 - 0 - - - - - 9 - - - - You eyes only - - - true - - - - + + + Qt::Vertical + + + + 20 + 40 + + + - - - + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoShare.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoShare.cpp new file mode 100644 index 000000000..3fd0f2527 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoShare.cpp @@ -0,0 +1,709 @@ + +/* + * Retroshare Photo Plugin. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "PhotoShare.h" +#include "ui_PhotoShare.h" + +#include +#include +#include + +#include +#include + +#include +#include + +#include "AlbumCreateDialog.h" +#include "AlbumItem.h" +#include "PhotoItem.h" + +/****** + * #define PHOTO_DEBUG 1 + *****/ + + +/**************************************************************** + * New Photo Display Widget. + * + * This has two 'lists'. + * Top list shows Albums. + * Lower list is photos from the selected Album. + * + * Notes: + * Each Item will be an AlbumItem, which contains a thumbnail & random details. + * We will limit Items to < 100. With a 'Filter to see more message. + * + * Thumbnails will come from Service. + * Option to Share albums / pictures onward (if permissions allow). + * Option to Download the albums to a specified directory. (is this required if sharing an album?) + * + * Will introduce a FullScreen SlideShow later... first get basics happening. + */ + +#define IS_ALBUM_ADMIN(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) +#define IS_ALBUM_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) +#define IS_ALBUM_N_SUBSCR_OR_ADMIN(subscribeFlags) ((subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_MASK) == 0) + + +/** Constructor */ +PhotoShare::PhotoShare(QWidget *parent) +: MainPage(parent) +{ + ui.setupUi(this); + + mAlbumSelected = NULL; + mPhotoSelected = NULL; + + connect( ui.toolButton_NewAlbum, SIGNAL(clicked()), this, SLOT(createAlbum())); + connect( ui.toolButton_ViewAlbum, SIGNAL(clicked()), this, SLOT(OpenAlbumDialog())); + connect( ui.toolButton_SlideShow, SIGNAL(clicked()), this, SLOT(OpenSlideShow())); + connect( ui.toolButton_subscribe, SIGNAL(clicked()), this, SLOT(subscribeToAlbum())); + connect(ui.toolButton_ViewPhoto, SIGNAL(clicked()), this, SLOT(OpenPhotoDialog())); + + connect( ui.pushButton_YourAlbums, SIGNAL(clicked()), this, SLOT(updateAlbums())); + connect( ui.pushButton_SharedAlbums, SIGNAL(clicked()), this, SLOT(updateAlbums())); + connect( ui.pushButton_SubscribedAlbums, SIGNAL(clicked()), this, SLOT(updateAlbums())); + + ui.pushButton_YourAlbums->setChecked(true); // default to your albums view + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000); + + /* setup TokenQueue */ + mPhotoQueue = new TokenQueue(rsPhoto->getTokenService(), this); + requestAlbumData(); +} + +void PhotoShare::notifySelection(PhotoShareItem *selection) +{ + + AlbumItem* aItem; + PhotoItem* pItem; + + if((aItem = dynamic_cast(selection)) != NULL) + { + + if(mPhotoSelected) + mPhotoSelected->setSelected(false); + + if(mAlbumSelected == aItem) + { + mAlbumSelected->setSelected(true); + } + else + { + if(mAlbumSelected == NULL) + { + mAlbumSelected = aItem; + } + else + { + mAlbumSelected->setSelected(false); + mAlbumSelected = aItem; + } + + mAlbumSelected->setSelected(true); + + // get photo data + std::list grpIds; + grpIds.push_back(mAlbumSelected->getAlbum().mMeta.mGroupId); + requestPhotoData(grpIds); + } + } + else if((pItem = dynamic_cast(selection)) != NULL) + { + if(mPhotoSelected == pItem) + { + mPhotoSelected->setSelected(true); + } + else + { + if(mPhotoSelected == NULL) + { + mPhotoSelected = pItem; + } + else + { + mPhotoSelected->setSelected(false); + mPhotoSelected = pItem; + } + + mPhotoSelected->setSelected(true); + } + } + else + { + + } + +} + + +void PhotoShare::checkUpdate() +{ + /* update */ + if (!rsPhoto) + return; + + if (rsPhoto->updated()) + { + //insertAlbums(); + std::list grpIds; + rsPhoto->groupsChanged(grpIds); + if(!grpIds.empty()) + { + RsTokReqOptions opts; + uint32_t token; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0); + } + + GxsMsgIdResult res; + rsPhoto->msgsChanged(res); + if(!res.empty()) + requestPhotoList(res); + } + + return; +} + + +/*************** New Photo Dialog ***************/ + +void PhotoShare::OpenSlideShow() +{ + // TODO. + if (!mAlbumSelected) { + // ALERT. + int ret = QMessageBox::information(this, tr("PhotoShare"), + tr("Please select an album before\n" + "requesting to edit it!"), + QMessageBox::Ok); + return; + } + + PhotoSlideShow *dlg = new PhotoSlideShow(mAlbumSelected->getAlbum(), NULL); + dlg->show(); +} + + +/*************** New Photo Dialog ***************/ + +void PhotoShare::createAlbum() +{ + AlbumCreateDialog albumCreate(mPhotoQueue, rsPhoto, this); + albumCreate.exec(); +} + +void PhotoShare::OpenAlbumDialog() +{ + if (mAlbumSelected) { + AlbumDialog dlg(mAlbumSelected->getAlbum(), mPhotoQueue, rsPhoto); + dlg.exec(); + } +} + +void PhotoShare::OpenPhotoDialog() +{ + if (mPhotoSelected) { + PhotoDialog *dlg = new PhotoDialog(rsPhoto, mPhotoSelected->getPhotoDetails()); + dlg->show(); + } +} + +/*************** Edit Photo Dialog ***************/ + +void PhotoShare::clearAlbums() +{ + clearPhotos(); + + std::cerr << "PhotoShare::clearAlbums()" << std::endl; + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + + QSetIterator sit(mAlbumItems); + + while(sit.hasNext()) + { + AlbumItem* item = sit.next(); + alayout->removeWidget(item); + item->setParent(NULL); + } + + // set no albums to be selected + if(mAlbumSelected) + { + mAlbumSelected->setSelected(false); + mAlbumSelected = NULL; + } +} + +void PhotoShare::deleteAlbums() +{ + std::cerr << "PhotoShare::clearAlbums()" << std::endl; + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + + QSetIterator sit(mAlbumItems); + + while(sit.hasNext()) + { + AlbumItem* item = sit.next(); + alayout->removeWidget(item); + delete item; + } + + mAlbumItems.clear(); + + mAlbumSelected = NULL; +} + + +void PhotoShare::clearPhotos() +{ + std::cerr << "PhotoShare::clearPhotos()" << std::endl; + + QLayout *layout = ui.scrollAreaWidgetContents_2->layout(); + + if(mAlbumSelected) + { + QSetIterator sit(mPhotoItems); + + while(sit.hasNext()) + { + PhotoItem* item = sit.next(); + layout->removeWidget(item); + item->setParent(NULL); + delete item; // remove item + } + mPhotoItems.clear(); + } + mPhotoSelected = NULL; +} + +void PhotoShare::updateAlbums() +{ + + clearAlbums(); + + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + QSetIterator sit(mAlbumItems); + + if(ui.pushButton_YourAlbums->isChecked()) + { + + ui.toolButton_subscribe->setEnabled(false); + ui.toolButton_NewAlbum->setEnabled(true); + ui.toolButton_SlideShow->setEnabled(true); + + while(sit.hasNext()){ + + AlbumItem* item = sit.next(); + uint32_t flags = item->getAlbum().mMeta.mSubscribeFlags; + + if(IS_ALBUM_ADMIN(flags)) + alayout->addWidget(item); + } + }else if(ui.pushButton_SubscribedAlbums->isChecked()) + { + + ui.toolButton_subscribe->setEnabled(true); + ui.toolButton_subscribe->setText("Unsubscribe From Album"); + ui.toolButton_subscribe->setIcon(QIcon(":/images/album_unsubscribe.png")); + //ui.toolButton_NewAlbum->setEnabled(false); + ui.toolButton_SlideShow->setEnabled(true); + + while(sit.hasNext()){ + + AlbumItem* item = sit.next(); + uint32_t flags = item->getAlbum().mMeta.mSubscribeFlags; + + if(IS_ALBUM_SUBSCRIBED(flags)) + alayout->addWidget(item); + } + + }else if(ui.pushButton_SharedAlbums->isChecked()) + { + + ui.toolButton_subscribe->setEnabled(true); + ui.toolButton_subscribe->setText("Subscribe To Album"); + ui.toolButton_subscribe->setIcon(QIcon(":/images/album_subscribe.png")); + //ui.toolButton_NewAlbum->setEnabled(false); + ui.toolButton_SlideShow->setEnabled(false); + + while(sit.hasNext()){ + + AlbumItem* item = sit.next(); + uint32_t flags = item->getAlbum().mMeta.mSubscribeFlags; + + if(IS_ALBUM_N_SUBSCR_OR_ADMIN(flags)) + alayout->addWidget(item); + + } + } +} + +void PhotoShare::deleteAlbum(const RsGxsGroupId &grpId) +{ + + QSetIterator sit(mAlbumItems); + + while(sit.hasNext()) + { + AlbumItem* item = sit.next(); + + if(item->getAlbum().mMeta.mGroupId == grpId){ + + if(mAlbumSelected == item) + { + item->setSelected(false); + mAlbumSelected = NULL; + } + + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + alayout->removeWidget(item); + mAlbumItems.remove(item); + item->setParent(NULL); + delete item; + return; + } + } +} + +void PhotoShare::addAlbum(const RsPhotoAlbum &album) +{ + std::cerr << " PhotoShare::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; + + deleteAlbum(album.mMeta.mGroupId); // remove from ui + AlbumItem *item = new AlbumItem(album, this, this); + mAlbumItems.insert(item); +} + + +void PhotoShare::addPhoto(const RsPhotoPhoto &photo) +{ + std::cerr << "PhotoShare::addPhoto() AlbumId: " << photo.mMeta.mGroupId; + std::cerr << " PhotoId: " << photo.mMeta.mMsgId; + std::cerr << std::endl; + + PhotoItem* item = new PhotoItem(this, photo, this); + mPhotoItems.insert(item); +} + +void PhotoShare::subscribeToAlbum() +{ + if(mAlbumSelected){ + RsGxsGroupId id = mAlbumSelected->getAlbum().mMeta.mGroupId; + uint32_t token; + + if(IS_ALBUM_SUBSCRIBED(mAlbumSelected->getAlbum().mMeta.mSubscribeFlags)) + rsPhoto->subscribeToAlbum(token, id, false); + else if(IS_ALBUM_ADMIN(mAlbumSelected->getAlbum().mMeta.mSubscribeFlags)) + return; + else if(IS_ALBUM_N_SUBSCR_OR_ADMIN( + mAlbumSelected->getAlbum().mMeta.mSubscribeFlags)) + rsPhoto->subscribeToAlbum(token, id, true); + else + return; + + mPhotoQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, 0); + } +} + +void PhotoShare::updatePhotos() +{ + + if(mAlbumSelected) + { + QSetIterator sit(mPhotoItems); + + while(sit.hasNext()) + { + QLayout *layout = ui.scrollAreaWidgetContents_2->layout(); + layout->addWidget(sit.next()); + } + } +} + +/**************************** Request / Response Filling of Data ************************/ + + +void PhotoShare::requestAlbumList(std::list& ids) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + uint32_t token; + mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); +} + +void PhotoShare::requestPhotoList(GxsMsgReq& req) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + uint32_t token; + mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, req, 0); + return; +} + + +void PhotoShare::loadAlbumList(const uint32_t &token) +{ + std::cerr << "PhotoShare::loadAlbumList()"; + std::cerr << std::endl; + + std::list albumIds; + rsPhoto->getGroupList(token, albumIds); + + requestAlbumData(albumIds); + + std::list::iterator it; + for(it = albumIds.begin(); it != albumIds.end(); it++) + { + requestPhotoList(*it); + } +} + + +void PhotoShare::requestAlbumData(std::list &ids) +{ + RsTokReqOptions opts; + uint32_t token; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, 0); +} + +void PhotoShare::requestAlbumData() +{ + RsTokReqOptions opts; + uint32_t token; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, 0); +} + +bool PhotoShare::loadAlbumData(const uint32_t &token) +{ + std::cerr << "PhotoShare::loadAlbumData()"; + std::cerr << std::endl; + + std::vector albums; + rsPhoto->getAlbum(token, albums); + + std::vector::iterator vit = albums.begin(); + + for(; vit != albums.end(); vit++) + { + RsPhotoAlbum& album = *vit; + + std::cerr << " PhotoShare::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; + + addAlbum(album); + } + + updateAlbums(); + return true; +} + + +void PhotoShare::requestPhotoList(const std::string &albumId) +{ + + std::list grpIds; + grpIds.push_back(albumId); + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + uint32_t token; + mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, grpIds, 0); +} + + +void PhotoShare::acknowledgeGroup(const uint32_t &token) +{ + RsGxsGroupId grpId; + rsPhoto->acknowledgeGrp(token, grpId); + + if(!grpId.empty()) + { + std::list grpIds; + grpIds.push_back(grpId); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t reqToken; + mPhotoQueue->requestGroupInfo(reqToken, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0); + } +} + +void PhotoShare::acknowledgeMessage(const uint32_t &token) +{ + std::pair p; + rsPhoto->acknowledgeMsg(token, p); + + // just acknowledge don't load it + // loading is only instigated by clicking an album (i.e. requesting photo data) + // but load it if the album is selected +// if(!p.first.empty()) +// { +// if(mAlbumSelected) +// { +// if(mAlbumSelected->getAlbum().mMeta.mGroupId == p.first) +// { +// std::list grpIds; +// grpIds.push_back(p.first); +// requestPhotoData(grpIds); +// } +// } +// } +} + +void PhotoShare::loadPhotoList(const uint32_t &token) +{ + std::cerr << "PhotoShare::loadPhotoList()"; + std::cerr << std::endl; + + GxsMsgIdResult res; + + rsPhoto->getMsgList(token, res); + requestPhotoData(res); +} + + +void PhotoShare::requestPhotoData(GxsMsgReq &photoIds) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + uint32_t token; + mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, photoIds, 0); +} + +void PhotoShare::requestPhotoData(const std::list& grpIds) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + uint32_t token; + mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0); +} + + +void PhotoShare::loadPhotoData(const uint32_t &token) +{ + std::cerr << "PhotoShare::loadPhotoData()"; + std::cerr << std::endl; + + clearPhotos(); + + PhotoResult res; + rsPhoto->getPhoto(token, res); + PhotoResult::iterator mit = res.begin(); + + + for(; mit != res.end(); mit++) + { + std::vector& photoV = mit->second; + std::vector::iterator vit = photoV.begin(); + + for(; vit != photoV.end(); vit++) + { + RsPhotoPhoto& photo = *vit; + addPhoto(photo); + std::cerr << "PhotoShare::loadPhotoData() AlbumId: " << photo.mMeta.mGroupId; + std::cerr << " PhotoId: " << photo.mMeta.mMsgId; + std::cerr << std::endl; + } + } + updatePhotos(); +} + + +/**************************** Request / Response Filling of Data ************************/ + +void PhotoShare::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "PhotoShare::loadRequest()"; + std::cerr << std::endl; + + if (queue == mPhotoQueue) + { + /* now switch on req */ + switch(req.mType) + { + case TOKENREQ_GROUPINFO: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_LIST: + loadAlbumList(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_DATA: + loadAlbumData(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeGroup(req.mToken); + break; + default: + std::cerr << "PhotoShare::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; + case TOKENREQ_MSGINFO: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_LIST: + loadPhotoList(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeMessage(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_DATA: + loadPhotoData(req.mToken); + break; + default: + std::cerr << "PhotoShare::loadRequest() ERROR: MSG: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; + case TOKENREQ_MSGRELATEDINFO: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_DATA: + loadPhotoData(req.mToken); + break; + default: + std::cerr << "PhotoShare::loadRequest() ERROR: MSG: INVALID ANS TYPE"; + std::cerr << std::endl; + break; + } + break; + default: + std::cerr << "PhotoShare::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} + + +/**************************** Request / Response Filling of Data ************************/ + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoShare.h b/retroshare-gui/src/gui/PhotoShare/PhotoShare.h new file mode 100644 index 000000000..e0de61063 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoShare.h @@ -0,0 +1,97 @@ +#ifndef PHOTOSHARE_H +#define PHOTOSHARE_H + +#include +#include +#include "ui_PhotoShare.h" + +#include "retroshare/rsphoto.h" +#include "retroshare-gui/mainpage.h" + +#include "AlbumCreateDialog.h" +#include "AlbumDialog.h" +#include "PhotoDialog.h" + +#include "AlbumItem.h" +#include "PhotoItem.h" +#include "PhotoSlideShow.h" + +#include "util/TokenQueue.h" +#include "PhotoShareItemHolder.h" + +namespace Ui { + class PhotoShare; +} + +class PhotoShare : public MainPage, public TokenResponse, public PhotoShareItemHolder +{ + Q_OBJECT + +public: + PhotoShare(QWidget *parent = 0); + + void notifySelection(PhotoShareItem* selection); + +private slots: + void checkUpdate(); + void createAlbum(); + void OpenAlbumDialog(); + void OpenPhotoDialog(); + void OpenSlideShow(); + void updateAlbums(); + void subscribeToAlbum(); + void deleteAlbum(const RsGxsGroupId&); + +private: + /* Request Response Functions for loading data */ + void requestAlbumList(std::list& ids); + void requestAlbumData(std::list &ids); + + /*! + * request data for all groups + */ + void requestAlbumData(); + void requestPhotoList(GxsMsgReq &albumIds); + void requestPhotoList(const std::string &albumId); + void requestPhotoData(GxsMsgReq &photoIds); + void requestPhotoData(const std::list &grpIds); + + void loadAlbumList(const uint32_t &token); + bool loadAlbumData(const uint32_t &token); + void loadPhotoList(const uint32_t &token); + void loadPhotoData(const uint32_t &token); + + void loadRequest(const TokenQueue *queue, const TokenRequest &req); + + void acknowledgeGroup(const uint32_t &token); + void acknowledgeMessage(const uint32_t &token); + + /* Grunt work of setting up the GUI */ + + void addAlbum(const RsPhotoAlbum &album); + void addPhoto(const RsPhotoPhoto &photo); + + void clearAlbums(); + void clearPhotos(); + void deleteAlbums(); + /*! + * Fills up photo ui with photos held in mPhotoItems (current groups photos) + */ + void updatePhotos(); + +private: + AlbumItem* mAlbumSelected; + PhotoItem* mPhotoSelected; + + + TokenQueue *mPhotoQueue; + + /* UI - from Designer */ + Ui::PhotoShare ui; + + QSet mAlbumItems; + QSet mPhotoItems; // the current album selected + +}; + +#endif // PHOTOSHARE_H diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui b/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui new file mode 100644 index 000000000..78e3ed538 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoShare.ui @@ -0,0 +1,346 @@ + + + PhotoShare + + + + 0 + 0 + 824 + 569 + + + + Form + + + + 0 + + + + + + 2 + + + + + Create Album + + + + :/images/add_image24.png:/images/add_image24.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + View Album + + + + :/images/kview_24.png:/images/kview_24.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Subscribe To Album + + + + :/images/album_subscribe.png:/images/album_subscribe.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Slide Show + + + + :/images/kuickshow.png:/images/kuickshow.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + false + + + + 6 + + + 0 + + + + + My Albums + + + + :/images/my_album_48.png:/images/my_album_48.png + + + + 48 + 48 + + + + true + + + true + + + true + + + + + + + Subscribed Albums + + + + :/images/subscribed_album_48.png:/images/subscribed_album_48.png + + + + 48 + 48 + + + + true + + + true + + + true + + + + + + + Shared Albums + + + + :/images/friends_album_48.png:/images/friends_album_48.png + + + + 48 + 48 + + + + true + + + false + + + true + + + true + + + + + + + + + + Qt::Vertical + + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 804 + 208 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + + + Qt::Horizontal + + + + 139 + 20 + + + + + + + + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 804 + 208 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + + + Qt::Horizontal + + + + 426 + 20 + + + + + + + + + + + + + 2 + + + 2 + + + + + View Photo + + + + :/images/kview_24.png:/images/kview_24.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoShareItemHolder.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoShareItemHolder.cpp new file mode 100644 index 000000000..e5d3bae28 --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoShareItemHolder.cpp @@ -0,0 +1,5 @@ +#include "PhotoShareItemHolder.h" + +PhotoShareItemHolder::PhotoShareItemHolder() +{ +} diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoShareItemHolder.h b/retroshare-gui/src/gui/PhotoShare/PhotoShareItemHolder.h new file mode 100644 index 000000000..91df3642a --- /dev/null +++ b/retroshare-gui/src/gui/PhotoShare/PhotoShareItemHolder.h @@ -0,0 +1,22 @@ +#ifndef PHOTOSHAREITEMHOLDER_H +#define PHOTOSHAREITEMHOLDER_H + +class PhotoShareItem +{ + +public: + PhotoShareItem() { return; } + virtual ~PhotoShareItem(){ return; } + virtual bool isSelected() = 0; + virtual void setSelected(bool selected) = 0; +}; + +class PhotoShareItemHolder +{ +public: + PhotoShareItemHolder(); + + virtual void notifySelection(PhotoShareItem* selection) = 0; +}; + +#endif // PHOTOSHAREITEMHOLDER_H diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoSlideDetails.ui b/retroshare-gui/src/gui/PhotoShare/PhotoSlideDetails.ui deleted file mode 100644 index 985d7bd4d..000000000 --- a/retroshare-gui/src/gui/PhotoShare/PhotoSlideDetails.ui +++ /dev/null @@ -1,129 +0,0 @@ - - - PhotoSlideDetails - - - - 0 - 0 - 667 - 707 - - - - - - - - - - Qt::Vertical - - - - - - - Name - - - - - - - Caption: - - - - - - - - - - Photographer: - - - - - - - - - - Description - - - - - - - - - - Where: - - - - - - - - - - When - - - - - - - - - - Other 1: - - - - - - - - - - HashTags: - - - - - - - - - - Image # - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.cpp b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.cpp index 3bf2b3cbc..e3997e0a6 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.cpp +++ b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.cpp @@ -27,8 +27,8 @@ #include /** Constructor */ -PhotoSlideShow::PhotoSlideShow(QWidget *parent) -: QWidget(parent) +PhotoSlideShow::PhotoSlideShow(const RsPhotoAlbum& album, QWidget *parent) +: QWidget(parent), mAlbum(album) { ui.setupUi(this); @@ -37,18 +37,29 @@ PhotoSlideShow::PhotoSlideShow(QWidget *parent) connect(ui.pushButton_ShowDetails, SIGNAL( clicked( void ) ), this, SLOT( showPhotoDetails( void ) ) ); connect(ui.pushButton_StartStop, SIGNAL( clicked( void ) ), this, SLOT( StartStop( void ) ) ); connect(ui.pushButton_Close, SIGNAL( clicked( void ) ), this, SLOT( closeShow( void ) ) ); + connect(ui.fullscreenButton, SIGNAL(clicked()),this, SLOT(setFullScreen())); - mPhotoQueue = new TokenQueue(rsPhoto, this); + mPhotoQueue = new TokenQueue(rsPhoto->getTokenService(), this); mRunning = true; mShotActive = true; mImageIdx = 0; - //loadImage(); + requestPhotos(); + loadImage(); //QTimer::singleShot(5000, this, SLOT(timerEvent())); } +PhotoSlideShow::~PhotoSlideShow(){ + + std::map::iterator mit = mPhotos.begin(); + + for(; mit != mPhotos.end(); mit++) + { + delete mit->second; + } +} void PhotoSlideShow::showPhotoDetails() { @@ -95,10 +106,14 @@ void PhotoSlideShow::StartStop() if (mRunning) { mRunning = false; + ui.pushButton_StartStop->setText(tr("Start")); + ui.pushButton_StartStop->setToolTip(tr("Start Slide Show")); } else { mRunning = true; + ui.pushButton_StartStop->setText(tr("Stop")); + ui.pushButton_StartStop->setToolTip(tr("Stop Slide Show")); if (!mShotActive) // make sure only one timer running { mShotActive = true; @@ -171,9 +186,7 @@ void PhotoSlideShow::loadImage() qtn.loadFromData(tn.data, tn.size, tn.type.c_str()); tn.data = 0; - //ui.imgLabel->setPixmap(qtn); - - QPixmap sqtn = qtn.scaled(ui.albumLabel->width(), ui.imgLabel->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap sqtn = qtn.scaled(800, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation); ui.imgLabel->setPixmap(sqtn); } @@ -207,81 +220,49 @@ void PhotoSlideShow::updateMoveButtons(uint32_t status) } } - - - -void PhotoSlideShow::clearDialog() +void PhotoSlideShow::requestPhotos() { -#if 0 - ui.lineEdit_Title->setText(QString("title")); - ui.lineEdit_Caption->setText(QString("Caption")); - ui.lineEdit_Where->setText(QString("Where")); - ui.lineEdit_When->setText(QString("When")); - - ui.scrollAreaWidgetContents->clearPhotos(); - ui.AlbumDrop->clearPhotos(); - - /* clean up album image */ - mAlbumData.mThumbnail.deleteImage(); - - RsPhotoAlbum emptyAlbum; - mAlbumData = emptyAlbum; - - /* add empty image */ - PhotoItem *item = new PhotoItem(NULL, mAlbumData); - ui.AlbumDrop->addPhotoItem(item); - - mAlbumEdit = false; -#endif + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + uint32_t token; + std::list grpIds; + grpIds.push_back(mAlbum.mMeta.mGroupId); + mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, 0); } - -void PhotoSlideShow::loadAlbum(const std::string &albumId) -{ - /* much like main load fns */ - clearDialog(); - - RsTokReqOptions opts; - uint32_t token; - std::list albumIds; - albumIds.push_back(albumId); - - // We need both Album and Photo Data. - - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, albumIds, 0); - -} - - bool PhotoSlideShow::loadPhotoData(const uint32_t &token) { std::cerr << "PhotoSlideShow::loadPhotoData()"; std::cerr << std::endl; - bool moreData = true; - while(moreData) - { - RsPhotoPhoto photo; - - if (rsPhoto->getPhoto(token, photo)) - { - RsPhotoPhoto *ptr = new RsPhotoPhoto; - *ptr = photo; - ptr->mThumbnail.data = 0; - ptr->mThumbnail.copyFrom(photo.mThumbnail); + PhotoResult res; + rsPhoto->getPhoto(token, res); + PhotoResult::iterator mit = res.begin(); - mPhotos[photo.mMeta.mMsgId] = ptr; - mPhotoOrder[ptr->mOrder] = photo.mMeta.mMsgId; - std::cerr << "PhotoSlideShow::addAddPhoto() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - } - else - { - moreData = false; - } - } + for(; mit != res.end(); mit++) + { + std::vector& photoV = mit->second; + std::vector::iterator vit = photoV.begin(); + int i = 0; + for(; vit != photoV.end(); vit++) + { + RsPhotoPhoto& photo = *vit; + RsPhotoPhoto *ptr = new RsPhotoPhoto; + *ptr = photo; + ptr->mThumbnail.data = 0; + ptr->mThumbnail.copyFrom(photo.mThumbnail); + ptr->mOrder = i++; + mPhotos[photo.mMeta.mMsgId] = ptr; + mPhotoOrder[ptr->mOrder] = photo.mMeta.mMsgId; + + std::cerr << "PhotoSlideShow::addAddPhoto() AlbumId: " << photo.mMeta.mGroupId; + std::cerr << " PhotoId: " << photo.mMeta.mMsgId; + std::cerr << std::endl; + } + } + + // Load and Start. loadImage(); @@ -290,36 +271,6 @@ bool PhotoSlideShow::loadPhotoData(const uint32_t &token) return true; } -bool PhotoSlideShow::loadAlbumData(const uint32_t &token) -{ - std::cerr << "PhotoSlideShow::loadAlbumData()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPhotoAlbum album; - if (rsPhoto->getAlbum(token, album)) - { - std::cerr << " PhotoSlideShow::loadAlbumData() AlbumId: " << album.mMeta.mGroupId << std::endl; - //updateAlbumDetails(album); - - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - uint32_t token; - std::list albumIds; - albumIds.push_back(album.mMeta.mGroupId); - mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, albumIds, 0); - } - else - { - moreData = false; - } - } - return true; -} - - void PhotoSlideShow::loadRequest(const TokenQueue *queue, const TokenRequest &req) { std::cerr << "PhotoSlideShow::loadRequest()"; @@ -330,20 +281,36 @@ void PhotoSlideShow::loadRequest(const TokenQueue *queue, const TokenRequest &re /* now switch on req */ switch(req.mType) { - case TOKENREQ_GROUPINFO: - loadAlbumData(req.mToken); - break; case TOKENREQ_MSGINFO: loadPhotoData(req.mToken); break; default: - std::cerr << "PhotoSlideShow::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; + std::cerr << "PhotoSlideShow::loadRequest() ERROR: REQ: INVALID REQ TYPE"; std::cerr << std::endl; break; } } } - +void PhotoSlideShow::setFullScreen() +{ + if (!isFullScreen()) { + // hide menu & toolbars + +#ifdef Q_WS_X11 + show(); + raise(); + setWindowState( windowState() | Qt::WindowFullScreen ); +#else + setWindowState( windowState() | Qt::WindowFullScreen ); + show(); + raise(); +#endif + } else { + + setWindowState( windowState() ^ Qt::WindowFullScreen ); + show(); + } +} diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.h b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.h index 7cd473035..23183035d 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.h +++ b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.h @@ -28,18 +28,17 @@ #include #include "util/TokenQueue.h" +#include "AlbumItem.h" class PhotoSlideShow : public QWidget, public TokenResponse { Q_OBJECT public: - PhotoSlideShow(QWidget *parent = 0); + PhotoSlideShow(const RsPhotoAlbum& mAlbum, QWidget *parent = 0); + virtual ~PhotoSlideShow(); - void loadAlbum(const std::string &albumId); -virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); - - void clearDialog(); + void loadRequest(const TokenQueue *queue, const TokenRequest &req); private slots: void showPhotoDetails(); @@ -48,17 +47,17 @@ private slots: void StartStop(); void timerEvent(); void closeShow(); - + void setFullScreen(); private: + void requestPhotos(); void loadImage(); void updateMoveButtons(uint32_t status); - bool loadPhotoData(const uint32_t &token); - bool loadAlbumData(const uint32_t &token); + bool loadPhotoData(const uint32_t &token); -//protected: +private: std::map mPhotos; std::map mPhotoOrder; @@ -67,7 +66,9 @@ private: int mImageIdx; bool mShotActive; - TokenQueue *mPhotoQueue; + RsPhotoAlbum mAlbum; + + TokenQueue *mPhotoQueue; Ui::PhotoSlideShow ui; }; diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui index 9bc91f506..bc771eec0 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui +++ b/retroshare-gui/src/gui/PhotoShare/PhotoSlideShow.ui @@ -10,8 +10,8 @@ 671 - - + + false @@ -92,6 +92,20 @@ + + + + + + + + :/images/window_fullscreen.png:/images/window_fullscreen.png + + + false + + + @@ -101,8 +115,11 @@ + + + - Stop/Run + Stop @@ -138,7 +155,8 @@ - + + diff --git a/retroshare-gui/src/gui/PhotoShare/Photo_images.qrc b/retroshare-gui/src/gui/PhotoShare/Photo_images.qrc index 3ab091103..7919a4500 100644 --- a/retroshare-gui/src/gui/PhotoShare/Photo_images.qrc +++ b/retroshare-gui/src/gui/PhotoShare/Photo_images.qrc @@ -1,5 +1,15 @@ - images/dummy.png + images/kuickshow.png + images/kview_24.png + images/kview_64.png + images/album_64.png + images/album_subscribe.png + images/album_unsubscribe.png + images/album_create_64.png + images/album_default_128.png + images/my_album_48.png + images/subscribed_album_48.png + images/friends_album_48.png diff --git a/retroshare-gui/src/gui/PhotoShare/images/album_64.png b/retroshare-gui/src/gui/PhotoShare/images/album_64.png new file mode 100644 index 000000000..12207ba89 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/album_64.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/album_create_64.png b/retroshare-gui/src/gui/PhotoShare/images/album_create_64.png new file mode 100644 index 000000000..9a1fe0961 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/album_create_64.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/album_default_128.png b/retroshare-gui/src/gui/PhotoShare/images/album_default_128.png new file mode 100644 index 000000000..bd459084e Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/album_default_128.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/album_subscribe.png b/retroshare-gui/src/gui/PhotoShare/images/album_subscribe.png new file mode 100644 index 000000000..fa66be123 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/album_subscribe.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/album_unsubscribe.png b/retroshare-gui/src/gui/PhotoShare/images/album_unsubscribe.png new file mode 100644 index 000000000..0f84b52af Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/album_unsubscribe.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/folder_images.png b/retroshare-gui/src/gui/PhotoShare/images/folder_images.png new file mode 100644 index 000000000..a737b3d50 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/folder_images.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/friends_album_48.png b/retroshare-gui/src/gui/PhotoShare/images/friends_album_48.png new file mode 100644 index 000000000..56162c7c1 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/friends_album_48.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/kuickshow.png b/retroshare-gui/src/gui/PhotoShare/images/kuickshow.png new file mode 100644 index 000000000..e86092028 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/kuickshow.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/kview_24.png b/retroshare-gui/src/gui/PhotoShare/images/kview_24.png new file mode 100644 index 000000000..094b6f5fd Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/kview_24.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/kview_32.png b/retroshare-gui/src/gui/PhotoShare/images/kview_32.png new file mode 100644 index 000000000..8eb922d7b Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/kview_32.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/kview_48.png b/retroshare-gui/src/gui/PhotoShare/images/kview_48.png new file mode 100644 index 000000000..9c1b75c33 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/kview_48.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/kview_64.png b/retroshare-gui/src/gui/PhotoShare/images/kview_64.png new file mode 100644 index 000000000..323ab96f8 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/kview_64.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/my_album_48.png b/retroshare-gui/src/gui/PhotoShare/images/my_album_48.png new file mode 100644 index 000000000..e16c05eb2 Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/my_album_48.png differ diff --git a/retroshare-gui/src/gui/PhotoShare/images/subscribed_album_48.png b/retroshare-gui/src/gui/PhotoShare/images/subscribed_album_48.png new file mode 100644 index 000000000..fc76f2e7f Binary files /dev/null and b/retroshare-gui/src/gui/PhotoShare/images/subscribed_album_48.png differ diff --git a/retroshare-gui/src/gui/Posted/PostedComments.cpp b/retroshare-gui/src/gui/Posted/PostedComments.cpp index 4e1f73bab..8340cdc49 100644 --- a/retroshare-gui/src/gui/Posted/PostedComments.cpp +++ b/retroshare-gui/src/gui/Posted/PostedComments.cpp @@ -22,19 +22,18 @@ */ #include "PostedComments.h" +#include "PostedCreateCommentDialog.h" -//#include #include + #include #include #include #include +#include -/****** - * #define PHOTO_DEBUG 1 - *****/ /**************************************************************** @@ -62,566 +61,52 @@ PostedComments::PostedComments(QWidget *parent) :QWidget(parent) { - ui.setupUi(this); + ui.setupUi(this); + ui.postFrame->setVisible(false); + ui.treeWidget->setup(rsPosted->getTokenService()); +} -#if 0 - mAddDialog = NULL; - mAlbumSelected = NULL; - mPhotoSelected = NULL; - mSlideShow = NULL; - - connect( ui.toolButton_NewAlbum, SIGNAL(clicked()), this, SLOT(OpenOrShowPhotoAddDialog())); - connect( ui.toolButton_EditAlbum, SIGNAL(clicked()), this, SLOT(OpenPhotoEditDialog())); - connect( ui.toolButton_SlideShow, SIGNAL(clicked()), this, SLOT(OpenSlideShow())); - - QTimer *timer = new QTimer(this); - timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); - timer->start(1000); - -#endif - - /* setup TokenQueue */ - //mPhotoQueue = new TokenQueue(rsPhoto, this); +void PostedComments::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ } -#if 0 - -void PhotoDialog::notifySelection(PhotoItem *item, int ptype) +void PostedComments::loadComments(const RsPostedPost& post) { - std::cerr << "PhotoDialog::notifySelection() from : " << ptype << " " << item; - std::cerr << std::endl; - - switch(ptype) - { - default: - case PHOTO_ITEM_TYPE_ALBUM: - notifyAlbumSelection(item); - break; - case PHOTO_ITEM_TYPE_PHOTO: - notifyPhotoSelection(item); - break; - } -} - -void PhotoDialog::notifyAlbumSelection(PhotoItem *item) -{ - std::cerr << "PhotoDialog::notifyAlbumSelection() from : " << item; - std::cerr << std::endl; - - if (mAlbumSelected) - { - std::cerr << "PhotoDialog::notifyAlbumSelection() unselecting old one : " << mAlbumSelected; - std::cerr << std::endl; - - mAlbumSelected->setSelected(false); - } - - mAlbumSelected = item; - insertPhotosForSelectedAlbum(); -} - - -void PhotoDialog::notifyPhotoSelection(PhotoItem *item) -{ - std::cerr << "PhotoDialog::notifyPhotoSelection() from : " << item; - std::cerr << std::endl; - - if (mPhotoSelected) - { - std::cerr << "PhotoDialog::notifyPhotoSelection() unselecting old one : " << mPhotoSelected; - std::cerr << std::endl; - - mPhotoSelected->setSelected(false); - } - - mPhotoSelected = item; -} - - -void PhotoDialog::checkUpdate() -{ - /* update */ - if (!rsPhoto) - return; - - if (rsPhoto->updated()) - { - //insertAlbums(); - requestAlbumList(); - } - - return; -} - - -/*************** New Photo Dialog ***************/ - -void PhotoDialog::OpenSlideShow() -{ - - // TODO. - if (!mAlbumSelected) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Please select an album before\n" - "requesting to edit it!"), - QMessageBox::Ok); - return; - } - - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::OpenPhotoEditDialog() MAJOR ERROR!"; - std::cerr << std::endl; - return; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; - - if (mSlideShow) - { - mSlideShow->show(); - } - else - { - mSlideShow = new PhotoSlideShow(NULL); - mSlideShow->show(); - } - mSlideShow->loadAlbum(albumId); - -} - - -/*************** New Photo Dialog ***************/ - -void PhotoDialog::OpenOrShowPhotoAddDialog() -{ - if (mAddDialog) - { - mAddDialog->show(); - } - else - { - mAddDialog = new PhotoAddDialog(NULL); - mAddDialog->show(); - } - mAddDialog->clearDialog(); -} - - -/*************** Edit Photo Dialog ***************/ - -void PhotoDialog::OpenPhotoEditDialog() -{ - /* check if we have an album selected */ - // THE TWO MessageBoxes - should be handled by disabling the Button!. - // TODO. - if (!mAlbumSelected) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Please select an album before\n" - "requesting to edit it!"), - QMessageBox::Ok); - return; - } - - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::OpenPhotoEditDialog() MAJOR ERROR!"; - std::cerr << std::endl; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; -#if 0 - uint32_t flags = mAlbumSelected->mAlbumDetails.mMeta.mGroupFlags; - - if (!(flags & OWN)) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Cannot Edit Someone Else's Album"), - QMessageBox::Ok); - return; - } -#endif - - OpenOrShowPhotoAddDialog(); - mAddDialog->loadAlbum(albumId); - -} - - -bool PhotoDialog::matchesAlbumFilter(const RsPhotoAlbum &album) -{ - - return true; -} - -double PhotoDialog::AlbumScore(const RsPhotoAlbum &album) -{ - return 1; -} - - -bool PhotoDialog::matchesPhotoFilter(const RsPhotoPhoto &photo) -{ - - return true; -} - -double PhotoDialog::PhotoScore(const RsPhotoPhoto &photo) -{ - return 1; -} - -void PhotoDialog::insertPhotosForSelectedAlbum() -{ - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum()"; + std::cerr << "PostedComments::loadComments(" << post.mMeta.mOrigMsgId << ")"; std::cerr << std::endl; - clearPhotos(); + mCurrentPost = post; + setUpPostFrame(); - //std::list albumIds; - if (mAlbumSelected) - { - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() MAJOR ERROR!"; - std::cerr << std::endl; - } + RsGxsGrpMsgIdPair threadId; - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; - //albumIds.push_back(albumId); + threadId.first = post.mMeta.mGroupId; + threadId.second = post.mMeta.mOrigMsgId; - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() AlbumId: " << albumId; - std::cerr << std::endl; - requestPhotoList(albumId); - } - //requestPhotoList(albumIds); + ui.treeWidget->requestComments(threadId); } -void PhotoDialog::clearAlbums() +void PostedComments::setUpPostFrame() { - std::cerr << "PhotoDialog::clearAlbums()" << std::endl; + ui.postFrame->setVisible(true); - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PhotoDialog::clearAlbums() missing litem"; - std::cerr << std::endl; - continue; - } - - PhotoItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PhotoDialog::clearAlbums() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "PhotoDialog::clearAlbums() Found Child, which is not a PhotoItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); pit++) - { - PhotoItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - mAlbumSelected = NULL; + QDateTime qtime; + qtime.setTime_t(mCurrentPost.mMeta.mPublishTs); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm"); + ui.dateLabel->setText(timestamp); + ui.fromLabel->setText(QString::fromUtf8(mCurrentPost.mMeta.mAuthorId.c_str())); + ui.titleLabel->setText("" + + QString::fromStdString(mCurrentPost.mMeta.mMsgName) + ""); + ui.siteLabel->setText("" + + QString::fromStdString(mCurrentPost.mLink) + ""); + + ui.scoreLabel->setText(QString("0")); + + ui.notesBrowser->setPlainText(QString::fromStdString(mCurrentPost.mNotes)); } -void PhotoDialog::clearPhotos() -{ - std::cerr << "PhotoDialog::clearPhotos()" << std::endl; - - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PhotoDialog::clearPhotos() missing litem"; - std::cerr << std::endl; - continue; - } - - PhotoItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PhotoDialog::clearPhotos() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "PhotoDialog::clearPhotos() Found Child, which is not a PhotoItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); pit++) - { - PhotoItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - - mPhotoSelected = NULL; - - -} - -void PhotoDialog::addAlbum(const RsPhotoAlbum &album) -{ - std::cerr << " PhotoDialog::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; - - PhotoItem *item = new PhotoItem(this, album); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); -} - - -void PhotoDialog::addPhoto(const RsPhotoPhoto &photo) -{ - std::cerr << "PhotoDialog::addPhoto() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - RsPhotoAlbum dummyAlbum; - dummyAlbum.mSetFlags = 0; - - PhotoItem *item = new PhotoItem(this, photo, dummyAlbum); - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - alayout->addWidget(item); - -} - -void PhotoDialog::deletePhotoItem(PhotoItem *item, uint32_t type) -{ - - - return; -} - - -/**************************** Request / Response Filling of Data ************************/ - - -void PhotoDialog::requestAlbumList() -{ - - std::list ids; - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); -} - - -void PhotoDialog::loadAlbumList(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadAlbumList()"; - std::cerr << std::endl; - - std::list albumIds; - rsPhoto->getGroupList(token, albumIds); - - requestAlbumData(albumIds); - - clearPhotos(); - - std::list::iterator it; - for(it = albumIds.begin(); it != albumIds.end(); it++) - { - requestPhotoList(*it); - } - -} - - -void PhotoDialog::requestAlbumData(const std::list &ids) -{ - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, 0); -} - - -bool PhotoDialog::loadAlbumData(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadAlbumData()"; - std::cerr << std::endl; - - clearAlbums(); - - bool moreData = true; - while(moreData) - { - RsPhotoAlbum album; - if (rsPhoto->getAlbum(token, album)) - { - std::cerr << " PhotoDialog::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; - - PhotoItem *item = new PhotoItem(this, album); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); - } - else - { - moreData = false; - } - } - - return true; -} - - -void PhotoDialog::requestPhotoList(const std::string &albumId) -{ - - std::list ids; - ids.push_back(albumId); - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - uint32_t token; - mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); -} - - - - -void PhotoDialog::loadPhotoList(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadPhotoList()"; - std::cerr << std::endl; - - - std::list photoIds; - - rsPhoto->getMsgList(token, photoIds); - requestPhotoData(photoIds); -} - - -void PhotoDialog::requestPhotoData(const std::list &photoIds) -{ - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, photoIds, 0); -} - - -void PhotoDialog::loadPhotoData(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadPhotoData()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPhotoPhoto photo; - - if (rsPhoto->getPhoto(token, photo)) - { - - std::cerr << "PhotoDialog::loadPhotoData() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - addPhoto(photo); - } - else - { - moreData = false; - } - } -} - - -/********************************/ - -void PhotoDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "PhotoDialog::loadRequest()"; - std::cerr << std::endl; - - if (queue == mPhotoQueue) - { - /* now switch on req */ - switch(req.mType) - { - case TOKENREQ_GROUPINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_LIST: - loadAlbumList(req.mToken); - break; - case RS_TOKREQ_ANSTYPE_DATA: - loadAlbumData(req.mToken); - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - case TOKENREQ_MSGINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_LIST: - loadPhotoList(req.mToken); - break; - //case RS_TOKREQ_ANSTYPE_DATA: - // loadPhotoData(req.mToken); - // break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - case TOKENREQ_MSGRELATEDINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_DATA: - loadPhotoData(req.mToken); - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } -} - - -#endif - diff --git a/retroshare-gui/src/gui/Posted/PostedComments.h b/retroshare-gui/src/gui/Posted/PostedComments.h index 78d52354d..3053f18e1 100644 --- a/retroshare-gui/src/gui/Posted/PostedComments.h +++ b/retroshare-gui/src/gui/Posted/PostedComments.h @@ -31,83 +31,24 @@ #include -//#include "gui/Posted/PostedItem.h" -//#include "gui/PhotoShare/PhotoAddDialog.h" -//#include "gui/PhotoShare/PhotoSlideShow.h" #include "util/TokenQueue.h" -class PostedComments: public QWidget, public TokenResponse +class PostedComments: public QWidget, public TokenResponse { Q_OBJECT public: PostedComments(QWidget *parent = 0); +public slots: + + void loadComments(const RsPostedPost& ); + private: - void loadRequest(const TokenQueue *queue, const TokenRequest &req) { return; } + void loadRequest(const TokenQueue *queue, const TokenRequest &req); + void setUpPostFrame(); -#if 0 -virtual void deletePhotoItem(PhotoItem *, uint32_t type); -virtual void notifySelection(PhotoItem *item, int ptype); - - void notifyAlbumSelection(PhotoItem *item); - void notifyPhotoSelection(PhotoItem *item); - -private slots: - - void checkUpdate(); - void OpenOrShowPhotoAddDialog(); - void OpenPhotoEditDialog(); - void OpenSlideShow(); -private: - - /* Request Response Functions for loading data */ - void requestAlbumList(); - void requestAlbumData(const std::list &ids); - void requestPhotoList(const std::string &albumId); - void requestPhotoData(const std::list &photoIds); - - void loadAlbumList(const uint32_t &token); - bool loadAlbumData(const uint32_t &token); - void loadPhotoList(const uint32_t &token); - void loadPhotoData(const uint32_t &token); - - void loadRequest(const TokenQueue *queue, const TokenRequest &req); - - - /* TODO: These functions must be filled in for proper filtering to work - * and tied to the GUI input - */ - - bool matchesAlbumFilter(const RsPhotoAlbum &album); - double AlbumScore(const RsPhotoAlbum &album); - bool matchesPhotoFilter(const RsPhotoPhoto &photo); - double PhotoScore(const RsPhotoPhoto &photo); - - /* Grunt work of setting up the GUI */ - - //bool FilterNSortAlbums(const std::list &albumIds, std::list &filteredAlbumIds, int count); - //bool FilterNSortPhotos(const std::list &photoIds, std::list &filteredPhotoIds, int count); - //void insertAlbums(); - //void insertPhotosForAlbum(const std::list &albumIds); - - void insertPhotosForSelectedAlbum(); - - void addAlbum(const RsPhotoAlbum &album); - void addPhoto(const RsPhotoPhoto &photo); - - void clearAlbums(); - void clearPhotos(); - - PhotoAddDialog *mAddDialog; - PhotoSlideShow *mSlideShow; - - PhotoItem *mAlbumSelected; - PhotoItem *mPhotoSelected; - -#endif - - TokenQueue *mPhotoQueue; + RsPostedPost mCurrentPost; /* UI - from Designer */ Ui::PostedComments ui; diff --git a/retroshare-gui/src/gui/Posted/PostedComments.ui b/retroshare-gui/src/gui/Posted/PostedComments.ui index 0b974c14f..817cc6ff7 100644 --- a/retroshare-gui/src/gui/Posted/PostedComments.ui +++ b/retroshare-gui/src/gui/Posted/PostedComments.ui @@ -1,169 +1,367 @@ - - - PostedComments - - - - 0 - 0 - 632 - 398 - - - - Form - - - - - - - - Hot - - - - - - - New - - - - - - - Top - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Today - - - - - Yesterday - - - - - This Week - - - - - This Month - - - - - This Year - - - - - - - - - - - - - - Refresh - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Showing 1-100 - - - - - - - Prev - - - - - - - Next - - - - - - - - - true - - - - - 0 - 0 - 382 - 302 - - - - - - - - - - 0 - 0 - - - - - 1 - - - - - - - - - - - + + + PostedComments + + + + 0 + 0 + 632 + 398 + + + + Form + + + + + + + 0 + 0 + + + + background-color: rgb(203, 203, 203); + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 20 + + + + 1 + + + + + + + + + /\ + + + + + + + score + + + + + + + \/ + + + + + + + + + + 0 + 0 + + + + + 12 + 75 + true + + + + Title this is a very very very very loooooooooooooooonnnnnnnnnnnnnnnnng title dont you think? yes it is and should wrap around I hope + + + true + + + true + + + + + + + + + + + + + + 0 + 0 + + + + + 9 + 75 + true + + + + Date + + + + + + + + 0 + 0 + + + + + 9 + + + + You eyes only + + + true + + + + + + + + + + + + 0 + 0 + + + + + 9 + 75 + true + + + + From + + + + + + + + 0 + 0 + + + + + 9 + + + + Signed by + + + true + + + + + + + + + + + + 0 + 0 + + + + + 9 + 75 + true + + + + Site + + + + + + + + 0 + 0 + + + + + 9 + + + + Signed by + + + true + + + + + + + + + + + + + + background-color: rgb(203, 203, 203); + + + + + + + + + false + + + + 6 + + + 0 + + + + + Hot + + + true + + + true + + + + + + + New + + + true + + + true + + + + + + + Top + + + true + + + false + + + true + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Refresh + + + + + + + + + + Comment + + + + + Author + + + + + Date + + + + + Points + + + + + + + + + GxsCommentTreeWidget + QTreeWidget +
gui/gxs/GxsCommentTreeWidget.h
+
+
+ + +
diff --git a/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.cpp b/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.cpp new file mode 100644 index 000000000..e5eaa27c6 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.cpp @@ -0,0 +1,30 @@ +#include "PostedCreateCommentDialog.h" +#include "ui_PostedCreateCommentDialog.h" + +PostedCreateCommentDialog::PostedCreateCommentDialog(TokenQueue *tokQ, const RsGxsGrpMsgIdPair &parentId, const RsGxsMessageId& threadId, QWidget *parent) : + QDialog(parent), + ui(new Ui::PostedCreateCommentDialog), mTokenQueue(tokQ), mParentId(parentId), mThreadId(threadId) +{ + ui->setupUi(this); + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(createComment())); +} + +void PostedCreateCommentDialog::createComment() +{ + RsPostedComment comment; + + comment.mComment = ui->commentTextEdit->document()->toPlainText().toStdString(); + comment.mMeta.mParentId = mParentId.second; + comment.mMeta.mGroupId = mParentId.first; + comment.mMeta.mThreadId = mThreadId; + + uint32_t token; + rsPosted->submitComment(token, comment); + mTokenQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, 0); + close(); +} + +PostedCreateCommentDialog::~PostedCreateCommentDialog() +{ + delete ui; +} diff --git a/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.h b/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.h new file mode 100644 index 000000000..8edae3e1a --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.h @@ -0,0 +1,31 @@ +#ifndef POSTEDCREATECOMMENTDIALOG_H +#define POSTEDCREATECOMMENTDIALOG_H + +#include +#include "retroshare/rsposted.h" +#include "util/TokenQueue.h" + +namespace Ui { + class PostedCreateCommentDialog; +} + +class PostedCreateCommentDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PostedCreateCommentDialog(TokenQueue* tokQ, const RsGxsGrpMsgIdPair& parentId, const RsGxsMessageId& threadId, QWidget *parent = 0); + ~PostedCreateCommentDialog(); + +private slots: + + void createComment(); + +private: + Ui::PostedCreateCommentDialog *ui; + TokenQueue* mTokenQueue; + RsGxsGrpMsgIdPair mParentId; + RsGxsMessageId mThreadId; +}; + +#endif // POSTEDCREATECOMMENTDIALOG_H diff --git a/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.ui b/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.ui new file mode 100644 index 000000000..ddecc9214 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCreateCommentDialog.ui @@ -0,0 +1,82 @@ + + + PostedCreateCommentDialog + + + + 0 + 0 + 372 + 145 + + + + Make Comment + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Comment</span></p></body></html> + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + PostedCreateCommentDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PostedCreateCommentDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp new file mode 100644 index 000000000..c9eebf008 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.cpp @@ -0,0 +1,29 @@ +#include "PostedCreatePostDialog.h" +#include "ui_PostedCreatePostDialog.h" + +PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *posted, const RsGxsGroupId& grpId, QWidget *parent): + QDialog(parent), mTokenQueue(tokenQ), mPosted(posted), mGrpId(grpId), + ui(new Ui::PostedCreatePostDialog) +{ + ui->setupUi(this); + connect(this, SIGNAL(accepted()), this, SLOT(createPost())); +} + +void PostedCreatePostDialog::createPost() +{ + RsPostedPost post; + post.mMeta.mGroupId = mGrpId; + post.mLink = ui->linkEdit->text().toStdString(); + post.mNotes = ui->notesTextEdit->toPlainText().toStdString(); + post.mMeta.mMsgName = ui->titleEdit->text().toStdString(); + + uint32_t token; + mPosted->submitPost(token, post); + mTokenQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_ACK, TOKEN_USER_TYPE_POST); + close(); +} + +PostedCreatePostDialog::~PostedCreatePostDialog() +{ + delete ui; +} diff --git a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h new file mode 100644 index 000000000..9a06042b8 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.h @@ -0,0 +1,41 @@ +#ifndef POSTEDCREATEPOSTDIALOG_H +#define POSTEDCREATEPOSTDIALOG_H + +#include +#include "retroshare/rsposted.h" +#include "PostedUserTypes.h" + +#include "util/TokenQueue.h" + +namespace Ui { + class PostedCreatePostDialog; +} + +class PostedCreatePostDialog : public QDialog +{ + Q_OBJECT + +public: + + /*! + * @param tokenQ parent callee token + * @param posted + */ + explicit PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted* posted, const RsGxsGroupId& grpId, QWidget *parent = 0); + ~PostedCreatePostDialog(); + +private slots: + + void createPost(); + +private: + Ui::PostedCreatePostDialog *ui; + + QString mLink; + QString mNotes; + RsPosted* mPosted; + RsGxsGroupId mGrpId; + TokenQueue* mTokenQueue; +}; + +#endif // POSTEDCREATEPOSTDIALOG_H diff --git a/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui new file mode 100644 index 000000000..e565194d0 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCreatePostDialog.ui @@ -0,0 +1,114 @@ + + + PostedCreatePostDialog + + + + 0 + 0 + 406 + 195 + + + + Create Post + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Title</span></p></body></html> + + + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Link</span></p></body></html> + + + + + + + + + + + + + + Notes + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + PostedCreatePostDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PostedCreatePostDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/retroshare-gui/src/gui/Posted/PostedDialog.cpp b/retroshare-gui/src/gui/Posted/PostedDialog.cpp index 934fd02dd..ba0c55432 100644 --- a/retroshare-gui/src/gui/Posted/PostedDialog.cpp +++ b/retroshare-gui/src/gui/Posted/PostedDialog.cpp @@ -40,622 +40,35 @@ /**************************************************************** - * New Photo Display Widget. + * Posted Dialog * - * This has two 'lists'. - * Top list shows Albums. - * Lower list is photos from the selected Album. - * - * Notes: - * Each Item will be an AlbumItem, which contains a thumbnail & random details. - * We will limit Items to < 100. With a 'Filter to see more message. - * - * Thumbnails will come from Service. - * Option to Share albums / pictures onward (if permissions allow). - * Option to Download the albums to a specified directory. (is this required if sharing an album?) - * - * Will introduce a FullScreen SlideShow later... first get basics happening. */ PostedDialog::PostedDialog(QWidget *parent) : MainPage(parent) { - ui.setupUi(this); + ui.setupUi(this); - mPostedList = new PostedListDialog(NULL); - mPostedComments = new PostedComments(NULL); + mPostedList = new PostedListDialog(this, NULL); + mPostedComments = new PostedComments(NULL); - QString list("List"); - ui.tabWidget->addTab(mPostedList, list); - QString comments("Comments"); - ui.tabWidget->addTab(mPostedComments, comments); + QString list("List"); + ui.tabWidget->addTab(mPostedList, list); + QString comments("Comments"); + ui.tabWidget->addTab(mPostedComments, comments); + connect(mPostedList, SIGNAL(loadComments( std::string ) ), mPostedComments, SLOT(loadComments( std::string ) ) ); } - -#if 0 - - - - -/** Constructor */ -PhotoDialog::PhotoDialog(QWidget *parent) -: MainPage(parent) +void PostedDialog::commentLoad(const RsPostedPost &post) { - ui.setupUi(this); - - mAddDialog = NULL; - mAlbumSelected = NULL; - mPhotoSelected = NULL; - mSlideShow = NULL; - - connect( ui.toolButton_NewAlbum, SIGNAL(clicked()), this, SLOT(OpenOrShowPhotoAddDialog())); - connect( ui.toolButton_EditAlbum, SIGNAL(clicked()), this, SLOT(OpenPhotoEditDialog())); - connect( ui.toolButton_SlideShow, SIGNAL(clicked()), this, SLOT(OpenSlideShow())); - - QTimer *timer = new QTimer(this); - timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); - timer->start(1000); - - - /* setup TokenQueue */ - mPhotoQueue = new TokenQueue(rsPhoto, this); - -} - - -void PhotoDialog::notifySelection(PhotoItem *item, int ptype) -{ - std::cerr << "PhotoDialog::notifySelection() from : " << ptype << " " << item; - std::cerr << std::endl; - - switch(ptype) - { - default: - case PHOTO_ITEM_TYPE_ALBUM: - notifyAlbumSelection(item); - break; - case PHOTO_ITEM_TYPE_PHOTO: - notifyPhotoSelection(item); - break; - } -} - -void PhotoDialog::notifyAlbumSelection(PhotoItem *item) -{ - std::cerr << "PhotoDialog::notifyAlbumSelection() from : " << item; - std::cerr << std::endl; - - if (mAlbumSelected) - { - std::cerr << "PhotoDialog::notifyAlbumSelection() unselecting old one : " << mAlbumSelected; - std::cerr << std::endl; - - mAlbumSelected->setSelected(false); - } - - mAlbumSelected = item; - insertPhotosForSelectedAlbum(); -} - - -void PhotoDialog::notifyPhotoSelection(PhotoItem *item) -{ - std::cerr << "PhotoDialog::notifyPhotoSelection() from : " << item; - std::cerr << std::endl; - - if (mPhotoSelected) - { - std::cerr << "PhotoDialog::notifyPhotoSelection() unselecting old one : " << mPhotoSelected; - std::cerr << std::endl; - - mPhotoSelected->setSelected(false); - } - - mPhotoSelected = item; -} - - -void PhotoDialog::checkUpdate() -{ - /* update */ - if (!rsPhoto) - return; - - if (rsPhoto->updated()) - { - //insertAlbums(); - requestAlbumList(); - } - - return; -} - - -/*************** New Photo Dialog ***************/ - -void PhotoDialog::OpenSlideShow() -{ - - // TODO. - if (!mAlbumSelected) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Please select an album before\n" - "requesting to edit it!"), - QMessageBox::Ok); - return; - } - - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::OpenPhotoEditDialog() MAJOR ERROR!"; - std::cerr << std::endl; - return; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; - - if (mSlideShow) - { - mSlideShow->show(); - } - else - { - mSlideShow = new PhotoSlideShow(NULL); - mSlideShow->show(); - } - mSlideShow->loadAlbum(albumId); - -} - - -/*************** New Photo Dialog ***************/ - -void PhotoDialog::OpenOrShowPhotoAddDialog() -{ - if (mAddDialog) - { - mAddDialog->show(); - } - else - { - mAddDialog = new PhotoAddDialog(NULL); - mAddDialog->show(); - } - mAddDialog->clearDialog(); -} - - -/*************** Edit Photo Dialog ***************/ - -void PhotoDialog::OpenPhotoEditDialog() -{ - /* check if we have an album selected */ - // THE TWO MessageBoxes - should be handled by disabling the Button!. - // TODO. - if (!mAlbumSelected) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Please select an album before\n" - "requesting to edit it!"), - QMessageBox::Ok); - return; - } - - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::OpenPhotoEditDialog() MAJOR ERROR!"; - std::cerr << std::endl; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; -#if 0 - uint32_t flags = mAlbumSelected->mAlbumDetails.mMeta.mGroupFlags; - - if (!(flags & OWN)) - { - // ALERT. - int ret = QMessageBox::information(this, tr("PhotoShare"), - tr("Cannot Edit Someone Else's Album"), - QMessageBox::Ok); - return; - } -#endif - - OpenOrShowPhotoAddDialog(); - mAddDialog->loadAlbum(albumId); - -} - - -bool PhotoDialog::matchesAlbumFilter(const RsPhotoAlbum &album) -{ - - return true; -} - -double PhotoDialog::AlbumScore(const RsPhotoAlbum &album) -{ - return 1; -} - - -bool PhotoDialog::matchesPhotoFilter(const RsPhotoPhoto &photo) -{ - - return true; -} - -double PhotoDialog::PhotoScore(const RsPhotoPhoto &photo) -{ - return 1; -} - -void PhotoDialog::insertPhotosForSelectedAlbum() -{ - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum()"; - std::cerr << std::endl; - - clearPhotos(); - - //std::list albumIds; - if (mAlbumSelected) - { - if (mAlbumSelected->mIsPhoto) - { - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() MAJOR ERROR!"; - std::cerr << std::endl; - } - - std::string albumId = mAlbumSelected->mAlbumDetails.mMeta.mGroupId; - //albumIds.push_back(albumId); - - std::cerr << "PhotoDialog::insertPhotosForSelectedAlbum() AlbumId: " << albumId; - std::cerr << std::endl; - requestPhotoList(albumId); - } - //requestPhotoList(albumIds); -} - - -void PhotoDialog::clearAlbums() -{ - std::cerr << "PhotoDialog::clearAlbums()" << std::endl; - - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PhotoDialog::clearAlbums() missing litem"; - std::cerr << std::endl; - continue; - } - - PhotoItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PhotoDialog::clearAlbums() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "PhotoDialog::clearAlbums() Found Child, which is not a PhotoItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); pit++) - { - PhotoItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - mAlbumSelected = NULL; - -} - -void PhotoDialog::clearPhotos() -{ - std::cerr << "PhotoDialog::clearPhotos()" << std::endl; - - std::list photoItems; - std::list::iterator pit; - - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PhotoDialog::clearPhotos() missing litem"; - std::cerr << std::endl; - continue; - } - - PhotoItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PhotoDialog::clearPhotos() item: " << item; - std::cerr << std::endl; - - photoItems.push_back(item); - } - else - { - std::cerr << "PhotoDialog::clearPhotos() Found Child, which is not a PhotoItem???"; - std::cerr << std::endl; - } - } - - for(pit = photoItems.begin(); pit != photoItems.end(); pit++) - { - PhotoItem *item = *pit; - alayout->removeWidget(item); - delete item; - } - - mPhotoSelected = NULL; - - -} - -void PhotoDialog::addAlbum(const RsPhotoAlbum &album) -{ - std::cerr << " PhotoDialog::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; - - PhotoItem *item = new PhotoItem(this, album); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); -} - - -void PhotoDialog::addPhoto(const RsPhotoPhoto &photo) -{ - std::cerr << "PhotoDialog::addPhoto() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - RsPhotoAlbum dummyAlbum; - dummyAlbum.mSetFlags = 0; - - PhotoItem *item = new PhotoItem(this, photo, dummyAlbum); - QLayout *alayout = ui.scrollAreaWidgetContents_2->layout(); - alayout->addWidget(item); - -} - -void PhotoDialog::deletePhotoItem(PhotoItem *item, uint32_t type) -{ - - - return; -} - - -/**************************** Request / Response Filling of Data ************************/ - - -void PhotoDialog::requestAlbumList() -{ - - std::list ids; - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); -} - - -void PhotoDialog::loadAlbumList(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadAlbumList()"; - std::cerr << std::endl; - - std::list albumIds; - rsPhoto->getGroupList(token, albumIds); - - requestAlbumData(albumIds); - - clearPhotos(); - - std::list::iterator it; - for(it = albumIds.begin(); it != albumIds.end(); it++) - { - requestPhotoList(*it); - } - -} - - -void PhotoDialog::requestAlbumData(const std::list &ids) -{ - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, 0); -} - - -bool PhotoDialog::loadAlbumData(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadAlbumData()"; - std::cerr << std::endl; - - clearAlbums(); - - bool moreData = true; - while(moreData) - { - RsPhotoAlbum album; - if (rsPhoto->getAlbum(token, album)) - { - std::cerr << " PhotoDialog::addAlbum() AlbumId: " << album.mMeta.mGroupId << std::endl; - - PhotoItem *item = new PhotoItem(this, album); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); - } - else - { - moreData = false; - } - } - - return true; -} - - -void PhotoDialog::requestPhotoList(const std::string &albumId) -{ - - std::list ids; - ids.push_back(albumId); - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - uint32_t token; - mPhotoQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, 0); + mPostedComments->loadComments(post); + ui.tabWidget->setCurrentWidget(mPostedComments); } -void PhotoDialog::loadPhotoList(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadPhotoList()"; - std::cerr << std::endl; - - - std::list photoIds; - - rsPhoto->getMsgList(token, photoIds); - requestPhotoData(photoIds); -} - - -void PhotoDialog::requestPhotoData(const std::list &photoIds) -{ - RsTokReqOptions opts; - uint32_t token; - mPhotoQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, photoIds, 0); -} - - -void PhotoDialog::loadPhotoData(const uint32_t &token) -{ - std::cerr << "PhotoDialog::loadPhotoData()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPhotoPhoto photo; - - if (rsPhoto->getPhoto(token, photo)) - { - - std::cerr << "PhotoDialog::loadPhotoData() AlbumId: " << photo.mMeta.mGroupId; - std::cerr << " PhotoId: " << photo.mMeta.mMsgId; - std::cerr << std::endl; - - addPhoto(photo); - } - else - { - moreData = false; - } - } -} - - -/********************************/ - -void PhotoDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "PhotoDialog::loadRequest()"; - std::cerr << std::endl; - - if (queue == mPhotoQueue) - { - /* now switch on req */ - switch(req.mType) - { - case TOKENREQ_GROUPINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_LIST: - loadAlbumList(req.mToken); - break; - case RS_TOKREQ_ANSTYPE_DATA: - loadAlbumData(req.mToken); - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - case TOKENREQ_MSGINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_LIST: - loadPhotoList(req.mToken); - break; - //case RS_TOKREQ_ANSTYPE_DATA: - // loadPhotoData(req.mToken); - // break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - case TOKENREQ_MSGRELATEDINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_DATA: - loadPhotoData(req.mToken); - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: MSG: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - default: - std::cerr << "PhotoDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } -} - - -/**************************** Request / Response Filling of Data ************************/ - - -#endif - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/Posted/PostedDialog.h b/retroshare-gui/src/gui/Posted/PostedDialog.h index 823d44850..4b491770d 100644 --- a/retroshare-gui/src/gui/Posted/PostedDialog.h +++ b/retroshare-gui/src/gui/Posted/PostedDialog.h @@ -31,28 +31,27 @@ #include -//#include "gui/Posted/PostedList.h" -//#include "gui/Posted/PostedComments.h" +class CommentHolder +{ +public: -//#include "gui/PhotoShare/PhotoAddDialog.h" -//#include "gui/PhotoShare/PhotoSlideShow.h" -//#include "util/TokenQueue.h" + /*! + * This should be used for loading comments of a message on a main comment viewing page + * @param msgId the message id for which comments will be requested + */ + virtual void commentLoad(const RsPostedPost&) = 0; +}; class PostedListDialog; class PostedComments; -class PostedDialog : public MainPage +class PostedDialog : public MainPage, public CommentHolder { Q_OBJECT public: PostedDialog(QWidget *parent = 0); - -//virtual void addTab(std::string item); - -private slots: - - //void OpenSlideShow(); + void commentLoad(const RsPostedPost &); private: diff --git a/retroshare-gui/src/gui/Posted/PostedDialog.ui b/retroshare-gui/src/gui/Posted/PostedDialog.ui index bf21aa5f6..757f2f61b 100644 --- a/retroshare-gui/src/gui/Posted/PostedDialog.ui +++ b/retroshare-gui/src/gui/Posted/PostedDialog.ui @@ -10,24 +10,79 @@ 557 - - - + + 1 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + 24 + 24 + + + + + + + :/images/posted_24.png + + + + + + + + 10 + 75 + true + + + + Posted Links + + + + + + + Qt::Horizontal + + + + 573 + 20 + + + + + + + -1 - - true - - + diff --git a/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp b/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp new file mode 100644 index 000000000..bf788971a --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedGroupDialog.cpp @@ -0,0 +1,90 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "PostedGroupDialog.h" +#include "util/TokenQueue.h" + +#include +#include + +#define POSTED_ENABLE_FLAG ( GXS_GROUP_FLAGS_ICON | \ + GXS_GROUP_FLAGS_DESCRIPTION | \ + GXS_GROUP_FLAGS_DISTRIBUTION | \ + GXS_GROUP_FLAGS_PUBLISHSIGN | \ + GXS_GROUP_FLAGS_SHAREKEYS | \ + GXS_GROUP_FLAGS_PERSONALSIGN | \ + GXS_GROUP_FLAGS_COMMENTS | \ + 0) + +#define POSTED_CREATE_DEFAULT_FLAG ( GXS_GROUP_DEFAULTS_DISTRIB_LOCAL | \ + GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED | \ + GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB | \ + GXS_GROUP_DEFAULTS_COMMENTS_NO | \ + 0) + +PostedGroupDialog::PostedGroupDialog(TokenQueue* tokenQueue, RsPosted* posted, QWidget *parent) + :GxsGroupDialog(tokenQueue, POSTED_ENABLE_FLAG, POSTED_CREATE_DEFAULT_FLAG, parent), + mPosted(posted) +{ +} + +PostedGroupDialog::PostedGroupDialog(const RsPostedGroup& grp, Mode mode, QWidget *parent) + :GxsGroupDialog(grp.mMeta, mode, parent), mGrp(grp) +{ +} + +QString PostedGroupDialog::serviceHeader() +{ + switch (mode()) + { + case MODE_CREATE: + return tr("Create New Posted Topic"); + case MODE_SHOW: + return tr("Posted Topic"); + case MODE_EDIT: + return tr("Edit Posted Topic"); + } + + return ""; +} + + +QPixmap PostedGroupDialog::serviceImage() +{ + return QPixmap(":/images/posted_add_64.png"); +} + +bool PostedGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta) +{ + // Specific Function. + RsPostedGroup grp; + grp.mDescription = getDescription().toStdString(); + grp.mMeta = meta; + + rsPosted->submitGroup(token, grp); + return true; +} + + + + + + diff --git a/retroshare-gui/src/gui/forumsv2/CreateForumV2.h b/retroshare-gui/src/gui/Posted/PostedGroupDialog.h similarity index 56% rename from retroshare-gui/src/gui/forumsv2/CreateForumV2.h rename to retroshare-gui/src/gui/Posted/PostedGroupDialog.h index fd4387b13..495d1a330 100644 --- a/retroshare-gui/src/gui/forumsv2/CreateForumV2.h +++ b/retroshare-gui/src/gui/Posted/PostedGroupDialog.h @@ -20,46 +20,38 @@ ****************************************************************/ -#ifndef _CREATE_FORUMV2_DIALOG_H -#define _CREATE_FORUMV2_DIALOG_H +#ifndef _POSTED_GROUP_DIALOG_H +#define _POSTED_GROUP_DIALOG_H -#include "ui_CreateForumV2.h" +#include "gui/gxs/GxsGroupDialog.h" +#include "retroshare/rsposted.h" -#include "util/TokenQueue.h" - -class CreateForumV2 : public QDialog, public TokenResponse +class PostedGroupDialog : public GxsGroupDialog { Q_OBJECT public: - CreateForumV2(QWidget *parent = 0); - void newForum(); /* cleanup */ + /*! + * This constructs a create dialog + */ + PostedGroupDialog(TokenQueue* tokenQueue, RsPosted* posted, QWidget *parent = NULL); - // Callback for all Loads. -virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); + /*! + * This constructs a show dialog which displays an already existing group + */ + PostedGroupDialog(const RsPostedGroup& grp, Mode mode, QWidget *parent = NULL); -private slots: - /* actions to take.... */ - void createForum(); - - // set private forum key share list - void setShareList(); +protected: + virtual QString serviceHeader(); + virtual QPixmap serviceImage(); + bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta); private: - void sendShareList(std::string forumId); - void completeCreateNewForum(const RsGroupMetaData &newForumMeta); - void loadNewForumId(const uint32_t &token); + RsPostedGroup mGrp; + RsPosted* mPosted; - std::list mShareList; - - QPixmap picture; - - TokenQueue *mForumQueue; - - /** Qt Designer generated object */ - Ui::CreateForumV2 ui; }; #endif diff --git a/retroshare-gui/src/gui/Posted/PostedItem.cpp b/retroshare-gui/src/gui/Posted/PostedItem.cpp index e1b57e754..d4c99dfff 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.cpp +++ b/retroshare-gui/src/gui/Posted/PostedItem.cpp @@ -35,286 +35,80 @@ #include #include -/**** - * #define DEBUG_ITEM 1 - ****/ /** Constructor */ -PostedItem::PostedItem(PostedHolder *parent, const RsPostedPost &post) -:QWidget(NULL) +PostedItem::PostedItem(PostedHolder *postHolder, const RsPostedPost &post) +:QWidget(NULL), mPostHolder(postHolder), mPost(post) { - setupUi(this); - setAttribute ( Qt::WA_DeleteOnClose, true ); + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); - titleLabel->setText(QString::fromUtf8(post.mMeta.mMsgName.c_str())); - //dateLabel->setText(QString("Whenever")); - fromLabel->setText(QString::fromUtf8(post.mMeta.mAuthorId.c_str())); - //siteLabel->setText(QString::fromUtf8(post.mMeta.mAuthorId.c_str())); - //scoreLabel->setText(QString("1140")); + setContent(mPost); - // exposed for testing... - float score = rsPosted->calcPostScore(post.mMeta); - time_t now = time(NULL); + connect( commentButton, SIGNAL( clicked() ), this, SLOT( loadComments() ) ); + connect( voteUpButton, SIGNAL(clicked()), this, SLOT(makeUpVote())); + connect( voteDownButton, SIGNAL(clicked()), this, SLOT( makeDownVote())); - QString fromLabelTxt = QString(" Age: ") + QString::number(now - post.mMeta.mPublishTs); - fromLabelTxt += QString(" Score: ") + QString::number(score); - fromLabel->setText(fromLabelTxt); - - uint32_t votes = 0; - uint32_t comments = 0; - rsPosted->extractPostedCache(post.mMeta.mServiceString, votes, comments); - scoreLabel->setText(QString::number(votes)); - QString commentLabel = QString("Comments: ") + QString::number(comments); - commentLabel += QString(" Votes: ") + QString::number(votes); - siteLabel->setText(commentLabel); - - QDateTime ts; - ts.setTime_t(post.mMeta.mPublishTs); - dateLabel->setText(ts.toString(QString("yyyy/MM/dd hh:mm:ss"))); - - return; + return; } - -#if 0 - -PhotoItem::PhotoItem(PhotoHolder *parent, const RsPhotoAlbum &album) -:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_ALBUM) +void PostedItem::setContent(const RsPostedPost &post) { - setupUi(this); - setAttribute ( Qt::WA_DeleteOnClose, true ); + mPost = post; + QDateTime qtime; + qtime.setTime_t(mPost.mMeta.mPublishTs); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm"); + dateLabel->setText(timestamp); + fromLabel->setText(QString::fromUtf8(post.mMeta.mAuthorId.c_str())); + titleLabel->setText("" + + QString::fromStdString(post.mMeta.mMsgName) + ""); + siteLabel->setText("" + + QString::fromStdString(post.mLink) + ""); - mIsPhoto = false; - setDummyText(); - updateAlbumText(album); // saves: mAlbumDetails = album; - updateImage(album.mThumbnail); + uint32_t up, down, nComments; + + bool ok = rsPosted->retrieveScores(mPost.mMeta.mServiceString, up, down, nComments); + + if(ok) + { + int32_t vote = up - down; + scoreLabel->setText(QString::number(vote)); + + numCommentsLabel->setText("

# Comments: " + + QString::number(nComments) + "

"); + } - setSelected(false); } - -PhotoItem::PhotoItem(PhotoHolder *parent, const RsPhotoPhoto &photo, const RsPhotoAlbum &album) -:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_PHOTO) +RsPostedPost PostedItem::getPost() const { - setupUi(this); - - setAttribute ( Qt::WA_DeleteOnClose, true ); - - mIsPhoto = true; - - setDummyText(); - updatePhotoText(photo); // saves: mPhotoDetails = photo; - updateAlbumText(album); // saves: mAlbumDetails = album; - - updateImage(photo.mThumbnail); - - setSelected(false); + return mPost; } - -PhotoItem::PhotoItem(PhotoHolder *parent, std::string path) // for new photos. -:QWidget(NULL), mParent(parent), mType(PHOTO_ITEM_TYPE_NEW) +void PostedItem::makeDownVote() { - setupUi(this); - - setAttribute ( Qt::WA_DeleteOnClose, true ); - - setDummyText(); - mIsPhoto = true; - - int width = 120; - int height = 120; - - //QPixmap qtn = QPixmap(QString::fromStdString(path)).scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - QPixmap qtn = QPixmap(QString::fromStdString(path)).scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); - imgLabel->setPixmap(qtn); - setSelected(false); + RsGxsGrpMsgIdPair msgId; + msgId.first = mPost.mMeta.mGroupId; + msgId.second = mPost.mMeta.mMsgId; + emit vote(msgId, false); } -void PhotoItem::updateParent(PhotoHolder *parent) // for external construction. +void PostedItem::makeUpVote() { - mParent = parent; + RsGxsGrpMsgIdPair msgId; + msgId.first = mPost.mMeta.mGroupId; + msgId.second = mPost.mMeta.mMsgId; + emit vote(msgId, true); } - -void PhotoItem::setDummyText() +void PostedItem::loadComments() { - titleLabel->setText(QString("Unknown")); - fromBoldLabel->setText(QString("By:")); - fromLabel->setText(QString("Unknown")); - statusBoldLabel->setText(QString("Where:")); - statusLabel->setText(QString("Unknown")); - dateBoldLabel->setText(QString("When:")); - dateLabel->setText(QString("Unknown")); + std::cerr << "PostedItem::loadComments() Requesting for " << mThreadId; + std::cerr << std::endl; + mPostHolder->showComments(mPost); } - - -void PhotoItem::updateAlbumText(const RsPhotoAlbum &album) -{ - mAlbumDetails = album; - mAlbumDetails.mThumbnail.data = 0; - updateText(); -} - -void PhotoItem::updatePhotoText(const RsPhotoPhoto &photo) -{ - // Save new Photo details. - mPhotoDetails = photo; - mPhotoDetails.mThumbnail.data = 0; - updateText(); -} - - - -void PhotoItem::updateText() -{ - // SET Album Values first -> then overwrite with Photo Values. - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - titleLabel->setText(QString::fromUtf8(mAlbumDetails.mMeta.mGroupName.c_str())); - } - - // This needs to be fixed!! TODO - fromLabel->setText(QString::fromStdString(mAlbumDetails.mMeta.mGroupId)); - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_AUTHOR) - { - // This needs to be fixed!! TODO - fromLabel->setText(QString::fromStdString(mAlbumDetails.mMeta.mGroupId)); - } - - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - statusLabel->setText(QString::fromUtf8(mAlbumDetails.mWhere.c_str())); - } - - if (mAlbumDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - dateLabel->setText(QString::fromUtf8(mAlbumDetails.mWhen.c_str())); - } - - // NOW Photo Bits. - if (mIsPhoto) - { - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_TITLE) - { - titleLabel->setText(QString::fromUtf8(mPhotoDetails.mMeta.mMsgName.c_str())); - } - - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_AUTHOR) - { - // This needs to be fixed!! TODO - fromLabel->setText(QString::fromStdString(mPhotoDetails.mMeta.mAuthorId)); - } - - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHERE) - { - statusLabel->setText(QString::fromUtf8(mPhotoDetails.mWhere.c_str())); - } - - if (mPhotoDetails.mSetFlags & RSPHOTO_FLAGS_ATTRIB_WHEN) - { - dateLabel->setText(QString::fromUtf8(mPhotoDetails.mWhen.c_str())); - } - } - -} - -void PhotoItem::updateImage(const RsPhotoThumbnail &thumbnail) -{ - if (thumbnail.data != NULL) - { - QPixmap qtn; - qtn.loadFromData(thumbnail.data, thumbnail.size, thumbnail.type.c_str()); - imgLabel->setPixmap(qtn); - } -} - -bool PhotoItem::getPhotoThumbnail(RsPhotoThumbnail &nail) -{ - const QPixmap *tmppix = imgLabel->pixmap(); - - QByteArray ba; - QBuffer buffer(&ba); - - if(!tmppix->isNull()) - { - // send chan image - - buffer.open(QIODevice::WriteOnly); - tmppix->save(&buffer, "PNG"); // writes image into ba in PNG format - - RsPhotoThumbnail tmpnail; - tmpnail.data = (uint8_t *) ba.data(); - tmpnail.size = ba.size(); - - nail.copyFrom(tmpnail); - - return true; - } - - nail.data = NULL; - nail.size = 0; - return false; -} - - -void PhotoItem::removeItem() -{ -#ifdef DEBUG_ITEM - std::cerr << "PhotoItem::removeItem()"; - std::cerr << std::endl; -#endif - hide(); - if (mParent) - { - mParent->deletePhotoItem(this, mType); - } -} - - -void PhotoItem::setSelected(bool on) -{ - mSelected = on; - if (mSelected) - { - mParent->notifySelection(this, mType); - frame->setStyleSheet("QFrame#frame{border: 2px solid #55CC55;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #55EE55, stop: 1 #CCCCCC);\nborder-radius: 10px}"); - } - else - { - frame->setStyleSheet("QFrame#frame{border: 2px solid #CCCCCC;\nbackground: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC);\nborder-radius: 10px}"); - } - update(); -} - -bool PhotoItem::isSelected() -{ - return mSelected; -} - - -void PhotoItem::mousePressEvent(QMouseEvent *event) -{ - /* We can be very cunning here? - * grab out position. - * flag ourselves as selected. - * then pass the mousePressEvent up for handling by the parent - */ - - QPoint pos = event->pos(); - - std::cerr << "PhotoItem::mousePressEvent(" << pos.x() << ", " << pos.y() << ")"; - std::cerr << std::endl; - - setSelected(true); - - QWidget::mousePressEvent(event); -} - - -const QPixmap *PhotoItem::getPixmap() -{ - return imgLabel->pixmap(); -} - -#endif diff --git a/retroshare-gui/src/gui/Posted/PostedItem.h b/retroshare-gui/src/gui/Posted/PostedItem.h index c0d830811..de968d019 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.h +++ b/retroshare-gui/src/gui/Posted/PostedItem.h @@ -34,8 +34,8 @@ class PostedItem; class PostedHolder { public: -virtual void deletePostedItem(PostedItem *, uint32_t ptype) = 0; -virtual void notifySelection(PostedItem *item, int ptype) = 0; + + virtual void showComments(const RsPostedPost& post) = 0; }; class PostedItem : public QWidget, private Ui::PostedItem @@ -43,21 +43,27 @@ class PostedItem : public QWidget, private Ui::PostedItem Q_OBJECT public: - PostedItem(PostedHolder *parent, const RsPostedPost &item); + PostedItem(PostedHolder *parent, const RsPostedPost &post); - //void setDummyText(); - //void updateParent(PhotoHolder *parent); // for external construction. - //void removeItem(); + RsPostedPost getPost() const; + void setContent(const RsPostedPost& post); - //void setSelected(bool on); - //bool isSelected(); +private slots: + void loadComments(); + void makeUpVote(); + void makeDownVote(); -protected: - //void mousePressEvent(QMouseEvent *event); +signals: + void vote(const RsGxsGrpMsgIdPair& msgId, bool up); private: uint32_t mType; bool mSelected; + + std::string mThreadId; + PostedHolder *mPostHolder; + RsPostedPost mPost; + }; diff --git a/retroshare-gui/src/gui/Posted/PostedItem.ui b/retroshare-gui/src/gui/Posted/PostedItem.ui index 6b8322dbe..8ffe66d74 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.ui +++ b/retroshare-gui/src/gui/Posted/PostedItem.ui @@ -53,14 +53,14 @@ border-radius: 10px}
- 1 + 0 - + /\ @@ -74,7 +74,7 @@ border-radius: 10px}
- + \/ @@ -250,7 +250,18 @@ border-radius: 10px}
- + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">#</span><span style=" font-size:8pt; font-weight:600;"> Comments: 0</span></p></body></html> + + + @@ -265,7 +276,7 @@ border-radius: 10px}
- + View Comments @@ -278,8 +289,6 @@ border-radius: 10px}
- - - + diff --git a/retroshare-gui/src/gui/Posted/PostedListDialog.cpp b/retroshare-gui/src/gui/Posted/PostedListDialog.cpp index b572f026b..922305912 100644 --- a/retroshare-gui/src/gui/Posted/PostedListDialog.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListDialog.cpp @@ -23,8 +23,12 @@ #include "PostedListDialog.h" -//#include +#include "gui/Posted/PostedGroupDialog.h" +#include "gui/Posted/PostedCreatePostDialog.h" +#include "gui/Posted/PostedDialog.h" + #include +#include #include #include @@ -59,118 +63,220 @@ #define IMAGE_FORUMAUTHD ":/images/konv_message2.png" #define IMAGE_COPYLINK ":/images/copyrslink.png" +// token types to deal with + + /** Constructor */ -PostedListDialog::PostedListDialog(QWidget *parent) -: RsAutoUpdatePage(1000,parent) +PostedListDialog::PostedListDialog(CommentHolder *commentHolder, QWidget *parent) +: RsAutoUpdatePage(1000,parent), mCommentHolder(commentHolder) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); - /* Setup Queue */ - mPostedQueue = new TokenQueue(rsPosted, this); + /* Setup Queue */ + mPostedQueue = new TokenQueue(rsPosted->getTokenService(), this); connect( ui.groupTreeWidget, SIGNAL( treeCustomContextMenuRequested( QPoint ) ), this, SLOT( groupListCustomPopupMenu( QPoint ) ) ); connect( ui.groupTreeWidget, SIGNAL( treeCurrentItemChanged(QString) ), this, SLOT( changedTopic(QString) ) ); - /* Initialize group tree */ - //ui.groupTreeWidget->initDisplayMenu(ui.displayButton); + connect(ui.hotSortButton, SIGNAL(clicked()), this, SLOT(getRankings())); + connect(ui.newSortButton, SIGNAL(clicked()), this, SLOT(getRankings())); + connect(ui.topSortButton, SIGNAL(clicked()), this, SLOT(getRankings())); - /* create forum tree */ + /* create posted tree */ yourTopics = ui.groupTreeWidget->addCategoryItem(tr("My Topics"), QIcon(IMAGE_FOLDER), true); subscribedTopics = ui.groupTreeWidget->addCategoryItem(tr("Subscribed Topics"), QIcon(IMAGE_FOLDERRED), true); popularTopics = ui.groupTreeWidget->addCategoryItem(tr("Popular Topics"), QIcon(IMAGE_FOLDERGREEN), false); otherTopics = ui.groupTreeWidget->addCategoryItem(tr("Other Topics"), QIcon(IMAGE_FOLDERYELLOW), false); - /* Hide platform specific features */ -#ifdef Q_WS_WIN + ui.hotSortButton->setChecked(true); -#endif + connect( ui.newTopicButton, SIGNAL( clicked() ), this, SLOT( newTopic() ) ); + connect(ui.refreshButton, SIGNAL(clicked()), this, SLOT(refreshTopics())); + connect(ui.submitPostButton, SIGNAL(clicked()), this, SLOT(newPost())); } +void PostedListDialog::getRankings() +{ + + if(mCurrTopicId.empty()) + return; + + std::cerr << "PostedListDialog::getHotRankings()"; + std::cerr << std::endl; + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + uint32_t token; + + QObject* button = sender(); + if(button == ui.hotSortButton) + { + rsPosted->requestPostRankings(token, RsPosted::HotRankType, mCurrTopicId); + }else if(button == ui.topSortButton) + { + rsPosted->requestPostRankings(token, RsPosted::TopRankType, mCurrTopicId); + }else if(button == ui.newSortButton) + { + rsPosted->requestPostRankings(token, RsPosted::NewRankType, mCurrTopicId); + }else{ + return; + } + + mPostedQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_DATA, TOKEN_USER_TYPE_POST_RANKINGS); +} + +void PostedListDialog::loadRankings(const uint32_t &token) +{ + + RsPostedPostRanking rankings; + + if(!rsPosted->getPostRanking(token, rankings)) + return; + + if(rankings.grpId != mCurrTopicId) + return; + + applyRanking(rankings.ranking); +} + +void PostedListDialog::applyRanking(const PostedRanking& ranks) +{ + std::cerr << "PostedListDialog::loadGroupThreadData_InsertThreads()"; + std::cerr << std::endl; + + shallowClearPosts(); + + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + + PostedRanking::const_iterator mit = ranks.begin(); + + for(; mit != ranks.end(); mit++) + { + const RsGxsMessageId& msgId = mit->second; + + if(mPosts.find(msgId) != mPosts.end()) + alayout->addWidget(mPosts[msgId]); + } + + return; +} + + + +void PostedListDialog::refreshTopics() +{ + std::cerr << "PostedListDialog::requestGroupSummary()"; + std::cerr << std::endl; + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + uint32_t token; + mPostedQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_USER_TYPE_TOPIC); +} void PostedListDialog::groupListCustomPopupMenu( QPoint /*point*/ ) { QMenu contextMnu( this ); - QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum())); - //action->setDisabled (mCurrTopicId.empty() || IS_FORUM_SUBSCRIBED(subscribeFlags)); - - action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum())); - //action->setEnabled (!mCurrTopicId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags)); - - contextMnu.addSeparator(); - - contextMnu.addAction(QIcon(IMAGE_NEWFORUM), tr("New Forum"), this, SLOT(newforum())); - - action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Forum Details"), this, SLOT(showForumDetails())); - action->setEnabled (!mCurrTopicId.empty ()); - - action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails())); - //action->setEnabled (!mCurrTopicId.empty () && IS_FORUM_ADMIN(subscribeFlags)); - - QAction *shareKeyAct = new QAction(QIcon(":/images/gpgp_key_generate.png"), tr("Share Forum"), &contextMnu); - connect( shareKeyAct, SIGNAL( triggered() ), this, SLOT( shareKey() ) ); - //shareKeyAct->setEnabled(!mCurrTopicId.empty() && IS_FORUM_ADMIN(subscribeFlags)); - contextMnu.addAction( shareKeyAct); - - QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu); - connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) ); - //restoreKeysAct->setEnabled(!mCurrTopicId.empty() && !IS_FORUM_ADMIN(subscribeFlags)); - contextMnu.addAction( restoreKeysAct); - - action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink())); - action->setEnabled(!mCurrTopicId.empty()); - - contextMnu.addSeparator(); - - action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsReadAll())); - //action->setEnabled (!mCurrTopicId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags)); - - action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnreadAll())); - //action->setEnabled (!mCurrTopicId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags)); - -#ifdef DEBUG_FORUMS - contextMnu.addSeparator(); - action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData())); - action->setEnabled (!mCurrTopicId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags)); -#endif + QAction *action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Post"), this, SLOT(newPost())); + action->setDisabled (mCurrTopicId.empty()); contextMnu.exec(QCursor::pos()); } +void PostedListDialog::newPost() +{ + if(mCurrTopicId.empty()) + return; + + PostedCreatePostDialog cp(mPostedQueue, rsPosted, mCurrTopicId, this); + cp.exec(); +} + +void PostedListDialog::submitVote(const RsGxsGrpMsgIdPair &msgId, bool up) +{ + uint32_t token; + RsPostedVote vote; + + vote.mMeta.mGroupId = msgId.first; + vote.mMeta.mParentId = msgId.second; + vote.mDirection = (uint8_t)up; + rsPosted->submitVote(token, vote); + + mPostedQueue->queueRequest(token, 0 , RS_TOKREQ_ANSTYPE_ACK, TOKEN_USER_TYPE_VOTE); +} + +void PostedListDialog::showComments(const RsPostedPost& post) +{ + mCommentHolder->commentLoad(post); +} + void PostedListDialog::updateDisplay() { - std::list groupIds; - std::list::iterator it; if (!rsPosted) return; - // TODO groupsChanged... HACK XXX. -#if 0 - if ((rsPosted->groupsChanged(groupIds)) || (rsPosted->updated())) - { - /* update Forums List */ - insertGroups(); - it = std::find(groupIds.begin(), groupIds.end(), mCurrTopicId); - if (it != groupIds.end()) - { - /* update threads as well */ - insertThreads(); - } - } -#endif + std::list groupIds; + std::map > msgs; + if (rsPosted->updated()) { /* update Forums List */ - insertGroups(); - insertThreads(); + + rsPosted->groupsChanged(groupIds); + if(!groupIds.empty()) + { + std::list::iterator it = std::find(groupIds.begin(), groupIds.end(), mCurrTopicId); + + if(it != groupIds.end()){ + requestGroupSummary(); + return; + } + } + + rsPosted->msgsChanged(msgs); + + if(!msgs.empty()) + { + + + std::map >::iterator mit = msgs.find(mCurrTopicId); + if(mit != msgs.end()) + { + updateDisplayedItems(mit->second); + } + } } } + +void PostedListDialog::updateDisplayedItems(const std::vector &msgIds) +{ + + RsTokReqOptions opts; + + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + + + GxsMsgReq msgs; + msgs[mCurrTopicId] = msgIds; + + std::cerr << "PostedListDialog::updateDisplayedItems(" << mCurrTopicId << ")"; + std::cerr << std::endl; + + uint32_t token; + mPostedQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgs, TOKEN_USER_TYPE_POST_MOD); + +} + + + void PostedListDialog::changedTopic(const QString &id) { mCurrTopicId = id.toStdString(); @@ -179,15 +285,25 @@ void PostedListDialog::changedTopic(const QString &id) /*********************** **** **** **** ***********************/ -/** Request / Response of Data ********************************/ +/** New / Edit Groups ********************************/ /*********************** **** **** **** ***********************/ -#define POSTEDDIALOG_LISTING 1 -#define POSTEDDIALOG_CURRENTFORUM 2 -#define POSTEDDIALOG_INSERTTHREADS 3 -#define POSTEDDIALOG_INSERTCHILD 4 -#define POSTEDDIALOG_INSERT_POST 5 -#define POSTEDDIALOG_REPLY_MESSAGE 6 +void PostedListDialog::newTopic() +{ + PostedGroupDialog cf (mPostedQueue, rsPosted, this); + cf.exec (); +} + +void PostedListDialog::showGroupDetails() +{ + if (mCurrTopicId.empty()) + { + return; + } + + PostedGroupDialog cf(mGroups[mCurrTopicId], GxsGroupDialog::MODE_SHOW, this); + cf.exec (); +} void PostedListDialog::insertGroups() @@ -200,10 +316,33 @@ void PostedListDialog::requestGroupSummary() std::cerr << "PostedListDialog::requestGroupSummary()"; std::cerr << std::endl; - std::list ids; RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; uint32_t token; - mPostedQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, ids, POSTEDDIALOG_LISTING); + mPostedQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_USER_TYPE_TOPIC); +} + +void PostedListDialog::acknowledgeGroup(const uint32_t &token) +{ + RsGxsGroupId grpId; + rsPosted->acknowledgeGrp(token, grpId); + + if(!grpId.empty()) + { + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + uint32_t reqToken; + mPostedQueue->requestGroupInfo(reqToken, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_USER_TYPE_TOPIC); + } +} + +void PostedListDialog::acknowledgePostMsg(const uint32_t &token) +{ + RsGxsGrpMsgIdPair msgId; + + // just acknowledge, don't load anything + rsPosted->acknowledgeMsg(token, msgId); } void PostedListDialog::loadGroupSummary(const uint32_t &token) @@ -225,6 +364,23 @@ void PostedListDialog::loadGroupSummary(const uint32_t &token) } } +void PostedListDialog::loadPostData(const uint32_t &token) +{ + loadGroupThreadData_InsertThreads(token); +} + +void PostedListDialog::acknowledgeVoteMsg(const uint32_t &token) +{ + RsGxsGrpMsgIdPair msgId; + + rsPosted->acknowledgeMsg(token, msgId); +} + +void PostedListDialog::loadVoteData(const uint32_t &token) +{ + return; +} + /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ @@ -232,7 +388,7 @@ void PostedListDialog::loadGroupSummary(const uint32_t &token) void PostedListDialog::requestGroupSummary_CurrentForum(const std::string &forumId) { - RsTokReqOptions opts; + RsTokReqOptions opts; std::list grpIds; grpIds.push_back(forumId); @@ -272,144 +428,190 @@ void PostedListDialog::loadGroupSummary_CurrentForum(const uint32_t &token) void PostedListDialog::insertThreads() { - loadCurrentForumThreads(mCurrTopicId); + loadCurrentTopicThreads(mCurrTopicId); } -void PostedListDialog::loadCurrentForumThreads(const std::string &forumId) +void PostedListDialog::loadCurrentTopicThreads(const std::string &topicId) { - std::cerr << "PostedListDialog::loadCurrentForumThreads(" << forumId << ")"; + std::cerr << "PostedListDialog::loadCurrentForumThreads(" << topicId << ")"; std::cerr << std::endl; - if (forumId.empty()) + if (topicId.empty()) { std::cerr << "PostedListDialog::loadCurrentForumThreads() Empty GroupId .. ignoring Req"; std::cerr << std::endl; return; - } - - /* if already active -> kill current loading */ - if (mThreadLoading) - { - /* Cleanup */ - } + } clearPosts(); - /* initiate loading */ - std::cerr << "PostedListDialog::loadCurrentForumThreads() Initiating Loading"; - std::cerr << std::endl; - - mThreadLoading = true; - - requestGroupThreadData_InsertThreads(forumId); + /* initiate loading */ + requestGroupThreadData_InsertThreads(topicId); } void PostedListDialog::requestGroupThreadData_InsertThreads(const std::string &groupId) { - RsTokReqOptions opts; + RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - std::list grpIds; + std::list grpIds; grpIds.push_back(groupId); std::cerr << "PostedListDialog::requestGroupThreadData_InsertThreads(" << groupId << ")"; std::cerr << std::endl; uint32_t token; - //mPostedQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, POSTEDDIALOG_INSERTTHREADS); - - // Do specific Posted Request.... - rsPosted->requestRanking(token, groupId); - // get the Queue to handle response. - mPostedQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_DATA, POSTEDDIALOG_INSERTTHREADS); - + mPostedQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds, TOKEN_USER_TYPE_POST); } void PostedListDialog::loadGroupThreadData_InsertThreads(const uint32_t &token) { - std::cerr << "PostedListDialog::loadGroupThreadData_InsertThreads()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsPostedPost post; - // Old Format. - //if (rsPosted->getPost(token, post)) + std::cerr << "PostedListDialog::loadGroupThreadData_InsertThreads()"; + std::cerr << std::endl; - if (rsPosted->getRankedPost(token, post)) - { - std::cerr << "PostedListDialog::loadGroupThreadData_InsertThreads() MsgId: " << post.mMeta.mMsgId; - std::cerr << std::endl; - - loadPost(post); - } - else - { - moreData = false; - } - } + clearPosts(); - mThreadLoading = false; + PostedPostResult result; + rsPosted->getPost(token, result); + std::vector& posts = result[mCurrTopicId]; + std::vector::iterator vit = posts.begin(); + for(; vit != posts.end(); vit++) + { + RsPostedPost& p = *vit; + loadPost(p); + } } void PostedListDialog::loadPost(const RsPostedPost &post) { - PostedItem *item = new PostedItem(this, post); - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - alayout->addWidget(item); + PostedItem *item = new PostedItem(this, post); + connect(item, SIGNAL(vote(RsGxsGrpMsgIdPair,bool)), this, SLOT(submitVote(RsGxsGrpMsgIdPair,bool))); + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + mPosts.insert(post.mMeta.mMsgId, item); + alayout->addWidget(item); } void PostedListDialog::clearPosts() { - std::cerr << "PostedListDialog::clearPosts()" << std::endl; + std::cerr << "PostedListDialog::clearPosts()" << std::endl; - std::list postedItems; - std::list::iterator pit; + std::list postedItems; + std::list::iterator pit; - QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - int count = alayout->count(); - for(int i = 0; i < count; i++) - { - QLayoutItem *litem = alayout->itemAt(i); - if (!litem) - { - std::cerr << "PostedListDialog::clearPosts() missing litem"; - std::cerr << std::endl; - continue; - } + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + int count = alayout->count(); + for(int i = 0; i < count; i++) + { + QLayoutItem *litem = alayout->itemAt(i); + if (!litem) + { + std::cerr << "PostedListDialog::clearPosts() missing litem"; + std::cerr << std::endl; + continue; + } - PostedItem *item = dynamic_cast(litem->widget()); - if (item) - { - std::cerr << "PostedListDialog::clearPosts() item: " << item; - std::cerr << std::endl; + PostedItem *item = dynamic_cast(litem->widget()); + if (item) + { + std::cerr << "PostedListDialog::clearPosts() item: " << item; + std::cerr << std::endl; - postedItems.push_back(item); - } - else - { - std::cerr << "PostedListDialog::clearPosts() Found Child, which is not a PostedItem???"; - std::cerr << std::endl; - } - } + postedItems.push_back(item); + } + else + { + std::cerr << "PostedListDialog::clearPosts() Found Child, which is not a PostedItem???"; + std::cerr << std::endl; + } + } - for(pit = postedItems.begin(); pit != postedItems.end(); pit++) - { - PostedItem *item = *pit; - alayout->removeWidget(item); - delete item; - } + for(pit = postedItems.begin(); pit != postedItems.end(); pit++) + { + PostedItem *item = *pit; + alayout->removeWidget(item); + delete item; + } + + mPosts.clear(); } +void PostedListDialog::shallowClearPosts() +{ + std::cerr << "PostedListDialog::clearPosts()" << std::endl; + std::list postedItems; + std::list::iterator pit; + + QLayout *alayout = ui.scrollAreaWidgetContents->layout(); + int count = alayout->count(); + for(int i = 0; i < count; i++) + { + QLayoutItem *litem = alayout->itemAt(i); + if (!litem) + { + std::cerr << "PostedListDialog::clearPosts() missing litem"; + std::cerr << std::endl; + continue; + } + + PostedItem *item = dynamic_cast(litem->widget()); + if (item) + { + std::cerr << "PostedListDialog::clearPosts() item: " << item; + std::cerr << std::endl; + + postedItems.push_back(item); + } + else + { + std::cerr << "PostedListDialog::clearPosts() Found Child, which is not a PostedItem???"; + std::cerr << std::endl; + } + } + + for(pit = postedItems.begin(); pit != postedItems.end(); pit++) + { + PostedItem *item = *pit; + alayout->removeWidget(item); + } + +} + +void PostedListDialog::updateCurrentDisplayComplete(const uint32_t &token) +{ + std::cerr << "PostedListDialog::loadGroupThreadData_InsertThreads()"; + std::cerr << std::endl; + + PostedPostResult result; + rsPosted->getPost(token, result); + + + if(result.find(mCurrTopicId) == result.end()) + return; + + std::vector& posts = result[mCurrTopicId]; + std::vector::iterator vit = posts.begin(); + + for(; vit != posts.end(); vit++) + { + + RsPostedPost& p = *vit; + + // modify post content + if(mPosts.find(p.mMeta.mMsgId) != mPosts.end()) + mPosts[p.mMeta.mMsgId]->setContent(p); + + } + +} /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ @@ -421,28 +623,88 @@ void PostedListDialog::loadRequest(const TokenQueue *queue, const TokenRequest & std::cerr << std::endl; if (queue == mPostedQueue) - { + { /* now switch on req */ - switch(req.mUserType) + switch(req.mUserType) { - case POSTEDDIALOG_LISTING: - loadGroupSummary(req.mToken); - break; - case POSTEDDIALOG_CURRENTFORUM: - loadGroupSummary_CurrentForum(req.mToken); - break; - - case POSTEDDIALOG_INSERTTHREADS: - loadGroupThreadData_InsertThreads(req.mToken); - break; - - default: - std::cerr << "PostedListDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; + case TOKEN_USER_TYPE_TOPIC: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_SUMMARY: + loadGroupSummary(req.mToken); + break; + default: + std::cerr << "Error, unexpected anstype:" << req.mAnsType << std::endl; + break; + } + break; + case TOKEN_USER_TYPE_POST: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgePostMsg(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_DATA: + loadPostData(req.mToken); + break; + default: + std::cerr << "Error, unexpected anstype:" << req.mAnsType << std::endl; + break; + } + break; + case TOKEN_USER_TYPE_VOTE: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeVoteMsg(req.mToken); + break; + default: + std::cerr << "Error, unexpected anstype:" << req.mAnsType << std::endl; + break; + } + break; + case TOKEN_USER_TYPE_POST_MOD: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_DATA: + updateCurrentDisplayComplete(req.mToken); + break; + default: + std::cerr << "Error, unexpected anstype:" << req.mAnsType << std::endl; + break; + } + break; + case TOKEN_USER_TYPE_POST_RANKINGS: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_DATA: + loadRankings(req.mToken); + break; + default: + std::cerr << "Error, unexpected anstype:" << req.mAnsType << std::endl; + break; + } + break; + default: + std::cerr << "PostedListDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; } } + + /* now switch on req */ + switch(req.mType) + { + case TOKENREQ_GROUPINFO: + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeGroup(req.mToken); + break; + } + break; + } } @@ -455,24 +717,19 @@ void PostedListDialog::loadRequest(const TokenQueue *queue, const TokenRequest & void PostedListDialog::groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, GroupItemInfo &groupItemInfo) { - groupItemInfo.id = QString::fromStdString(groupInfo.mGroupId); groupItemInfo.name = QString::fromUtf8(groupInfo.mGroupName.c_str()); //groupItemInfo.description = QString::fromUtf8(groupInfo.forumDesc); groupItemInfo.popularity = groupInfo.mPop; groupItemInfo.lastpost = QDateTime::fromTime_t(groupInfo.mLastPost); - if (groupInfo.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) { - groupItemInfo.name += " (" + tr("AUTHD") + ")"; - groupItemInfo.icon = QIcon(IMAGE_FORUMAUTHD); - } else { - groupItemInfo.icon = QIcon(IMAGE_FORUM); - } + } void PostedListDialog::insertGroupData(const std::list &groupList) { - std::list::const_iterator it; + + std::list::const_iterator it; QList adminList; QList subList; @@ -481,53 +738,51 @@ void PostedListDialog::insertGroupData(const std::list &groupLi std::multimap popMap; for (it = groupList.begin(); it != groupList.end(); it++) { - /* sort it into Publish (Own), Subscribed, Popular and Other */ - uint32_t flags = it->mSubscribeFlags; + /* sort it into Publish (Own), Subscribed, Popular and Other */ + uint32_t flags = it->mSubscribeFlags; - GroupItemInfo groupItemInfo; - groupInfoToGroupItemInfo(*it, groupItemInfo); + GroupItemInfo groupItemInfo; + groupInfoToGroupItemInfo(*it, groupItemInfo); - if (flags & RSGXS_GROUP_SUBSCRIBE_ADMIN) { - adminList.push_back(groupItemInfo); - } else if (flags & RSGXS_GROUP_SUBSCRIBE_SUBSCRIBED) { - /* subscribed forum */ - subList.push_back(groupItemInfo); - } else { - /* rate the others by popularity */ - popMap.insert(std::make_pair(it->mPop, groupItemInfo)); - } - } + // if (flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { + adminList.push_back(groupItemInfo); + // } else if (flags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { + /* subscribed forum */ + // subList.push_back(groupItemInfo); + // } else { + /* rate the others by popularity */ +// popMap.insert(std::make_pair(it->mPop, groupItemInfo)); + } +// } - /* iterate backwards through popMap - take the top 5 or 10% of list */ - uint32_t popCount = 5; - if (popCount < popMap.size() / 10) - { - popCount = popMap.size() / 10; - } + /* iterate backwards through popMap - take the top 5 or 10% of list */ + uint32_t popCount = 5; + if (popCount < popMap.size() / 10) + { + popCount = popMap.size() / 10; + } - uint32_t i = 0; - uint32_t popLimit = 0; + uint32_t i = 0; + uint32_t popLimit = 0; std::multimap::reverse_iterator rit; - for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++) ; + for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++) ; if (rit != popMap.rend()) { - popLimit = rit->first; + popLimit = rit->first; } for (rit = popMap.rbegin(); rit != popMap.rend(); rit++) { - if (rit->second.popularity < (int) popLimit) { - otherList.append(rit->second); - } else { - popList.append(rit->second); - } - } + if (rit->second.popularity < (int) popLimit) { + otherList.append(rit->second); + } else { + popList.append(rit->second); + } + } - /* now we can add them in as a tree! */ + /* now we can add them in as a tree! */ ui.groupTreeWidget->fillGroupItems(yourTopics, adminList); ui.groupTreeWidget->fillGroupItems(subscribedTopics, subList); ui.groupTreeWidget->fillGroupItems(popularTopics, popList); ui.groupTreeWidget->fillGroupItems(otherTopics, otherList); - - // updateMessageSummaryList(""); } /**************************************************************************************/ diff --git a/retroshare-gui/src/gui/Posted/PostedListDialog.h b/retroshare-gui/src/gui/Posted/PostedListDialog.h index 80383d28d..e2554dcd1 100644 --- a/retroshare-gui/src/gui/Posted/PostedListDialog.h +++ b/retroshare-gui/src/gui/Posted/PostedListDialog.h @@ -24,6 +24,7 @@ #ifndef MRK_POSTED_LIST_DIALOG_H #define MRK_POSTED_LIST_DIALOG_H + #include "retroshare-gui/mainpage.h" #include "ui_PostedListDialog.h" @@ -35,64 +36,115 @@ #include "gui/common/GroupTreeWidget.h" #include "util/TokenQueue.h" - #include "retroshare-gui/RsAutoUpdatePage.h" +#include "PostedUserTypes.h" -class PostedListDialog : public RsAutoUpdatePage, public PostedHolder, public TokenResponse + +class CommentHolder; + +/*********************** **** **** **** ***********************/ +/** Request / Response of Data ********************************/ +/*********************** **** **** **** ***********************/ + +#define POSTEDDIALOG_LISTING 1 +#define POSTEDDIALOG_CURRENTFORUM 2 +#define POSTEDDIALOG_INSERTTHREADS 3 +#define POSTEDDIALOG_INSERTCHILD 4 +#define POSTEDDIALOG_INSERT_POST 5 +#define POSTEDDIALOG_REPLY_MESSAGE 6 + +class PostedListDialog : public RsAutoUpdatePage, public PostedHolder, public TokenResponse { Q_OBJECT public: - PostedListDialog(QWidget *parent = 0); - -virtual void deletePostedItem(PostedItem *, uint32_t ptype) { return; } -virtual void notifySelection(PostedItem *item, int ptype) { return; } + PostedListDialog(CommentHolder* commentHolder, QWidget *parent = 0); + void showComments(const RsPostedPost& post); private slots: -void groupListCustomPopupMenu( QPoint /*point*/ ); -void changedTopic(const QString &id); + void groupListCustomPopupMenu( QPoint /*point*/ ); + void changedTopic(const QString &id); + + void newTopic(); + void showGroupDetails(); + void newPost(); + void refreshTopics(); + + void submitVote(const RsGxsGrpMsgIdPair& msgId, bool up); + + void getRankings(); private: -void clearPosts(); + void clearPosts(); -void updateDisplay(); -void loadPost(const RsPostedPost &post); + /*! + * Only removes it from layout + */ + void shallowClearPosts(); -void insertGroups(); -void requestGroupSummary(); -void loadGroupSummary(const uint32_t &token); + void updateDisplay(); + void loadPost(const RsPostedPost &post); -void requestGroupSummary_CurrentForum(const std::string &forumId); -void loadGroupSummary_CurrentForum(const uint32_t &token); + void insertGroups(); + void requestGroupSummary(); + void acknowledgeGroup(const uint32_t &token); + void loadGroupSummary(const uint32_t &token); -void insertThreads(); -void loadCurrentForumThreads(const std::string &forumId); - -void requestGroupThreadData_InsertThreads(const std::string &forumId); -void loadGroupThreadData_InsertThreads(const uint32_t &token); + void requestGroupSummary_CurrentForum(const std::string &forumId); + void loadGroupSummary_CurrentForum(const uint32_t &token); -void insertGroupData(const std::list &groupList); -void groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, GroupItemInfo &groupItemInfo); + // posts + void acknowledgePostMsg(const uint32_t &token); + void loadPostData(const uint32_t &token); + void insertThreads(); + void loadCurrentTopicThreads(const std::string &forumId); + void requestGroupThreadData_InsertThreads(const std::string &forumId); + void loadGroupThreadData_InsertThreads(const uint32_t &token); - void loadRequest(const TokenQueue *queue, const TokenRequest &req); + // votes + + void acknowledgeVoteMsg(const uint32_t& token); + void loadVoteData(const uint32_t &token); + + // ranking + + void loadRankings(const uint32_t& token); + void applyRanking(const PostedRanking& ranks); - QTreeWidgetItem *yourTopics; - QTreeWidgetItem *subscribedTopics; - QTreeWidgetItem *popularTopics; - QTreeWidgetItem *otherTopics; + // update displayed item - bool mThreadLoading; - std::string mCurrTopicId; + void updateDisplayedItems(const std::vector& msgIds); + void updateCurrentDisplayComplete(const uint32_t& token); - TokenQueue *mPostedQueue; + void insertGroupData(const std::list &groupList); + void groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, GroupItemInfo &groupItemInfo); - /* UI - from Designer */ - Ui::PostedListDialog ui; + void loadRequest(const TokenQueue *queue, const TokenRequest &req); + +private: + + QTreeWidgetItem *yourTopics; + QTreeWidgetItem *subscribedTopics; + QTreeWidgetItem *popularTopics; + QTreeWidgetItem *otherTopics; + + + bool mThreadLoading; + RsGxsGroupId mCurrTopicId; + + QMap mGroups; + QMap mPosts; + TokenQueue *mPostedQueue; + + CommentHolder* mCommentHolder; + + /* UI - from Designer */ + Ui::PostedListDialog ui; }; diff --git a/retroshare-gui/src/gui/Posted/PostedListDialog.ui b/retroshare-gui/src/gui/Posted/PostedListDialog.ui index b0ccaa7ee..2bddcaefc 100644 --- a/retroshare-gui/src/gui/Posted/PostedListDialog.ui +++ b/retroshare-gui/src/gui/Posted/PostedListDialog.ui @@ -1,228 +1,270 @@ - - - PostedListDialog - - - - 0 - 0 - 792 - 426 - - - - Form - - - - - - - - Hot - - - - - - - New - - - - - - - Top - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Today - - - - - Yesterday - - - - - This Week - - - - - This Month - - - - - This Year - - - - - - - - - - Qt::Horizontal - - - - - - - New Link Group - - - - - - - Submit Post - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - Refresh - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Showing 1-100 - - - - - - - Prev - - - - - - - Next - - - - - - - - - true - - - - - 0 - 0 - 461 - 330 - - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 309 - - - - - - - - - - - - - - - - - GroupTreeWidget - QWidget -
gui/common/GroupTreeWidget.h
- 1 -
-
- - -
+ + + PostedListDialog + + + + 0 + 0 + 792 + 426 + + + + Form + + + + + + + + false + + + + 6 + + + 0 + + + + + Hot + + + true + + + true + + + + + + + New + + + true + + + true + + + + + + + Top + + + true + + + false + + + true + + + + + + + + + + Refresh + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Today + + + + + Yesterday + + + + + This Week + + + + + This Month + + + + + This Year + + + + + + + + + + Qt::Horizontal + + + + + + + New Topic + + + + + + + Submit Post + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Showing 1-100 + + + + + + + Prev + + + + + + + Next + + + + + + + + + true + + + + + 0 + 0 + 426 + 327 + + + + + 0 + 0 + + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 309 + + + + + + + + + + + + + + + + + GroupTreeWidget + QWidget +
gui/common/GroupTreeWidget.h
+ 1 +
+
+ + +
diff --git a/retroshare-gui/src/gui/Posted/PostedUserTypes.h b/retroshare-gui/src/gui/Posted/PostedUserTypes.h new file mode 100644 index 000000000..e802ae986 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedUserTypes.h @@ -0,0 +1,10 @@ +#ifndef POSTEDUSERTYPES_H +#define POSTEDUSERTYPES_H + +#define TOKEN_USER_TYPE_POST 4 +#define TOKEN_USER_TYPE_VOTE 5 +#define TOKEN_USER_TYPE_TOPIC 6 +#define TOKEN_USER_TYPE_POST_MOD 7 +#define TOKEN_USER_TYPE_POST_RANKINGS 8 + +#endif // POSTEDUSERTYPES_H diff --git a/retroshare-gui/src/gui/Posted/Posted_images.qrc b/retroshare-gui/src/gui/Posted/Posted_images.qrc new file mode 100644 index 000000000..34fce9491 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/Posted_images.qrc @@ -0,0 +1,9 @@ + + + images/posted_24.png + images/posted_32.png + images/posted_48.png + images/posted_64.png + images/posted_add_64.png + + diff --git a/retroshare-gui/src/gui/Posted/images/posted_128.png b/retroshare-gui/src/gui/Posted/images/posted_128.png new file mode 100644 index 000000000..178143057 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_128.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_16.png b/retroshare-gui/src/gui/Posted/images/posted_16.png new file mode 100644 index 000000000..6c07665a4 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_16.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_24.png b/retroshare-gui/src/gui/Posted/images/posted_24.png new file mode 100644 index 000000000..8de05ae32 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_24.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_256.png b/retroshare-gui/src/gui/Posted/images/posted_256.png new file mode 100644 index 000000000..901f51100 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_256.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_32.png b/retroshare-gui/src/gui/Posted/images/posted_32.png new file mode 100644 index 000000000..36ef018c3 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_32.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_48.png b/retroshare-gui/src/gui/Posted/images/posted_48.png new file mode 100644 index 000000000..b71b1cff3 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_48.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_64.png b/retroshare-gui/src/gui/Posted/images/posted_64.png new file mode 100644 index 000000000..fbfaf5e58 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_64.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_add_128.png b/retroshare-gui/src/gui/Posted/images/posted_add_128.png new file mode 100644 index 000000000..40da463d1 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_add_128.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_add_256.png b/retroshare-gui/src/gui/Posted/images/posted_add_256.png new file mode 100644 index 000000000..e6ab57407 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_add_256.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_add_32.png b/retroshare-gui/src/gui/Posted/images/posted_add_32.png new file mode 100644 index 000000000..996452344 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_add_32.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_add_48.png b/retroshare-gui/src/gui/Posted/images/posted_add_48.png new file mode 100644 index 000000000..0c2418a53 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_add_48.png differ diff --git a/retroshare-gui/src/gui/Posted/images/posted_add_64.png b/retroshare-gui/src/gui/Posted/images/posted_add_64.png new file mode 100644 index 000000000..d87421a52 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/posted_add_64.png differ diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index f9be0fa38..0d38765fd 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -23,7 +23,6 @@ #include "gui/TheWire/PulseAddDialog.h" -#include "gui/PhotoShare/PhotoDetailsDialog.h" #include "gui/PhotoShare/PhotoDrop.h" #include diff --git a/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.cpp b/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.cpp index 99cb57215..782d5f3c2 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.cpp +++ b/retroshare-gui/src/gui/WikiPoos/WikiAddDialog.cpp @@ -53,21 +53,26 @@ void WikiAddDialog::createGroup() std::cerr << std::endl; - RsWikiGroup group; + RsWikiCollection group; +#if 0 group.mShareOptions.mShareType = 0; group.mShareOptions.mShareGroupId = "unknown"; group.mShareOptions.mPublishKey = "unknown"; group.mShareOptions.mCommentMode = 0; group.mShareOptions.mResizeMode = 0; +#endif group.mMeta.mGroupName = ui.lineEdit_Name->text().toStdString(); group.mCategory = "Unknown"; uint32_t token; bool isNew = true; + +#if 0 // Don't worry about getting the response? rsWiki->createGroup(token, group, isNew); +#endif clearDialog(); diff --git a/retroshare-gui/src/gui/WikiPoos/WikiDialog.cpp b/retroshare-gui/src/gui/WikiPoos/WikiDialog.cpp index 955ad9a5d..289220fb8 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiDialog.cpp +++ b/retroshare-gui/src/gui/WikiPoos/WikiDialog.cpp @@ -28,6 +28,8 @@ #include "gui/WikiPoos/WikiAddDialog.h" #include "gui/WikiPoos/WikiEditDialog.h" +#include "gui/gxs/WikiGroupDialog.h" + #include #include @@ -35,21 +37,26 @@ #include +#define USE_PEGMMD_RENDERER 1 + +#ifdef USE_PEGMMD_RENDERER +#include "markdown_lib.h" +#endif + /****** * #define WIKI_DEBUG 1 *****/ #define WIKI_DEBUG 1 -#define WIKIDIALOG_LISTING_GROUPLIST 1 #define WIKIDIALOG_LISTING_GROUPDATA 2 -#define WIKIDIALOG_LISTING_ORIGINALPAGES 3 -#define WIKIDIALOG_LISTING_LATESTPAGES 4 #define WIKIDIALOG_LISTING_PAGES 5 #define WIKIDIALOG_MOD_LIST 6 #define WIKIDIALOG_MOD_PAGES 7 #define WIKIDIALOG_WIKI_PAGE 8 +#define WIKIDIALOG_EDITTREE_DATA 9 + /** Constructor */ WikiDialog::WikiDialog(QWidget *parent) @@ -65,16 +72,19 @@ WikiDialog::WikiDialog(QWidget *parent) connect( ui.toolButton_NewGroup, SIGNAL(clicked()), this, SLOT(OpenOrShowAddGroupDialog())); connect( ui.toolButton_NewPage, SIGNAL(clicked()), this, SLOT(OpenOrShowAddPageDialog())); connect( ui.toolButton_Edit, SIGNAL(clicked()), this, SLOT(OpenOrShowEditDialog())); + connect( ui.toolButton_Republish, SIGNAL(clicked()), this, SLOT(OpenOrShowRepublishDialog())); + + // Usurped until Refresh works normally + connect( ui.toolButton_Delete, SIGNAL(clicked()), this, SLOT(insertWikiGroups())); connect( ui.treeWidget_Pages, SIGNAL(itemSelectionChanged()), this, SLOT(groupTreeChanged())); - connect( ui.treeWidget_Mods, SIGNAL(itemSelectionChanged()), this, SLOT(modTreeChanged())); QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); /* setup TokenQueue */ - mWikiQueue = new TokenQueue(rsWiki, this); + mWikiQueue = new TokenQueue(rsWiki->getTokenService(), this); } @@ -111,17 +121,6 @@ void WikiDialog::OpenOrShowAddPageDialog() std::cerr << "WikiDialog::OpenOrShowAddPageDialog() GroupId: " << groupId; std::cerr << std::endl; -#if 0 - RsWikiGroup group; - if (!rsWiki->getGroup(groupId, group)) - { - std::cerr << "WikiDialog::OpenOrShowAddPageDialog() Failed to Get Group"; - std::cerr << std::endl; - } - - mEditDialog->setGroup(group); -#endif - mEditDialog->setupData(groupId, ""); mEditDialog->setNewPage(); @@ -129,81 +128,110 @@ void WikiDialog::OpenOrShowAddPageDialog() } + void WikiDialog::OpenOrShowAddGroupDialog() { - if (mAddGroupDialog) - { - mAddGroupDialog->show(); - } - else - { - mAddGroupDialog = new WikiAddDialog(NULL); - mAddGroupDialog->show(); - } + newGroup(); } +/*********************** **** **** **** ***********************/ +/** New / Edit Groups ********************************/ +/*********************** **** **** **** ***********************/ -void WikiDialog::OpenOrShowEditDialog() +void WikiDialog::newGroup() +{ + WikiGroupDialog cf(mWikiQueue, this); + cf.wikitype(); + + cf.exec (); +} + +void WikiDialog::showGroupDetails() { std::string groupId = getSelectedGroup(); if (groupId == "") { - std::cerr << "WikiDialog::OpenOrShowAddPageDialog() No Group selected"; + std::cerr << "WikiDialog::showGroupDetails() No Group selected"; + std::cerr << std::endl; + return; + } +} + +void WikiDialog::editGroupDetails() +{ + std::string groupId = getSelectedGroup(); + if (groupId == "") + { + std::cerr << "WikiDialog::editGroupDetails() No Group selected"; std::cerr << std::endl; return; } - std::string modId = getSelectedMod(); - std::string realPageId; + //WikiGroupDialog cf (this); + //cf.existingGroup(groupId, GXS_GROUP_DIALOG_EDIT_MODE); + + //cf.exec (); +} + + + +void WikiDialog::OpenOrShowEditDialog() +{ + std::string groupId; std::string pageId; std::string origPageId; - if (!getSelectedPage(pageId, origPageId)) + if (!getSelectedPage(groupId, pageId, origPageId)) { - std::cerr << "WikiDialog::OpenOrShowAddPageDialog() No PageId selected"; + std::cerr << "WikiDialog::OpenOrShowAddPageDialog() No Group or PageId selected"; std::cerr << std::endl; return; } - if (modId == "") - { - realPageId = pageId; - } - else - { - realPageId = modId; - } - + std::cerr << "WikiDialog::OpenOrShowAddPageDialog()"; + std::cerr << std::endl; if (!mEditDialog) { mEditDialog = new WikiEditDialog(NULL); } -#if 0 - RsWikiGroup group; - rsWiki->getGroup(groupId, group); - mEditDialog->setGroup(group); - - RsWikiPage page; - rsWiki->getPage(realPageId, page); - mEditDialog->setPreviousPage(page); -#endif - mEditDialog->setupData(groupId, realPageId); - + mEditDialog->setupData(groupId, pageId); mEditDialog->show(); } +void WikiDialog::OpenOrShowRepublishDialog() +{ + OpenOrShowEditDialog(); + + std::string groupId; + std::string pageId; + std::string origPageId; + + if (!getSelectedPage(groupId, pageId, origPageId)) + { + std::cerr << "WikiDialog::OpenOrShowAddRepublishDialog() No Group or PageId selected"; + std::cerr << std::endl; + if (mEditDialog) + { + mEditDialog->hide(); + } + return; + } + + mEditDialog->setRepublishMode(origPageId); +} void WikiDialog::groupTreeChanged() { /* */ + std::string groupId; std::string pageId; std::string origPageId; - getSelectedPage(pageId, origPageId); + getSelectedPage(groupId, pageId, origPageId); if (pageId == mPageSelected) { return; /* nothing changed */ @@ -213,40 +241,32 @@ void WikiDialog::groupTreeChanged() { /* clear Mods */ clearGroupTree(); - clearModsTree(); - return; } - - clearModsTree(); - - insertModsForPage(origPageId); - requestWikiPage(pageId); + RsGxsGrpMsgIdPair origPagePair = std::make_pair(groupId, origPageId); + RsGxsGrpMsgIdPair pagepair = std::make_pair(groupId, pageId); + requestWikiPage(pagepair); } -void WikiDialog::modTreeChanged() +void WikiDialog::updateWikiPage(const RsWikiSnapshot &page) { - /* */ - std::string pageId = getSelectedMod(); - if (pageId == mModSelected) - { - return; /* nothing changed */ - } +#ifdef USE_PEGMMD_RENDERER + /* render as HTML */ + int extensions = 0; + char *answer = markdown_to_string((char *) page.mPage.c_str(), extensions, HTML_FORMAT); - if (pageId == "") - { - clearWikiPage(); - return; - } + QString renderedText = QString::fromUtf8(answer); + ui.textBrowser->setHtml(renderedText); - requestWikiPage(pageId); -} - - -void WikiDialog::updateWikiPage(const RsWikiPage &page) -{ - ui.textBrowser->setPlainText(QString::fromStdString(page.mPage)); + // free answer. + free(answer); +#else + /* render as HTML */ + QString renderedText = "IN (dummy) RENDERED TEXT MODE:\n"; + renderedText += QString::fromStdString(page.mPage); + ui.textBrowser->setPlainText(renderedText); +#endif } @@ -261,12 +281,6 @@ void WikiDialog::clearGroupTree() ui.treeWidget_Pages->clear(); } -void WikiDialog::clearModsTree() -{ - ui.treeWidget_Mods->clear(); -} - - #define WIKI_GROUP_COL_GROUPNAME 0 #define WIKI_GROUP_COL_GROUPID 1 @@ -276,85 +290,7 @@ void WikiDialog::clearModsTree() #define WIKI_GROUP_COL_ORIGPAGEID 2 -#if 0 -######################################################### -void WikiDialog::insertWikiGroups() -{ - - std::cerr << "WikiDialog::insertWikiGroups()"; - std::cerr << std::endl; - - /* clear it all */ - clearGroupTree(); - - std::list groupIds; - std::list::iterator it; - - rsWiki->getGroupList(groupIds); - - for(it = groupIds.begin(); it != groupIds.end(); it++) - { - /* add a group Item */ - RsWikiGroup group; - rsWiki->getGroup(*it, group); - - QTreeWidgetItem *groupItem = new QTreeWidgetItem(NULL); - groupItem->setText(WIKI_GROUP_COL_GROUPNAME, QString::fromStdString(group.mName)); - groupItem->setText(WIKI_GROUP_COL_GROUPID, QString::fromStdString(group.mGroupId)); - ui.treeWidget_Pages->addTopLevelItem(groupItem); - - std::cerr << "Group: " << group.mName; - std::cerr << std::endl; - - std::list pageIds; - std::list::iterator pit; - - rsWiki->getOrigPageList(*it, pageIds); - - for(pit = pageIds.begin(); pit != pageIds.end(); pit++) - { - std::cerr << "\tOrigPageId: " << *pit; - std::cerr << std::endl; - - /* get newest page */ - RsWikiPage page; - std::string latestPageId; - if (!rsWiki->getLatestPage(*pit, latestPageId)) - { - std::cerr << "\tgetLatestPage() Failed"; - std::cerr << std::endl; - } - - if (!rsWiki->getPage(latestPageId, page)) - { - std::cerr << "\tgetPage() Failed"; - std::cerr << std::endl; - } - - std::cerr << "\tLatestPageId: " << latestPageId; - std::cerr << std::endl; - std::cerr << "\tExtracted OrigPageId: " << page.mOrigPageId; - std::cerr << std::endl; - std::cerr << "\tExtracted PageId: " << page.mPageId; - std::cerr << std::endl; - - QTreeWidgetItem *pageItem = new QTreeWidgetItem(NULL); - pageItem->setText(WIKI_GROUP_COL_PAGENAME, QString::fromStdString(page.mName)); - pageItem->setText(WIKI_GROUP_COL_PAGEID, QString::fromStdString(page.mPageId)); - pageItem->setText(WIKI_GROUP_COL_ORIGPAGEID, QString::fromStdString(page.mOrigPageId)); - - groupItem->addChild(pageItem); - - std::cerr << "\tPage: " << page.mName; - std::cerr << std::endl; - } - } -} -######################################################### -#endif - - -bool WikiDialog::getSelectedPage(std::string &pageId, std::string &origPageId) +bool WikiDialog::getSelectedPage(std::string &groupId, std::string &pageId, std::string &origPageId) { #ifdef WIKI_DEBUG std::cerr << "WikiDialog::getSelectedPage()" << std::endl; @@ -384,6 +320,7 @@ bool WikiDialog::getSelectedPage(std::string &pageId, std::string &origPageId) /* check if it has changed */ + groupId = parent->text(WIKI_GROUP_COL_GROUPID).toStdString(); pageId = item->text(WIKI_GROUP_COL_PAGEID).toStdString(); origPageId = item->text(WIKI_GROUP_COL_ORIGPAGEID).toStdString(); @@ -432,67 +369,6 @@ std::string WikiDialog::getSelectedGroup() return groupId; } -#define WIKI_MODS_COL_ORIGPAGEID 0 -#define WIKI_MODS_COL_PAGEID 1 - -#if 0 -######################################################### -void WikiDialog::insertModsForPage(std::string &origPageId) -{ - /* clear it all */ - //clearPhotos(); - //ui.photoLayout->clear(); - - /* create a list of albums */ - - std::list pageIds; - std::list::const_iterator it; - - rsWiki->getPageVersions(origPageId, pageIds); - - - for(it = pageIds.begin(); it != pageIds.end(); it++) - { - RsWikiPage page; - rsWiki->getPage(*it, page); - - QTreeWidgetItem *modItem = new QTreeWidgetItem(NULL); - modItem->setText(WIKI_MODS_COL_ORIGPAGEID, QString::fromStdString(page.mOrigPageId)); - modItem->setText(WIKI_MODS_COL_PAGEID, QString::fromStdString(page.mPageId)); - ui.treeWidget_Mods->addTopLevelItem(modItem); - } -} -######################################################### -#endif - - - -std::string WikiDialog::getSelectedMod() -{ - std::string pageId; -#ifdef WIKI_DEBUG - std::cerr << "WikiDialog::getSelectedMod()" << std::endl; -#endif - - /* get current item */ - QTreeWidgetItem *item = ui.treeWidget_Mods->currentItem(); - - if (!item) - { - /* leave current list */ -#ifdef WIKI_DEBUG - std::cerr << "WikiDialog::getSelectedMod() Nothing selected" << std::endl; -#endif - return pageId; - } - - pageId = item->text(WIKI_MODS_COL_PAGEID).toStdString(); -#ifdef WIKI_DEBUG - std::cerr << "WikiDialog::getSelectedMod() PageId: " << pageId << std::endl; -#endif - return pageId; -} - /************************** Request / Response *************************/ /*** Loading Main Index ***/ @@ -507,37 +383,13 @@ void WikiDialog::requestGroupList() std::cerr << "WikiDialog::requestGroupList()"; std::cerr << std::endl; - std::list ids; RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token; - mWikiQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, ids, WIKIDIALOG_LISTING_GROUPLIST); + mWikiQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, WIKIDIALOG_LISTING_GROUPDATA); } -void WikiDialog::loadGroupList(const uint32_t &token) -{ - std::cerr << "WikiDialog::loadGroupList()"; - std::cerr << std::endl; - - std::list groupIds; - rsWiki->getGroupList(token, groupIds); - - if (groupIds.size() > 0) - { - requestGroupData(groupIds); - } - else - { - std::cerr << "WikiDialog::loadGroupList() ERROR No Groups..."; - std::cerr << std::endl; - } -} - -void WikiDialog::requestGroupData(const std::list &groupIds) -{ - RsTokReqOptions opts; - uint32_t token; - mWikiQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, WIKIDIALOG_LISTING_GROUPDATA); -} void WikiDialog::loadGroupData(const uint32_t &token) { @@ -546,289 +398,168 @@ void WikiDialog::loadGroupData(const uint32_t &token) clearGroupTree(); - bool moreData = true; - while(moreData) + std::vector datavector; + std::vector::iterator vit; + + if (!rsWiki->getCollections(token, datavector)) { - RsWikiGroup group; - if (rsWiki->getGroupData(token, group)) - { - /* Add Widget, and request Pages */ - - std::cerr << "WikiDialog::addGroup() GroupId: " << group.mMeta.mGroupId; - std::cerr << " Group: " << group.mMeta.mGroupName; - std::cerr << std::endl; - - QTreeWidgetItem *groupItem = new QTreeWidgetItem(); - groupItem->setText(WIKI_GROUP_COL_GROUPNAME, QString::fromStdString(group.mMeta.mGroupName)); - groupItem->setText(WIKI_GROUP_COL_GROUPID, QString::fromStdString(group.mMeta.mGroupId)); - ui.treeWidget_Pages->addTopLevelItem(groupItem); - - /* request pages */ - std::list groupIds; - groupIds.push_back(group.mMeta.mGroupId); - - requestOriginalPages(groupIds); - } - else - { - moreData = false; - } + std::cerr << "WikiDialog::loadGroupData() Error getting GroupData"; + std::cerr << std::endl; + return; + } + + for(vit = datavector.begin(); vit != datavector.end(); vit++) + { + RsWikiCollection &group = *vit; + + /* Add Widget, and request Pages */ + + std::cerr << "WikiDialog::addGroup() GroupId: " << group.mMeta.mGroupId; + std::cerr << " Group: " << group.mMeta.mGroupName; + std::cerr << std::endl; + + QTreeWidgetItem *groupItem = new QTreeWidgetItem(); + groupItem->setText(WIKI_GROUP_COL_GROUPNAME, QString::fromStdString(group.mMeta.mGroupName)); + groupItem->setText(WIKI_GROUP_COL_GROUPID, QString::fromStdString(group.mMeta.mGroupId)); + ui.treeWidget_Pages->addTopLevelItem(groupItem); + + /* request pages */ + std::list groupIds; + groupIds.push_back(group.mMeta.mGroupId); + + requestPages(groupIds); + //requestOriginalPages(groupIds); } - //return true; } -void WikiDialog::requestOriginalPages(const std::list &groupIds) -{ - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_ORIGMSG; - uint32_t token; - mWikiQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, groupIds, WIKIDIALOG_LISTING_ORIGINALPAGES); -} -void WikiDialog::loadOriginalPages(const uint32_t &token) +void WikiDialog::requestPages(const std::list &groupIds) { - std::cerr << "WikiDialog::loadOriginalPages()"; + std::cerr << "WikiDialog::requestPages()"; std::cerr << std::endl; - /* translate into latest pages */ - std::list msgIds; - if (rsWiki->getMsgList(token, msgIds)) - { - std::cerr << "WikiDialog::loadOriginalPages() Loaded " << msgIds.size(); - std::cerr << std::endl; - } - else - { - std::cerr << "WikiDialog::loadOriginalPages() ERROR No Data"; - std::cerr << std::endl; - return; - } - - requestLatestPages(msgIds); - -} - -void WikiDialog::requestLatestPages(const std::list &msgIds) -{ RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mOptions = (RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD); // We want latest version of Thread Heads. uint32_t token; - mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, msgIds, WIKIDIALOG_LISTING_LATESTPAGES); + mWikiQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, WIKIDIALOG_LISTING_PAGES); } -void WikiDialog::loadLatestPages(const uint32_t &token) -{ - std::cerr << "WikiDialog::loadLatestPages()"; - std::cerr << std::endl; - - std::list msgIds; - if (rsWiki->getMsgList(token, msgIds)) - { - std::cerr << "WikiDialog::loadLatestPages() Loaded " << msgIds.size(); - std::cerr << std::endl; - } - else - { - std::cerr << "WikiDialog::loadLatestPages() ERROR No Data"; - std::cerr << std::endl; - return; - } - - /* request actual data */ - requestPages(msgIds); - -} - -void WikiDialog::requestPages(const std::list &msgIds) -{ - RsTokReqOptions opts; - uint32_t token; - mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIDIALOG_LISTING_PAGES); -} void WikiDialog::loadPages(const uint32_t &token) { - std::cerr << "WikiDialog::loadLatestPages()"; + std::cerr << "WikiDialog::loadPages()"; std::cerr << std::endl; /* find parent in GUI Tree - stick children */ QTreeWidgetItem *groupItem = NULL; - - bool moreData = true; - while(moreData) - { - RsWikiPage page; - if (rsWiki->getMsgData(token, page)) - { - if (!groupItem) - { - /* find the entry */ - int itemCount = ui.treeWidget_Pages->topLevelItemCount(); - for (int nIndex = 0; nIndex < itemCount;) - { - QTreeWidgetItem *tmpItem = ui.treeWidget_Pages->topLevelItem(nIndex); - std::string tmpid = tmpItem->data(WIKI_GROUP_COL_GROUPID, - Qt::DisplayRole).toString().toStdString(); - if (tmpid == page.mMeta.mGroupId) - { - groupItem = tmpItem; - break; - } - } - - if (!groupItem) - { - /* error */ - std::cerr << "WikiDialog::loadPages() ERROR Unable to find group"; - std::cerr << std::endl; - return; - } - } - - - std::cerr << "WikiDialog::loadPages() PageId: " << page.mMeta.mMsgId; - std::cerr << " Page: " << page.mMeta.mMsgName; - std::cerr << std::endl; - - QTreeWidgetItem *pageItem = new QTreeWidgetItem(); - pageItem->setText(WIKI_GROUP_COL_PAGENAME, QString::fromStdString(page.mMeta.mMsgName)); - pageItem->setText(WIKI_GROUP_COL_PAGEID, QString::fromStdString(page.mMeta.mMsgId)); - pageItem->setText(WIKI_GROUP_COL_ORIGPAGEID, QString::fromStdString(page.mMeta.mOrigMsgId)); - - groupItem->addChild(pageItem); - - } - else - { - moreData = false; - } - } - //return true; -} - - -/***** Mods *****/ - -void WikiDialog::insertModsForPage(const std::string &origPageId) -{ - requestModPageList(origPageId); -} - -void WikiDialog::requestModPageList(const std::string &origMsgId) -{ - RsTokReqOptions opts; - opts.mOptions = RS_TOKREQOPT_MSG_VERSIONS; - - std::list msgIds; - msgIds.push_back(origMsgId); - - uint32_t token; - mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_LIST, opts, msgIds, WIKIDIALOG_MOD_LIST); -} - - -void WikiDialog::loadModPageList(const uint32_t &token) -{ - std::cerr << "WikiDialog::loadModPages()"; - std::cerr << std::endl; - - /* translate into latest pages */ - std::list msgIds; - if (rsWiki->getMsgList(token, msgIds)) + std::vector snapshots; + std::vector::iterator vit; + if (!rsWiki->getSnapshots(token, snapshots)) { - std::cerr << "WikiDialog::loadModPageList() Loaded " << msgIds.size(); - std::cerr << std::endl; - } - else - { - std::cerr << "WikiDialog::loadModPageList() ERROR No Data"; - std::cerr << std::endl; + // ERROR return; } - requestModPages(msgIds); + for(vit = snapshots.begin(); vit != snapshots.end(); vit++) + { + RsWikiSnapshot page = *vit; + if (!groupItem) + { + /* find the entry */ + int itemCount = ui.treeWidget_Pages->topLevelItemCount(); + for (int nIndex = 0; nIndex < itemCount; nIndex++) + { + QTreeWidgetItem *tmpItem = ui.treeWidget_Pages->topLevelItem(nIndex); + std::string tmpid = tmpItem->data(WIKI_GROUP_COL_GROUPID, + Qt::DisplayRole).toString().toStdString(); + if (tmpid == page.mMeta.mGroupId) + { + groupItem = tmpItem; + break; + } + } + if (!groupItem) + { + /* error */ + std::cerr << "WikiDialog::loadPages() ERROR Unable to find group"; + std::cerr << std::endl; + return; + } + } + + + std::cerr << "WikiDialog::loadPages() PageId: " << page.mMeta.mMsgId; + std::cerr << " Page: " << page.mMeta.mMsgName; + std::cerr << std::endl; + + QTreeWidgetItem *pageItem = new QTreeWidgetItem(); + pageItem->setText(WIKI_GROUP_COL_PAGENAME, QString::fromStdString(page.mMeta.mMsgName)); + pageItem->setText(WIKI_GROUP_COL_PAGEID, QString::fromStdString(page.mMeta.mMsgId)); + pageItem->setText(WIKI_GROUP_COL_ORIGPAGEID, QString::fromStdString(page.mMeta.mOrigMsgId)); + + groupItem->addChild(pageItem); + } } -void WikiDialog::requestModPages(const std::list &msgIds) -{ - RsTokReqOptions opts; - - uint32_t token; - mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIDIALOG_MOD_PAGES); -} - - -void WikiDialog::loadModPages(const uint32_t &token) -{ - std::cerr << "WikiDialog::loadModPages()"; - std::cerr << std::endl; - - bool moreData = true; - while(moreData) - { - RsWikiPage page; - if (rsWiki->getMsgData(token, page)) - { - std::cerr << "WikiDialog::loadModPages() PageId: " << page.mMeta.mMsgId; - std::cerr << " Page: " << page.mMeta.mMsgName; - std::cerr << std::endl; - - QTreeWidgetItem *modItem = new QTreeWidgetItem(); - modItem->setText(WIKI_MODS_COL_ORIGPAGEID, QString::fromStdString(page.mMeta.mOrigMsgId)); - modItem->setText(WIKI_MODS_COL_PAGEID, QString::fromStdString(page.mMeta.mMsgId)); - ui.treeWidget_Mods->addTopLevelItem(modItem); - - } - else - { - moreData = false; - } - } -} - - - /***** Wiki *****/ - -void WikiDialog::requestWikiPage(const std::string &msgId) +void WikiDialog::requestWikiPage(const RsGxsGrpMsgIdPair &msgId) { - RsTokReqOptions opts; + std::cerr << "WikiDialog::requestWikiPage(" << msgId.first << "," << msgId.second << ")"; + std::cerr << std::endl; - std::list msgIds; - msgIds.push_back(msgId); + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; uint32_t token; - mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIDIALOG_WIKI_PAGE); + + GxsMsgReq msgIds; + std::vector &vect_msgIds = msgIds[msgId.first]; + vect_msgIds.push_back(msgId.second); + + mWikiQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIDIALOG_WIKI_PAGE); + + //mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIDIALOG_WIKI_PAGE); } void WikiDialog::loadWikiPage(const uint32_t &token) { - std::cerr << "WikiDialog::loadModPages()"; + std::cerr << "WikiDialog::loadWikiPage()"; std::cerr << std::endl; // Should only have one WikiPage.... - bool moreData = true; - while(moreData) - { - RsWikiPage page; - if (rsWiki->getMsgData(token, page)) - { - std::cerr << "WikiDialog::loadModPages() PageId: " << page.mMeta.mMsgId; - std::cerr << " Page: " << page.mMeta.mMsgName; - std::cerr << std::endl; + std::vector snapshots; + if (!rsWiki->getSnapshots(token, snapshots)) + { + std::cerr << "WikiDialog::loadWikiPage() ERROR"; + std::cerr << std::endl; - updateWikiPage(page); - } - else - { - moreData = false; - } - } + // ERROR + return; + } + + if (snapshots.size() != 1) + { + std::cerr << "WikiDialog::loadWikiPage() SIZE ERROR"; + std::cerr << std::endl; + + // ERROR + return; + } + + + RsWikiSnapshot page = snapshots[0]; + + std::cerr << "WikiDialog::loadWikiPage() PageId: " << page.mMeta.mMsgId; + std::cerr << " Page: " << page.mMeta.mMsgName; + std::cerr << std::endl; + + updateWikiPage(page); } @@ -843,40 +574,24 @@ void WikiDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) /* now switch on req */ switch(req.mUserType) { - case WIKIDIALOG_LISTING_GROUPLIST: - loadGroupList(req.mToken); - break; - case WIKIDIALOG_LISTING_GROUPDATA: loadGroupData(req.mToken); break; - case WIKIDIALOG_LISTING_ORIGINALPAGES: - loadOriginalPages(req.mToken); - break; - - case WIKIDIALOG_LISTING_LATESTPAGES: - loadLatestPages(req.mToken); - break; - case WIKIDIALOG_LISTING_PAGES: loadPages(req.mToken); break; - case WIKIDIALOG_MOD_LIST: - loadModPageList(req.mToken); - break; - - case WIKIDIALOG_MOD_PAGES: - loadModPages(req.mToken); - break; - case WIKIDIALOG_WIKI_PAGE: loadWikiPage(req.mToken); break; +#define GXSGROUP_NEWGROUPID 1 + case GXSGROUP_NEWGROUPID: + insertWikiGroups(); + break; default: - std::cerr << "PhotoDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << "WikiDialog::loadRequest() ERROR: INVALID TYPE"; std::cerr << std::endl; break; } diff --git a/retroshare-gui/src/gui/WikiPoos/WikiDialog.h b/retroshare-gui/src/gui/WikiPoos/WikiDialog.h index 664dba952..39fc80339 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiDialog.h +++ b/retroshare-gui/src/gui/WikiPoos/WikiDialog.h @@ -51,52 +51,39 @@ private slots: void OpenOrShowAddPageDialog(); void OpenOrShowAddGroupDialog(); void OpenOrShowEditDialog(); + void OpenOrShowRepublishDialog(); void groupTreeChanged(); - void modTreeChanged(); + + void newGroup(); + void showGroupDetails(); + void editGroupDetails(); + + void insertWikiGroups(); private: void clearWikiPage(); void clearGroupTree(); -void clearModsTree(); -void insertWikiGroups(); -void insertModsForPage(const std::string &origPageId); +void updateWikiPage(const RsWikiSnapshot &page); -void updateWikiPage(const RsWikiPage &page); - -bool getSelectedPage(std::string &pageId, std::string &origPageId); +bool getSelectedPage(std::string &groupId, std::string &pageId, std::string &origPageId); std::string getSelectedPage(); std::string getSelectedGroup(); -std::string getSelectedMod(); - - void requestGroupList(); -void loadGroupList(const uint32_t &token); -void requestGroupData(const std::list &groupIds); void loadGroupData(const uint32_t &token); -void requestOriginalPages(const std::list &groupIds); -void loadOriginalPages(const uint32_t &token); -void requestLatestPages(const std::list &msgIds); -void loadLatestPages(const uint32_t &token); -void requestPages(const std::list &msgIds); + +void requestPages(const std::list &groupIds); void loadPages(const uint32_t &token); - -void requestModPageList(const std::string &origMsgId); -void loadModPageList(const uint32_t &token); -void requestModPages(const std::list &msgIds); -void loadModPages(const uint32_t &token); - -void requestWikiPage(const std::string &msgId); +void requestWikiPage(const RsGxsGrpMsgIdPair &msgId); void loadWikiPage(const uint32_t &token); TokenQueue *mWikiQueue; - WikiAddDialog *mAddPageDialog; WikiAddDialog *mAddGroupDialog; WikiEditDialog *mEditDialog; diff --git a/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui b/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui index 433002c13..3db94846c 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui +++ b/retroshare-gui/src/gui/WikiPoos/WikiDialog.ui @@ -6,95 +6,145 @@ 0 0 - 774 - 608 + 764 + 514 - + - + Qt::Horizontal - - - Qt::Vertical - - - - true + + + + 0 - - - - 0 - 0 - 205 - 285 - - - - - - - - Wiki Group + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + 24 + 24 + - - - Page + + + + :/images/wikibook_32.png + + + true + + + + + + + + 10 + 75 + true + - - - Id + Wiki Pages - - - - - - - - - true - - - - - 0 - 0 - 205 - 284 - - - - - - + + + + - Page Modification + New Group - - - - By + + + :/images/resource-group-new.png:/images/resource-group-new.png - - - - - - + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + + + true + + + + + 0 + 0 + 268 + 456 + + + + + 0 + + + + + + Wiki Group + + + + + Page + + + + + Id + + + + + + + + + + + 0 + - + QFrame::StyledPanel @@ -102,6 +152,9 @@ QFrame::Raised + + 2 + @@ -110,6 +163,19 @@ << + + + :/images/arrow-left.png:/images/arrow-left.png + + + + 24 + 24 + + + + true + @@ -120,6 +186,19 @@ >> + + + :/images/arrow-right.png:/images/arrow-right.png + + + + 24 + 24 + + + + true + @@ -130,12 +209,25 @@ - - - false - + - << Mod + Republish + + + + :/images/republish.png:/images/republish.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true @@ -144,15 +236,21 @@ Edit - - - - - - false + + + :/images/story-editor.png:/images/story-editor.png - - Mod >> + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true @@ -163,30 +261,68 @@ - - - - New Group - - - New Page + + + :/images/appointment-new.png:/images/appointment-new.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + - false + true - Delete + Refresh + + + + :/images/republish.png:/images/republish.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -203,43 +339,37 @@ 0 0 - 528 - 511 + 465 + 456 QWidget#scrollAreaWidgetContents{border: none;} - - - 0 - - - 0 - + - + - + + + + 75 + true + + + + Search + + - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 0 - 0 - - - + + + + diff --git a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp index da95f920c..29bcb20e9 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp +++ b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.cpp @@ -21,11 +21,39 @@ * */ +#include +#include "gui/gxs/GxsIdTreeWidgetItem.h" #include "gui/WikiPoos/WikiEditDialog.h" #include +#define USE_PEGMMD_RENDERER 1 + +#ifdef USE_PEGMMD_RENDERER +#include "markdown_lib.h" +#endif + + +#define WIKIEDITDIALOG_GROUP 0x0001 +#define WIKIEDITDIALOG_PAGE 0x0002 +#define WIKIEDITDIALOG_BASEHISTORY 0x0003 +#define WIKIEDITDIALOG_EDITTREE 0x0004 + + +#define WET_COL_DATE 0 +#define WET_COL_AUTHORID 1 +#define WET_COL_PAGEID 2 + +#define WET_DATA_COLUMN 0 + +#define WET_ROLE_ORIGPAGEID Qt::UserRole +#define WET_ROLE_PAGEID Qt::UserRole + 1 +#define WET_ROLE_PARENTID Qt::UserRole + 2 + +#define WET_ROLE_SORT Qt::UserRole + 3 + + /** Constructor */ WikiEditDialog::WikiEditDialog(QWidget *parent) : QWidget(parent) @@ -35,38 +63,380 @@ WikiEditDialog::WikiEditDialog(QWidget *parent) connect(ui.pushButton_Cancel, SIGNAL( clicked( void ) ), this, SLOT( cancelEdit( void ) ) ); connect(ui.pushButton_Revert, SIGNAL( clicked( void ) ), this, SLOT( revertEdit( void ) ) ); connect(ui.pushButton_Submit, SIGNAL( clicked( void ) ), this, SLOT( submitEdit( void ) ) ); + connect(ui.pushButton_Preview, SIGNAL( clicked( void ) ), this, SLOT( previewToggle( void ) ) ); + connect(ui.pushButton_History, SIGNAL( clicked( void ) ), this, SLOT( historyToggle( void ) ) ); + connect(ui.toolButton_Show, SIGNAL( clicked( void ) ), this, SLOT( detailsToggle( void ) ) ); + connect(ui.toolButton_Hide, SIGNAL( clicked( void ) ), this, SLOT( detailsToggle( void ) ) ); + connect(ui.textEdit, SIGNAL( textChanged( void ) ), this, SLOT( textChanged( void ) ) ); + connect(ui.checkBox_OldHistory, SIGNAL( clicked( void ) ), this, SLOT( oldHistoryChanged( void ) ) ); + connect(ui.checkBox_Merge, SIGNAL( clicked( void ) ), this, SLOT( mergeModeToggle( void ) ) ); + connect(ui.pushButton_Merge, SIGNAL( clicked( void ) ), this, SLOT( generateMerge( void ) ) ); + connect(ui.treeWidget_History, SIGNAL( itemSelectionChanged( void ) ), this, SLOT( historySelected( void ) ) ); - mWikiQueue = new TokenQueue(rsWiki, this); + mWikiQueue = new TokenQueue(rsWiki->getTokenService(), this); + + mThreadCompareRole = new RSTreeWidgetItemCompareRole; + mThreadCompareRole->setRole(WET_COL_DATE, WET_ROLE_SORT); + + mRepublishMode = false; + mPreviewMode = false; + mPageLoading = false; + + mIgnoreTextChange = false; + mTextChanged = false; + mCurrentText = ""; + + mHistoryLoaded = false; + mHistoryMergeMode = false; + + ui.checkBox_OldHistory->setChecked(false); + mOldHistoryEnabled = false; + ui.groupBox_History->hide(); + detailsToggle(); } -void WikiEditDialog::setGroup(RsWikiGroup &group) +WikiEditDialog::~WikiEditDialog() { - mWikiGroup = group; + delete (mThreadCompareRole); +} - ui.lineEdit_Group->setText(QString::fromStdString(mWikiGroup.mMeta.mGroupName)); +void WikiEditDialog::mergeModeToggle() +{ + mHistoryMergeMode = ui.checkBox_Merge->isChecked(); + updateHistoryStatus(); +} + +void WikiEditDialog::generateMerge() +{ + std::cerr << "WikiEditDialog::generateMerge() TODO" << std::endl; + +} + +void WikiEditDialog::textChanged() +{ + if (mIgnoreTextChange) + { + std::cerr << "WikiEditDialog::textChanged() Ignored" << std::endl; + return; + } + std::cerr << "WikiEditDialog::textChanged()" << std::endl; + + mTextChanged = true; + ui.pushButton_Revert->setEnabled(true); + ui.pushButton_Submit->setEnabled(true); + ui.label_Status->setText("Modified"); + + // Disable Selection in Edit History. + ui.treeWidget_History->setSelectionMode(QAbstractItemView::NoSelection); + updateHistoryStatus(); + + // unselect anything. } -void WikiEditDialog::setPreviousPage(RsWikiPage &page) +void WikiEditDialog::textReset() { + std::cerr << "WikiEditDialog::textReset()" << std::endl; + + mTextChanged = false; + ui.pushButton_Revert->setEnabled(false); + ui.pushButton_Submit->setEnabled(false); + ui.label_Status->setText("Original"); + + // Enable Selection in Edit History. + ui.treeWidget_History->setSelectionMode(QAbstractItemView::SingleSelection); + updateHistoryStatus(); +} + +void WikiEditDialog::historySelected() +{ + std::cerr << "WikiEditDialog::historySelected()" << std::endl; + + QList selected = ui.treeWidget_History->selectedItems(); + if (selected.empty()) + { + std::cerr << "WikiEditDialog::historySelected() ERROR Nothing selected" << std::endl; + return; + } + QTreeWidgetItem *item = *(selected.begin()); + + RsGxsGrpMsgIdPair newSnapshot = mThreadMsgIdPair; + std::string pageId = item->data(WET_DATA_COLUMN, WET_ROLE_PAGEID).toString().toStdString(); + newSnapshot.second = pageId; + + std::cerr << "WikiEditDialog::historySelected() New PageId: " << pageId; + std::cerr << std::endl; + + requestPage(newSnapshot); +} + + +void WikiEditDialog::oldHistoryChanged() +{ + mOldHistoryEnabled = ui.checkBox_OldHistory->isChecked(); + updateHistoryStatus(); +} + + +void WikiEditDialog::updateHistoryStatus() +{ + std::cerr << "WikiEditDialog::updateHistoryStatus()"; + std::cerr << std::endl; + + /* iterate through every History Item */ + int count = ui.treeWidget_History->topLevelItemCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *item = ui.treeWidget_History->topLevelItem(i); + bool isLatest = (i==count-1); + updateHistoryChildren(item, isLatest); + updateHistoryItem(item, isLatest); + } +} + +void WikiEditDialog::updateHistoryChildren(QTreeWidgetItem *item, bool isLatest) +{ + int count = item->childCount(); + for(int i = 0; i < count; i++) + { + QTreeWidgetItem *child = item->child(i); + + if (child->childCount() > 0) + { + updateHistoryChildren(child, isLatest); + } + updateHistoryItem(child, isLatest); + } +} + + +void WikiEditDialog::updateHistoryItem(QTreeWidgetItem *item, bool isLatest) +{ + bool isSelectable = true; + if (mTextChanged) + { + isSelectable = false; + } + else if ((!mOldHistoryEnabled) && (!isLatest)) + { + isSelectable = false; + } + + if (isSelectable) + { + std::cerr << "WikiEditDialog::updateHistoryItem() isSelectable"; + std::cerr << std::endl; + + item->setFlags(Qt::ItemIsSelectable | + Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + + if (mHistoryMergeMode) + { + QVariant qvar = item->data(WET_COL_PAGEID, Qt::CheckStateRole); + std::cerr << "WikiEditDialog::CheckStateRole:: VariantType: " << (int) qvar.type(); + std::cerr << std::endl; + if (!qvar.isValid()) + { + item->setData(WET_COL_PAGEID, Qt::CheckStateRole, Qt::Unchecked); + } + + } + else + { + item->setData(WET_COL_PAGEID, Qt::CheckStateRole, QVariant()); + } + } + else + { + std::cerr << "WikiEditDialog::updateHistoryItem() NOT isSelectable"; + std::cerr << std::endl; + + item->setData(WET_COL_PAGEID, Qt::CheckStateRole, QVariant()); + item->setFlags(Qt::ItemIsUserCheckable); + } +} + +void WikiEditDialog::detailsToggle() +{ + std::cerr << "WikiEditDialog::detailsToggle()"; + std::cerr << std::endl; + if (ui.toolButton_Hide->isHidden()) + { + ui.toolButton_Hide->show(); + ui.toolButton_Show->hide(); + + ui.label_PrevVersion->show(); + ui.label_Group->show(); + ui.label_Tags->show(); + ui.lineEdit_PrevVersion->show(); + ui.lineEdit_Group->show(); + ui.lineEdit_Tags->show(); + } + else + { + ui.toolButton_Hide->hide(); + ui.toolButton_Show->show(); + + ui.label_PrevVersion->hide(); + ui.label_Group->hide(); + ui.label_Tags->hide(); + ui.lineEdit_PrevVersion->hide(); + ui.lineEdit_Group->hide(); + ui.lineEdit_Tags->hide(); + } +} + +void WikiEditDialog::historyToggle() +{ + std::cerr << "WikiEditDialog::historyToggle()"; + std::cerr << std::endl; + if (ui.groupBox_History->isHidden()) + { + ui.groupBox_History->show(); + ui.pushButton_History->setText(tr("Hide Edit History")); + } + else + { + ui.groupBox_History->hide(); + ui.pushButton_History->setText(tr("Show Edit History")); + } +} + + +void WikiEditDialog::previewToggle() +{ + std::cerr << "WikiEditDialog::previewToggle()"; + std::cerr << std::endl; + + if (mPreviewMode) + { + mPreviewMode = false; + ui.pushButton_Preview->setText(tr("Preview")); + } + else + { + // Save existing Text into buffer. + mCurrentText = ui.textEdit->toPlainText(); + mPreviewMode = true; + ui.pushButton_Preview->setText(tr("Edit Page")); + } + + + mIgnoreTextChange = true; + redrawPage(); + mIgnoreTextChange = false; + + std::cerr << "WikiEditDialog::previewToggle() END"; + std::cerr << std::endl; +} + + +void WikiEditDialog::redrawPage() +{ + std::cerr << "WikiEditDialog::redrawPage()"; + std::cerr << std::endl; + + if (mPreviewMode) + { +#ifdef USE_PEGMMD_RENDERER + /* render as HTML */ + QByteArray byte_array = mCurrentText.toUtf8(); + + int extensions = 0; + char *answer = markdown_to_string(byte_array.data(), extensions, HTML_FORMAT); + + QString renderedText = QString::fromUtf8(answer); + ui.textEdit->setHtml(renderedText); + + // free answer. + free(answer); +#else + /* render as HTML */ + QString renderedText = "IN (dummy) RENDERED TEXT MODE:\n"; + renderedText += mCurrentText; + ui.textEdit->setPlainText(renderedText); +#endif + + + /* disable edit */ + ui.textEdit->setReadOnly(true); + } + else + { + /* plain text - for editing */ + ui.textEdit->setPlainText(mCurrentText); + + /* enable edit */ + ui.textEdit->setReadOnly(false); + } +} + + +void WikiEditDialog::setGroup(RsWikiCollection &group) +{ + std::cerr << "WikiEditDialog::setGroup(): " << group; + std::cerr << std::endl; + + mWikiCollection = group; + + ui.lineEdit_Group->setText(QString::fromStdString(mWikiCollection.mMeta.mGroupName)); +} + + +void WikiEditDialog::setPreviousPage(RsWikiSnapshot &page) +{ + std::cerr << "WikiEditDialog::setPreviousPage(): " << page; + std::cerr << std::endl; + mNewPage = false; - mWikiPage = page; + mWikiSnapshot = page; - ui.lineEdit_Page->setText(QString::fromStdString(mWikiPage.mMeta.mMsgName)); - ui.lineEdit_PrevVersion->setText(QString::fromStdString(mWikiPage.mMeta.mMsgId)); - ui.textEdit->setPlainText(QString::fromStdString(mWikiPage.mPage)); + ui.lineEdit_Page->setText(QString::fromStdString(mWikiSnapshot.mMeta.mMsgName)); + ui.lineEdit_PrevVersion->setText(QString::fromStdString(mWikiSnapshot.mMeta.mMsgId)); + mCurrentText = QString::fromUtf8(mWikiSnapshot.mPage.c_str()); + + mIgnoreTextChange = true; + redrawPage(); + mIgnoreTextChange = false; + + textReset(); } void WikiEditDialog::setNewPage() { mNewPage = true; + mRepublishMode = false; + mHistoryLoaded = false; ui.lineEdit_Page->setText(""); ui.lineEdit_PrevVersion->setText(""); - ui.textEdit->setPlainText(""); + + mCurrentText = ""; + redrawPage(); + ui.treeWidget_History->clear(); + ui.groupBox_History->hide(); + ui.pushButton_History->setText(tr("Show Edit History")); + + ui.headerFrame->setHeaderImage(QPixmap(":/images/appointment-new_64.png")); + ui.headerFrame->setHeaderText(tr("Create New Wiki Page")); + setWindowTitle(tr("Create New Wiki Page")); + + /* fill in the available OwnIds for signing */ + ui.comboBox_IdChooser->loadIds(IDCHOOSER_ID_REQUIRED, ""); + + textReset(); } +void WikiEditDialog::setRepublishMode(RsGxsMessageId &origMsgId) +{ + mRepublishMode = true; + mRepublishOrigId = origMsgId; + ui.pushButton_Submit->setText(tr("Republish")); +} + + + void WikiEditDialog::cancelEdit() { hide(); @@ -77,41 +447,129 @@ void WikiEditDialog::revertEdit() { if (mNewPage) { - ui.textEdit->setPlainText(""); + mCurrentText = ""; } else { - ui.textEdit->setPlainText(QString::fromStdString(mWikiPage.mPage)); + ui.textEdit->setPlainText(QString::fromStdString(mWikiSnapshot.mPage)); + mCurrentText = QString::fromUtf8(mWikiSnapshot.mPage.c_str()); } + redrawPage(); + textReset(); } void WikiEditDialog::submitEdit() { + std::cerr << "WikiEditDialog::submitEdit()"; + std::cerr << std::endl; + if (mNewPage) { - mWikiPage.mMeta.mGroupId = mWikiGroup.mMeta.mGroupId; - mWikiPage.mMeta.mOrigMsgId = ""; - mWikiPage.mMeta.mMsgId = ""; - mWikiPage.mPrevId = ""; + mWikiSnapshot.mMeta.mGroupId = mWikiCollection.mMeta.mGroupId; + mWikiSnapshot.mMeta.mOrigMsgId = ""; + mWikiSnapshot.mMeta.mMsgId = ""; +#if 0 + mWikiSnapshot.mPrevId = ""; +#endif + std::cerr << "WikiEditDialog::submitEdit() Is New Page"; + std::cerr << std::endl; + } + else if (mRepublishMode) + { + std::cerr << "WikiEditDialog::submitEdit() In Republish Mode"; + std::cerr << std::endl; + // A New Version of the ThreadHead. + mWikiSnapshot.mMeta.mGroupId = mWikiCollection.mMeta.mGroupId; + mWikiSnapshot.mMeta.mOrigMsgId = mRepublishOrigId; + mWikiSnapshot.mMeta.mParentId = ""; + mWikiSnapshot.mMeta.mThreadId = ""; + mWikiSnapshot.mMeta.mMsgId = ""; } else { - mWikiPage.mPrevId = mWikiPage.mMeta.mMsgId; - mWikiPage.mMeta.mMsgId = ""; + std::cerr << "WikiEditDialog::submitEdit() In Child Edit Mode"; + std::cerr << std::endl; + + // A Child of the current message. + bool isFirstChild = false; + if (mWikiSnapshot.mMeta.mParentId == "") + { + isFirstChild = true; + } + + mWikiSnapshot.mMeta.mGroupId = mWikiCollection.mMeta.mGroupId; + + if (isFirstChild) + { + mWikiSnapshot.mMeta.mThreadId = mWikiSnapshot.mMeta.mOrigMsgId; + // Special HACK here... parentId points to specific Msg, rather than OrigMsgId. + // This allows versioning to work well. + mWikiSnapshot.mMeta.mParentId = mWikiSnapshot.mMeta.mMsgId; + } + else + { + // ThreadId is the same. + mWikiSnapshot.mMeta.mParentId = mWikiSnapshot.mMeta.mOrigMsgId; + } + + mWikiSnapshot.mMeta.mMsgId = ""; + mWikiSnapshot.mMeta.mOrigMsgId = ""; } - mWikiPage.mMeta.mMsgName = ui.lineEdit_Page->text().toStdString(); - mWikiPage.mPage = ui.textEdit->toPlainText().toStdString(); + + mWikiSnapshot.mMeta.mMsgName = ui.lineEdit_Page->text().toStdString(); + + if (!mPreviewMode) + { + /* can just use the current text */ + mCurrentText = ui.textEdit->toPlainText(); + } + + { + // complicated way of preserving Utf8 text */ + QByteArray byte_array = mCurrentText.toUtf8(); + mWikiSnapshot.mPage = std::string(byte_array.data()); + } + + RsGxsId authorId; + if (ui.comboBox_IdChooser->getChosenId(authorId)) + { + mWikiSnapshot.mMeta.mAuthorId = authorId; + std::cerr << "CreateGxsForumMsg::createMsg() AuthorId: " << authorId; + std::cerr << std::endl; + } + else + { + std::cerr << "CreateGxsForumMsg::createMsg() ERROR GETTING AuthorId!"; + std::cerr << std::endl; + } + + std::cerr << "WikiEditDialog::submitEdit() PageTitle: " << mWikiSnapshot.mMeta.mMsgName; + std::cerr << std::endl; + std::cerr << "WikiEditDialog::submitEdit() GroupId: " << mWikiSnapshot.mMeta.mGroupId; + std::cerr << std::endl; + std::cerr << "WikiEditDialog::submitEdit() OrigMsgId: " << mWikiSnapshot.mMeta.mOrigMsgId; + std::cerr << std::endl; + std::cerr << "WikiEditDialog::submitEdit() MsgId: " << mWikiSnapshot.mMeta.mMsgId; + std::cerr << std::endl; + std::cerr << "WikiEditDialog::submitEdit() ThreadId: " << mWikiSnapshot.mMeta.mThreadId; + std::cerr << std::endl; + std::cerr << "WikiEditDialog::submitEdit() ParentId: " << mWikiSnapshot.mMeta.mParentId; + std::cerr << "WikiEditDialog::submitEdit() AuthorId: " << mWikiSnapshot.mMeta.mAuthorId; + std::cerr << std::endl; uint32_t token; - bool isNew = mNewPage; - rsWiki->createPage(token, mWikiPage, isNew); + //bool isNew = mNewPage; + //rsWiki->createPage(token, mWikiSnapshot, isNew); + rsWiki->submitSnapshot(token, mWikiSnapshot); hide(); } void WikiEditDialog::setupData(const std::string &groupId, const std::string &pageId) { + mRepublishMode = false; + mHistoryLoaded = false; if (groupId != "") { requestGroup(groupId); @@ -119,8 +577,17 @@ void WikiEditDialog::setupData(const std::string &groupId, const std::string &pa if (pageId != "") { - requestPage(pageId); + RsGxsGrpMsgIdPair msgId = std::make_pair(groupId, pageId); + requestPage(msgId); } + + ui.headerFrame->setHeaderImage(QPixmap(":/images/story-editor_48.png")); + ui.headerFrame->setHeaderText(tr("Edit Wiki Page")); + setWindowTitle(tr("Edit Wiki Page")); + + /* fill in the available OwnIds for signing */ + ui.comboBox_IdChooser->loadIds(IDCHOOSER_ID_REQUIRED, ""); + } @@ -135,8 +602,9 @@ void WikiEditDialog::requestGroup(const std::string &groupId) ids.push_back(groupId); RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token; - mWikiQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, 0); + mWikiQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, WIKIEDITDIALOG_GROUP); } void WikiEditDialog::loadGroup(const uint32_t &token) @@ -144,24 +612,34 @@ void WikiEditDialog::loadGroup(const uint32_t &token) std::cerr << "WikiEditDialog::loadGroup()"; std::cerr << std::endl; - RsWikiGroup group; - if (rsWiki->getGroupData(token, group)) + std::vector groups; + if (rsWiki->getCollections(token, groups)) { - setGroup(group); + if (groups.size() != 1) + { + std::cerr << "WikiEditDialog::loadGroup() ERROR No group data"; + std::cerr << std::endl; + return; + } + setGroup(groups[0]); } } -void WikiEditDialog::requestPage(const std::string &msgId) +void WikiEditDialog::requestPage(const RsGxsGrpMsgIdPair &msgId) { - std::cerr << "WikiEditDialog::requestGroup()"; + std::cerr << "WikiEditDialog::requestPage()"; std::cerr << std::endl; - std::list ids; - ids.push_back(msgId); RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + + GxsMsgReq msgIds; + std::vector &vect_msgIds = msgIds[msgId.first]; + vect_msgIds.push_back(msgId.second); uint32_t token; - mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, ids, 0); + mWikiQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIEDITDIALOG_PAGE); + mPageLoading = true; } void WikiEditDialog::loadPage(const uint32_t &token) @@ -169,13 +647,256 @@ void WikiEditDialog::loadPage(const uint32_t &token) std::cerr << "WikiEditDialog::loadPage()"; std::cerr << std::endl; - RsWikiPage page; - if (rsWiki->getMsgData(token, page)) + std::vector snapshots; + + if (rsWiki->getSnapshots(token, snapshots)) { + if (snapshots.size() != 1) + { + std::cerr << "WikiEditDialog::loadGroup() ERROR No group data"; + std::cerr << std::endl; + return; + } + + RsWikiSnapshot &page = snapshots[0]; setPreviousPage(page); + + /* request the history now */ + mThreadMsgIdPair.first = page.mMeta.mGroupId; + if (page.mMeta.mThreadId.empty()) + { + mThreadMsgIdPair.second = page.mMeta.mOrigMsgId; + } + else + { + mThreadMsgIdPair.second = page.mMeta.mThreadId; + } + if (!mHistoryLoaded) + { + requestBaseHistory(mThreadMsgIdPair); + } } + mPageLoading = false; } + +/*********************** LOAD EDIT HISTORY **********************/ + +void WikiEditDialog::requestBaseHistory(const RsGxsGrpMsgIdPair &origMsgId) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_VERSIONS; + std::vector msgIds; + msgIds.push_back(origMsgId); + uint32_t token; + mWikiQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, WIKIEDITDIALOG_BASEHISTORY); + ui.treeWidget_History->clear(); +} + +void WikiEditDialog::loadBaseHistory(const uint32_t &token) +{ + std::cerr << "WikiEditDialog::loadBaseHistory()"; + std::cerr << std::endl; + + + std::vector snapshots; + std::vector::iterator vit; + if (!rsWiki->getRelatedSnapshots(token, snapshots)) + { + // ERROR + std::cerr << "WikiEditDialog::loadBaseHistory() ERROR"; + std::cerr << std::endl; + return; + } + + for(vit = snapshots.begin(); vit != snapshots.end(); vit++) + { + RsWikiSnapshot &page = *vit; + + std::cerr << "WikiEditDialog::loadBaseHistory() TopLevel Result: PageTitle: " << page.mMeta.mMsgName; + std::cerr << " GroupId: " << page.mMeta.mGroupId; + std::cerr << std::endl; + std::cerr << "\tOrigMsgId: " << page.mMeta.mOrigMsgId; + std::cerr << " MsgId: " << page.mMeta.mMsgId; + std::cerr << std::endl; + std::cerr << "\tThreadId: " << page.mMeta.mThreadId; + std::cerr << " ParentId: " << page.mMeta.mParentId; + std::cerr << std::endl; + + GxsIdTreeWidgetItem *modItem = new GxsIdTreeWidgetItem(mThreadCompareRole); + modItem->setData(WET_DATA_COLUMN, WET_ROLE_ORIGPAGEID, QString::fromStdString(page.mMeta.mOrigMsgId)); + modItem->setData(WET_DATA_COLUMN, WET_ROLE_PAGEID, QString::fromStdString(page.mMeta.mMsgId)); + + modItem->setData(WET_DATA_COLUMN, WET_ROLE_PARENTID, QString::fromStdString(page.mMeta.mParentId)); + + { + // From Forum stuff. + QDateTime qtime; + QString text; + QString sort; + qtime.setTime_t(page.mMeta.mPublishTs); + sort = qtime.toString("yyyyMMdd_hhmmss"); + text = qtime.toString("dd/MM/yy hh:mm"); + + modItem->setText(WET_COL_DATE, text); + modItem->setData(WET_COL_DATE, WET_ROLE_SORT, sort); + } + modItem->setId(page.mMeta.mAuthorId, WET_COL_AUTHORID); + modItem->setText(WET_COL_PAGEID, QString::fromStdString(page.mMeta.mMsgId)); + + ui.treeWidget_History->addTopLevelItem(modItem); + } + + /* then we need to request all pages from this thread */ + requestEditTreeData(); +} + + +void WikiEditDialog::requestEditTreeData() //const RsGxsGroupId &groupId) +{ + // SWITCH THIS TO A THREAD REQUEST - WHEN WE CAN! + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + + std::list groupIds; + groupIds.push_back(mThreadMsgIdPair.first); + + uint32_t token; + mWikiQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, WIKIEDITDIALOG_EDITTREE); +} + + +void WikiEditDialog::loadEditTreeData(const uint32_t &token) +{ + std::cerr << "WikiEditDialog::loadEditTreeData()"; + std::cerr << std::endl; + + + std::vector snapshots; + std::vector::iterator vit; + if (!rsWiki->getSnapshots(token, snapshots)) + { + // ERROR + std::cerr << "WikiEditDialog::loadEditTreeData() ERROR"; + std::cerr << std::endl; + return; + } + + std::cerr << "WikiEditDialog::loadEditTreeData() Loaded " << snapshots.size(); + std::cerr << std::endl; + std::cerr << "WikiEditDialog::loadEditTreeData() Using ThreadId: " << mThreadMsgIdPair.second; + std::cerr << std::endl; + + + std::map items; + std::map::iterator iit; + std::list unparented; + std::list::iterator uit; + + // Grab the existing TopLevelItems, and insert into map. + int itemCount = ui.treeWidget_History->topLevelItemCount(); + for (int nIndex = 0; nIndex < itemCount; nIndex++) + { + QTreeWidgetItem *item = ui.treeWidget_History->topLevelItem(nIndex); + + /* index by MsgId --> ONLY For Wiki Thread Head Items... SPECIAL HACK FOR HERE! */ + std::string msgId = item->data(WET_DATA_COLUMN, WET_ROLE_PAGEID).toString().toStdString(); + items[msgId] = item; + } + + + for(vit = snapshots.begin(); vit != snapshots.end(); vit++) + { + RsWikiSnapshot &snapshot = *vit; + + std::cerr << "Result: PageTitle: " << snapshot.mMeta.mMsgName; + std::cerr << " GroupId: " << snapshot.mMeta.mGroupId; + std::cerr << std::endl; + std::cerr << "\tOrigMsgId: " << snapshot.mMeta.mOrigMsgId; + std::cerr << " MsgId: " << snapshot.mMeta.mMsgId; + std::cerr << std::endl; + std::cerr << "\tThreadId: " << snapshot.mMeta.mThreadId; + std::cerr << " ParentId: " << snapshot.mMeta.mParentId; + std::cerr << std::endl; + + if (snapshot.mMeta.mParentId == "") + { + /* Ignore! */ + std::cerr << "Ignoring ThreadHead Item"; + std::cerr << std::endl; + continue; + } + + if (snapshot.mMeta.mThreadId != mThreadMsgIdPair.second) + { + /* Ignore! */ + std::cerr << "Ignoring Different Thread Item"; + std::cerr << std::endl; + continue; + } + + /* create an Entry */ + GxsIdTreeWidgetItem *modItem = new GxsIdTreeWidgetItem(mThreadCompareRole); + modItem->setData(WET_DATA_COLUMN, WET_ROLE_ORIGPAGEID, QString::fromStdString(snapshot.mMeta.mOrigMsgId)); + modItem->setData(WET_DATA_COLUMN, WET_ROLE_PAGEID, QString::fromStdString(snapshot.mMeta.mMsgId)); + modItem->setData(WET_DATA_COLUMN, WET_ROLE_PARENTID, QString::fromStdString(snapshot.mMeta.mParentId)); + + { + // From Forum stuff. + QDateTime qtime; + QString text; + QString sort; + qtime.setTime_t(snapshot.mMeta.mPublishTs); + sort = qtime.toString("yyyyMMdd_hhmmss"); + text = qtime.toString("dd/MM/yy hh:mm"); + + modItem->setText(WET_COL_DATE, text); + modItem->setData(WET_COL_DATE, WET_ROLE_SORT, sort); + } + modItem->setId(snapshot.mMeta.mAuthorId, WET_COL_AUTHORID); + modItem->setText(WET_COL_PAGEID, QString::fromStdString(snapshot.mMeta.mMsgId)); + + /* find the parent */ + iit = items.find(snapshot.mMeta.mParentId); + if (iit != items.end()) + { + (iit->second)->addChild(modItem); + } + else + { + unparented.push_back(modItem); + } + items[snapshot.mMeta.mOrigMsgId] = modItem; + } + + for(uit = unparented.begin(); uit != unparented.end(); uit++) + { + std::string parentId = (*uit)->data(WET_DATA_COLUMN, WET_ROLE_PARENTID).toString().toStdString(); + + + iit = items.find(parentId); + if (iit != items.end()) + { + (iit->second)->addChild(*uit); + } + else + { + /* ERROR */ + std::cerr << "Unparented!!!"; + std::cerr << std::endl; + } + } + + // Enable / Disable Items. + mHistoryLoaded = true; + updateHistoryStatus(); +} + + + void WikiEditDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) { std::cerr << "WikiEditDialog::loadRequest()"; @@ -183,19 +904,27 @@ void WikiEditDialog::loadRequest(const TokenQueue *queue, const TokenRequest &re if (queue == mWikiQueue) { - /* now switch on req */ - switch(req.mType) + switch(req.mUserType) { - case TOKENREQ_GROUPINFO: - loadGroup(req.mToken); + case WIKIEDITDIALOG_GROUP: + loadGroup(req.mToken); + break; + + case WIKIEDITDIALOG_PAGE: + loadPage(req.mToken); + break; + + case WIKIEDITDIALOG_BASEHISTORY: + loadBaseHistory(req.mToken); + break; + + case WIKIEDITDIALOG_EDITTREE: + loadEditTreeData(req.mToken); + break; + default: + std::cerr << "WikiEditDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; break; - case TOKENREQ_MSGRELATEDINFO: - loadPage(req.mToken); - break; - default: - std::cerr << "WikiEditDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; } } } @@ -203,3 +932,7 @@ void WikiEditDialog::loadRequest(const TokenQueue *queue, const TokenRequest &re + + + + diff --git a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.h b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.h index 631f83c5e..0898d285d 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.h +++ b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.h @@ -29,40 +29,86 @@ #include #include "util/TokenQueue.h" +class RSTreeWidgetItemCompareRole; + class WikiEditDialog : public QWidget, public TokenResponse { Q_OBJECT public: WikiEditDialog(QWidget *parent = 0); + ~WikiEditDialog(); void setNewPage(); void setupData(const std::string &groupId, const std::string &pageId); void loadRequest(const TokenQueue *queue, const TokenRequest &req); +void setRepublishMode(RsGxsMessageId &origMsgId); + private slots: void cancelEdit(); void revertEdit(); void submitEdit(); +void previewToggle(); +void historyToggle(); +void detailsToggle(); +void textChanged(); +void textReset(); + +void historySelected(); +void oldHistoryChanged(); +void mergeModeToggle(); +void generateMerge(); private: -void setGroup(RsWikiGroup &group); -void setPreviousPage(RsWikiPage &page); +void updateHistoryStatus(); +void updateHistoryChildren(QTreeWidgetItem *item, bool isLatest); +void updateHistoryItem(QTreeWidgetItem *item, bool isLatest); -void requestPage(const std::string &msgId); +void redrawPage(); + +void setGroup(RsWikiCollection &group); +void setPreviousPage(RsWikiSnapshot &page); + +void requestPage(const RsGxsGrpMsgIdPair &msgId); void loadPage(const uint32_t &token); void requestGroup(const std::string &groupId); void loadGroup(const uint32_t &token); +void requestBaseHistory(const RsGxsGrpMsgIdPair &origMsgId); +void loadBaseHistory(const uint32_t &token); +void requestEditTreeData(); +void loadEditTreeData(const uint32_t &token); + + + bool mNewPage; - RsWikiGroup mWikiGroup; - RsWikiPage mWikiPage; + + bool mPreviewMode; + bool mPageLoading; + bool mHistoryLoaded; + bool mHistoryMergeMode; + bool mOldHistoryEnabled; + + bool mRepublishMode; + bool mIgnoreTextChange; // when we do it programmatically. + bool mTextChanged; + + QString mCurrentText; + + RsGxsGrpMsgIdPair mThreadMsgIdPair; + RsGxsMessageId mRepublishOrigId; + + RsWikiCollection mWikiCollection; + RsWikiSnapshot mWikiSnapshot; Ui::WikiEditDialog ui; + RSTreeWidgetItemCompareRole *mThreadCompareRole; + TokenQueue *mWikiQueue; }; diff --git a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui index 5e8df9a33..698ff4ee3 100644 --- a/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui +++ b/retroshare-gui/src/gui/WikiPoos/WikiEditDialog.ui @@ -6,163 +6,345 @@ 0 0 - 647 - 618 + 946 + 568 - - - - - Wiki Page + + + 0 + + + 0 + + + + + QFrame::StyledPanel - - - - - Wiki Group: + + QFrame::Raised + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + - - groupBox - - - - - - - true - - - - - Qt::Horizontal - - - 168 - 20 - - - - - - - - Page Name: - - - - - - - - 10 - 0 - - - - - - - - Edit ID - - - - - - - - - - Previous Version - - - - - - - - 10 - 0 - - - - true - - - - - - - Prev ID - - - - - - - - 1 - 0 - - - - true - + + + Page Edit History + + + + + + Enable Obsolete Edits + + + + + + + Chose for Merge + + + + + + + false + + + Merge for Republish (TODO) + + + + + + + + Publish Date + + + + + By + + + + + PageId + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + \/ + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 10 + 0 + + + + + + + + /\ + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + + + Wiki Group: + + + frame + + + + + + + true + + + + + + + Page Name: + + + + + + + + 10 + 0 + + + + + + + + Previous Version + + + + + + + + 10 + 0 + + + + true + + + + + + + Tags + + + + + + + + 10 + 0 + + + + + + + true + + + + + + + + + + + + + + Show Edit History + + + + + + + Qt::Horizontal + + + + 178 + 20 + + + + + + + + + + + Status + + + + + + + Preview + + + + + + + + + + + + + + Cancel + + + + + + + Revert + + + + + + + Qt::Horizontal + + + + 228 + 20 + + + + + + + + Submit + + + + + + + - - - - - - - - - Cancel - - - - - - - Revert - - - - - - - Qt::Horizontal - - - - 228 - 20 - - - - - - - - Submit - - - - - + + + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1 +
+ + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
+
+
diff --git a/retroshare-gui/src/gui/WikiPoos/Wiki_images.qrc b/retroshare-gui/src/gui/WikiPoos/Wiki_images.qrc index 3ab091103..1ea8313ef 100644 --- a/retroshare-gui/src/gui/WikiPoos/Wiki_images.qrc +++ b/retroshare-gui/src/gui/WikiPoos/Wiki_images.qrc @@ -1,5 +1,16 @@ - images/dummy.png + images/arrow-left.png + images/arrow-right.png + images/resource-group-new.png + images/appointment-new.png + images/book2_32.png + images/story-editor.png + images/story-editor_48.png + images/republish.png + images/resource-group-new_48.png + images/wikibook_32.png + images/resource-group_64.png + images/appointment-new_64.png diff --git a/retroshare-gui/src/gui/WikiPoos/images/appointment-new.png b/retroshare-gui/src/gui/WikiPoos/images/appointment-new.png new file mode 100644 index 000000000..aa5207585 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/appointment-new.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/appointment-new_64.png b/retroshare-gui/src/gui/WikiPoos/images/appointment-new_64.png new file mode 100644 index 000000000..7b99cd877 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/appointment-new_64.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/arrow-left-double.png b/retroshare-gui/src/gui/WikiPoos/images/arrow-left-double.png new file mode 100644 index 000000000..b5f026336 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/arrow-left-double.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/arrow-left.png b/retroshare-gui/src/gui/WikiPoos/images/arrow-left.png new file mode 100644 index 000000000..befac61d1 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/arrow-left.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/arrow-right-double.png b/retroshare-gui/src/gui/WikiPoos/images/arrow-right-double.png new file mode 100644 index 000000000..082ba7135 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/arrow-right-double.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/arrow-right.png b/retroshare-gui/src/gui/WikiPoos/images/arrow-right.png new file mode 100644 index 000000000..a8267ff09 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/arrow-right.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/book2_128.png b/retroshare-gui/src/gui/WikiPoos/images/book2_128.png new file mode 100644 index 000000000..d612516f2 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/book2_128.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/book2_16.png b/retroshare-gui/src/gui/WikiPoos/images/book2_16.png new file mode 100644 index 000000000..b6c943717 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/book2_16.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/book2_32.png b/retroshare-gui/src/gui/WikiPoos/images/book2_32.png new file mode 100644 index 000000000..2f2432548 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/book2_32.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/book2_48.png b/retroshare-gui/src/gui/WikiPoos/images/book2_48.png new file mode 100644 index 000000000..a0ff7814d Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/book2_48.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/book2_64.png b/retroshare-gui/src/gui/WikiPoos/images/book2_64.png new file mode 100644 index 000000000..ac460f5fd Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/book2_64.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/republish.png b/retroshare-gui/src/gui/WikiPoos/images/republish.png new file mode 100644 index 000000000..afa2a9d77 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/republish.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/resource-group-new.png b/retroshare-gui/src/gui/WikiPoos/images/resource-group-new.png new file mode 100644 index 000000000..cd5ea5f14 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/resource-group-new.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/resource-group-new_48.png b/retroshare-gui/src/gui/WikiPoos/images/resource-group-new_48.png new file mode 100644 index 000000000..ae785fc54 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/resource-group-new_48.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/resource-group.png b/retroshare-gui/src/gui/WikiPoos/images/resource-group.png new file mode 100644 index 000000000..2b37baddd Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/resource-group.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/resource-group_64.png b/retroshare-gui/src/gui/WikiPoos/images/resource-group_64.png new file mode 100644 index 000000000..84cfa89fa Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/resource-group_64.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/story-editor.png b/retroshare-gui/src/gui/WikiPoos/images/story-editor.png new file mode 100644 index 000000000..296e08797 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/story-editor.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/story-editor_48.png b/retroshare-gui/src/gui/WikiPoos/images/story-editor_48.png new file mode 100644 index 000000000..18e300d2e Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/story-editor_48.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/view-refresh.png b/retroshare-gui/src/gui/WikiPoos/images/view-refresh.png new file mode 100644 index 000000000..afa2a9d77 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/view-refresh.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/wikibook_128.png b/retroshare-gui/src/gui/WikiPoos/images/wikibook_128.png new file mode 100644 index 000000000..2c879d444 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/wikibook_128.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/wikibook_32.png b/retroshare-gui/src/gui/WikiPoos/images/wikibook_32.png new file mode 100644 index 000000000..a443e7021 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/wikibook_32.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/wikibook_48.png b/retroshare-gui/src/gui/WikiPoos/images/wikibook_48.png new file mode 100644 index 000000000..4c7d37d88 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/wikibook_48.png differ diff --git a/retroshare-gui/src/gui/WikiPoos/images/wikibook_64.png b/retroshare-gui/src/gui/WikiPoos/images/wikibook_64.png new file mode 100644 index 000000000..4a98cada7 Binary files /dev/null and b/retroshare-gui/src/gui/WikiPoos/images/wikibook_64.png differ diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp index 3b82e1041..a85a67dd5 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp @@ -37,12 +37,13 @@ #define COLUMN_COUNT 2 #define COLUMN_DATA COLUMN_NAME -#define ROLE_ID Qt::UserRole -#define ROLE_NAME Qt::UserRole + 1 -#define ROLE_DESCRIPTION Qt::UserRole + 2 -#define ROLE_POPULARITY Qt::UserRole + 3 -#define ROLE_LASTPOST Qt::UserRole + 4 -#define ROLE_SEARCH_SCORE Qt::UserRole + 5 +#define ROLE_ID Qt::UserRole +#define ROLE_NAME Qt::UserRole + 1 +#define ROLE_DESCRIPTION Qt::UserRole + 2 +#define ROLE_POPULARITY Qt::UserRole + 3 +#define ROLE_LASTPOST Qt::UserRole + 4 +#define ROLE_SEARCH_SCORE Qt::UserRole + 5 +#define ROLE_SUBSCRIBE_FLAGS Qt::UserRole + 6 #define ROLE_COLOR Qt::UserRole + 6 #define FILTER_NAME_INDEX 0 @@ -69,6 +70,7 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) : connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(ui->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(itemClicked(QTreeWidgetItem*,int))); /* Add own item delegate */ RSItemDelegate *itemDelegate = new RSItemDelegate(this); @@ -232,6 +234,19 @@ void GroupTreeWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetIt emit treeCurrentItemChanged(id); } +void GroupTreeWidget::itemClicked(QTreeWidgetItem *item, int column) +{ + Q_UNUSED(column); + + QString id; + + if (item) { + id = item->data(COLUMN_DATA, ROLE_ID).toString(); + } + + emit treeItemClicked(id); +} + QTreeWidgetItem *GroupTreeWidget::addCategoryItem(const QString &name, const QIcon &icon, bool expand) { QFont font; @@ -318,6 +333,8 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList< item->setToolTip(COLUMN_NAME, tooltip); item->setToolTip(COLUMN_POPULARITY, tooltip); + item->setData(COLUMN_DATA, ROLE_SUBSCRIBE_FLAGS, itemInfo.subscribeFlags); + /* Set color */ QBrush brush; if (itemInfo.privatekey) { @@ -413,6 +430,16 @@ QTreeWidgetItem *GroupTreeWidget::activateId(const QString &id, bool focus) return item; } +int GroupTreeWidget::subscribeFlags(const QString &id) +{ + QTreeWidgetItem *item = getItemFromId(id); + if (item == NULL) { + return 0; + } + + return item->data(COLUMN_DATA, ROLE_SUBSCRIBE_FLAGS).toInt(); +} + void GroupTreeWidget::calculateScore(QTreeWidgetItem *item, const QString &filterText) { if (item) { diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.h b/retroshare-gui/src/gui/common/GroupTreeWidget.h index 062c6a35a..1a7fecff7 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.h +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.h @@ -47,6 +47,7 @@ public: { popularity = 0; privatekey = false; + subscribeFlags = 0; } public: @@ -57,6 +58,7 @@ public: QDateTime lastpost; QIcon icon; bool privatekey; + int subscribeFlags; }; class GroupTreeWidget : public QWidget @@ -93,9 +95,12 @@ public: void setTextColorCategory(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_CATEGORY] = color; } void setTextColorPrivateKey(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_PRIVATEKEY] = color; } + int subscribeFlags(const QString &id); + signals: void treeCustomContextMenuRequested(const QPoint &pos); void treeCurrentItemChanged(const QString &id); + void treeItemClicked(const QString &id); protected: void changeEvent(QEvent *e); @@ -103,6 +108,7 @@ protected: private slots: void customContextMenuRequested(const QPoint &pos); void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void itemClicked(QTreeWidgetItem *item, int column); void filterChanged(); void sort(); diff --git a/retroshare-gui/src/gui/common/LinkTextBrowser.cpp b/retroshare-gui/src/gui/common/LinkTextBrowser.cpp index 96438a43d..583609c23 100644 --- a/retroshare-gui/src/gui/common/LinkTextBrowser.cpp +++ b/retroshare-gui/src/gui/common/LinkTextBrowser.cpp @@ -1,4 +1,5 @@ #include +#include #include "LinkTextBrowser.h" @@ -34,3 +35,27 @@ void LinkTextBrowser::linkClicked(const QUrl &url) QDesktopServices::openUrl(url); } +void LinkTextBrowser::setPlaceholderText(const QString &text) +{ + placeholderText = text; + viewport()->repaint(); +} + +void LinkTextBrowser::paintEvent(QPaintEvent *event) +{ + QTextBrowser::paintEvent(event); + + if (placeholderText.isEmpty() == false && document()->isEmpty()) { + QWidget *vieportWidget = viewport(); + QPainter painter(vieportWidget); + + QPen pen = painter.pen(); + QColor color = pen.color(); + color.setAlpha(128); + pen.setColor(color); + painter.setPen(pen); + + painter.drawText(QRect(QPoint(), vieportWidget->size()), Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap, placeholderText); + } +} + diff --git a/retroshare-gui/src/gui/common/LinkTextBrowser.h b/retroshare-gui/src/gui/common/LinkTextBrowser.h index f5c29165a..f0b9e0246 100644 --- a/retroshare-gui/src/gui/common/LinkTextBrowser.h +++ b/retroshare-gui/src/gui/common/LinkTextBrowser.h @@ -10,8 +10,15 @@ class LinkTextBrowser : public QTextBrowser public: explicit LinkTextBrowser(QWidget *parent = 0); + void setPlaceholderText(const QString &text); + private slots: void linkClicked(const QUrl &url); + +protected: + void paintEvent(QPaintEvent *event); + + QString placeholderText; }; #endif // LINKTEXTBROWSER_H diff --git a/retroshare-gui/src/gui/common/RSTreeWidget.cpp b/retroshare-gui/src/gui/common/RSTreeWidget.cpp new file mode 100644 index 000000000..e863e3be2 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTreeWidget.cpp @@ -0,0 +1,52 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2012, RetroShare Team + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "RSTreeWidget.h" + +RSTreeWidget::RSTreeWidget(QWidget *parent) : QTreeWidget(parent) +{ +} + +void RSTreeWidget::setPlaceholderText(const QString &text) +{ + placeholderText = text; + viewport()->repaint(); +} + +void RSTreeWidget::paintEvent(QPaintEvent *event) +{ + QTreeWidget::paintEvent(event); + + if (placeholderText.isEmpty() == false && model() && model()->rowCount() == 0) { + QWidget *vieportWidget = viewport(); + QPainter painter(vieportWidget); + + QPen pen = painter.pen(); + QColor color = pen.color(); + color.setAlpha(128); + pen.setColor(color); + painter.setPen(pen); + + painter.drawText(QRect(QPoint(), vieportWidget->size()), Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap, placeholderText); + } +} diff --git a/retroshare-gui/src/gui/common/RSTreeWidget.h b/retroshare-gui/src/gui/common/RSTreeWidget.h new file mode 100644 index 000000000..80a0f0d05 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTreeWidget.h @@ -0,0 +1,43 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2012, RetroShare Team + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _RSTREEWIDGET_H +#define _RSTREEWIDGET_H + +#include + +/* Subclassing QTreeWidget */ +class RSTreeWidget : public QTreeWidget +{ + Q_OBJECT + +public: + RSTreeWidget(QWidget *parent = 0); + + void setPlaceholderText(const QString &text); + +protected: + void paintEvent(QPaintEvent *event); + + QString placeholderText; +}; + +#endif diff --git a/retroshare-gui/src/gui/forumsv2/CreateForumV2.cpp b/retroshare-gui/src/gui/forumsv2/CreateForumV2.cpp deleted file mode 100644 index 5b83e52f0..000000000 --- a/retroshare-gui/src/gui/forumsv2/CreateForumV2.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2008 Robert Fernie - * - * 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 (at your option) 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. - * - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include - -#include "util/misc.h" -#include "CreateForumV2.h" -#include "gui/common/PeerDefs.h" - -#include - -#include -#include - -#include - -#define CREATEFORUMSV2_NEWFORUMID 1 - - -/** Constructor */ -CreateForumV2::CreateForumV2(QWidget *parent) -: QDialog(parent) -{ - /* Invoke the Qt Designer generated object setup routine */ - ui.setupUi(this); - - ui.headerFrame->setHeaderImage(QPixmap(":/images/konversation64.png")); - ui.headerFrame->setHeaderText(tr("New Forum")); - - mForumQueue = new TokenQueue(rsForumsV2, this); - - // connect up the buttons. - connect( ui.buttonBox, SIGNAL(accepted()), this, SLOT(createForum())); - connect( ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); - connect( ui.pubKeyShare_cb, SIGNAL( clicked() ), this, SLOT( setShareList( ) )); - - if (!ui.pubKeyShare_cb->isChecked()) { - ui.contactsdockWidget->hide(); - this->resize(this->size().width() - ui.contactsdockWidget->size().width(), this->size().height()); - } - - /* initialize key share list */ - ui.keyShareList->setHeaderText(tr("Contacts:")); - ui.keyShareList->setModus(FriendSelectionWidget::MODUS_CHECK); - ui.keyShareList->start(); - - newForum(); -} - -void CreateForumV2::newForum() -{ - /* enforce Public for the moment */ - ui.typePublic->setChecked(true); - - ui.typePrivate->setEnabled(false); - ui.typeEncrypted->setEnabled(true); - -#ifdef RS_RELEASE_VERSION - ui.typePrivate->setVisible(false); - ui.typeEncrypted->setVisible(true); -#endif - - ui.msgAnon->setChecked(true); - //ui.msgAuth->setEnabled(false); - - ui.forumName->clear(); - ui.forumDesc->clear(); - - ui.forumName->setFocus(); -} - -void CreateForumV2::createForum() -{ - QString name = misc::removeNewLine(ui.forumName->text()); - QString desc = ui.forumDesc->toPlainText(); //toHtml(); - uint32_t flags = 0; - - if(name.isEmpty()) { - /* error message */ - QMessageBox::warning(this, "RetroShare", tr("Please add a Name"), QMessageBox::Ok, QMessageBox::Ok); - return; //Don't add a empty name!! - } - - if (ui.typePublic->isChecked()) { - flags |= RS_DISTRIB_PUBLIC; - } else if (ui.typePrivate->isChecked()) { - flags |= RS_DISTRIB_PRIVATE; - } else if (ui.typeEncrypted->isChecked()) { - flags |= RS_DISTRIB_ENCRYPTED; - } - - if (ui.msgAuth->isChecked()) { - flags |= RS_DISTRIB_AUTHEN_REQ; - } else if (ui.msgAnon->isChecked()) { - flags |= RS_DISTRIB_AUTHEN_ANON; - } - - if (rsForumsV2) { - - - uint32_t token; - RsForumV2Group grp; - grp.mMeta.mGroupName = std::string(name.toUtf8()); - grp.mDescription = std::string(desc.toUtf8()); - grp.mMeta.mGroupFlags = flags; - - rsForumsV2->createGroup(token, grp, true); - - // get the Queue to handle response. - mForumQueue->queueRequest(token, TOKENREQ_MSGINFO, RS_TOKREQ_ANSTYPE_SUMMARY, CREATEFORUMSV2_NEWFORUMID); - - } -} - -void CreateForumV2::completeCreateNewForum(const RsGroupMetaData &newForumMeta) -{ - sendShareList(newForumMeta.mGroupId); - - close(); -} - - -void CreateForumV2::sendShareList(std::string forumId) -{ - if (!rsForumsV2) - { - std::cerr << "CreateForumV2::sendShareList() ForumsV2 not active"; - std::cerr << std::endl; - return; - } - - if (ui.pubKeyShare_cb->isChecked()) - { - std::list shareList; - ui.keyShareList->selectedSslIds(shareList, false); - rsForumsV2->groupShareKeys(forumId, shareList); - } - close(); -} - - - - - - -void CreateForumV2::setShareList() -{ - if (ui.pubKeyShare_cb->isChecked()){ - this->resize(this->size().width() + ui.contactsdockWidget->size().width(), this->size().height()); - ui.contactsdockWidget->show(); - } else { // hide share widget - ui.contactsdockWidget->hide(); - this->resize(this->size().width() - ui.contactsdockWidget->size().width(), this->size().height()); - } -} - -void CreateForumV2::loadNewForumId(const uint32_t &token) -{ - std::cerr << "CreateForumV2::loadNewForumId()"; - std::cerr << std::endl; - - std::list groupInfo; - rsForumsV2->getGroupSummary(token, groupInfo); - - if (groupInfo.size() == 1) - { - RsGroupMetaData fi = groupInfo.front(); - completeCreateNewForum(fi); - } - else - { - std::cerr << "CreateForumV2::loadNewForumId() ERROR INVALID Number of Forums Created"; - std::cerr << std::endl; - } -} - - - - - - - - -void CreateForumV2::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "CreateForumV2::loadRequest() UserType: " << req.mUserType; - std::cerr << std::endl; - - if (queue == mForumQueue) - { - /* now switch on req */ - switch(req.mUserType) - { - - case CREATEFORUMSV2_NEWFORUMID: - loadNewForumId(req.mToken); - break; - default: - std::cerr << "CreateForumV2::loadRequest() UNKNOWN UserType "; - std::cerr << std::endl; - - } - } -} - - - diff --git a/retroshare-gui/src/gui/forumsv2/CreateForumV2.ui b/retroshare-gui/src/gui/forumsv2/CreateForumV2.ui deleted file mode 100644 index adfbf45d1..000000000 --- a/retroshare-gui/src/gui/forumsv2/CreateForumV2.ui +++ /dev/null @@ -1,304 +0,0 @@ - - - CreateForumV2 - - - - 0 - 0 - 672 - 495 - - - - Create new Forum - - - - :/images/rstray3.png:/images/rstray3.png - - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - - Name - - - - - - - - - - - - true - - - - 0 - 0 - - - - - 300 - 524287 - - - - - 220 - 0 - - - - - 0 - 0 - - - - check peers you would like to share private publish key with - - - false - - - QDockWidget::NoDockWidgetFeatures - - - Share Key With - - - - - 0 - - - 0 - - - - - - 0 - 4 - - - - - 20 - 0 - - - - - 300 - 16777215 - - - - - 220 - 0 - - - - - 200 - 0 - - - - - - - - - - - - - - Description - - - - - - - - - - - - Type: - - - - 6 - - - - - Public - Anyone can read and publish (Shared Publish Key) - - - - - - - Restricted - Anyone can read, limited publishing (Private Publish Key) - - - - - - - Private - (Private Publish Key required to view Messages) - - - - - - - - - - Key Sharing - - - - 0 - - - 6 - - - - - Key recipients can publish to restricted-type channels, and can view and publish for private-type channels - - - Share Private Publish Key - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - Allowed Messages - - - - 0 - - - 6 - - - - - Authenticated Messages - - - - - - - Anonymous Messages - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - HeaderFrame - QFrame -
gui/common/HeaderFrame.h
- 1 -
- - FriendSelectionWidget - QWidget -
gui/common/FriendSelectionWidget.h
- 1 -
-
- - - - -
diff --git a/retroshare-gui/src/gui/forumsv2/EditForumV2Details.cpp b/retroshare-gui/src/gui/forumsv2/EditForumV2Details.cpp deleted file mode 100644 index 60a8ddbda..000000000 --- a/retroshare-gui/src/gui/forumsv2/EditForumV2Details.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2010 RetroShare Team - * - * 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 (at your option) 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. - * - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include "EditForumV2Details.h" - -#include - -#include "util/misc.h" - -#include -#include -#include - - -/** Default constructor */ -EditForumV2Details::EditForumV2Details(std::string forumId, QWidget *parent, Qt::WFlags flags) - : QDialog(parent, flags), m_forumId(forumId) -{ - /* Invoke Qt Designer generated QObject setup routine */ - ui.setupUi(this); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(applyDialog())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); - - loadForum(); -} - -void EditForumV2Details::loadForum() -{ - if (!rsForumsV2) { - return; - } - -#warning "EditForumV2Details incomplete" -#if 0 - ForumInfo info; - rsForumsV2->getForumInfo(m_forumId, info); - - // set name - ui.nameline->setText(QString::fromStdWString(info.forumName)); - - // set description - ui.DescriptiontextEdit->setText(QString::fromStdWString(info.forumDesc)); -#endif - -} - -void EditForumV2Details::applyDialog() -{ - if (!rsForumsV2) { - return; - } - - // if text boxes have not been edited leave alone - if (!ui.nameline->isModified() && !ui.DescriptiontextEdit->document()->isModified()) { - return; - } - -#warning "EditForumV2Details incomplete" -#if 0 - - ForumInfo info; - - info.forumName = misc::removeNewLine(ui.nameline->text()).toStdWString(); - info.forumDesc = ui.DescriptiontextEdit->document()->toPlainText().toStdWString(); - - rsForumsV2->setForumInfo(m_forumId, info); -#endif - - /* close the Dialog after the Changes applied */ - close(); -} diff --git a/retroshare-gui/src/gui/forumsv2/EditForumV2Details.ui b/retroshare-gui/src/gui/forumsv2/EditForumV2Details.ui deleted file mode 100644 index bd1136f50..000000000 --- a/retroshare-gui/src/gui/forumsv2/EditForumV2Details.ui +++ /dev/null @@ -1,87 +0,0 @@ - - - EditForumV2Details - - - - 0 - 0 - 436 - 355 - - - - Forum Details - - - - :/images/rstray3.png:/images/rstray3.png - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - 0 - - - - - :/images/info16.png:/images/info16.png - - - Edit Forum Details - - - - - - Forum Info - - - - - - Forum Name - - - - - - - - - - Forum Description - - - - - - - - - - - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/forumsv2/ForumV2Details.cpp b/retroshare-gui/src/gui/forumsv2/ForumV2Details.cpp deleted file mode 100644 index 70414deb8..000000000 --- a/retroshare-gui/src/gui/forumsv2/ForumV2Details.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 2009 RetroShare Team - * - * 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 (at your option) 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. - * - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ -#include "ForumV2Details.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - - -/* Define the format used for displaying the date and time */ -#define DATETIME_FMT "MMM dd hh:mm:ss" - -/** Default constructor */ -ForumV2Details::ForumV2Details(QWidget *parent, Qt::WFlags flags) - : QDialog(parent, flags) -{ - /* Invoke Qt Designer generated QObject setup routine */ - ui.setupUi(this); - - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); - - ui.nameline ->setReadOnly(true); - ui.popline ->setReadOnly(true); - ui.postline ->setReadOnly(true); - ui.IDline ->setReadOnly(true); - ui.DescriptiontextEdit ->setReadOnly(true); - - ui.radioButton_authd->setEnabled(false); - ui.radioButton_anonymous->setEnabled(false); -} - - -/** - Overloads the default show() slot so we can set opacity*/ - -void -ForumV2Details::show() -{ - //loadSettings(); - if(!this->isVisible()) { - QDialog::show(); - - } -} - -void ForumV2Details::closeEvent (QCloseEvent * event) -{ - QWidget::closeEvent(event); -} - -void ForumV2Details::showDetails(std::string mCurrForumId) -{ - fId = mCurrForumId; - loadDialog(); -} - -void ForumV2Details::loadDialog() -{ - if (!rsForumsV2) - { - return; - } - -#warning "ForumV2Details Incomplete" -#if 0 - ForumInfo fi; - rsForumsV2->getForumInfo(fId, fi); - - // Set Forum Name - ui.nameline->setText(QString::fromStdWString(fi.forumName)); - - // Set Popularity - ui.popline->setText(QString::number(fi.pop)); - - // Set Last Post Date - if (fi.lastPost) { - QDateTime qtime; - qtime.setTime_t(fi.lastPost); - QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); - ui.postline->setText(timestamp); - } - - // Set Forum ID - ui.IDline->setText(QString::fromStdString(fi.forumId)); - - // Set Forum Description - ui.DescriptiontextEdit->setText(QString::fromStdWString(fi.forumDesc)); - - if (fi.forumFlags & RS_DISTRIB_AUTHEN_REQ) - { - ui.radioButton_authd->setChecked(true); - ui.radioButton_anonymous->setChecked(false); - } - if (fi.forumFlags & RS_DISTRIB_AUTHEN_ANON) - { - ui.radioButton_authd->setChecked(false); - ui.radioButton_anonymous->setChecked(true); - } -#endif - -} diff --git a/retroshare-gui/src/gui/forumsv2/ForumV2Details.ui b/retroshare-gui/src/gui/forumsv2/ForumV2Details.ui deleted file mode 100644 index 68129fe45..000000000 --- a/retroshare-gui/src/gui/forumsv2/ForumV2Details.ui +++ /dev/null @@ -1,175 +0,0 @@ - - - ForumV2Details - - - - 0 - 0 - 436 - 355 - - - - Forum Details - - - - :/images/rstray3.png:/images/rstray3.png - - - - - - 0 - - - - - :/images/info16.png:/images/info16.png - - - Forum Details - - - - - - Forum Info - - - - - - Forum Name - - - - - - - - - - Popularity - - - - - - - true - - - - - - - Last Post - - - - - - - true - - - - - - - Forum ID - - - - - - - - - - Forum Description - - - - - - - - - - - - - - - - - :/images/encrypted22.png:/images/encrypted22.png - - - Security - - - - - - Allowed Messages - - - - - - Authenticated Messages - - - - - - - Anonymous Messages - - - true - - - - - - - - - - Qt::Vertical - - - - 358 - 172 - - - - - - - - - - - - - - QDialogButtonBox::Close - - - - - - - - - - - - diff --git a/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp b/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp new file mode 100644 index 000000000..926400320 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsCircleChooser.cpp @@ -0,0 +1,108 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "GxsCircleChooser.h" + +#include + +#include + +#include + +/** Constructor */ +GxsCircleChooser::GxsCircleChooser(QWidget *parent) +: QComboBox(parent), mFlags(0) +{ + return; +} + +void GxsCircleChooser::loadCircles(uint32_t chooserFlags) +{ + mFlags = chooserFlags; + loadGxsCircles(); +} + + +bool MakeGxsCircleDesc(const RsGxsCircleId &id, QString &desc) +{ + RsGxsCircleDetails details; + + if (rsGxsCircles->getCircleDetails(id, details)) + { + desc = QString::fromUtf8(details.mCircleName.c_str()); + } + else + { + desc += "Unknown"; + } + + desc += " (Ext) ["; + desc += QString::fromStdString(id.substr(0,5)); + desc += "...]"; + + return true; +} + + +void GxsCircleChooser::loadGxsCircles() +{ + std::list ids; + rsGxsCircles->getCircleIdList(ids); + + if (ids.empty()) + { + std::cerr << "GxsCircleChooser::loadGxsCircles() ERROR no ids"; + std::cerr << std::endl; + return; + } + + std::list::iterator it; + for(it = ids.begin(); it != ids.end(); it++) + { + /* add to Chooser */ + QString str; + if (!MakeGxsCircleDesc(*it, str)) + { + std::cerr << "GxsCircleChooser::loadGxsCircles() ERROR Desc for Id: " << *it; + std::cerr << std::endl; + continue; + } + QString id = QString::fromStdString(*it); + + addItem(str, id); + } +} + +bool GxsCircleChooser::getChosenCircle(RsGxsCircleId &id) +{ + if (count() < 1) + { + return false; + } + + int idx = currentIndex(); + + QVariant var = itemData(idx); + id = var.toString().toStdString(); + + return true; +} + diff --git a/retroshare-gui/src/gui/gxs/GxsCircleChooser.h b/retroshare-gui/src/gui/gxs/GxsCircleChooser.h new file mode 100644 index 000000000..74986e02f --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsCircleChooser.h @@ -0,0 +1,45 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GXS_CIRCLES_CHOOSER_H +#define _GXS_CIRCLES_CHOOSER_H + +#include +#include + +class GxsCircleChooser : public QComboBox +{ + Q_OBJECT + +public: + GxsCircleChooser(QWidget *parent = NULL); + + void loadCircles(uint32_t chooserFlags); + bool getChosenCircle(RsGxsCircleId &id); + +private: + void loadGxsCircles(); + uint32_t mFlags; +}; + +#endif + diff --git a/retroshare-gui/src/gui/gxs/GxsCircleLabel.cpp b/retroshare-gui/src/gui/gxs/GxsCircleLabel.cpp new file mode 100644 index 000000000..02f9f0800 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsCircleLabel.cpp @@ -0,0 +1,103 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "GxsCircleLabel.h" + +#include + +#include + +#include + +/** Constructor */ +GxsCircleLabel::GxsCircleLabel(QWidget *parent) +:QLabel(parent), mTimer(NULL), mCount(0) +{ + mTimer = new QTimer(this); + mTimer->setSingleShot(true); + connect(mTimer, SIGNAL(timeout()), this, SLOT(loadId())); + + return; +} + +void GxsCircleLabel::setCircleId(const RsGxsCircleId &id) +{ + mId = id; + if (mId == "") + { + setText("No Circle"); + } + else + { + loadGxsCircle(); + } +} + +bool GxsCircleLabel::getCircleId(RsGxsCircleId &id) +{ + id = mId; + return true; +} + +static bool MakeCircleDesc(const RsGxsCircleId &id, QString &str) +{ + RsGxsCircleDetails details; + + if (!rsGxsCircles->getCircleDetails(id, details)) + { + str = "Loading... " + QString::fromStdString(id.substr(0,5)); + return false; + } + + str = QString::fromUtf8(details.mCircleName.c_str()); + + str += " (Ext) ["; + str += QString::fromStdString(id.substr(0,5)); + str += "...]"; + + return true; +} + +#define MAX_ATTEMPTS 3 + +void GxsCircleLabel::loadGxsCircle() +{ + mCount++; + + /* try and get details - if not there ... set callback */ + QString desc; + bool loaded = MakeCircleDesc(mId, desc); + + setText(desc); + + if (loaded) + { + return; + } + + if (mCount < MAX_ATTEMPTS) + { + /* timer event to try again (circles take longer) */ + mTimer->setInterval(mCount * 3000); + mTimer->start(); + } +} + diff --git a/retroshare-gui/src/gui/gxs/GxsCircleLabel.h b/retroshare-gui/src/gui/gxs/GxsCircleLabel.h new file mode 100644 index 000000000..03f43d62a --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsCircleLabel.h @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GXS_CIRCLE_LABEL_H +#define _GXS_CIRCLE_LABEL_H + +#include +#include +#include + +class GxsCircleLabel : public QLabel +{ + Q_OBJECT + +public: + GxsCircleLabel(QWidget *parent = NULL); + + void setCircleId(const RsGxsCircleId &id); + bool getCircleId(RsGxsCircleId &id); + +private slots: + void loadGxsCircle(); + +private: + + QTimer *mTimer; + RsGxsCircleId mId; + int mCount; +}; + +#endif + diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp new file mode 100644 index 000000000..5332e57e6 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp @@ -0,0 +1,388 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2008 Robert Fernie +* +* 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 (at your option) 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. +* +* 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., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#include +#include +#include + +#include "gui/gxs/GxsCommentTreeWidget.h" +#include "gui/Posted/PostedCreateCommentDialog.h" + +#include + +#define PCITEM_COLUMN_COMMENT 0 +#define PCITEM_COLUMN_AUTHOR 1 +#define PCITEM_COLUMN_DATE 2 +#define PCITEM_COLUMN_SERVSTRING 3 +#define PCITEM_COLUMN_MSGID 4 +#define PCITEM_COLUMN_PARENTID 5 + +#define GXSCOMMENTS_LOADTHREAD 1 + +// Temporarily make this specific. +#include "retroshare/rsposted.h" + +/* Images for context menu icons */ +#define IMAGE_MESSAGE ":/images/folder-draft.png" + +GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent) + :QTreeWidget(parent), mRsService(NULL), mTokenQueue(NULL) +{ +// QTreeWidget* widget = this; + + setContextMenuPolicy(Qt::CustomContextMenu); +// QFont font = QFont("ARIAL", 10); +// font.setBold(true); + +// QString name("test"); +// QTreeWidgetItem *item = new QTreeWidgetItem(); +// item->setText(0, name); +// item->setFont(0, font); +// item->setSizeHint(0, QSize(18, 18)); +// item->setForeground(0, QBrush(QColor(79, 79, 79))); + +// addTopLevelItem(item); +// item->setExpanded(true); + + return; +} + +void GxsCommentTreeWidget::setCurrentMsgId(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + + Q_UNUSED(previous); + + if(current) + { + mCurrentMsgId = current->text(PCITEM_COLUMN_MSGID).toStdString(); + } +} + +void GxsCommentTreeWidget::customPopUpMenu(const QPoint& point) +{ + QMenu contextMnu( this ); + QAction* action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Reply to Comment"), this, SLOT(replyToComment())); + action->setDisabled(mCurrentMsgId.empty()); + action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Comment"), this, SLOT(makeComment())); + action->setDisabled(mThreadId.first.empty()); + contextMnu.exec(QCursor::pos()); +} + +void GxsCommentTreeWidget::makeComment() +{ + PostedCreateCommentDialog pcc(mTokenQueue, mThreadId, mThreadId.second, this); + pcc.exec(); +} + +void GxsCommentTreeWidget::replyToComment() +{ + RsGxsGrpMsgIdPair msgId; + msgId.first = mThreadId.first; + msgId.second = mCurrentMsgId; + PostedCreateCommentDialog pcc(mTokenQueue, msgId, mThreadId.second, this); + pcc.exec(); +} + +void GxsCommentTreeWidget::setup(RsTokenService *service) +{ + mRsService = service; + mTokenQueue = new TokenQueue(service, this); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customPopUpMenu(QPoint))); + connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(setCurrentMsgId(QTreeWidgetItem*, QTreeWidgetItem*))); + + return; +} + + +/* Load Comments */ +void GxsCommentTreeWidget::requestComments(const RsGxsGrpMsgIdPair& threadId) +{ + /* request comments */ + + mThreadId = threadId; + service_requestComments(threadId); +} + +void GxsCommentTreeWidget::service_requestComments(const RsGxsGrpMsgIdPair& threadId) +{ + /* request comments */ + std::cerr << "GxsCommentTreeWidget::service_requestComments(" << threadId.second << ")"; + std::cerr << std::endl; + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; + + std::vector msgIds; + msgIds.push_back(threadId); + + uint32_t token; + mTokenQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, GXSCOMMENTS_LOADTHREAD); +} + + +/* Generic Handling */ +void GxsCommentTreeWidget::clearItems() +{ + mPendingInsertMap.clear(); + mLoadingMap.clear(); +} + + +void GxsCommentTreeWidget::completeItems() +{ + /* handle pending items */ + std::string parentId; + QTreeWidgetItem *parent = NULL; + QList topLevelItems; + + std::map::iterator lit; + std::multimap::iterator pit; + + std::cerr << "GxsCommentTreeWidget::completeItems() " << mPendingInsertMap.size(); + std::cerr << " PendingItems"; + std::cerr << std::endl; + + for(pit = mPendingInsertMap.begin(); pit != mPendingInsertMap.end(); pit++) + { + std::cerr << "GxsCommentTreeWidget::completeItems() item->parent: " << pit->first; + std::cerr << std::endl; + + if (pit->first != parentId) + { + /* find parent */ + parentId = pit->first; + lit = mLoadingMap.find(pit->first); + if (lit != mLoadingMap.end()) + { + parent = lit->second; + } + else + { + parent = NULL; + } + } + + if (parent) + { + std::cerr << "GxsCommentTreeWidget::completeItems() Added to Parent"; + std::cerr << std::endl; + + parent->addChild(pit->second); + } + else if (parentId == mThreadId.second) + { + std::cerr << "GxsCommentTreeWidget::completeItems() Added to topLevelItems"; + std::cerr << std::endl; + + topLevelItems.append(pit->second); + } + else + { + + /* missing parent -> insert At Top Level */ + QTreeWidgetItem *missingItem = service_createMissingItem(pit->first); + + std::cerr << "GxsCommentTreeWidget::completeItems() Added MissingItem"; + std::cerr << std::endl; + + parent = missingItem; + parent->addChild(pit->second); + topLevelItems.append(parent); + } + } + + /* now push final tree into Tree */ + clear(); + insertTopLevelItems(0, topLevelItems); + + /* cleanup temp stuff */ + mLoadingMap.clear(); + mPendingInsertMap.clear(); +} + + +void GxsCommentTreeWidget::addItem(std::string itemId, std::string parentId, QTreeWidgetItem *item) +{ + std::cerr << "GxsCommentTreeWidget::addItem() Id: " << itemId; + std::cerr << " ParentId: " << parentId; + std::cerr << std::endl; + + /* store in map -> for children */ + mLoadingMap[itemId] = item; + + std::map::iterator it; + it = mLoadingMap.find(parentId); + if (it != mLoadingMap.end()) + { + std::cerr << "GxsCommentTreeWidget::addItem() Added to Parent"; + std::cerr << std::endl; + + it->second->addChild(item); + } + else + { + std::cerr << "GxsCommentTreeWidget::addItem() Added to Pending List"; + std::cerr << std::endl; + + mPendingInsertMap.insert(std::make_pair(parentId, item)); + } +} + +void GxsCommentTreeWidget::loadThread(const uint32_t &token) +{ + clearItems(); + + service_loadThread(token); + + completeItems(); +} + +void GxsCommentTreeWidget::acknowledgeComment(const uint32_t &token) +{ + RsGxsGrpMsgIdPair msgId; + rsPosted->acknowledgeMsg(token, msgId); + + // simply reload data + service_requestComments(mThreadId); +} + + +void GxsCommentTreeWidget::service_loadThread(const uint32_t &token) +{ + std::cerr << "GxsCommentTreeWidget::service_loadThread() ERROR must be overloaded!"; + std::cerr << std::endl; + + PostedRelatedCommentResult commentResult; + rsPosted->getRelatedComment(token, commentResult); + + std::vector& commentV = commentResult[mThreadId]; + std::vector::iterator vit = commentV.begin(); + + for(; vit != commentV.end(); vit++) + { + RsPostedComment& comment = *vit; + /* convert to a QTreeWidgetItem */ + std::cerr << "GxsCommentTreeWidget::service_loadThread() Got Comment: " << comment.mMeta.mMsgId; + std::cerr << std::endl; + + QTreeWidgetItem *item = new QTreeWidgetItem(); + QString text; + + { + QDateTime qtime; + qtime.setTime_t(comment.mMeta.mPublishTs); + + text = qtime.toString("yyyy-MM-dd hh:mm:ss"); + item->setText(PCITEM_COLUMN_DATE, text); + } + + text = QString::fromUtf8(comment.mComment.c_str()); + item->setText(PCITEM_COLUMN_COMMENT, text); + + text = QString::fromUtf8(comment.mMeta.mAuthorId.c_str()); + if (text.isEmpty()) + { + item->setText(PCITEM_COLUMN_AUTHOR, tr("Anonymous")); + } + else + { + item->setText(PCITEM_COLUMN_AUTHOR, text); + } + + text = QString::fromUtf8(comment.mMeta.mMsgId.c_str()); + item->setText(PCITEM_COLUMN_MSGID, text); + + text = QString::fromUtf8(comment.mMeta.mParentId.c_str()); + item->setText(PCITEM_COLUMN_PARENTID, text); + + text = QString::fromUtf8("0"); + //text = QString::fromUtf8(comment.mMeta.mServiceString.c_str()); + item->setText(PCITEM_COLUMN_SERVSTRING, text); + + addItem(comment.mMeta.mMsgId, comment.mMeta.mParentId, item); + } + + return; +} + +QTreeWidgetItem *GxsCommentTreeWidget::service_createMissingItem(const RsGxsMessageId& parent) +{ + std::cerr << "GxsCommentTreeWidget::service_createMissingItem()"; + std::cerr << std::endl; + + QTreeWidgetItem *item = new QTreeWidgetItem(); + QString text("Unknown"); + + item->setText(PCITEM_COLUMN_DATE, text); + + item->setText(PCITEM_COLUMN_COMMENT, text); + + item->setText(PCITEM_COLUMN_AUTHOR, text); + + item->setText(PCITEM_COLUMN_MSGID, text); + + item->setText(PCITEM_COLUMN_SERVSTRING, text); + + text = QString::fromUtf8(parent.c_str()); + item->setText(PCITEM_COLUMN_PARENTID, text); + + return item; +} + + + +void GxsCommentTreeWidget::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "GxsCommentTreeWidget::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; + + if (queue != mTokenQueue) + { + std::cerr << "GxsCommentTreeWidget::loadRequest() Queue ERROR"; + std::cerr << std::endl; + return; + } + + /* now switch on req */ + switch(req.mType) + { + + case TOKENREQ_MSGINFO: + { + switch(req.mAnsType) + { + case RS_TOKREQ_ANSTYPE_ACK: + acknowledgeComment(req.mToken); + break; + case RS_TOKREQ_ANSTYPE_DATA: + loadThread(req.mToken); + break; + } + } + break; + default: + std::cerr << "GxsCommentTreeWidget::loadRequest() UNKNOWN UserType "; + std::cerr << std::endl; + break; + + } +} diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h new file mode 100644 index 000000000..f494e25e3 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.h @@ -0,0 +1,82 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2008 Robert Fernie +* +* 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 (at your option) 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. +* +* 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., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#ifndef _GXS_COMMENT_TREE_WIDGET_H +#define _GXS_COMMENT_TREE_WIDGET_H + +#include + +#include "util/TokenQueue.h" + +class GxsCommentTreeWidget : public QTreeWidget, public TokenResponse +{ + Q_OBJECT + +public: + GxsCommentTreeWidget(QWidget *parent = 0); + void setup(RsTokenService *service); + + void requestComments(const RsGxsGrpMsgIdPair& threadId); + void getCurrentMsgId(RsGxsMessageId& parentId); + void applyRankings(std::map& positions); + + void loadRequest(const TokenQueue *queue, const TokenRequest &req); + +protected: + + /* to be overloaded */ + virtual void service_requestComments(const RsGxsGrpMsgIdPair& threadId); + virtual void service_loadThread(const uint32_t &token); + virtual QTreeWidgetItem *service_createMissingItem(const RsGxsMessageId& parent); + + void clearItems(); + void completeItems(); + + void acknowledgeComment(const uint32_t& token); + void loadThread(const uint32_t &token); + + void addItem(std::string itemId, std::string parentId, QTreeWidgetItem *item); + +public slots: + void customPopUpMenu(const QPoint& point); + void setCurrentMsgId(QTreeWidgetItem* current, QTreeWidgetItem* previous); + + + void makeComment(); + void replyToComment(); + +protected: + + /* Data */ + RsGxsGrpMsgIdPair mThreadId; + RsGxsMessageId mCurrentMsgId; + + std::map mLoadingMap; + std::multimap mPendingInsertMap; + + TokenQueue *mTokenQueue; + RsTokenService *mRsService; + +}; + + +#endif + diff --git a/retroshare-gui/src/gui/gxs/GxsForumGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsForumGroupDialog.cpp new file mode 100644 index 000000000..d440c6c11 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsForumGroupDialog.cpp @@ -0,0 +1,98 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "GxsForumGroupDialog.h" + +#include +#include + +// To start with we only have open forums - with distribution controls. + +const uint32_t ForumCreateEnabledFlags = ( GXS_GROUP_FLAGS_ICON | + GXS_GROUP_FLAGS_DESCRIPTION | + GXS_GROUP_FLAGS_DISTRIBUTION | + // GXS_GROUP_FLAGS_PUBLISHSIGN | + GXS_GROUP_FLAGS_SHAREKEYS | + // GXS_GROUP_FLAGS_PERSONALSIGN | + // GXS_GROUP_FLAGS_COMMENTS | + 0); + +const uint32_t ForumCreateDefaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC | + //GXS_GROUP_DEFAULTS_DISTRIB_GROUP | + //GXS_GROUP_DEFAULTS_DISTRIB_LOCAL | + + GXS_GROUP_DEFAULTS_PUBLISH_OPEN | + //GXS_GROUP_DEFAULTS_PUBLISH_THREADS | + //GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED | + //GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED | + + //GXS_GROUP_DEFAULTS_PERSONAL_GPG | + GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED | + //GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB | + + //GXS_GROUP_DEFAULTS_COMMENTS_YES | + GXS_GROUP_DEFAULTS_COMMENTS_NO | + 0); + + + +GxsForumGroupDialog::GxsForumGroupDialog(TokenQueue *tokenQueue, QWidget *parent) + :GxsGroupDialog(tokenQueue, ForumCreateEnabledFlags, ForumCreateDefaultsFlags, parent) +{ + +} + +GxsForumGroupDialog::GxsForumGroupDialog(const RsGxsForumGroup &group, Mode mode, QWidget *parent) + :GxsGroupDialog(group.mMeta, mode, parent) +{ + return; +} + +QString GxsForumGroupDialog::serviceHeader() +{ + switch (mode()) + { + case MODE_CREATE: + return tr("Create New Forum"); + case MODE_SHOW: + return tr("Forum"); + case MODE_EDIT: + return tr("Edit Forum"); + } + + return ""; +} + +QPixmap GxsForumGroupDialog::serviceImage() +{ + return QPixmap(":/images/konversation64.png"); +} + +bool GxsForumGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta) +{ + // Specific Function. + RsGxsForumGroup grp; + grp.mMeta = meta; + //grp.mDescription = std::string(desc.toUtf8()); + + rsGxsForums->createGroup(token, grp); + return true; +} diff --git a/retroshare-gui/src/gui/forumsv2/ForumV2Details.h b/retroshare-gui/src/gui/gxs/GxsForumGroupDialog.h similarity index 60% rename from retroshare-gui/src/gui/forumsv2/ForumV2Details.h rename to retroshare-gui/src/gui/gxs/GxsForumGroupDialog.h index 765564c1f..2277b38bd 100644 --- a/retroshare-gui/src/gui/forumsv2/ForumV2Details.h +++ b/retroshare-gui/src/gui/gxs/GxsForumGroupDialog.h @@ -1,7 +1,7 @@ /**************************************************************** * RetroShare is distributed under the following license: * - * Copyright (C) 2009 RetroShare Team + * Copyright (C) 2008 Robert Fernie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,42 +19,25 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ -#ifndef _FORUMV2DETAILS_H -#define _FORUMV2DETAILS_H -#include +#ifndef _GXSFORUM_GROUP_DIALOG_H +#define _GXSFORUM_GROUP_DIALOG_H -#include "ui_ForumV2Details.h" +#include "GxsGroupDialog.h" +#include -class ForumV2Details : public QDialog +class GxsForumGroupDialog : public GxsGroupDialog { - Q_OBJECT + Q_OBJECT - public: - - /** Default constructor */ - ForumV2Details(QWidget *parent = 0, Qt::WFlags flags = 0); - /** Default destructor */ - - void showDetails(std::string mCurrForumId); - -signals: - void configChanged() ; - -public slots: - /** Overloaded QWidget.show */ - void show(); +public: + GxsForumGroupDialog(TokenQueue *tokenQueue, QWidget *parent); + GxsForumGroupDialog(const RsGxsForumGroup &group, Mode mode, QWidget *parent); protected: - void closeEvent (QCloseEvent * event); - -private: - void loadDialog(); - - std::string fId; - /** Qt Designer generated object */ - Ui::ForumV2Details ui; - + virtual QString serviceHeader(); + virtual QPixmap serviceImage(); + virtual bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta); }; #endif diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp new file mode 100644 index 000000000..7d32ede06 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -0,0 +1,543 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "util/misc.h" +#include "GxsGroupDialog.h" +#include "gui/common/PeerDefs.h" +#include "gxs/rsgxsflags.h" + +#include + +#include +#include + +#include + +// Control of Publish Signatures. +#define RSGXS_GROUP_SIGN_PUBLISH_MASK 0x000000ff +#define RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED 0x00000001 +#define RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED 0x00000002 +#define RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD 0x00000004 +#define RSGXS_GROUP_SIGN_PUBLISH_NONEREQ 0x00000008 + +// Author Signature. +#define RSGXS_GROUP_SIGN_AUTHOR_MASK 0x0000ff00 +#define RSGXS_GROUP_SIGN_AUTHOR_GPG 0x00000100 +#define RSGXS_GROUP_SIGN_AUTHOR_REQUIRED 0x00000200 +#define RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN 0x00000400 +#define RSGXS_GROUP_SIGN_AUTHOR_NONE 0x00000800 + +#define GXSGROUP_NEWGROUPID 1 +#define GXSGROUP_LOADGROUP 2 + +/** Constructor */ +GxsGroupDialog::GxsGroupDialog(TokenQueue *tokenQueue, uint32_t enableFlags, uint16_t defaultFlags, QWidget *parent) + : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint), mTokenQueue(tokenQueue), mMode(MODE_CREATE), mEnabledFlags(enableFlags), mReadonlyFlags(0), mDefaultsFlags(defaultFlags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + init(); +} + +GxsGroupDialog::GxsGroupDialog(const RsGroupMetaData &grpMeta, Mode mode, QWidget *parent) + : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint), mTokenQueue(NULL), mGrpMeta(grpMeta), mMode(mode), mEnabledFlags(0), mReadonlyFlags(0), mDefaultsFlags(0) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + init(); +} + +void GxsGroupDialog::init() +{ + // connect up the buttons. + connect( ui.buttonBox, SIGNAL(accepted()), this, SLOT(submitGroup())); + connect( ui.buttonBox, SIGNAL(rejected()), this, SLOT(cancelDialog())); + connect( ui.pubKeyShare_cb, SIGNAL( clicked() ), this, SLOT( setShareList( ) )); + + connect( ui.groupLogo, SIGNAL(clicked() ), this , SLOT(addGroupLogo())); + connect( ui.addLogoButton, SIGNAL(clicked() ), this , SLOT(addGroupLogo())); + + ui.typePublic->setChecked(true); + updateCircleOptions(); + + connect( ui.typePublic, SIGNAL(clicked()), this , SLOT(updateCircleOptions())); + connect( ui.typeGroup, SIGNAL(clicked()), this , SLOT(updateCircleOptions())); + connect( ui.typeLocal, SIGNAL(clicked()), this , SLOT(updateCircleOptions())); + + if (!ui.pubKeyShare_cb->isChecked()) + { + ui.contactsdockWidget->hide(); + this->resize(this->size().width() - ui.contactsdockWidget->size().width(), this->size().height()); + } + + /* initialize key share list */ + ui.keyShareList->setHeaderText(tr("Contacts:")); + ui.keyShareList->setModus(FriendSelectionWidget::MODUS_CHECK); + ui.keyShareList->start(); + + /* Setup Reasonable Defaults */ + + ui.idChooser->loadIds(0,""); + ui.circleComboBox->loadCircles(0); + + initMode(); +} + +void GxsGroupDialog::showEvent(QShowEvent*) +{ + QString header = serviceHeader(); + ui.headerFrame->setHeaderText(header); + setWindowTitle(header); + ui.headerFrame->setHeaderImage(serviceImage()); +} + +void GxsGroupDialog::initMode() +{ + switch (mode()) + { + case MODE_CREATE: + { + ui.buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + ui.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create Group")); + newGroup(); + } + break; + + case MODE_SHOW: + { + ui.buttonBox->setStandardButtons(QDialogButtonBox::Close); + } + break; +//TODO +// case MODE_EDIT: +// { +// ui.createButton->setText(tr("Submit Changes")); +// } +// break; + } +} + + +void GxsGroupDialog::clearForm() +{ + ui.groupName->clear(); + ui.groupDesc->clear(); + ui.groupName->setFocus(); +} + +void GxsGroupDialog::setupDefaults() +{ + /* Enable / Show Parts based on Flags */ + + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_MASK) + { + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC) + { + ui.typePublic->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_GROUP) + { + ui.typeGroup->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_DISTRIB_LOCAL) + { + ui.typeLocal->setChecked(true); + } + else + { + // default + ui.typePublic->setChecked(true); + } + } + + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PUBLISH_MASK) + { + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED) + { + ui.publish_encrypt->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED) + { + ui.publish_required->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PUBLISH_THREADS) + { + ui.publish_threads->setChecked(true); + } + else + { + // default + ui.publish_open->setChecked(true); + } + } + + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PERSONAL_MASK) + { + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PERSONAL_PGP) + { + ui.personal_pgp->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED) + { + ui.personal_required->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB) + { + ui.personal_ifnopub->setChecked(true); + } + else + { + // default + ui.personal_ifnopub->setChecked(true); + } + } + + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_COMMENTS_MASK) + { + if (mDefaultsFlags & GXS_GROUP_DEFAULTS_COMMENTS_YES) + { + ui.comments_allowed->setChecked(true); + } + else if (mDefaultsFlags & GXS_GROUP_DEFAULTS_COMMENTS_NO) + { + ui.comments_no->setChecked(true); + } + else + { + // default + ui.comments_no->setChecked(true); + } + } +} + +void GxsGroupDialog::setupVisibility() +{ + { + ui.groupLogo->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ICON); + ui.addLogoButton->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_ICON); + } + + { + ui.groupDesc->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DESCRIPTION); + ui.groupDescLabel->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DESCRIPTION); + } + + { + ui.distribGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_DISTRIBUTION); + } + + { + ui.publishGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_PUBLISHSIGN); + } + + { + ui.pubKeyShare_cb->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_SHAREKEYS); + } + + { + ui.personalGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_PERSONALSIGN); + } + + { + ui.commentGroupBox->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_COMMENTS); + } + + { + ui.extraFrame->setVisible(mEnabledFlags & GXS_GROUP_FLAGS_EXTRA); + } +} + + +void GxsGroupDialog::newGroup() +{ + setupDefaults(); + setupVisibility(); + clearForm(); + +} + +void GxsGroupDialog::submitGroup() +{ + std::cerr << "GxsGroupDialog::submitGroup()"; + std::cerr << std::endl; + + /* switch depending on mode */ + switch (mode()) + { + case MODE_CREATE: + { + /* just close if down */ + createGroup(); + } + break; + + case MODE_SHOW: + { + /* just close if down */ + cancelDialog(); + } + break; + + case MODE_EDIT: + { + /* TEMP: just close if down */ + cancelDialog(); + } + break; + } +} + +void GxsGroupDialog::createGroup() +{ + std::cerr << "GxsGroupDialog::createGroup()"; + std::cerr << std::endl; + + QString name = misc::removeNewLine(ui.groupName->text()); + uint32_t flags = 0; + + if(name.isEmpty()) + { + /* error message */ + QMessageBox::warning(this, "RetroShare", tr("Please add a Name"), QMessageBox::Ok, QMessageBox::Ok); + return; //Don't add a empty name!! + } + + uint32_t token; + RsGroupMetaData meta; + + // Fill in the MetaData as best we can. + meta.mGroupName = std::string(name.toUtf8()); + + meta.mGroupFlags = flags; + meta.mSignFlags = getGroupSignFlags(); + + setCircleParameters(meta); + + if (service_CreateGroup(token, meta)) + { + // get the Queue to handle response. + if(mTokenQueue != NULL) + mTokenQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, GXSGROUP_NEWGROUPID); + } + close(); +} + +uint32_t GxsGroupDialog::getGroupSignFlags() +{ + /* grab from the ui options -> */ + uint32_t signFlags = 0; + if (ui.publish_encrypt->isChecked()) { + signFlags |= RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED; + } else if (ui.publish_required->isChecked()) { + signFlags |= RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED; + } else if (ui.publish_threads->isChecked()) { + signFlags |= RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD; + } else { // publish_open (default). + signFlags |= RSGXS_GROUP_SIGN_PUBLISH_NONEREQ; + } + +// Author Signature. + if (ui.personal_pgp->isChecked()) { + signFlags |= RSGXS_GROUP_SIGN_AUTHOR_GPG; + } else if (ui.personal_required->isChecked()) { + signFlags |= RSGXS_GROUP_SIGN_AUTHOR_REQUIRED; + } else if (ui.personal_ifnopub->isChecked()) { + signFlags |= RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN; + } else { // shouldn't allow this one. + signFlags |= RSGXS_GROUP_SIGN_AUTHOR_NONE; + } + return signFlags; +} + +void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags) +{ + if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_ENCRYPTED) { + ui.publish_encrypt->setChecked(true); + } else if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_ALLSIGNED) { + ui.publish_required->setChecked(true); + } else if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD) { + ui.publish_threads->setChecked(true); + } else if (signFlags & RSGXS_GROUP_SIGN_PUBLISH_NONEREQ) { + ui.publish_open->setChecked(true); + } + + if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_GPG) { + ui.personal_pgp->setChecked(true); + } else if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_REQUIRED) { + ui.personal_required->setChecked(true); + } else if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN) { + ui.personal_ifnopub->setChecked(true); + } else if (signFlags & RSGXS_GROUP_SIGN_AUTHOR_NONE) { + // Its the same... but not quite. + //ui.personal_noifpub->setChecked(); + } + + /* guess at comments */ + if ((signFlags & RSGXS_GROUP_SIGN_PUBLISH_THREADHEAD) + && (signFlags & RSGXS_GROUP_SIGN_AUTHOR_IFNOPUBSIGN)) + { + ui.comments_allowed->setChecked(true); + } + else + { + ui.comments_no->setChecked(true); + } +} + + + +/**** Above logic is flawed, and will be removed shortly + * + * + ****/ + +void GxsGroupDialog::updateCircleOptions() +{ + if (ui.typeGroup->isChecked()) + { + ui.circleComboBox->setEnabled(true); + ui.circleComboBox->setVisible(true); + } + else + { + ui.circleComboBox->setEnabled(false); + ui.circleComboBox->setVisible(false); + } + + if (ui.typeLocal->isChecked()) + { + ui.localComboBox->setEnabled(true); + ui.localComboBox->setVisible(true); + } + else + { + ui.localComboBox->setEnabled(false); + ui.localComboBox->setVisible(false); + } +} + +void GxsGroupDialog::setCircleParameters(RsGroupMetaData &meta) +{ + bool problem = false; + if (ui.typePublic->isChecked()) + { + meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; + meta.mCircleId.clear(); + } + else if (ui.typeGroup->isChecked()) + { + meta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; + if (!ui.circleComboBox->getChosenCircle(meta.mCircleId)) + { + problem = true; + } + } + else if (ui.typeGroup->isChecked()) + { + meta.mCircleType = GXS_CIRCLE_TYPE_YOUREYESONLY; + meta.mCircleId.clear(); + meta.mOriginator.clear(); + meta.mInternalCircle = "Internal Circle Id"; + + problem = true; + } + else + { + problem = true; + } + + if (problem) + { + // error. + meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; + meta.mCircleId.clear(); + meta.mOriginator.clear(); + meta.mInternalCircle.clear(); + } +} + + + +void GxsGroupDialog::cancelDialog() +{ + std::cerr << "GxsGroupDialog::cancelDialog() Should Close!"; + std::cerr << std::endl; + + close(); +} + +void GxsGroupDialog::addGroupLogo() +{ + QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Group Logo"), 64, 64); + + if (img.isNull()) + return; + + picture = img; + + // to show the selected + ui.groupLogo->setPixmap(picture); +} + +QPixmap GxsGroupDialog::getLogo() +{ + return picture; +} + +QString GxsGroupDialog::getDescription() +{ + return ui.groupDesc->document()->toPlainText(); +} + +/*********************************************************************************** + Share Lists. + ***********************************************************************************/ + +void GxsGroupDialog::sendShareList(std::string groupId) +{ + close(); +} + +void GxsGroupDialog::setShareList() +{ + if (ui.pubKeyShare_cb->isChecked()){ + this->resize(this->size().width() + ui.contactsdockWidget->size().width(), this->size().height()); + ui.contactsdockWidget->show(); + } else { // hide share widget + ui.contactsdockWidget->hide(); + this->resize(this->size().width() - ui.contactsdockWidget->size().width(), this->size().height()); + } +} + +void GxsGroupDialog::wikitype() +{ + // hide logo Button/Label + ui.groupLogo->hide(); + ui.addLogoButton->hide(); + + ui.headerFrame->setHeaderImage(QPixmap(":/images/resource-group-new_48.png")) ; + ui.pubKeyShare_cb->setText(tr("Add Wiki Moderators")); + ui.contactsdockWidget->setWindowTitle(tr("Select Wiki Moderators")); +} diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.h b/retroshare-gui/src/gui/gxs/GxsGroupDialog.h new file mode 100644 index 000000000..beae5e965 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.h @@ -0,0 +1,224 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GXS_GROUP_DIALOG_H +#define _GXS_GROUP_DIALOG_H + +#include "ui_GxsGroupDialog.h" + +#include "util/TokenQueue.h" + + +/******** + * Notes: + * + * This is a generic Group Dialog, which is expected to be overloaded to include + * specific data for a specific service. + * + * To acheive this, we have a GxsGroupExtension widget + * - programmatically added to the GUI. + * - called to fill in fields in the Data Structures. + * + * To enable extension, we have a bunch of flags so various options can + * be shown / disabled for each specific service. + * - Enabled. + * - Defaults. + * - ReadOnly + * + * This form will be used for Create/Edit & View of Group Info. + */ + +class GxsGroupExtension: public QWidget +{ +public: + GxsGroupExtension() : QWidget() { return; } + +}; + + +/*** Group flags affect what is visually enabled that gets input into the grpMeta ***/ + +#define GXS_GROUP_FLAGS_ICON 0x00000001 +#define GXS_GROUP_FLAGS_DESCRIPTION 0x00000002 +#define GXS_GROUP_FLAGS_DISTRIBUTION 0x00000004 +#define GXS_GROUP_FLAGS_PUBLISHSIGN 0x00000008 +#define GXS_GROUP_FLAGS_SHAREKEYS 0x00000010 +#define GXS_GROUP_FLAGS_PERSONALSIGN 0x00000020 +#define GXS_GROUP_FLAGS_COMMENTS 0x00000040 + +#define GXS_GROUP_FLAGS_EXTRA 0x00000100 + +/*** Default flags are used to determine privacy of group, signatures required *** + *** whether publish or id and whether comments are allowed or not ***/ + + +#define GXS_GROUP_DEFAULTS_DISTRIB_MASK 0x0000000f +#define GXS_GROUP_DEFAULTS_PUBLISH_MASK 0x000000f0 +#define GXS_GROUP_DEFAULTS_PERSONAL_MASK 0x00000f00 +#define GXS_GROUP_DEFAULTS_COMMENTS_MASK 0x0000f000 + +#define GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC 0x00000001 +#define GXS_GROUP_DEFAULTS_DISTRIB_GROUP 0x00000002 +#define GXS_GROUP_DEFAULTS_DISTRIB_LOCAL 0x00000004 + +#define GXS_GROUP_DEFAULTS_PUBLISH_OPEN 0x00000010 +#define GXS_GROUP_DEFAULTS_PUBLISH_THREADS 0x00000020 +#define GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED 0x00000040 +#define GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED 0x00000080 + +#define GXS_GROUP_DEFAULTS_PERSONAL_PGP 0x00000100 +#define GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED 0x00000200 +#define GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB 0x00000400 + +#define GXS_GROUP_DEFAULTS_COMMENTS_YES 0x00001000 +#define GXS_GROUP_DEFAULTS_COMMENTS_NO 0x00002000 + +/*! + * The aim of this dialog is to be convenient to encapsulate group + * creation code for several GXS services such forums, channels + * and posted + * The functionality provided are for group creation are: + * - Specifying the authentication type of the group + * - Specifying group image + * - + * The main limitation is that it will not deal with the actual service GXS Group + * data structure, but the meta structure which is the same across GXS services + * The long term plan is perhap logic structure (i.e. code) will be moved into each GXS \n + * service for better customisation of group creation, or perhaps not! + */ +class GxsGroupDialog : public QDialog +{ + Q_OBJECT + +public: + enum Mode { + MODE_CREATE, + MODE_SHOW, + MODE_EDIT + }; + +public: + + /*! + * Constructs a GxsGroupDialog for creating group + * @param tokenQueue This should be the TokenQueue of the (parent) service + * in order to receive acknowledgement of group creation, if set to NULL with create mode \n + * creation will not happen + * @param enableFlags This determines what options are enabled such as Icon, Description, publish type and key sharing + * @param defaultFlags This deter + * @param parent The parent dialog + * @param mode + */ + GxsGroupDialog(TokenQueue* tokenQueue, uint32_t enableFlags, uint16_t defaultFlags, QWidget *parent = NULL); + + /*! + * Contructs a GxsGroupDialog for display a group or editing + * @param grpMeta This is used to fill out the dialog + * @param mode This determines whether the dialog starts in show or edit mode (Edit not supported yet) + * @param parent + */ + GxsGroupDialog(const RsGroupMetaData& grpMeta, Mode mode, QWidget *parent = NULL); + void wikitype(); + + uint32_t mode() { return mMode; } + +private: + void newGroup(); + void init(); + void initMode(); + + // Functions that can be overloaded for specific stuff. + +protected slots: + void submitGroup(); + void addGroupLogo(); + +protected: + virtual void showEvent(QShowEvent*); + + virtual QString serviceHeader() = 0; + virtual QPixmap serviceImage() = 0; + + /*! + * Main purpose is to help tansfer meta data to service + * + * @param token This should be set to the token retrieved + * @param meta The deriving GXS service should set their grp meta to this value + */ + virtual bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta) = 0; + + /*! + * This returns a group logo from the ui \n + * Should be calleld by deriving service + * @return The logo for the service + */ + QPixmap getLogo(); + + /*! + * This returns a group description string from the ui + * @return group description string + */ + virtual QString getDescription(); + + +private slots: + + /* actions to take.... */ + void cancelDialog(); + + // set private forum key share list + void setShareList(); + + void updateCircleOptions(); + +private: + + + void setCircleParameters(RsGroupMetaData &meta); + + + void setGroupSignFlags(uint32_t signFlags); + uint32_t getGroupSignFlags(); + void setupDefaults(); + void setupVisibility(); + void clearForm(); + void createGroup(); + void sendShareList(std::string forumId); + void loadNewGroupId(const uint32_t &token); + + + std::list mShareList; + QPixmap picture; + TokenQueue *mTokenQueue; + RsGroupMetaData mGrpMeta; + + uint32_t mMode; + uint32_t mEnabledFlags; + uint32_t mReadonlyFlags; + uint32_t mDefaultsFlags; + + /** Qt Designer generated object */ + Ui::GxsGroupDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui new file mode 100644 index 000000000..6c30bc5eb --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.ui @@ -0,0 +1,505 @@ + + + GxsGroupDialog + + + + 0 + 0 + 695 + 658 + + + + Create New + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + + + 0 + + + 4 + + + + + 6 + + + 0 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + :/images/channels.png + + + true + + + + + + + 6 + + + 6 + + + + + Name + + + + + + + + + + + + 9 + + + 3 + + + + + Add Icon + + + + :/images/add_image24.png:/images/add_image24.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Key recipients can publish to restricted-type Wiki Group, and can view and publish for private-type channels + + + Share Publish Key + + + + + + + + + + + + + + true + + + + 0 + 0 + + + + + 300 + 524287 + + + + + 220 + 0 + + + + + 0 + 0 + + + + check peers you would like to share private publish key with + + + false + + + QDockWidget::NoDockWidgetFeatures + + + Share Key With + + + + + 0 + + + 0 + + + + + + 0 + 4 + + + + + 20 + 0 + + + + + 300 + 16777215 + + + + + 220 + 0 + + + + + 200 + 0 + + + + + + + + + + + + + + Description + + + + + + + + + + + + Message Distribution + + + + 0 + + + 4 + + + + + + + Public + + + + + + + Restricted to Group + + + + + + + Only For Your Friends + + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 40 + 20 + + + + + + + + + Some Friends + + + + + Another Group + + + + + Family? + + + + + Enemies + + + + + + + + + + + + + Publish Signatures + + + + 0 + + + 4 + + + + + Open + + + + + + + New Thread + + + + + + + Required + + + + + + + Encrypted Msgs + + + + + + + + + + Personal Signatures + + + + 0 + + + 4 + + + + + PGP Required + + + + + + + Signature Required + + + + + + + If No Publish Signature + + + + + + + + + + Comments + + + + 0 + + + 4 + + + + + Allow Comments + + + + + + + No Comments + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
+
+ + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1 +
+ + FriendSelectionWidget + QWidget +
gui/common/FriendSelectionWidget.h
+ 1 +
+ + GxsCircleChooser + QComboBox +
gui/gxs/GxsCircleChooser.h
+
+
+ + + + +
diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp new file mode 100644 index 000000000..0b1fadb48 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp @@ -0,0 +1,143 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "GxsIdChooser.h" + +#include + +#include + +#include + +/** Constructor */ +GxsIdChooser::GxsIdChooser(QWidget *parent) +: QComboBox(parent), mFlags(IDCHOOSER_ANON_DEFAULT), mDefaultId("") +{ + return; +} + +void GxsIdChooser::loadIds(uint32_t chooserFlags, RsGxsId defId) +{ + mFlags = chooserFlags; + mDefaultId = defId; + loadPrivateIds(); +} + + +bool MakeIdDesc(const RsGxsId &id, QString &desc) +{ + RsIdentityDetails details; + + if (!rsIdentity->getIdDetails(id, details)) + { + return false; + } + + desc = QString::fromUtf8(details.mNickname.c_str()); + if (details.mPgpLinked) + { + desc += " (PGP) ["; + } + else + { + desc += " (Anon) ["; + } + desc += QString::fromStdString(id.substr(0,5)); + desc += "...]"; + + return true; +} + + +void GxsIdChooser::loadPrivateIds() +{ + std::list ids; + rsIdentity->getOwnIds(ids); + + + if (ids.empty()) + { + std::cerr << "GxsIdChooser::loadPrivateIds() ERROR no ids"; + std::cerr << std::endl; + return; + } + + //rsIdentity->getDefaultId(defId); + // Prefer to use an application specific default??? + int def = -1; + + if (!(mFlags & IDCHOOSER_ID_REQUIRED)) + { + /* add No Signature option */ + QString str = "No Signature"; + QString id = ""; + + addItem(str, id); + if (mFlags & IDCHOOSER_ANON_DEFAULT) + { + def = 0; + } + } + + int i = 1; + std::list::iterator it; + for(it = ids.begin(); it != ids.end(); it++, i++) + { + /* add to Chooser */ + QString str; + if (!MakeIdDesc(*it, str)) + { + std::cerr << "GxsIdChooser::loadPrivateIds() ERROR Desc for Id: " << *it; + std::cerr << std::endl; + continue; + } + QString id = QString::fromStdString(*it); + + addItem(str, id); + + if (mDefaultId == *it) + { + def = i; + } + } + + if (def >= 0) + { + setCurrentIndex(def); + //ui.comboBox->setCurrentIndex(def); + } +} + +bool GxsIdChooser::getChosenId(RsGxsId &id) +{ + if (count() < 1) + { + return false; + } + + int idx = currentIndex(); + + QVariant var = itemData(idx); + id = var.toString().toStdString(); + + return true; +} + diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.h b/retroshare-gui/src/gui/gxs/GxsIdChooser.h new file mode 100644 index 000000000..39606442a --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.h @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GXS_ID_CHOOSER_H +#define _GXS_ID_CHOOSER_H + +#include +#include + +#define IDCHOOSER_ID_REQUIRED 0x0001 +#define IDCHOOSER_ANON_DEFAULT 0x0002 + +class GxsIdChooser : public QComboBox +{ + Q_OBJECT + +public: + GxsIdChooser(QWidget *parent = NULL); + + void loadIds(uint32_t chooserFlags, RsGxsId defId); + bool getChosenId(RsGxsId &id); + +private: + void loadPrivateIds(); + + uint32_t mFlags; + RsGxsId mDefaultId; +}; + +#endif + diff --git a/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp b/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp new file mode 100644 index 000000000..26189b803 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp @@ -0,0 +1,124 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "GxsIdLabel.h" + +#include + +#include + +#include + +/** Constructor */ +GxsIdLabel::GxsIdLabel(QWidget *parent) +:QLabel(parent), mTimer(NULL), mCount(0) +{ + mTimer = new QTimer(this); + mTimer->setSingleShot(true); + connect(mTimer, SIGNAL(timeout()), this, SLOT(loadId())); + + return; +} + +void GxsIdLabel::setId(const RsGxsId &id) +{ + mId = id; + if (mId == "") + { + setText("No Signature"); + } + else + { + loadId(); + } +} + +bool GxsIdLabel::getId(RsGxsId &id) +{ + id = mId; + return true; +} + +static bool MakeIdDesc(const RsGxsId &id, QString &str) +{ + RsIdentityDetails details; + + if (!rsIdentity->getIdDetails(id, details)) + { + str = "Loading... " + QString::fromStdString(id.substr(0,5)); + return false; + } + + str = QString::fromUtf8(details.mNickname.c_str()); + + bool addCode = true; + if (details.mPgpLinked) + { + str += " (PGP) ["; + if (details.mPgpKnown) + { + /* look up real name */ + std::string authorName = rsPeers->getPeerName(details.mPgpId); + str += QString::fromUtf8(authorName.c_str()); + str += "]"; + + addCode = false; + } + } + else + { + str += " (Anon) ["; + } + + if (addCode) + { + str += QString::fromStdString(id.substr(0,5)); + str += "...]"; + } + + return true; +} + +#define MAX_ATTEMPTS 3 + +void GxsIdLabel::loadId() +{ + mCount++; + + /* try and get details - if not there ... set callback */ + QString desc; + bool loaded = MakeIdDesc(mId, desc); + + setText(desc); + + if (loaded) + { + return; + } + + if (mCount < MAX_ATTEMPTS) + { + /* timer event to try again */ + mTimer->setInterval(mCount * 1000); + mTimer->start(); + } +} + diff --git a/retroshare-gui/src/gui/gxs/GxsIdLabel.h b/retroshare-gui/src/gui/gxs/GxsIdLabel.h new file mode 100644 index 000000000..e0e7c4992 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsIdLabel.h @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GXS_ID_LABEL_H +#define _GXS_ID_LABEL_H + +#include +#include +#include + +class GxsIdLabel : public QLabel +{ + Q_OBJECT + +public: + GxsIdLabel(QWidget *parent = NULL); + + void setId(const RsGxsId &id); + bool getId(RsGxsId &id); + +private slots: + void loadId(); + +private: + + QTimer *mTimer; + RsGxsId mId; + int mCount; +}; + +#endif + diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp new file mode 100644 index 000000000..17668bb61 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -0,0 +1,137 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "GxsIdTreeWidgetItem.h" + +#include + +#include + +/** Constructor */ +GxsIdTreeWidgetItem::GxsIdTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *parent) +:RSTreeWidgetItem(compareRole, parent), QObject(NULL), mTimer(NULL), mCount(0), mColumn(0) +{ + init(); +} + +GxsIdTreeWidgetItem::GxsIdTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent) +:RSTreeWidgetItem(compareRole, parent), QObject(NULL), mTimer(NULL), mCount(0), mColumn(0) +{ + init(); +} + +void GxsIdTreeWidgetItem::init() +{ + mTimer = new QTimer(this); + mTimer->setSingleShot(true); + connect(mTimer, SIGNAL(timeout()), this, SLOT(loadId())); +} + +void GxsIdTreeWidgetItem::setId(const RsGxsId &id, int column) +{ + std::cerr << " GxsIdTreeWidgetItem::setId(" << id << "," << column << ")"; + std::cerr << std::endl; + + mId = id; + mColumn = column; + if (mId == "") + { + setText(mColumn, "No Signature"); + } + else + { + loadId(); + } +} + +bool GxsIdTreeWidgetItem::getId(RsGxsId &id) +{ + id = mId; + return true; +} + +static bool MakeIdDesc(const RsGxsId &id, QString &str) +{ + RsIdentityDetails details; + + if (!rsIdentity->getIdDetails(id, details)) + { + str = "Loading... " + QString::fromStdString(id.substr(0,5)); + return false; + } + + str = QString::fromUtf8(details.mNickname.c_str()); + + bool addCode = true; + if (details.mPgpLinked) + { + str += " (PGP) ["; + if (details.mPgpKnown) + { + /* look up real name */ + std::string authorName = rsPeers->getPeerName(details.mPgpId); + str += QString::fromUtf8(authorName.c_str()); + str += "]"; + + addCode = false; + } + } + else + { + str += " (Anon) ["; + } + + if (addCode) + { + str += QString::fromStdString(id.substr(0,5)); + str += "...]"; + } + + return true; +} + +#define MAX_ATTEMPTS 5 + +void GxsIdTreeWidgetItem::loadId() +{ + std::cerr << " GxsIdTreeWidgetItem::loadId() Id: " << mId << ", mCount: " << mCount; + std::cerr << std::endl; + + mCount++; + + /* try and get details - if not there ... set callback */ + QString desc; + bool loaded = MakeIdDesc(mId, desc); + + setText(mColumn, desc); + + if (loaded) + { + return; + } + + if (mCount < MAX_ATTEMPTS) + { + /* timer event to try again */ + mTimer->setInterval(mCount * 1000); + mTimer->start(); + } +} diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h new file mode 100644 index 000000000..9b61bff28 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h @@ -0,0 +1,55 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GXS_ID_TREEWIDGETITEM_H +#define _GXS_ID_TREEWIDGETITEM_H + +#include +#include + +#include "gui/common/RSTreeWidgetItem.h" + +class GxsIdTreeWidgetItem : public QObject, public RSTreeWidgetItem +{ + Q_OBJECT + +public: + GxsIdTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *parent = NULL); + GxsIdTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent); + + void setId(const RsGxsId &id, int column); + bool getId(RsGxsId &id); + +private slots: + void loadId(); + +private: + void init(); + + QTimer *mTimer; + RsGxsId mId; + int mCount; + int mColumn; +}; + +#endif + diff --git a/retroshare-gui/src/gui/gxs/WikiGroupDialog.cpp b/retroshare-gui/src/gui/gxs/WikiGroupDialog.cpp new file mode 100644 index 000000000..95a1b4399 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/WikiGroupDialog.cpp @@ -0,0 +1,152 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "WikiGroupDialog.h" + +#include +#include + +const uint32_t WikiCreateEnabledFlags = ( GXS_GROUP_FLAGS_ICON | + GXS_GROUP_FLAGS_DESCRIPTION | + GXS_GROUP_FLAGS_DISTRIBUTION | + // GXS_GROUP_FLAGS_PUBLISHSIGN | + GXS_GROUP_FLAGS_SHAREKEYS | + // GXS_GROUP_FLAGS_PERSONALSIGN | + // GXS_GROUP_FLAGS_COMMENTS | + 0); + +uint32_t WikiCreateDefaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC | + //GXS_GROUP_DEFAULTS_DISTRIB_GROUP | + //GXS_GROUP_DEFAULTS_DISTRIB_LOCAL | + + GXS_GROUP_DEFAULTS_PUBLISH_OPEN | + //GXS_GROUP_DEFAULTS_PUBLISH_THREADS | + //GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED | + //GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED | + + //GXS_GROUP_DEFAULTS_PERSONAL_GPG | + GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED | + //GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB | + + //GXS_GROUP_DEFAULTS_COMMENTS_YES | + GXS_GROUP_DEFAULTS_COMMENTS_NO | + 0); + + +WikiGroupDialog::WikiGroupDialog(TokenQueue *tokenQueue, QWidget *parent) + :GxsGroupDialog(tokenQueue, WikiCreateEnabledFlags, WikiCreateDefaultsFlags, parent) +{ + + // To start with we only have open forums - with distribution controls. +#if 0 + uint32_t enabledFlags = ( GXS_GROUP_FLAGS_ICON | + GXS_GROUP_FLAGS_DESCRIPTION | + GXS_GROUP_FLAGS_DISTRIBUTION | + // GXS_GROUP_FLAGS_PUBLISHSIGN | + GXS_GROUP_FLAGS_SHAREKEYS | + // GXS_GROUP_FLAGS_PERSONALSIGN | + // GXS_GROUP_FLAGS_COMMENTS | + 0); + + uint32_t readonlyFlags = 0; + + uint32_t defaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC | + //GXS_GROUP_DEFAULTS_DISTRIB_GROUP | + //GXS_GROUP_DEFAULTS_DISTRIB_LOCAL | + + GXS_GROUP_DEFAULTS_PUBLISH_OPEN | + //GXS_GROUP_DEFAULTS_PUBLISH_THREADS | + //GXS_GROUP_DEFAULTS_PUBLISH_REQUIRED | + //GXS_GROUP_DEFAULTS_PUBLISH_ENCRYPTED | + + //GXS_GROUP_DEFAULTS_PERSONAL_GPG | + GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED | + //GXS_GROUP_DEFAULTS_PERSONAL_IFNOPUB | + + //GXS_GROUP_DEFAULTS_COMMENTS_YES | + GXS_GROUP_DEFAULTS_COMMENTS_NO | + 0); + + //setFlags(enabledFlags, readonlyFlags, defaultsFlags); + setFlags(enabledFlags, defaultsFlags); +#endif + +} + +WikiGroupDialog::WikiGroupDialog(const RsWikiCollection &collection, QWidget *parent) + :GxsGroupDialog(collection.mMeta, MODE_SHOW, parent) +{ +#if 0 + + // To start with we only have open forums - with distribution controls. + + uint32_t enabledFlags = ( GXS_GROUP_FLAGS_ICON | + GXS_GROUP_FLAGS_DESCRIPTION | + GXS_GROUP_FLAGS_DISTRIBUTION | + GXS_GROUP_FLAGS_SHAREKEYS | + 0); + + uint32_t readonlyFlags = 0; + + uint32_t defaultsFlags = ( GXS_GROUP_DEFAULTS_DISTRIB_PUBLIC | + GXS_GROUP_DEFAULTS_PUBLISH_OPEN | + GXS_GROUP_DEFAULTS_PERSONAL_REQUIRED | + GXS_GROUP_DEFAULTS_COMMENTS_NO | + 0); + + setFlags(enabledFlags, defaultsFlags); +#endif + +} + +QString WikiGroupDialog::serviceHeader() +{ + switch (mode()) + { + case MODE_CREATE: + return tr("Create New Wiki Group"); + case MODE_SHOW: + return tr("Wiki Group"); + case MODE_EDIT: + return tr("Edit Wiki Group"); + } + + return ""; +} + +QPixmap WikiGroupDialog::serviceImage() +{ + return QPixmap(":/images/resource-group_64.png"); +} + +bool WikiGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta) +{ + // Specific Function. + RsWikiCollection grp; + grp.mMeta = meta; + //grp.mDescription = std::string(desc.toUtf8()); + std::cerr << "WikiGroupDialog::service_CreateGroup() storing to Queue"; + std::cerr << std::endl; + + rsWiki->submitCollection(token, grp); + + return true; +} diff --git a/retroshare-gui/src/gui/forumsv2/EditForumV2Details.h b/retroshare-gui/src/gui/gxs/WikiGroupDialog.h similarity index 64% rename from retroshare-gui/src/gui/forumsv2/EditForumV2Details.h rename to retroshare-gui/src/gui/gxs/WikiGroupDialog.h index 55c9c2bc7..b35333065 100644 --- a/retroshare-gui/src/gui/forumsv2/EditForumV2Details.h +++ b/retroshare-gui/src/gui/gxs/WikiGroupDialog.h @@ -1,7 +1,7 @@ /**************************************************************** * RetroShare is distributed under the following license: * - * Copyright (C) 2010 RetroShare Team + * Copyright (C) 2008 Robert Fernie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,34 +19,30 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ -#ifndef _EDITFORUMV2DETAILS_H -#define _EDITFORUMV2DETAILS_H -#include +#ifndef _WIKI_GROUP_DIALOG_H +#define _WIKI_GROUP_DIALOG_H -#include "ui_EditForumV2Details.h" +#include "GxsGroupDialog.h" +#include "retroshare/rswiki.h" -class EditForumV2Details : public QDialog +class WikiGroupDialog : public GxsGroupDialog { - Q_OBJECT + Q_OBJECT public: - /** Default constructor */ - EditForumV2Details(std::string forumId = "", QWidget *parent = 0, Qt::WFlags flags = 0); + WikiGroupDialog(TokenQueue *tokenQueue, QWidget *parent); + WikiGroupDialog(const RsWikiCollection &collection, QWidget *parent); -signals: - void configChanged(); - -private slots: - void applyDialog(); +protected: + virtual QString serviceHeader(); + virtual QPixmap serviceImage(); + virtual bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta); private: - void loadForum(); - std::string m_forumId; + RsWikiCollection mGrp; - /** Qt Designer generated object */ - Ui::EditForumV2Details ui; }; #endif diff --git a/retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.cpp b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp similarity index 68% rename from retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.cpp rename to retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp index bb884c5c5..f0c0e85cb 100644 --- a/retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.cpp +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.cpp @@ -19,7 +19,7 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ -#include "CreateForumV2Msg.h" +#include "CreateGxsForumMsg.h" #include #include @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include "gui/settings/rsharesettings.h" @@ -42,20 +42,26 @@ #include -#define CREATEFORUMV2MSG_FORUMINFO 1 -#define CREATEFORUMV2MSG_PARENTMSG 2 +#define CREATEGXSFORUMMSG_FORUMINFO 1 +#define CREATEGXSFORUMMSG_PARENTMSG 2 /** Constructor */ -CreateForumV2Msg::CreateForumV2Msg(std::string fId, std::string pId) -: QMainWindow(NULL), mForumId(fId), mParentId(pId) +CreateGxsForumMsg::CreateGxsForumMsg(const std::string &fId, const std::string &pId) +: QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mForumId(fId), mParentId(pId) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); /* Setup Queue */ - mForumQueue = new TokenQueue(rsForumsV2, this); + mForumQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + + QString text = pId.empty() ? tr("Start New Thread") : tr("Post Forum Message"); + setWindowTitle(text); + + ui.headerFrame->setHeaderImage(QPixmap(":/images/konversation64.png")); + ui.headerFrame->setHeaderText(text); Settings->loadWidgetInformation(this); @@ -64,8 +70,8 @@ CreateForumV2Msg::CreateForumV2Msg(std::string fId, std::string pId) connect(ui.hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); // connect up the buttons. - connect( ui.postmessage_action, SIGNAL( triggered (bool) ), this, SLOT( createMsg( ) ) ); - connect( ui.close_action, SIGNAL( triggered (bool) ), this, SLOT( cancelMsg( ) ) ); + connect( ui.buttonBox, SIGNAL(accepted()), this, SLOT(createMsg())); + connect( ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect( ui.emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidgetForums())); connect( ui.attachFileButton, SIGNAL(clicked() ), this , SLOT(addFile())); connect( ui.pastersButton, SIGNAL(clicked() ), this , SLOT(pasteLink())); @@ -81,14 +87,14 @@ CreateForumV2Msg::CreateForumV2Msg(std::string fId, std::string pId) } /** context menu searchTablewidget2 **/ -void CreateForumV2Msg::forumMessageCostumPopupMenu(QPoint point) +void CreateGxsForumMsg::forumMessageCostumPopupMenu(QPoint point) { QMenu *contextMnu = ui.forumMessage->createStandardContextMenu(point); contextMnu->addSeparator(); QAction *pasteLinkAct = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); QAction *pasteLinkFullAct = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste full RetroShare Link"), this, SLOT(pasteLinkFull())); - contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste my certificate link"), this, SLOT(pasteOwnCertificateLink())); + contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste own certificate link"), this, SLOT(pasteOwnCertificateLink())); if (RSLinkClipboard::empty()) { pasteLinkAct->setDisabled (true); @@ -99,12 +105,15 @@ void CreateForumV2Msg::forumMessageCostumPopupMenu(QPoint point) delete(contextMnu); } -void CreateForumV2Msg::newMsg() +void CreateGxsForumMsg::newMsg() { /* clear all */ mParentMsgLoaded = false; mForumMetaLoaded = false; + /* fill in the available OwnIds for signing */ + ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, ""); + /* request Data */ { RsTokReqOptions opts; @@ -116,7 +125,7 @@ void CreateForumV2Msg::newMsg() std::cerr << std::endl; uint32_t token; - mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEFORUMV2MSG_FORUMINFO); + mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEGXSFORUMMSG_FORUMINFO); } @@ -132,12 +141,14 @@ void CreateForumV2Msg::newMsg() std::cerr << std::endl; uint32_t token; - mForumQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEFORUMV2MSG_PARENTMSG); +#ifdef TOGXS + mForumQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_PARENTMSG); +#endif } } -void CreateForumV2Msg::saveForumInfo(const RsGroupMetaData &meta) +void CreateGxsForumMsg::saveForumInfo(const RsGroupMetaData &meta) { mForumMeta = meta; mForumMetaLoaded = true; @@ -145,7 +156,7 @@ void CreateForumV2Msg::saveForumInfo(const RsGroupMetaData &meta) loadFormInformation(); } -void CreateForumV2Msg::saveParentMsg(const RsForumV2Msg &msg) +void CreateGxsForumMsg::saveParentMsg(const RsGxsForumMsg &msg) { mParentMsg = msg; mParentMsgLoaded = true; @@ -153,23 +164,23 @@ void CreateForumV2Msg::saveParentMsg(const RsForumV2Msg &msg) loadFormInformation(); } -void CreateForumV2Msg::loadFormInformation() +void CreateGxsForumMsg::loadFormInformation() { if ((!mParentMsgLoaded) && (mParentId != "")) { - std::cerr << "CreateForumV2Msg::loadMsgInformation() ParentMsg not Loaded Yet"; + std::cerr << "CreateGxsForumMsg::loadMsgInformation() ParentMsg not Loaded Yet"; std::cerr << std::endl; return; } if (!mForumMetaLoaded) { - std::cerr << "CreateForumV2Msg::loadMsgInformation() ForumMeta not Loaded Yet"; + std::cerr << "CreateGxsForumMsg::loadMsgInformation() ForumMeta not Loaded Yet"; std::cerr << std::endl; return; } - std::cerr << "CreateForumV2Msg::loadMsgInformation() Data Available!"; + std::cerr << "CreateGxsForumMsg::loadMsgInformation() Data Available!"; std::cerr << std::endl; QString name = QString::fromUtf8(mForumMeta.mGroupName.c_str()); @@ -205,7 +216,11 @@ void CreateForumV2Msg::loadFormInformation() ui.forumSubject->setFocus(); } +#ifdef TOGXS if (mForumMeta.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) +#else + if (1) +#endif { ui.signBox->setChecked(true); ui.signBox->setEnabled(false); @@ -222,7 +237,7 @@ void CreateForumV2Msg::loadFormInformation() -void CreateForumV2Msg::createMsg() +void CreateGxsForumMsg::createMsg() { QString name = misc::removeNewLine(ui.forumSubject->text()); QString desc; @@ -237,7 +252,7 @@ void CreateForumV2Msg::createMsg() return; //Don't add a empty Subject!! } - RsForumV2Msg msg; + RsGxsForumMsg msg; msg.mMeta.mGroupId = mForumId; msg.mMeta.mParentId = mParentId; msg.mMeta.mMsgId = ""; @@ -248,13 +263,36 @@ void CreateForumV2Msg::createMsg() msg.mMeta.mMsgName = std::string(name.toUtf8()); msg.mMsg = std::string(desc.toUtf8()); +#ifdef TOGXS msg.mMeta.mMsgFlags = RS_DISTRIB_AUTHEN_REQ; +#endif if ((msg.mMsg == "") && (msg.mMeta.mMsgName == "")) - return; /* do nothing */ - + return; /* do nothing */ + + if (ui.signBox->isChecked()) + { + RsGxsId authorId; + if (ui.idChooser->getChosenId(authorId)) + { + msg.mMeta.mAuthorId = authorId; + std::cerr << "CreateGxsForumMsg::createMsg() AuthorId: " << authorId; + std::cerr << std::endl; + } + else + { + std::cerr << "CreateGxsForumMsg::createMsg() ERROR GETTING AuthorId!"; + std::cerr << std::endl; + } + } + else + { + std::cerr << "CreateGxsForumMsg::createMsg() No Signature (for now :)"; + std::cerr << std::endl; + } + uint32_t token; - rsForumsV2->createMsg(token, msg, true); + rsGxsForums->createMsg(token, msg); close(); @@ -287,37 +325,32 @@ void CreateForumV2Msg::createMsg() -void CreateForumV2Msg::closeEvent (QCloseEvent * /*event*/) +void CreateGxsForumMsg::closeEvent (QCloseEvent * /*event*/) { Settings->saveWidgetInformation(this); } -void CreateForumV2Msg::cancelMsg() -{ - close(); -} - -void CreateForumV2Msg::smileyWidgetForums() +void CreateGxsForumMsg::smileyWidgetForums() { Emoticons::showSmileyWidget(this, ui.emoticonButton, SLOT(addSmileys()), false); } -void CreateForumV2Msg::addSmileys() +void CreateGxsForumMsg::addSmileys() { ui.forumMessage->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); } -void CreateForumV2Msg::addFile() +void CreateGxsForumMsg::addFile() { QStringList files; if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { - ui.hashBox->addAttachments(files); + ui.hashBox->addAttachments(files,RS_FILE_REQ_ANONYMOUS_ROUTING); } } -void CreateForumV2Msg::fileHashingFinished(QList hashedFiles) +void CreateGxsForumMsg::fileHashingFinished(QList hashedFiles) { - std::cerr << "CreateForumV2Msg::fileHashingFinished() started." << std::endl; + std::cerr << "CreateGxsForumMsg::fileHashingFinished() started." << std::endl; QString mesgString; @@ -331,7 +364,7 @@ void CreateForumV2Msg::fileHashingFinished(QList hashedFiles) } #ifdef CHAT_DEBUG - std::cerr << "CreateForumV2Msg::anchorClicked mesgString : " << mesgString.toStdString() << std::endl; + std::cerr << "CreateGxsForumMsg::anchorClicked mesgString : " << mesgString.toStdString() << std::endl; #endif if (!mesgString.isEmpty()) { @@ -341,17 +374,17 @@ void CreateForumV2Msg::fileHashingFinished(QList hashedFiles) ui.forumMessage->setFocus( Qt::OtherFocusReason ); } -void CreateForumV2Msg::pasteLink() +void CreateGxsForumMsg::pasteLink() { ui.forumMessage->insertHtml(RSLinkClipboard::toHtml()) ; } -void CreateForumV2Msg::pasteLinkFull() +void CreateGxsForumMsg::pasteLinkFull() { ui.forumMessage->insertHtml(RSLinkClipboard::toHtmlFull()) ; } -void CreateForumV2Msg::pasteOwnCertificateLink() +void CreateGxsForumMsg::pasteOwnCertificateLink() { RetroShareLink link ; std::string ownId = rsPeers->getOwnId() ; @@ -363,13 +396,13 @@ void CreateForumV2Msg::pasteOwnCertificateLink() -void CreateForumV2Msg::loadForumInfo(const uint32_t &token) +void CreateGxsForumMsg::loadForumInfo(const uint32_t &token) { - std::cerr << "CreateForumV2Msg::loadForumInfo()"; + std::cerr << "CreateGxsForumMsg::loadForumInfo()"; std::cerr << std::endl; std::list groupInfo; - rsForumsV2->getGroupSummary(token, groupInfo); + rsGxsForums->getGroupSummary(token, groupInfo); if (groupInfo.size() == 1) { @@ -378,28 +411,38 @@ void CreateForumV2Msg::loadForumInfo(const uint32_t &token) } else { - std::cerr << "CreateForumV2Msg::loadForumInfo() ERROR INVALID Number of Forums"; + std::cerr << "CreateGxsForumMsg::loadForumInfo() ERROR INVALID Number of Forums"; std::cerr << std::endl; } } -void CreateForumV2Msg::loadParentMsg(const uint32_t &token) +void CreateGxsForumMsg::loadParentMsg(const uint32_t &token) { - std::cerr << "CreateForumV2Msg::loadParentMsg()"; + std::cerr << "CreateGxsForumMsg::loadParentMsg()"; std::cerr << std::endl; // Only grab one.... ignore more (shouldn't be any). - RsForumV2Msg msg; - rsForumsV2->getMsgData(token, msg); - saveParentMsg(msg); + std::vector msgs; + if (rsGxsForums->getMsgData(token, msgs)) + { + if (msgs.size() != 1) + { + /* error */ + std::cerr << "CreateGxsForumMsg::loadParentMsg() ERROR wrong number of msgs"; + std::cerr << std::endl; + + + } + saveParentMsg(msgs[0]); + } } -void CreateForumV2Msg::loadRequest(const TokenQueue *queue, const TokenRequest &req) +void CreateGxsForumMsg::loadRequest(const TokenQueue *queue, const TokenRequest &req) { - std::cerr << "CreateForumV2::loadRequest() UserType: " << req.mUserType; + std::cerr << "CreateGxsForum::loadRequest() UserType: " << req.mUserType; std::cerr << std::endl; if (queue == mForumQueue) @@ -407,15 +450,15 @@ void CreateForumV2Msg::loadRequest(const TokenQueue *queue, const TokenRequest & /* now switch on req */ switch(req.mUserType) { - case CREATEFORUMV2MSG_FORUMINFO: + case CREATEGXSFORUMMSG_FORUMINFO: loadForumInfo(req.mToken); break; - case CREATEFORUMV2MSG_PARENTMSG: + case CREATEGXSFORUMMSG_PARENTMSG: loadParentMsg(req.mToken); break; default: - std::cerr << "CreateForumV2::loadRequest() UNKNOWN UserType "; + std::cerr << "CreateGxsForum::loadRequest() UNKNOWN UserType "; std::cerr << std::endl; } diff --git a/retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.h b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h similarity index 83% rename from retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.h rename to retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h index 5b5de0194..7227234fd 100644 --- a/retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.h +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.h @@ -20,26 +20,25 @@ ****************************************************************/ -#ifndef _CREATE_FORUMV2_MSG_DIALOG_H -#define _CREATE_FORUMV2_MSG_DIALOG_H +#ifndef _CREATE_GXSFORUM_MSG_DIALOG_H +#define _CREATE_GXSFORUM_MSG_DIALOG_H -#include "ui_CreateForumV2Msg.h" +#include "ui_CreateGxsForumMsg.h" #include "util/TokenQueue.h" -#include +#include - -class CreateForumV2Msg : public QMainWindow, public TokenResponse +class CreateGxsForumMsg : public QDialog, public TokenResponse { Q_OBJECT public: - CreateForumV2Msg(std::string fId, std::string pId); + CreateGxsForumMsg(const std::string &fId, const std::string &pId); void newMsg(); /* cleanup */ virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); - + private slots: /** Create the context popup menu and it's submenus */ void forumMessageCostumPopupMenu( QPoint point ); @@ -47,7 +46,6 @@ private slots: void fileHashingFinished(QList hashedFiles); /* actions to take.... */ void createMsg(); - void cancelMsg(); void pasteLink(); void pasteLinkFull(); void pasteOwnCertificateLink(); @@ -60,26 +58,25 @@ protected: void closeEvent (QCloseEvent * event); private: - void saveForumInfo(const RsGroupMetaData &meta); - void saveParentMsg(const RsForumV2Msg &msg); + void saveParentMsg(const RsGxsForumMsg &msg); void loadFormInformation(); void loadForumInfo(const uint32_t &token); void loadParentMsg(const uint32_t &token); - + std::string mForumId; std::string mParentId; - + bool mParentMsgLoaded; bool mForumMetaLoaded; - RsForumV2Msg mParentMsg; + RsGxsForumMsg mParentMsg; RsGroupMetaData mForumMeta; TokenQueue *mForumQueue; /** Qt Designer generated object */ - Ui::CreateForumV2Msg ui; + Ui::CreateGxsForumMsg ui; }; #endif diff --git a/retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.ui b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui similarity index 54% rename from retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.ui rename to retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui index 39c8025b7..fcd330af9 100644 --- a/retroshare-gui/src/gui/forumsv2/CreateForumV2Msg.ui +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui @@ -1,7 +1,7 @@ - CreateForumV2Msg - + CreateGxsForumMsg + 0 @@ -17,21 +17,27 @@ :/images/rstray3.png:/images/rstray3.png - - Qt::ToolButtonTextUnderIcon - - - - - 0 - - - 0 - - - - - + + + 0 + + + 0 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + QFrame::NoFrame @@ -39,48 +45,37 @@ QFrame::Raised
- - 6 - - - 6 + + 0 - - - - - Forum - - - - - - - false - - - - + + + Forum + + + + + + + false + + - - - - - Subject - - - - - - - + + + Subject + + + + +
- + @@ -170,6 +165,9 @@ + + + @@ -206,112 +204,78 @@
- - - - QFrame::NoFrame + + + + Forum Post - - QFrame::Raised - - - - 6 - - - 6 - + - - - Forum Post + + + Qt::CustomContextMenu - - - - - Qt::CustomContextMenu - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> - - - - - - - - - - Attach files via drag and drop - - - - - - 0 - 0 - - - - You can attach files via drag and drop here in this window - - - true - - - - + + + + Attach files via drag and drop + + + + + + + 0 + 0 + + + + You can attach files via drag and drop here in this window + + + true + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + +
- - - - - - toolBar - - - false - - - TopToolBarArea - - - false - - - - - - - - :/images/mail_send24.png:/images/mail_send24.png - - - Post Forum Msg - - - - - - :/images/button_cancel.png:/images/button_cancel.png - - - Close - - + + + + + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
+
+ + HeaderFrame + QFrame +
gui/common/HeaderFrame.h
+ 1 +
HashBox QScrollArea diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp new file mode 100644 index 000000000..95104d008 --- /dev/null +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -0,0 +1,1893 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012, RetroShare Team + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include "GxsForumThreadWidget.h" +#include "ui_GxsForumThreadWidget.h" +#include "GxsForumsFillThread.h" +#include "gui/GxsForumsDialog.h" +#include "gui/RetroShareLink.h" +#include "gui/common/RSTreeWidgetItem.h" +#include "gui/common/RSItemDelegate.h" +#include "gui/settings/rsharesettings.h" +#include "gui/gxs/GxsIdTreeWidgetItem.h" +#include "util/HandleRichText.h" +#include "gui/gxs/GxsForumGroupDialog.h" +#include "CreateGxsForumMsg.h" +#include "gui/msgs/MessageComposer.h" + +#include +#include +// These should be in retroshare/ folder. +#include "gxs/rsgxsflags.h" + +#include + +#define DEBUG_FORUMS + +/* Images for context menu icons */ +#define IMAGE_MESSAGE ":/images/folder-draft.png" +#define IMAGE_MESSAGEREPLY ":/images/mail_reply.png" +#define IMAGE_MESSAGEREMOVE ":/images/mail_delete.png" +#define IMAGE_DOWNLOAD ":/images/start.png" +#define IMAGE_DOWNLOADALL ":/images/startall.png" +#define IMAGE_COPYLINK ":/images/copyrslink.png" + +#define VIEW_LAST_POST 0 +#define VIEW_THREADED 1 +#define VIEW_FLAT 2 + +/* Thread constants */ +#define COLUMN_THREAD_COUNT 6 +#define COLUMN_THREAD_TITLE 0 +#define COLUMN_THREAD_READ 1 +#define COLUMN_THREAD_DATE 2 +#define COLUMN_THREAD_AUTHOR 3 +#define COLUMN_THREAD_SIGNED 4 +#define COLUMN_THREAD_CONTENT 5 + +#define COLUMN_THREAD_DATA 0 // column for storing the userdata like msgid and parentid + +#define ROLE_THREAD_MSGID Qt::UserRole +#define ROLE_THREAD_STATUS Qt::UserRole + 1 +#define ROLE_THREAD_MISSING Qt::UserRole + 2 +// no need to copy, don't count in ROLE_THREAD_COUNT +#define ROLE_THREAD_READCHILDREN Qt::UserRole + 3 +#define ROLE_THREAD_UNREADCHILDREN Qt::UserRole + 4 +#define ROLE_THREAD_SORT Qt::UserRole + 5 + +#define ROLE_THREAD_COUNT 3 + +#define TOKEN_TYPE_CURRENTFORUM 1 +#define TOKEN_TYPE_INSERT_POST 2 +#define TOKEN_TYPE_REPLY_MESSAGE 3 + +GxsForumThreadWidget::GxsForumThreadWidget(const std::string &forumId, QWidget *parent) : + QWidget(parent), + ui(new Ui::GxsForumThreadWidget) +{ + ui->setupUi(this); + + mForumId = forumId; + mSubscribeFlags = 0; + mInProcessSettings = false; + mUnreadCount = 0; + mNewCount = 0; + + mThreadQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + + mInMsgAsReadUnread = false; + + mThreadCompareRole = new RSTreeWidgetItemCompareRole; + mThreadCompareRole->setRole(COLUMN_THREAD_DATE, ROLE_THREAD_SORT); + + connect(ui->threadTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(threadListCustomPopupMenu(QPoint))); + + connect(ui->newmessageButton, SIGNAL(clicked()), this, SLOT(createmessage())); + connect(ui->newthreadButton, SIGNAL(clicked()), this, SLOT(createthread())); + + connect(ui->threadTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(changedThread())); + connect(ui->threadTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(clickedThread(QTreeWidgetItem*,int))); + connect(ui->viewBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changedViewBox())); + + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(togglethreadview())); + connect(ui->previousButton, SIGNAL(clicked()), this, SLOT(previousMessage())); + connect(ui->nextButton, SIGNAL(clicked()), this, SLOT(nextMessage())); + connect(ui->nextUnreadButton, SIGNAL(clicked()), this, SLOT(nextUnreadMessage())); + connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(downloadAllFiles())); + + // HACK - TEMPORARY HIJACKING THIS BUTTON FOR REFRESH. + connect(ui->refreshButton, SIGNAL(clicked()), this, SLOT(forceUpdateDisplay())); + + connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString))); + connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); + + /* Set own item delegate */ + RSItemDelegate *itemDelegate = new RSItemDelegate(this); + itemDelegate->setSpacing(QSize(0, 2)); + ui->threadTreeWidget->setItemDelegate(itemDelegate); + + /* Set header resize modes and initial section sizes */ + QHeaderView * ttheader = ui->threadTreeWidget->header () ; + ttheader->setResizeMode (COLUMN_THREAD_TITLE, QHeaderView::Interactive); + ttheader->resizeSection (COLUMN_THREAD_DATE, 140); + ttheader->resizeSection (COLUMN_THREAD_TITLE, 290); + + ui->threadTreeWidget->sortItems(COLUMN_THREAD_DATE, Qt::DescendingOrder); + + /* Set text of column "Read" to empty - without this the column has a number as header text */ + QTreeWidgetItem *headerItem = ui->threadTreeWidget->headerItem(); + headerItem->setText(COLUMN_THREAD_READ, ""); + +//#AFTER MERGE + setTextColorNotSubscribed(Qt::black); + setTextColorUnread(Qt::black); + setTextColorUnreadChildren(Qt::gray); + setTextColorRead(Qt::gray); + setTextColorMissing(Qt::darkRed); + + /* Initialize group tree */ +//#AFTER MERGE ui.forumTreeWidget->initDisplayMenu(ui.displayButton); + + /* add filter actions */ +//#AFTER MERGE ui.filterLineEdit->addFilter(QIcon(), tr("Title"), COLUMN_THREAD_TITLE, tr("Search Title")); +//#AFTER MERGE ui.filterLineEdit->addFilter(QIcon(), tr("Date"), COLUMN_THREAD_DATE, tr("Search Date")); +//#AFTER MERGE ui.filterLineEdit->addFilter(QIcon(), tr("Author"), COLUMN_THREAD_AUTHOR, tr("Search Author")); +//#AFTER MERGE ui.filterLineEdit->addFilter(QIcon(), tr("Content"), COLUMN_THREAD_CONTENT, tr("Search Content")); +//#AFTER MERGE ui.filterLineEdit->setCurrentFilter(COLUMN_THREAD_TITLE); + + mLastViewType = -1; + + // load settings + processSettings(true); + + /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ + ttheader->resizeSection (COLUMN_THREAD_READ, 24); + ttheader->setResizeMode (COLUMN_THREAD_READ, QHeaderView::Fixed); + ttheader->hideSection (COLUMN_THREAD_CONTENT); + + ui->progressBar->hide(); + ui->progressText->hide(); + ui->progressBarLayout->setEnabled(false); + +// mTimer = new QTimer; +// mTimer->setInterval(1000); +// mTimer->setSingleShot(true); + +// QObject::connect(mTimer, SIGNAL(timeout()), this, SLOT(updateDisplay())); + +// mTimer->start(); + + mFillThread = NULL; + + ui->forumName->setText(tr("Loading")); + insertThreads(); + + ui->threadTreeWidget->installEventFilter(this); +} + +GxsForumThreadWidget::~GxsForumThreadWidget() +{ + if (mFillThread) { + mFillThread->stop(); + delete(mFillThread); + mFillThread = NULL; + } + + delete ui; + +// delete(mTimer); + delete(mThreadQueue); + delete(mThreadCompareRole); +} + +void GxsForumThreadWidget::processSettings(bool load) +{ + mInProcessSettings = true; + + QHeaderView *header = ui->threadTreeWidget->header(); + + Settings->beginGroup(QString("GxsForumsDialog")); + + if (load) { + // load settings + + // expandFiles + bool bValue = Settings->value("expandButton", true).toBool(); + ui->expandButton->setChecked(bValue); + togglethreadview_internal(); + + // filterColumn +//#AFTER MERGE ui.filterLineEdit->setCurrentFilter(Settings->value("filterColumn", COLUMN_THREAD_TITLE).toInt()); + + // index of viewBox + ui->viewBox->setCurrentIndex(Settings->value("viewBox", VIEW_THREADED).toInt()); + + // state of thread tree + header->restoreState(Settings->value("ThreadTree").toByteArray()); + + // state of splitter + ui->threadSplitter->restoreState(Settings->value("threadSplitter").toByteArray()); + } else { + // save settings + + // state of thread tree + Settings->setValue("ThreadTree", header->saveState()); + + // state of splitter + Settings->setValue("threadSplitter", ui->threadSplitter->saveState()); + } + + Settings->endGroup(); + mInProcessSettings = false; +} + +QString GxsForumThreadWidget::forumName(bool withUnreadCount) +{ + QString name = ui->forumName->text(); + + if (withUnreadCount && mUnreadCount) { + name += QString(" (%1)").arg(mUnreadCount); + } + + return name; +} + +QIcon GxsForumThreadWidget::forumIcon() +{ + if (mThreadQueue->activeRequestExist(TOKEN_TYPE_CURRENTFORUM) || mFillThread) { + return QIcon(":/images/kalarm.png"); + } + + if (mNewCount) { + return QIcon(":/images/message-state-new.png"); + } + + return QIcon(); +} + +void GxsForumThreadWidget::updateInterface() +{ + if (mFillThread) { + ui->newthreadButton->setEnabled(false); + } else { + if (mThreadQueue->activeRequestExist(TOKEN_TYPE_CURRENTFORUM)) { + ui->newthreadButton->setEnabled(false); + } else { + ui->newthreadButton->setEnabled (IS_GROUP_SUBSCRIBED(mSubscribeFlags)); + } + } + + emit forumChanged(this); +} + +void GxsForumThreadWidget::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::StyleChange: + calculateIconsAndFonts(); + break; + default: + // remove compiler warnings + break; + } +} + +#ifdef TODO +void GxsForumThreadWidget::updateDisplay() +{ + std::list forumIds; + std::list::iterator it; + if (!rsGxsForums) + return; + +#if 0 + // TODO groupsChanged... HACK XXX. + if ((rsGxsForums->groupsChanged(forumIds)) || (rsGxsForums->updated())) + { + /* update Forums List */ + insertForums(); + + it = std::find(forumIds.begin(), forumIds.end(), mCurrForumId); + if (it != forumIds.end()) + { + /* update threads as well */ + insertThreads(); + } + } +#endif + + /* The proper version (above) can be done with a data request -> TODO */ + if (rsGxsForums->updated()) + { + /* update Forums List */ + insertThreads(); + } +} +#endif + +void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/) +{ + if (mFillThread) { + return; + } + + QMenu contextMnu(this); + + QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply"), &contextMnu); + connect(replyAct, SIGNAL(triggered()), this, SLOT(createmessage())); + + QAction *newthreadAct = new QAction(QIcon(IMAGE_DOWNLOADALL), tr("Start New Thread"), &contextMnu); + newthreadAct->setEnabled (IS_GROUP_SUBSCRIBED(mSubscribeFlags)); + connect(newthreadAct , SIGNAL(triggered()), this, SLOT(createthread())); + + QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr("Reply to Author"), &contextMnu); + connect(replyauthorAct, SIGNAL(triggered()), this, SLOT(replytomessage())); + + QAction* expandAll = new QAction(tr("Expand all"), &contextMnu); + connect(expandAll, SIGNAL(triggered()), ui->threadTreeWidget, SLOT(expandAll())); + + QAction* collapseAll = new QAction(tr( "Collapse all"), &contextMnu); + connect(collapseAll, SIGNAL(triggered()), ui->threadTreeWidget, SLOT(collapseAll())); + + QAction *markMsgAsRead = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read"), &contextMnu); + connect(markMsgAsRead, SIGNAL(triggered()), this, SLOT(markMsgAsRead())); + + QAction *markMsgAsReadChildren = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read") + " (" + tr ("with children") + ")", &contextMnu); + connect(markMsgAsReadChildren, SIGNAL(triggered()), this, SLOT(markMsgAsReadChildren())); + + QAction *markMsgAsUnread = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread"), &contextMnu); + connect(markMsgAsUnread, SIGNAL(triggered()), this, SLOT(markMsgAsUnread())); + + QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu); + connect(markMsgAsUnreadChildren, SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren())); + + if (IS_GROUP_SUBSCRIBED(mSubscribeFlags)) { + QList rows; + QList rowsRead; + QList rowsUnread; + int nCount = getSelectedMsgCount(&rows, &rowsRead, &rowsUnread); + + if (rowsUnread.size() == 0) { + markMsgAsRead->setDisabled(true); + } + if (rowsRead.size() == 0) { + markMsgAsUnread->setDisabled(true); + } + + bool hasUnreadChildren = false; + bool hasReadChildren = false; + int rowCount = rows.count(); + for (int i = 0; i < rowCount; i++) { + if (hasUnreadChildren || rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN).toBool()) { + hasUnreadChildren = true; + } + if (hasReadChildren || rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN).toBool()) { + hasReadChildren = true; + } + } + markMsgAsReadChildren->setEnabled(hasUnreadChildren); + markMsgAsUnreadChildren->setEnabled(hasReadChildren); + + if (nCount == 1) { + replyAct->setEnabled (true); + replyauthorAct->setEnabled (true); + } else { + replyAct->setDisabled (true); + replyauthorAct->setDisabled (true); + } + } else { + markMsgAsRead->setDisabled(true); + markMsgAsReadChildren->setDisabled(true); + markMsgAsUnread->setDisabled(true); + markMsgAsUnreadChildren->setDisabled(true); + replyAct->setDisabled (true); + replyauthorAct->setDisabled (true); + } + + contextMnu.addAction(replyAct); + contextMnu.addAction(newthreadAct); + contextMnu.addAction(replyauthorAct); + QAction* action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink())); + action->setEnabled(!mForumId.empty() && !mThreadId.empty()); + contextMnu.addSeparator(); + contextMnu.addAction(markMsgAsRead); + contextMnu.addAction(markMsgAsReadChildren); + contextMnu.addAction(markMsgAsUnread); + contextMnu.addAction(markMsgAsUnreadChildren); + contextMnu.addSeparator(); + contextMnu.addAction(expandAll); + contextMnu.addAction(collapseAll); + + contextMnu.exec(QCursor::pos()); +} + +bool GxsForumThreadWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui->threadTreeWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && keyEvent->key() == Qt::Key_Space) { + // Space pressed + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + clickedThread (item, COLUMN_THREAD_READ); + return true; // eat event + } + } + } + // pass the event on to the parent class + return QWidget::eventFilter(obj, event); +} + +void GxsForumThreadWidget::togglethreadview() +{ + // save state of button + Settings->setValueToGroup("GxsForumsDialog", "expandButton", ui->expandButton->isChecked()); + + togglethreadview_internal(); +} + +void GxsForumThreadWidget::togglethreadview_internal() +{ + if (ui->expandButton->isChecked()) { + ui->postText->setVisible(true); + ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui->expandButton->setToolTip(tr("Hide")); + } else { + ui->postText->setVisible(false); + ui->expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } +} + +void GxsForumThreadWidget::changedThread() +{ + /* just grab the ids of the current item */ + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + + if (!item || !item->isSelected()) { + mThreadId.clear(); + } else { + mThreadId = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); + } + + if (mFillThread) { + return; + } + + insertPost(); +} + +void GxsForumThreadWidget::clickedThread(QTreeWidgetItem *item, int column) +{ + if (mFillThread) { + return; + } + + if (mForumId.empty() || !IS_GROUP_SUBSCRIBED(mSubscribeFlags)) { + return; + } + + if (item == NULL) { + return; + } + + if (column == COLUMN_THREAD_READ) { + QList rows; + rows.append(item); + uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + setMsgReadStatus(rows, IS_MSG_UNREAD(status)); + } +} + +#ifdef TODO +void GxsForumThreadWidget::forumMsgReadStatusChanged(const QString &forumId, const QString &msgId, int status) +{ + if (mInMsgAsReadUnread) { + return; + } + + if (forumId.toStdString() == mCurrForumId) { + /* Search exisiting item */ + QTreeWidgetItemIterator itemIterator(ui->threadTreeWidget); + QTreeWidgetItem *item = NULL; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString() == msgId) { + // update status + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status); + + QTreeWidgetItem *parentItem = item; + while (parentItem->parent()) { + parentItem = parentItem->parent(); + } + calculateIconsAndFonts(parentItem); + break; + } + } + } + updateMessageSummaryList(forumId.toStdString()); +} +#endif + +void GxsForumThreadWidget::calculateIconsAndFonts(QTreeWidgetItem *item, bool &hasReadChilddren, bool &hasUnreadChilddren) +{ + uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + + bool isNew = IS_MSG_NEW(status); + bool unread = IS_MSG_UNREAD(status); + bool missing = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool(); + + // set icon + if (missing) { + item->setIcon(COLUMN_THREAD_READ, QIcon()); + item->setIcon(COLUMN_THREAD_TITLE, QIcon()); + } else { + if (unread) { + item->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-unread.png")); + } else { + item->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-read.png")); + } + if (isNew) { + item->setIcon(COLUMN_THREAD_TITLE, QIcon(":/images/message-state-new.png")); + } else { + item->setIcon(COLUMN_THREAD_TITLE, QIcon()); + } + } + + int index; + int itemCount = item->childCount(); + + bool myReadChilddren = false; + bool myUnreadChilddren = false; + + for (index = 0; index < itemCount; ++index) { + calculateIconsAndFonts(item->child(index), myReadChilddren, myUnreadChilddren); + } + + // set font + for (int i = 0; i < COLUMN_THREAD_COUNT; ++i) { + QFont qf = item->font(i); + + if (!IS_GROUP_SUBSCRIBED(mSubscribeFlags)) { + qf.setBold(false); + item->setTextColor(i, textColorNotSubscribed()); + } else if (unread || isNew) { + qf.setBold(true); + item->setTextColor(i, textColorUnread()); + } else if (myUnreadChilddren) { + qf.setBold(true); + item->setTextColor(i, textColorUnreadChildren()); + } else { + qf.setBold(false); + item->setTextColor(i, textColorRead()); + } + if (missing) { + /* Missing message */ + item->setTextColor(i, textColorMissing()); + } + item->setFont(i, qf); + } + + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN, hasReadChilddren || myReadChilddren); + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN, hasUnreadChilddren || myUnreadChilddren); + + hasReadChilddren = hasReadChilddren || myReadChilddren || !unread; + hasUnreadChilddren = hasUnreadChilddren || myUnreadChilddren || unread; +} + +void GxsForumThreadWidget::calculateUnreadCount() +{ + unsigned int unreadCount = 0; + unsigned int newCount = 0; + + QTreeWidgetItemIterator itemIterator(ui->threadTreeWidget); + QTreeWidgetItem *item = NULL; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (IS_MSG_UNREAD(status)) { + ++unreadCount; + } + if (IS_MSG_NEW(status)) { + ++newCount; + } + } + + bool changed = false; + if (mUnreadCount != unreadCount) { + mUnreadCount = unreadCount; + changed = true; + } + if (mNewCount != newCount) { + mNewCount = newCount; + changed = true; + } + + if (changed) { + updateInterface(); + } +} + +void GxsForumThreadWidget::calculateIconsAndFonts(QTreeWidgetItem *item /*= NULL*/) +{ + bool dummy1 = false; + bool dummy2 = false; + + if (item) { + calculateIconsAndFonts(item, dummy1, dummy2); + return; + } + + int index; + int itemCount = ui->threadTreeWidget->topLevelItemCount(); + + for (index = 0; index < itemCount; ++index) { + dummy1 = false; + dummy2 = false; + calculateIconsAndFonts(ui->threadTreeWidget->topLevelItem(index), dummy1, dummy2); + } +} + +static void cleanupItems (QList &items) +{ + QList::iterator item; + for (item = items.begin (); item != items.end (); item++) { + if (*item) { + delete (*item); + } + } + items.clear(); +} + +void GxsForumThreadWidget::fillThreadFinished() +{ +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::fillThreadFinished" << std::endl; +#endif + + // thread has finished + GxsForumsFillThread *thread = dynamic_cast(sender()); + if (thread) { + if (thread == mFillThread) { + // current thread has finished, hide progressbar and release thread + ui->progressBar->hide(); + ui->progressText->hide(); + ui->progressBarLayout->setEnabled(false); + mFillThread = NULL; + updateInterface(); + + ui->threadTreeWidget->setPlaceholderText(""); + } + + if (thread->wasStopped()) { + // thread was stopped +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::fillThreadFinished Thread was stopped" << std::endl; +#endif + } else { +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::fillThreadFinished Add messages" << std::endl; +#endif + + ui->threadTreeWidget->setSortingEnabled(false); + + /* add all messages in! */ + if (mLastViewType != thread->mViewType || mLastForumID != mForumId) { + ui->threadTreeWidget->clear(); + mLastViewType = thread->mViewType; + mLastForumID = mForumId; + ui->threadTreeWidget->insertTopLevelItems(0, thread->mItems); + + // clear list + thread->mItems.clear(); + } else { + fillThreads (thread->mItems, thread->mExpandNewMessages, thread->mItemToExpand); + + // cleanup list + cleanupItems (thread->mItems); + } + + ui->threadTreeWidget->setSortingEnabled(true); + + if (thread->mFocusMsgId.empty() == false) { + /* Search exisiting item */ + QTreeWidgetItemIterator itemIterator(ui->threadTreeWidget); + QTreeWidgetItem *item = NULL; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == thread->mFocusMsgId) { + ui->threadTreeWidget->setCurrentItem(item); + ui->threadTreeWidget->setFocus(); + break; + } + } + } + + QList::iterator itemIt; + for (itemIt = thread->mItemToExpand.begin(); itemIt != thread->mItemToExpand.end(); ++itemIt) { + if ((*itemIt)->isHidden() == false) { + (*itemIt)->setExpanded(true); + } + } + thread->mItemToExpand.clear(); + + if (ui->filterLineEdit->text().isEmpty() == false) { + filterItems(ui->filterLineEdit->text()); + } + insertPost (); + calculateIconsAndFonts(); + calculateUnreadCount(); + updateInterface(); + } + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::fillThreadFinished Delete thread" << std::endl; +#endif + + thread->deleteLater(); + thread = NULL; + } + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::fillThreadFinished done" << std::endl; +#endif +} + +void GxsForumThreadWidget::fillThreadProgress(int current, int count) +{ + // show fill progress + if (count) { + ui->progressBar->setValue(current * ui->progressBar->maximum() / count); + } +} + +void GxsForumThreadWidget::fillThreadStatus(QString text) +{ + ui->progressText->setText(text); +} + +// HACK until update works. +void GxsForumThreadWidget::forceUpdateDisplay() +{ + std::cerr << "GxsForumThreadWidget::forceUpdateDisplay()"; + std::cerr << std::endl; + + /* update Thread List */ + insertThreads(); +} + +QTreeWidgetItem *GxsForumThreadWidget::convertMsgToThreadWidget(const RsGxsForumMsg &msg, bool useChildTS, uint32_t filterColumn) +{ + GxsIdTreeWidgetItem *item = new GxsIdTreeWidgetItem(mThreadCompareRole); + QString text; + + item->setText(COLUMN_THREAD_TITLE, QString::fromUtf8(msg.mMeta.mMsgName.c_str())); + + QDateTime qtime; + QString sort; + + if (useChildTS) + qtime.setTime_t(msg.mMeta.mChildTs); + else + qtime.setTime_t(msg.mMeta.mPublishTs); + +//#AFTER MERGE text = DateTime::formatDateTime(qtime); + sort = qtime.toString("yyyyMMdd_hhmmss"); + + if (useChildTS) + { + qtime.setTime_t(msg.mMeta.mPublishTs); + text += " / "; +//#AFTER MERGE text += DateTime::formatDateTime(qtime); + sort += "_" + qtime.toString("yyyyMMdd_hhmmss"); + } + item->setText(COLUMN_THREAD_DATE, text); + item->setData(COLUMN_THREAD_DATE, ROLE_THREAD_SORT, sort); + + item->setId(msg.mMeta.mAuthorId, COLUMN_THREAD_AUTHOR); +//#TODO +#if 0 + text = QString::fromUtf8(authorName.c_str()); + + if (text.isEmpty()) + { + item->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous")); + } + else + { + item->setText(COLUMN_THREAD_AUTHOR, text); + } +#endif +//#TODO +#ifdef TOGXS + if (msgInfo.mMeta.mMsgFlags & RS_DISTRIB_AUTHEN_REQ) + { + item->setText(COLUMN_THREAD_SIGNED, tr("signed")); + item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signed.png")); + } + else + { + item->setText(COLUMN_THREAD_SIGNED, tr("none")); + item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signature-unknown.png")); + } +#endif + + if (filterColumn == COLUMN_THREAD_CONTENT) { + // need content for filter + QTextDocument doc; + doc.setHtml(QString::fromUtf8(msg.mMsg.c_str())); + item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" "))); + } + + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msg.mMeta.mMsgId)); +//#TODO +#if 0 + if (IS_GROUP_SUBSCRIBED(subscribeFlags) && !(msginfo.mMsgFlags & RS_DISTRIB_MISSING_MSG)) { + rsGxsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status); + } else { + // show message as read + status = RSGXS_MSG_STATUS_READ; + } +#endif + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, msg.mMeta.mMsgStatus); + + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, false); + + return item; +} + +QTreeWidgetItem *GxsForumThreadWidget::generateMissingItem(const std::string &msgId) +{ + GxsIdTreeWidgetItem *item = new GxsIdTreeWidgetItem(mThreadCompareRole); + item->setText(COLUMN_THREAD_TITLE, tr("[ ... Missing Message ... ]")); + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(msgId)); + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, true); + + return item; +} + +void GxsForumThreadWidget::insertThreads() +{ +#ifdef DEBUG_FORUMS + /* get the current Forum */ + std::cerr << "GxsForumsDialog::insertThreads()" << std::endl; +#endif + + if (mFillThread) { +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::insertThreads() stop current fill thread" << std::endl; +#endif + // stop current fill thread + GxsForumsFillThread *thread = mFillThread; + mFillThread = NULL; + thread->stop(); + delete(thread); + + ui->progressBar->hide(); + ui->progressText->hide(); + } + + mSubscribeFlags = 0; + + ui->newmessageButton->setEnabled(false); + ui->newthreadButton->setEnabled(false); + + ui->postText->clear(); + ui->threadTitle->clear(); + + if (mForumId.empty()) + { + /* not an actual forum - clear */ + ui->threadTreeWidget->clear(); + /* when no Thread selected - clear */ + ui->forumName->clear(); + /* clear last stored forumID */ + mForumId.erase(); + mLastForumID.erase(); + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsDialog::insertThreads() Current Thread Invalid" << std::endl; +#endif + + return; + } + +//#TODO +// ui->threadTitle->setText(tr("Loading")); + + // Get Current Forum Info... then complete insertForumThreads(). + requestGroupSummary_CurrentForum(mForumId); +} + +void GxsForumThreadWidget::insertForumThreads(const RsGroupMetaData &fi) +{ + mSubscribeFlags = fi.mSubscribeFlags; + ui->forumName->setText(QString::fromUtf8(fi.mGroupName.c_str())); + + ui->progressBarLayout->setEnabled(true); + + ui->progressText->show(); + ui->progressBar->reset(); + ui->progressBar->show(); + + ui->threadTreeWidget->setPlaceholderText(tr("Loading")); + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsDialog::insertThreads() Start filling Forum threads" << std::endl; +#endif + + // create fill thread + mFillThread = new GxsForumsFillThread(this); + + // set data + mFillThread->mCompareRole = mThreadCompareRole; + mFillThread->mForumId = mForumId; +//#AFTER MERGE mFillThread->mFilterColumn = ui->filterLineEdit->currentFilter(); + mFillThread->mFilterColumn = COLUMN_THREAD_TITLE; + mFillThread->mSubscribeFlags = mSubscribeFlags; + mFillThread->mExpandNewMessages = Settings->getExpandNewMessages(); + mFillThread->mViewType = ui->viewBox->currentIndex(); + if (mLastViewType != mFillThread->mViewType || mLastForumID != mForumId) { + mFillThread->mFillComplete = true; + } + + mFillThread->mFlatView = false; + mFillThread->mUseChildTS = false; + + switch (mFillThread->mViewType) { + case VIEW_LAST_POST: + mFillThread->mUseChildTS = true; + break; + case VIEW_FLAT: + mFillThread->mFlatView = true; + break; + case VIEW_THREADED: + break; + } + + ui->threadTreeWidget->setRootIsDecorated(!mFillThread->mFlatView); + + // connect thread + connect(mFillThread, SIGNAL(finished()), this, SLOT(fillThreadFinished()), Qt::BlockingQueuedConnection); + connect(mFillThread, SIGNAL(status(QString)), this, SLOT(fillThreadStatus(QString))); + connect(mFillThread, SIGNAL(progress(int,int)), this, SLOT(fillThreadProgress(int,int))); + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::insertThreads() Start fill thread" << std::endl; +#endif + + // start thread + mFillThread->start(); + updateInterface(); +} + +void GxsForumThreadWidget::fillThreads(QList &threadList, bool expandNewMessages, QList &itemToExpand) +{ +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsDialog::fillThreads()" << std::endl; +#endif + + int index = 0; + QTreeWidgetItem *threadItem; + QList::iterator newThread; + + // delete not existing + while (index < ui->threadTreeWidget->topLevelItemCount()) { + threadItem = ui->threadTreeWidget->topLevelItem(index); + + // search existing new thread + int found = -1; + for (newThread = threadList.begin (); newThread != threadList.end (); ++newThread) { + if (threadItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*newThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + found = index; + break; + } + } + if (found >= 0) { + index++; + } else { + delete(ui->threadTreeWidget->takeTopLevelItem(index)); + } + } + + // iterate all new threads + for (newThread = threadList.begin (); newThread != threadList.end (); ++newThread) { + // search existing thread + int found = -1; + int count = ui->threadTreeWidget->topLevelItemCount(); + for (index = 0; index < count; ++index) { + threadItem = ui->threadTreeWidget->topLevelItem(index); + if (threadItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*newThread)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + found = index; + break; + } + } + + if (found >= 0) { + // set child data + int i; + for (i = 0; i < COLUMN_THREAD_COUNT; ++i) { + threadItem->setText(i, (*newThread)->text(i)); + } + for (i = 0; i < ROLE_THREAD_COUNT; ++i) { + threadItem->setData(COLUMN_THREAD_DATA, Qt::UserRole + i, (*newThread)->data(COLUMN_THREAD_DATA, Qt::UserRole + i)); + } + + // fill recursive + fillChildren(threadItem, *newThread, expandNewMessages, itemToExpand); + } else { + // add new thread + ui->threadTreeWidget->addTopLevelItem (*newThread); + threadItem = *newThread; + *newThread = NULL; + } + + uint32_t status = threadItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (expandNewMessages && IS_MSG_UNREAD(status)) { + QTreeWidgetItem *parentItem = threadItem; + while ((parentItem = parentItem->parent()) != NULL) { + if (std::find(itemToExpand.begin(), itemToExpand.end(), parentItem) == itemToExpand.end()) { + itemToExpand.push_back(parentItem); + } + } + } + } + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsDialog::fillThreads() done" << std::endl; +#endif +} + +void GxsForumThreadWidget::fillChildren(QTreeWidgetItem *parentItem, QTreeWidgetItem *newParentItem, bool expandNewMessages, QList &itemToExpand) +{ + int index = 0; + int newIndex; + int newCount = newParentItem->childCount(); + + QTreeWidgetItem *childItem; + QTreeWidgetItem *newChildItem; + + // delete not existing + while (index < parentItem->childCount()) { + childItem = parentItem->child(index); + + // search existing new child + int found = -1; + int count = newParentItem->childCount(); + for (newIndex = 0; newIndex < count; ++newIndex) { + newChildItem = newParentItem->child(newIndex); + if (newChildItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == childItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + found = index; + break; + } + } + if (found >= 0) { + index++; + } else { + delete(parentItem->takeChild (index)); + } + } + + // iterate all new children + for (newIndex = 0; newIndex < newCount; ++newIndex) { + newChildItem = newParentItem->child(newIndex); + + // search existing child + int found = -1; + int count = parentItem->childCount(); + for (index = 0; index < count; ++index) { + childItem = parentItem->child(index); + if (childItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == newChildItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + found = index; + break; + } + } + + if (found >= 0) { + // set child data + int i; + for (i = 0; i < COLUMN_THREAD_COUNT; ++i) { + childItem->setText(i, newChildItem->text(i)); + } + for (i = 0; i < ROLE_THREAD_COUNT; ++i) { + childItem->setData(COLUMN_THREAD_DATA, Qt::UserRole + i, newChildItem->data(COLUMN_THREAD_DATA, Qt::UserRole + i)); + } + + // fill recursive + fillChildren(childItem, newChildItem, expandNewMessages, itemToExpand); + } else { + // add new child + childItem = newParentItem->takeChild(newIndex); + parentItem->addChild(childItem); + newIndex--; + newCount--; + } + + uint32_t status = childItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (expandNewMessages && IS_MSG_UNREAD(status)) { + QTreeWidgetItem *parentItem = childItem; + while ((parentItem = parentItem->parent()) != NULL) { + if (std::find(itemToExpand.begin(), itemToExpand.end(), parentItem) == itemToExpand.end()) { + itemToExpand.push_back(parentItem); + } + } + } + } +} + +void GxsForumThreadWidget::insertPost() +{ + if (mForumId.empty() || mThreadId.empty()) + { + ui->postText->setText(""); + ui->threadTitle->setText(""); + ui->previousButton->setEnabled(false); + ui->nextButton->setEnabled(false); + ui->newmessageButton->setEnabled (false); + return; + } + + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + if (item) { + QTreeWidgetItem *parentItem = item->parent(); + int index = parentItem ? parentItem->indexOfChild(item) : ui->threadTreeWidget->indexOfTopLevelItem(item); + int count = parentItem ? parentItem->childCount() : ui->threadTreeWidget->topLevelItemCount(); + ui->previousButton->setEnabled(index > 0); + ui->nextButton->setEnabled(index < count - 1); + } else { + // there is something wrong + ui->previousButton->setEnabled(false); + ui->nextButton->setEnabled(false); + return; + } + + ui->postText->setPlaceholderText(tr("Loading")); + ui->threadTitle->setText(tr("Loading")); + + ui->newmessageButton->setEnabled(IS_GROUP_SUBSCRIBED(mSubscribeFlags) && mThreadId.empty() == false); + + /* blank text, incase we get nothing */ + ui->postText->setText(""); + /* request Post */ + + // Get Forum Post ... then complete insertPostData(). + RsGxsGrpMsgIdPair postId = std::make_pair(mForumId, mThreadId); + requestMsgData_InsertPost(postId); +} + +void GxsForumThreadWidget::insertPostData(const RsGxsForumMsg &msg) +{ + /* As some time has elapsed since request - check that this is still the current msg. + * otherwise, another request will fill the data + */ + + ui->postText->setPlaceholderText(""); + ui->threadTitle->setText(""); + + if ((msg.mMeta.mGroupId != mForumId) || (msg.mMeta.mMsgId != mThreadId)) + { + std::cerr << "GxsForumsDialog::insertPostData() Ignoring Invalid Data...."; + std::cerr << std::endl; + std::cerr << "\t CurrForumId: " << mForumId << " != msg.GroupId: " << msg.mMeta.mGroupId; + std::cerr << std::endl; + std::cerr << "\t or CurrThdId: " << mThreadId << " != msg.MsgId: " << msg.mMeta.mMsgId; + std::cerr << std::endl; + std::cerr << std::endl; + return; + } + + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + + bool setToReadOnActive = Settings->getForumMsgSetToReadOnActivate(); + uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + + QList row; + row.append(item); + + if (IS_MSG_NEW(status)) { + if (setToReadOnActive) { + /* set to read */ + setMsgReadStatus(row, true); + } else { + /* set to unread by user */ + setMsgReadStatus(row, false); + } + } else { + if (setToReadOnActive && IS_MSG_UNREAD(status)) { + /* set to read */ + setMsgReadStatus(row, true); + } + } + +//#AFTER MERGE ui.time_label->setText(DateTime::formatLongDateTime(msg.mMeta.mPublishTs)); + + std::string authorName = rsPeers->getPeerName(msg.mMeta.mAuthorId); + QString text = QString::fromUtf8(authorName.c_str()); + +//#AFTER MERGE merge from ForumsDialog + if (text.isEmpty()) + { + ui->by_label->setText( tr("By") + " " + tr("Anonymous")); + } + else + { + ui->by_label->setText( tr("By") + " " + text ); + } + + QString extraTxt = RsHtml().formatText(ui->postText->document(), QString::fromUtf8(msg.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); + + ui->postText->setHtml(extraTxt); + ui->threadTitle->setText(QString::fromUtf8(msg.mMeta.mMsgName.c_str())); +} + +void GxsForumThreadWidget::previousMessage() +{ + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + if (item == NULL) { + return; + } + + QTreeWidgetItem *parentItem = item->parent(); + int index = parentItem ? parentItem->indexOfChild(item) : ui->threadTreeWidget->indexOfTopLevelItem(item); + if (index > 0) { + QTreeWidgetItem *previousItem = parentItem ? parentItem->child(index - 1) : ui->threadTreeWidget->topLevelItem(index - 1); + if (previousItem) { + ui->threadTreeWidget->setCurrentItem(previousItem); + } + } +} + +void GxsForumThreadWidget::nextMessage() +{ + QTreeWidgetItem *item = ui->threadTreeWidget->currentItem(); + if (item == NULL) { + return; + } + + QTreeWidgetItem *parentItem = item->parent(); + int index = parentItem ? parentItem->indexOfChild(item) : ui->threadTreeWidget->indexOfTopLevelItem(item); + int count = parentItem ? parentItem->childCount() : ui->threadTreeWidget->topLevelItemCount(); + if (index < count - 1) { + QTreeWidgetItem *nextItem = parentItem ? parentItem->child(index + 1) : ui->threadTreeWidget->topLevelItem(index + 1); + if (nextItem) { + ui->threadTreeWidget->setCurrentItem(nextItem); + } + } +} + +void GxsForumThreadWidget::downloadAllFiles() +{ + QStringList urls; + if (RsHtml::findAnchors(ui->postText->toHtml(), urls) == false) { + return; + } + + if (urls.count() == 0) { + return; + } + + RetroShareLink::process(urls, RetroShareLink::TYPE_FILE/*, true*/); +} + +void GxsForumThreadWidget::nextUnreadMessage() +{ + QTreeWidgetItem *currentItem = ui->threadTreeWidget->currentItem(); + + while (TRUE) { + QTreeWidgetItemIterator itemIterator = currentItem ? QTreeWidgetItemIterator(currentItem, QTreeWidgetItemIterator::NotHidden) : QTreeWidgetItemIterator(ui->threadTreeWidget, QTreeWidgetItemIterator::NotHidden); + + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item == currentItem) { + continue; + } + + uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (IS_MSG_UNREAD(status)) { + ui->threadTreeWidget->setCurrentItem(item); + ui->threadTreeWidget->scrollToItem(item, QAbstractItemView::EnsureVisible); + return; + } + } + + if (currentItem == NULL) { + break; + } + + /* start from top */ + currentItem = NULL; + } +} + +// TODO +#if 0 +void GxsForumsDialog::removemessage() +{ + //std::cerr << "GxsForumsDialog::removemessage()" << std::endl; + std::string cid, mid; + if (!getCurrentMsg(cid, mid)) + { + //std::cerr << "GxsForumsDialog::removemessage()"; + //std::cerr << " No Message selected" << std::endl; + return; + } + + rsMsgs -> MessageDelete(mid); +} +#endif + +/* get selected messages + the messages tree is single selected, but who knows ... */ +int GxsForumThreadWidget::getSelectedMsgCount(QList *rows, QList *rowsRead, QList *rowsUnread) +{ + if (rowsRead) rowsRead->clear(); + if (rowsUnread) rowsUnread->clear(); + + QList selectedItems = ui->threadTreeWidget->selectedItems(); + for(QList::iterator it = selectedItems.begin(); it != selectedItems.end(); it++) { + if (rows) rows->append(*it); + if (rowsRead || rowsUnread) { + uint32_t status = (*it)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (IS_MSG_UNREAD(status)) { + if (rowsUnread) rowsUnread->append(*it); + } else { + if (rowsRead) rowsRead->append(*it); + } + } + } + + return selectedItems.size(); +} + +void GxsForumThreadWidget::setMsgReadStatus(QList &rows, bool read) +{ + QList::iterator row; + std::list changedItems; + + mInMsgAsReadUnread = true; + + for (row = rows.begin(); row != rows.end(); ++row) { + if ((*row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool()) { + /* Missing message */ + continue; + } + + uint32_t status = (*row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + + uint32_t statusNew = (status & ~(GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED)); // orig status, without UNREAD and UNPROCESSED. + if (!read) { + statusNew |= GXS_SERV::GXS_MSG_STATUS_UNREAD; + } + + if (status != statusNew) // is it different? + { + std::string msgId = (*row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); + + // NB: MUST BE PART OF ACTIVE THREAD--- OR ELSE WE MUST STORE GROUPID SOMEWHERE!. + // LIKE THIS BELOW... + //std::string grpId = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_GROUPID).toString().toStdString(); + + RsGxsGrpMsgIdPair msgPair = std::make_pair(mForumId, msgId); + + uint32_t token; + rsGxsForums->setMessageReadStatus(token, msgPair, read); + + (*row)->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, statusNew); + + QTreeWidgetItem *parentItem = *row; + while (parentItem->parent()) { + parentItem = parentItem->parent(); + } + if (std::find(changedItems.begin(), changedItems.end(), parentItem) == changedItems.end()) { + changedItems.push_back(parentItem); + } + } + } + + mInMsgAsReadUnread = false; + + if (changedItems.size()) { + for (std::list::iterator it = changedItems.begin(); it != changedItems.end(); it++) { + calculateIconsAndFonts(*it); + } +//#TODO updateMessageSummaryList(mForumId); + calculateUnreadCount(); + } +} + +void GxsForumThreadWidget::markMsgAsReadUnread (bool read, bool children, bool forum) +{ + if (mForumId.empty() || !IS_GROUP_SUBSCRIBED(mSubscribeFlags)) { + return; + } + + /* get selected messages */ + QList rows; + if (forum) { + int itemCount = ui->threadTreeWidget->topLevelItemCount(); + for (int item = 0; item < itemCount; item++) { + rows.push_back(ui->threadTreeWidget->topLevelItem(item)); + } + } else { + getSelectedMsgCount (&rows, NULL, NULL); + } + + if (children) { + /* add children */ + QList allRows; + + while (rows.isEmpty() == false) { + QTreeWidgetItem *row = rows.takeFirst(); + + /* add only items with the right state or with not RSGXS_MSG_STATUS_READ */ + uint32_t status = row->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + bool isUnread = IS_MSG_UNREAD(status); + if (isUnread == read || IS_MSG_NEW(status)) { + allRows.append(row); + } + + for (int i = 0; i < row->childCount(); i++) { + /* add child to main list and let the main loop do the work */ + rows.append(row->child(i)); + } + } + + if (allRows.isEmpty()) { + /* nothing to do */ + return; + } + + setMsgReadStatus(allRows, read); + + return; + } + + setMsgReadStatus(rows, read); +} + +void GxsForumThreadWidget::markMsgAsRead() +{ + markMsgAsReadUnread(true, false, false); +} + +void GxsForumThreadWidget::markMsgAsReadChildren() +{ + markMsgAsReadUnread(true, true, false); +} + +void GxsForumThreadWidget::markMsgAsUnread() +{ + markMsgAsReadUnread(false, false, false); +} + +void GxsForumThreadWidget::markMsgAsUnreadChildren() +{ + markMsgAsReadUnread(false, true, false); +} + +void GxsForumThreadWidget::setAllMsgReadStatus(bool read) +{ + markMsgAsReadUnread(read, true, true); +} + +void GxsForumThreadWidget::copyMessageLink() +{ + if (mForumId.empty() || mThreadId.empty()) { + return; + } + +// THIS CODE CALLS getForumInfo() to verify that the Ids are valid. +// As we are switching to Request/Response this is now harder to do... +// So not bothering any more - shouldn't be necessary. +// IF we get errors - fix them, rather than patching here. +#if 0 + ForumInfo fi; + if (rsGxsForums->getForumInfo(mForumId, fi)) { + RetroShareLink link; + if (link.createForum(mForumId, mThreadId)) { + QList urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } + } +#endif + + QMessageBox::warning(this, "RetroShare", "ToDo"); +} + +void GxsForumThreadWidget::createmessage() +{ + if (mForumId.empty () || !IS_GROUP_SUBSCRIBED(mSubscribeFlags)) { + return; + } + + CreateGxsForumMsg *cfm = new CreateGxsForumMsg(mForumId, mThreadId); + cfm->show(); + + /* window will destroy itself! */ +} + +void GxsForumThreadWidget::createthread() +{ + if (mForumId.empty ()) { + QMessageBox::information(this, tr("RetroShare"), tr("No Forum Selected!")); + return; + } + + CreateGxsForumMsg *cfm = new CreateGxsForumMsg(mForumId, ""); + cfm->show(); + + /* window will destroy itself! */ +} + +static QString buildReplyHeader(const RsMsgMetaData &meta) +{ + RetroShareLink link; + link.createMessage(meta.mAuthorId, ""); + QString from = link.toHtml(); + + QString header = QString("-----%1-----").arg(QApplication::translate("GxsForumsDialog", "Original Message")); + header += QString("
%1: %2
").arg(QApplication::translate("GxsForumsDialog", "From"), from); + +//#AFTER MERGE header += QString("
%1: %2
").arg(QApplication::translate("GxsForumsDialog", "Sent"), DateTime::formatLongDateTime(meta.mPublishTs)); + header += QString("%1: %2

").arg(QApplication::translate("GxsForumsDialog", "Subject"), QString::fromUtf8(meta.mMsgName.c_str())); + header += "
"; + +//#AFTER MERGE header += QApplication::translate("GxsForumsDialog", "On %1, %2 wrote:").arg(DateTime::formatDateTime(meta.mPublishTs), from); + + return header; +} + +void GxsForumThreadWidget::replytomessage() +{ + if (mForumId.empty() || mThreadId.empty()) { + QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to a non-existant Message")); + return; + } + + // Get Message ... then complete replyMessageData(). + RsGxsGrpMsgIdPair postId = std::make_pair(mForumId, mThreadId); + requestMsgData_ReplyMessage(postId); +} + +void GxsForumThreadWidget::replyMessageData(const RsGxsForumMsg &msg) +{ + if ((msg.mMeta.mGroupId != mForumId) || (msg.mMeta.mMsgId != mThreadId)) + { + std::cerr << "GxsForumsDialog::replyMessageData() ERROR Message Ids have changed!"; + std::cerr << std::endl; + return; + } + + // NB: TODO REMOVE rsPeers references. + if (rsPeers->getPeerName(msg.mMeta.mAuthorId) !="") + { + MessageComposer *msgDialog = MessageComposer::newMsg(); + msgDialog->setTitleText(QString::fromUtf8(msg.mMeta.mMsgName.c_str()), MessageComposer::REPLY); + + msgDialog->setQuotedMsg(QString::fromUtf8(msg.mMsg.c_str()), buildReplyHeader(msg.mMeta)); + + msgDialog->addRecipient(MessageComposer::TO, msg.mMeta.mAuthorId, false); + msgDialog->show(); + msgDialog->activateWindow(); + + /* window will destroy itself! */ + } + else + { + QMessageBox::information(this, tr("RetroShare"),tr("You cant reply to an Anonymous Author")); + } +} + +void GxsForumThreadWidget::changedViewBox() +{ + if (mInProcessSettings) { + return; + } + + // save index + Settings->setValueToGroup("GxsForumsDialog", "viewBox", ui->viewBox->currentIndex()); + + ui->threadTreeWidget->clear(); + + insertThreads(); +} + +void GxsForumThreadWidget::filterColumnChanged(int column) +{ + if (mInProcessSettings) { + return; + } + + if (column == COLUMN_THREAD_CONTENT) { + // need content ... refill + insertThreads(); + } else { + filterItems(ui->filterLineEdit->text()); + } + + // save index + Settings->setValueToGroup("GxsForumsDialog", "filterColumn", column); +} + +void GxsForumThreadWidget::filterItems(const QString& text) +{ +//#AFTER MERGE int filterColumn = ui.filterLineEdit->currentFilter(); + int filterColumn = COLUMN_THREAD_TITLE; + + int count = ui->threadTreeWidget->topLevelItemCount(); + for (int index = 0; index < count; ++index) { + filterItem(ui->threadTreeWidget->topLevelItem(index), text, filterColumn); + } +} + +bool GxsForumThreadWidget::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn) +{ + bool visible = true; + + if (text.isEmpty() == false) { + if (item->text(filterColumn).contains(text, Qt::CaseInsensitive) == false) { + visible = false; + } + } + + int visibleChildCount = 0; + int count = item->childCount(); + for (int nIndex = 0; nIndex < count; ++nIndex) { + if (filterItem(item->child(nIndex), text, filterColumn)) { + visibleChildCount++; + } + } + + if (visible || visibleChildCount) { + item->setHidden(false); + } else { + item->setHidden(true); + } + + return (visible || visibleChildCount); +} + +/*********************** **** **** **** ***********************/ +/** Request / Response of Data ********************************/ +/*********************** **** **** **** ***********************/ + +void GxsForumThreadWidget::requestGroupSummary_CurrentForum(const std::string &forumId) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + std::list tokens; + mThreadQueue->activeRequestTokens(TOKEN_TYPE_CURRENTFORUM, tokens); + if (!tokens.empty()) { + std::list::iterator tokenIt; + for (tokenIt = tokens.begin(); tokenIt != tokens.end(); ++tokenIt) { + std::cerr << "GxsForumThreadWidget::requestGroupSummary() Canceling Request: " << *tokenIt; + std::cerr << std::endl; + + mThreadQueue->cancelRequest(*tokenIt); + } + } + + std::list grpIds; + grpIds.push_back(forumId); + + std::cerr << "GxsForumsDialog::requestGroupSummary_CurrentForum(" << forumId << ")"; + std::cerr << std::endl; + + uint32_t token; + mThreadQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds, TOKEN_TYPE_CURRENTFORUM); +} + +void GxsForumThreadWidget::loadGroupSummary_CurrentForum(const uint32_t &token) +{ + std::cerr << "GxsForumsDialog::loadGroupSummary_CurrentForum()"; + std::cerr << std::endl; + + std::list groupInfo; + rsGxsForums->getGroupSummary(token, groupInfo); + + if (groupInfo.size() == 1) + { + RsGroupMetaData fi = groupInfo.front(); + insertForumThreads(fi); + } + else + { + std::cerr << "GxsForumsDialog::loadGroupSummary_CurrentForum() ERROR Invalid Number of Groups..."; + std::cerr << std::endl; + + updateInterface(); + } +} + +/*********************** **** **** **** ***********************/ +/*********************** **** **** **** ***********************/ + +void GxsForumThreadWidget::requestMsgData_InsertPost(const RsGxsGrpMsgIdPair &msgId) +{ +#if 0 + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + + std::cerr << "GxsForumsDialog::requestMsgData_InsertPost(" << msgId.first << "," << msgId.second << ")"; + std::cerr << std::endl; + + std::vector msgIds; + msgIds.push_back(msgId); + uint32_t token; + mForumQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_INSERT_POST); +#else + + std::list tokens; + mThreadQueue->activeRequestTokens(TOKEN_TYPE_INSERT_POST, tokens); + if (!tokens.empty()) { + std::list::iterator tokenIt; + for (tokenIt = tokens.begin(); tokenIt != tokens.end(); ++tokenIt) { +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumThreadWidget::requestMsgData_InsertPost() Canceling Request: " << *tokenIt; + std::cerr << std::endl; +#endif + mThreadQueue->cancelRequest(*tokenIt); + } + } + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + + std::cerr << "GxsForumsDialog::requestMsgData_InsertPost(" << msgId.first << "," << msgId.second << ")"; + std::cerr << std::endl; + + GxsMsgReq msgIds; + std::vector &vect = msgIds[msgId.first]; + vect.push_back(msgId.second); + + uint32_t token; + mThreadQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_INSERT_POST); +#endif +} + +void GxsForumThreadWidget::loadMsgData_InsertPost(const uint32_t &token) +{ + std::cerr << "GxsForumsDialog::loadMsgData_InsertPost()"; + std::cerr << std::endl; + + std::vector msgs; + if (rsGxsForums->getMsgData(token, msgs)) { + if (msgs.size() != 1) { + std::cerr << "GxsForumsDialog::loadMsgData_InsertPost() ERROR Wrong number of answers"; + std::cerr << std::endl; + return; + } + insertPostData(msgs[0]); + } else { + std::cerr << "GxsForumsDialog::loadMsgData_InsertPost() ERROR Missing Message Data..."; + std::cerr << std::endl; + } +} + +/*********************** **** **** **** ***********************/ +/*********************** **** **** **** ***********************/ + +void GxsForumThreadWidget::requestMsgData_ReplyMessage(const RsGxsGrpMsgIdPair &msgId) +{ +#if 0 + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; + + std::cerr << "GxsForumsDialog::requestMsgData_ReplyMessage(" << msgId.first << "," << msgId.second << ")"; + std::cerr << std::endl; + + std::vector msgIds; + msgIds.push_back(msgId); + uint32_t token; + mThreadQueue->requestMsgRelatedInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_REPLY_MESSAGE); +#else + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + + std::cerr << "GxsForumsDialog::requestMsgData_ReplyMessage(" << msgId.first << "," << msgId.second << ")"; + std::cerr << std::endl; + + GxsMsgReq msgIds; + std::vector &vect = msgIds[msgId.first]; + vect.push_back(msgId.second); + + uint32_t token; + mThreadQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_REPLY_MESSAGE); +#endif +} + +void GxsForumThreadWidget::loadMsgData_ReplyMessage(const uint32_t &token) +{ + std::cerr << "GxsForumsDialog::loadMsgData_ReplyMessage()"; + std::cerr << std::endl; + + std::vector msgs; +#if 0 + if (rsGxsForums->getRelatedMessages(token, msgs)) +#else + if (rsGxsForums->getMsgData(token, msgs)) +#endif + { + if (msgs.size() != 1) + { + std::cerr << "GxsForumsDialog::loadMsgData_ReplyMessage() ERROR Wrong number of answers"; + std::cerr << std::endl; + return; + } + + replyMessageData(msgs[0]); + } + else + { + std::cerr << "GxsForumsDialog::loadMsgData_ReplyMessage() ERROR Missing Message Data..."; + std::cerr << std::endl; + } +} + +/*********************** **** **** **** ***********************/ +/*********************** **** **** **** ***********************/ + +void GxsForumThreadWidget::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "GxsForumsDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; + + if (queue == mThreadQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case TOKEN_TYPE_CURRENTFORUM: + loadGroupSummary_CurrentForum(req.mToken); + break; + + case TOKEN_TYPE_INSERT_POST: + loadMsgData_InsertPost(req.mToken); + break; + + case TOKEN_TYPE_REPLY_MESSAGE: + loadMsgData_ReplyMessage(req.mToken); + break; + + default: + std::cerr << "GxsForumsDialog::loadRequest() ERROR: INVALID TYPE"; + std::cerr << std::endl; + break; + } + } +} diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h new file mode 100644 index 000000000..7aefac457 --- /dev/null +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -0,0 +1,168 @@ +#ifndef GXSFORUMTHREADWIDGET_H +#define GXSFORUMTHREADWIDGET_H + +#include + +#include "util/TokenQueue.h" + +class QTreeWidgetItem; +class RSTreeWidgetItemCompareRole; +class RsGxsForumMsg; +class GxsForumsFillThread; + +namespace Ui { +class GxsForumThreadWidget; +} + +class GxsForumThreadWidget : public QWidget, public TokenResponse +{ + Q_OBJECT + + Q_PROPERTY(QColor textColorRead READ textColorRead WRITE setTextColorRead) + Q_PROPERTY(QColor textColorUnread READ textColorUnread WRITE setTextColorUnread) + Q_PROPERTY(QColor textColorUnreadChildren READ textColorUnreadChildren WRITE setTextColorUnreadChildren) + Q_PROPERTY(QColor textColorNotSubscribed READ textColorNotSubscribed WRITE setTextColorNotSubscribed) + Q_PROPERTY(QColor textColorMissing READ textColorMissing WRITE setTextColorMissing) + +public: + explicit GxsForumThreadWidget(const std::string &forumId, QWidget *parent = NULL); + ~GxsForumThreadWidget(); + + QColor textColorRead() const { return mTextColorRead; } + QColor textColorUnread() const { return mTextColorUnread; } + QColor textColorUnreadChildren() const { return mTextColorUnreadChildren; } + QColor textColorNotSubscribed() const { return mTextColorNotSubscribed; } + QColor textColorMissing() const { return mTextColorMissing; } + + void setTextColorRead(QColor color) { mTextColorRead = color; } + void setTextColorUnread(QColor color) { mTextColorUnread = color; } + void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color; } + void setTextColorNotSubscribed(QColor color) { mTextColorNotSubscribed = color; } + void setTextColorMissing(QColor color) { mTextColorMissing = color; } + + std::string forumId() { return mForumId; } + QString forumName(bool withUnreadCount); + QIcon forumIcon(); + unsigned int newCount() { return mNewCount; } + unsigned int unreadCount() { return mUnreadCount; } + + QTreeWidgetItem *convertMsgToThreadWidget(const RsGxsForumMsg &msg, bool useChildTS, uint32_t filterColumn); + QTreeWidgetItem *generateMissingItem(const std::string &msgId); + + void setAllMsgReadStatus(bool read); + + // Callback for all Loads. + virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); + +signals: + void forumChanged(QWidget *widget); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + void changeEvent(QEvent *e); + +private slots: + void forceUpdateDisplay(); // TEMP HACK FN. + +// void updateDisplay(); + + /** Create the context popup menu and it's submenus */ + void threadListCustomPopupMenu(QPoint point); + + void changedThread(); + void clickedThread (QTreeWidgetItem *item, int column); + + void replytomessage(); + void replyMessageData(const RsGxsForumMsg &msg); + + //void print(); + //void printpreview(); + + //void removemessage(); + void markMsgAsRead(); + void markMsgAsReadChildren(); + void markMsgAsUnread(); + void markMsgAsUnreadChildren(); + + void copyMessageLink(); + + /* handle splitter */ + void togglethreadview(); + + void createthread(); + void createmessage(); + + void previousMessage(); + void nextMessage(); + void nextUnreadMessage(); + void downloadAllFiles(); + + void changedViewBox(); + + void filterColumnChanged(int column); + void filterItems(const QString &text); + + void fillThreadFinished(); + void fillThreadProgress(int current, int count); + void fillThreadStatus(QString text); + +private: + void insertForumThreads(const RsGroupMetaData &fi); + void insertPostData(const RsGxsForumMsg &msg); // Second Half. + + void insertThreads(); + void insertPost(); + +// void forumMsgReadStatusChanged(const QString &forumId, const QString &msgId, int status); + + void fillThreads(QList &threadList, bool expandNewMessages, QList &itemToExpand); + void fillChildren(QTreeWidgetItem *parentItem, QTreeWidgetItem *newParentItem, bool expandNewMessages, QList &itemToExpand); + + int getSelectedMsgCount(QList *pRows, QList *pRowsRead, QList *pRowsUnread); + void setMsgReadStatus(QList &rows, bool read); + void markMsgAsReadUnread(bool read, bool children, bool forum); + void calculateIconsAndFonts(QTreeWidgetItem *item = NULL); + void calculateIconsAndFonts(QTreeWidgetItem *item, bool &hasReadChilddren, bool &hasUnreadChilddren); + void calculateUnreadCount(); + + void togglethreadview_internal(); + + bool filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); + + void processSettings(bool bLoad); + + void updateInterface(); + + std::string mForumId; + std::string mLastForumID; + std::string mThreadId; + int mSubscribeFlags; + bool mInProcessSettings; + bool mInMsgAsReadUnread; + int mLastViewType; + RSTreeWidgetItemCompareRole *mThreadCompareRole; + TokenQueue *mThreadQueue; +// QTimer *mTimer; + GxsForumsFillThread *mFillThread; + unsigned int mUnreadCount; + unsigned int mNewCount; + + void requestGroupSummary_CurrentForum(const std::string &forumId); + void loadGroupSummary_CurrentForum(const uint32_t &token); + + void requestMsgData_InsertPost(const RsGxsGrpMsgIdPair &msgId); + void loadMsgData_InsertPost(const uint32_t &token); + void requestMsgData_ReplyMessage(const RsGxsGrpMsgIdPair &msgId); + void loadMsgData_ReplyMessage(const uint32_t &token); + + /* Color definitions (for standard see qss.default) */ + QColor mTextColorRead; + QColor mTextColorUnread; + QColor mTextColorUnreadChildren; + QColor mTextColorNotSubscribed; + QColor mTextColorMissing; + + Ui::GxsForumThreadWidget *ui; +}; + +#endif // GXSFORUMTHREADWIDGET_H diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui new file mode 100644 index 000000000..9e2e6b664 --- /dev/null +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui @@ -0,0 +1,518 @@ + + + GxsForumThreadWidget + + + + 0 + 0 + 622 + 412 + + + + Form + + + + 0 + + + + + Qt::Vertical + + + + + + + + 0 + 32 + + + + QFrame::Box + + + QFrame::Sunken + + + + 2 + + + + + Qt::NoFocus + + + Start new Thread for Selected Forum + + + + :/images/mail_new.png:/images/mail_new.png + + + + 24 + 16 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + Search forums + + + + + + + + + + 3 + + + + + + 2 + 0 + + + + + 0 + 0 + + + + + 16777215 + 1677215 + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + true + + + true + + + + Title + + + + + + + + + :/images/message-state-header.png:/images/message-state-header.png + + + + + Date + + + + + Author + + + + + Signed + + + + + + + + 3 + + + + + + 10 + 75 + true + + + + Loading + + + + + + + + 16777215 + 25 + + + + 1000 + + + 0 + + + + + + + + + 3 + + + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Reply Message + + + + :/images/mail_reply.png:/images/mail_reply.png + + + true + + + + + + + false + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Previous Thread + + + + + + + :/images/back.png:/images/back.png + + + true + + + + + + + false + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Next Thread + + + + + + + :/images/forward.png:/images/forward.png + + + true + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Download all files + + + + :/images/down.png:/images/down.png + + + true + + + + + + + Qt::Vertical + + + + + + + + 10 + + + + + + + + + + + + 10 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Next unread + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + true + + + true + + + + + + + Qt::Vertical + + + + + + + Refresh + + + + + + + + + + + 0 + 10 + + + + + 9 + + + + + + + + + + LinkTextBrowser + QTextBrowser +
gui/common/LinkTextBrowser.h
+
+ + LineEditClear + QLineEdit +
gui/common/LineEditClear.h
+
+ + RSTreeWidget + QTreeWidget +
gui/common/RSTreeWidget.h
+
+
+ + + + +
diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.cpp new file mode 100644 index 000000000..ef00b6c3b --- /dev/null +++ b/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.cpp @@ -0,0 +1,260 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012, RetroShare Team + * + * 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 (at your option) 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. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "GxsForumsFillThread.h" +#include "GxsForumThreadWidget.h" + +#include + +#include + +#define DEBUG_FORUMS + +GxsForumsFillThread::GxsForumsFillThread(GxsForumThreadWidget *parent) + : QThread(parent), mParent(parent) +{ + mStopped = false; + mCompareRole = NULL; + + mExpandNewMessages = true; + mFillComplete = false; + + mFilterColumn = 0; + mSubscribeFlags = 0; + + mViewType = 0; + mFlatView = false; + mUseChildTS = false; +} + +GxsForumsFillThread::~GxsForumsFillThread() +{ +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::~GxsForumsFillThread" << std::endl; +#endif + + // remove all items (when items are available, the thread was terminated) + QList::iterator item; + for (item = mItems.begin (); item != mItems.end (); item++) { + if (*item) { + delete (*item); + } + } + mItems.clear(); + + mItemToExpand.clear(); +} + +void GxsForumsFillThread::stop() +{ + disconnect(); + mStopped = true; + QApplication::processEvents(); + wait(); +} + +void GxsForumsFillThread::run() +{ + RsTokenService *service = rsGxsForums->getTokenService(); + + emit status(tr("Waiting")); + + /* get all messages of the forum */ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST; + + std::list grpIds; + grpIds.push_back(mForumId); + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::run() forum id " << mForumId << std::endl; +#endif + + uint32_t token; + service->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds); + + /* wait for the answer */ + uint32_t requestStatus; + while (!wasStopped()) { + requestStatus = service->requestStatus(token); + if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED || + requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) { + break; + } + msleep(100); + } + + if (wasStopped()) { +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::run() thread stopped, cancel request" << std::endl; +#endif + + /* cancel request */ + service->cancelRequest(token); + return; + } + + if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) { +//#TODO + return; + } + +//#TODO +// if (failed) { +// mService->cancelRequest(token); +// return; +// } + + emit status(tr("Retrieving")); + + /* get messages */ + std::vector msgs; + if (!rsGxsForums->getMsgData(token, msgs)) { + return; + } + + emit status(tr("Loading")); + + int count = msgs.size(); + int pos = 0; + QList > threadList; + QPair threadPair; + + /* add all threads */ + std::vector::iterator msgIt; + for (msgIt = msgs.begin(); msgIt != msgs.end(); ) { + if (wasStopped()) { + break; + } + + const RsGxsForumMsg &msg = *msgIt; + + if (!msg.mMeta.mParentId.empty()) { + ++msgIt; + continue; + } + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::run() Adding TopLevel Thread: mId: " << msg.mMeta.mMsgId << std::endl; +#endif + + QTreeWidgetItem *item = mParent->convertMsgToThreadWidget(msg, mUseChildTS, mFilterColumn); + threadList.push_back(QPair(msg.mMeta.mMsgId, item)); + + mItems.append(item); + emit progress(++pos, count); + + msgIt = msgs.erase(msgIt); + } + + /* process messages */ + while (msgs.size()) { + while (threadList.size() > 0) { + if (wasStopped()) { + break; + } + + threadPair = threadList.front(); + threadList.pop_front(); + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::run() Getting Children of : " << threadPair.first << std::endl; +#endif + /* iterate through child */ + for (msgIt = msgs.begin(); msgIt != msgs.end(); ) { + const RsGxsForumMsg &msg = *msgIt; + + if (msg.mMeta.mParentId != threadPair.first) { + ++msgIt; + continue; + } + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::run() adding " << msg.mMeta.mMsgId << std::endl; +#endif + + QTreeWidgetItem *item = mParent->convertMsgToThreadWidget(msg, mUseChildTS, mFilterColumn); + if (mFlatView) { + mItems.append(item); + } else { + threadPair.second->addChild(item); + } + + + /* add item to process list */ + threadList.push_back(QPair(msg.mMeta.mMsgId, item)); + + emit progress(++pos, count); + msgIt = msgs.erase(msgIt); + } + } + + if (wasStopped()) { + break; + } + + /* process missing messages */ + + /* search for a message with missing parent */ + for (msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) { + const RsGxsForumMsg &msg = *msgIt; + + /* search for parent */ + std::vector::iterator msgIt1; + for (msgIt1 = msgs.begin(); msgIt1 != msgs.end(); ++msgIt1) { + if (wasStopped()) { + break; + } + + const RsGxsForumMsg &msg1 = *msgIt1; + + if (msg.mMeta.mParentId == msg1.mMeta.mMsgId) { + /* found parent */ + break; + } + } + + if (wasStopped()) { + break; + } + + if (msgIt1 != msgs.end()) { + /* parant found */ + continue; + } + + /* add dummy item */ + QTreeWidgetItem *item = mParent->generateMissingItem(msg.mMeta.mParentId); + threadList.push_back(QPair(msg.mMeta.mParentId, item)); + + mItems.append(item); + break; + } + } + +#ifdef DEBUG_FORUMS + std::cerr << "GxsForumsFillThread::run() stopped: " << (wasStopped() ? "yes" : "no") << std::endl; +#endif +} diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.h b/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.h new file mode 100644 index 000000000..7bc2a8123 --- /dev/null +++ b/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.h @@ -0,0 +1,46 @@ +#ifndef GXSFORUMSFILLTHREAD_H +#define GXSFORUMSFILLTHREAD_H + +#include + +class GxsForumThreadWidget; +class RSTreeWidgetItemCompareRole; +class QTreeWidgetItem; + +class GxsForumsFillThread : public QThread +{ + Q_OBJECT + +public: + GxsForumsFillThread(GxsForumThreadWidget *parent); + ~GxsForumsFillThread(); + + void run(); + void stop(); + bool wasStopped() { return mStopped; } + +signals: + void progress(int current, int count); + void status(QString text); + +public: + std::string mForumId; + int mFilterColumn; + int mSubscribeFlags; + bool mFillComplete; + int mViewType; + bool mFlatView; + bool mUseChildTS; + bool mExpandNewMessages; + std::string mFocusMsgId; + RSTreeWidgetItemCompareRole *mCompareRole; + + QList mItems; + QList mItemToExpand; + +private: + GxsForumThreadWidget *mParent; + volatile bool mStopped; +}; + +#endif // GXSFORUMSFILLTHREAD_H diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp b/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp index 3f37f9df8..b6e1fc2a3 100644 --- a/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp @@ -19,33 +19,30 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ -#include -#include -#include -#include -#include -#include -#include +#include #include #include "ApplicationWindow.h" #include -#include "gui/PhotoShare/PhotoDialog.h" -#include "gui/WikiPoos/WikiDialog.h" -#include "gui/TheWire/WireDialog.h" #include "gui/Identity/IdDialog.h" -#include "gui/ForumsV2Dialog.h" +#include "gui/Circles/CirclesDialog.h" +#include "gui/PhotoShare/PhotoShare.h" +#include "gui/WikiPoos/WikiDialog.h" #include "gui/Posted/PostedDialog.h" +#include "gui/GxsForumsDialog.h" + +// THESE HAVE TO BE CONVERTED TO VEG FORMAT +#if USE_VEG_SERVICE +#include "gui/TheWire/WireDialog.h" +#endif //#include "GamesDialog.h" //#include "CalDialog.h" //#include "PhotoDialog.h" //#include "StatisticDialog.h" -#define FONT QFont("Arial", 9) - /* Images for toolbar icons */ #define IMAGE_RETROSHARE ":/images/RetroShare16.png" #define IMAGE_ABOUT ":/images/informations_24x24.png" @@ -57,7 +54,10 @@ #define IMAGE_CALENDAR ":/images/calendar.png" #define IMAGE_LIBRARY ":/images/library.png" #define IMAGE_PLUGINS ":/images/extension_32.png" -#define IMAGE_FORUMSV2 ":/images/konversation.png" +#define IMAGE_GXSFORUMS ":/images/konversation.png" +#define IMAGE_WIKI ":/images/wikibook_32.png" +#define IMAGE_POSTED ":/images/posted_32.png" + /** Constructor */ ApplicationWindow::ApplicationWindow(QWidget* parent, Qt::WFlags flags) @@ -72,7 +72,6 @@ ApplicationWindow::ApplicationWindow(QWidget* parent, Qt::WFlags flags) // Setting icons this->setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); - loadStyleSheet("Default"); /* Create the config pages and actions */ QActionGroup *grp = new QActionGroup(this); @@ -81,10 +80,6 @@ ApplicationWindow::ApplicationWindow(QWidget* parent, Qt::WFlags flags) //ui.stackPages->add(statisticDialog = new StatisticDialog(ui.stackPages), // createPageAction(QIcon(IMAGE_STATISTIC), tr("Statistics"), grp)); - //PhotoDialog *photoDialog = NULL; - //ui.stackPages->add(photoDialog = new PhotoDialog(ui.stackPages), - // createPageAction(QIcon(IMAGE_PHOTO), tr("Photo View"), grp)); - //GamesDialog *gamesDialog = NULL; //ui.stackPages->add(gamesDialog = new GamesDialog(ui.stackPages), // createPageAction(QIcon(IMAGE_GAMES), tr("Games Launcher"), grp)); @@ -97,41 +92,51 @@ ApplicationWindow::ApplicationWindow(QWidget* parent, Qt::WFlags flags) ui.stackPages->add(idDialog = new IdDialog(ui.stackPages), createPageAction(QIcon(IMAGE_LIBRARY), tr("Identities"), grp)); - PhotoDialog *photoDialog = NULL; - ui.stackPages->add(photoDialog = new PhotoDialog(ui.stackPages), - createPageAction(QIcon(IMAGE_PHOTO), tr("Photo View"), grp)); + CirclesDialog *circlesDialog = NULL; + ui.stackPages->add(circlesDialog = new CirclesDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_LIBRARY), tr("Circles"), grp)); + + PhotoShare *photoShare = NULL; + ui.stackPages->add(photoShare = new PhotoShare(ui.stackPages), + createPageAction(QIcon(IMAGE_PHOTO), tr("Photo Share"), grp)); + + PostedDialog *postedDialog = NULL; + ui.stackPages->add(postedDialog = new PostedDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_POSTED), tr("Posted Links"), grp)); WikiDialog *wikiDialog = NULL; ui.stackPages->add(wikiDialog = new WikiDialog(ui.stackPages), - createPageAction(QIcon(IMAGE_LIBRARY), tr("Wiki Pages"), grp)); + createPageAction(QIcon(IMAGE_WIKI), tr("Wiki Pages"), grp)); + GxsForumsDialog *gxsforumsDialog = NULL; + ui.stackPages->add(gxsforumsDialog = new GxsForumsDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_GXSFORUMS), tr("GxsForums"), grp)); + +// THESE HAVE TO BE CONVERTED TO VEG FORMAT +#if USE_VEG_SERVICE WireDialog *wireDialog = NULL; ui.stackPages->add(wireDialog = new WireDialog(ui.stackPages), createPageAction(QIcon(IMAGE_BWGRAPH), tr("The Wire"), grp)); - ForumsV2Dialog *forumsV2Dialog = NULL; - ui.stackPages->add(forumsV2Dialog = new ForumsV2Dialog(ui.stackPages), - createPageAction(QIcon(IMAGE_FORUMSV2), tr("ForumsV2"), grp)); - - PostedDialog *postedDialog = NULL; - ui.stackPages->add(postedDialog = new PostedDialog(ui.stackPages), - createPageAction(QIcon(IMAGE_LIBRARY), tr("Posted Links"), grp)); - +#endif /* Create the toolbar */ ui.toolBar->addActions(grp->actions()); ui.toolBar->addSeparator(); connect(grp, SIGNAL(triggered(QAction *)), ui.stackPages, SLOT(showPage(QAction *))); - + ui.stackPages->setCurrentIndex(0); } /** Creates a new action associated with a config page. */ QAction* ApplicationWindow::createPageAction(QIcon img, QString text, QActionGroup *group) { + QFont font; QAction *action = new QAction(img, text, group); + font = action->font(); + font.setPointSize(9); action->setCheckable(true); - action->setFont(FONT); + action->setFont(font); return action; } @@ -139,36 +144,13 @@ QAction* ApplicationWindow::createPageAction(QIcon img, QString text, QActionGro * the specified slot (if given). */ void ApplicationWindow::addAction(QAction *action, const char *slot) { - action->setFont(FONT); + QFont font = action->font(); + font.setPointSize(9); + action->setFont(font); ui.toolBar->addAction(action); connect(action, SIGNAL(triggered()), this, slot); } -/** Overloads the default show so we can load settings */ -void ApplicationWindow::show() -{ - - if (!this->isVisible()) { - QMainWindow::show(); - } else { - QMainWindow::activateWindow(); - setWindowState(windowState() & (~Qt::WindowMinimized | Qt::WindowActive)); - QMainWindow::raise(); - } -} - - -/** Shows the config dialog with focus set to the given page. */ -void ApplicationWindow::show(Page page) -{ - /* Show the dialog. */ - show(); - - /* Set the focus to the specified page. */ - ui.stackPages->setCurrentIndex((int)page); -} - - /** Destructor. */ ApplicationWindow::~ApplicationWindow() { @@ -176,12 +158,6 @@ ApplicationWindow::~ApplicationWindow() // delete exampleDialog; } -/** Create and bind actions to events. Setup for initial - * tray menu configuration. */ -void ApplicationWindow::createActions() -{ -} - void ApplicationWindow::closeEvent(QCloseEvent *e) { //Settings->saveWidgetInformation(this); @@ -189,53 +165,3 @@ void ApplicationWindow::closeEvent(QCloseEvent *e) hide(); e->ignore(); } - - -void ApplicationWindow::updateMenu() -{ - toggleVisibilityAction->setText(isVisible() ? tr("Hide") : tr("Show")); -} - -void ApplicationWindow::toggleVisibility(QSystemTrayIcon::ActivationReason e) -{ - if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick){ - if(isHidden()){ - show(); - if(isMinimized()){ - if(isMaximized()){ - showMaximized(); - }else{ - showNormal(); - } - } - raise(); - activateWindow(); - }else{ - hide(); - } - } -} - -void ApplicationWindow::toggleVisibilitycontextmenu() -{ - if (isVisible()) - hide(); - else - show(); -} - - - -void ApplicationWindow::loadStyleSheet(const QString &sheetName) -{ - QFile file(":/qss/" + sheetName.toLower() + ".qss"); - file.open(QFile::ReadOnly); - QString styleSheet = QLatin1String(file.readAll()); - - - qApp->setStyleSheet(styleSheet); - -} - - - diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.h b/retroshare-gui/src/gui/unfinished/ApplicationWindow.h index 04c70b88c..e60cceff2 100644 --- a/retroshare-gui/src/gui/unfinished/ApplicationWindow.h +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.h @@ -22,34 +22,16 @@ #ifndef _ApplicationWindow_H #define _ApplicationWindow_H -#include #include -#include - -#include "ExampleDialog.h" - +//#include "ExampleDialog.h" #include "ui_ApplicationWindow.h" - class ApplicationWindow : public QMainWindow { Q_OBJECT public: - /** Main dialog pages. */ - enum Page { - Graph = 0, /** Network Graph */ - Channels = 1, /** Channels page. */ - SharedDirectories = 2, /** Shared Directories page. */ - Search = 3, /** Search page. */ - Transfers = 4, /** Transfers page. */ - Chat = 5, /** Chat page. */ - Messages = 6, /** Messages page. */ - Statistics = 8 /** Statistic page. */ - - }; - /** Default Constructor */ ApplicationWindow(QWidget *parent = 0, Qt::WFlags flags = 0); @@ -60,54 +42,23 @@ public: * the dialogs, so we can add them to the * Notify Class... */ - - ExampleDialog *exampleDialog; + + //ExampleDialog *exampleDialog; //ChannelsDialog *channelsDialog; //GroupsDialog *groupsDialog; //StatisticDialog *statisticDialog; -public slots: - /** Called when this dialog is to be displayed */ - void show(); - /** Shows the config dialog with focus set to the given page. */ - void show(Page page); - - -private slots: - - void updateMenu(); - - void toggleVisibility(QSystemTrayIcon::ActivationReason e); - void toggleVisibilitycontextmenu(); - - protected: void closeEvent(QCloseEvent *); - -private slots: - - - private: - - /** Create the actions on the tray menu or menubar */ - void createActions(); - /** Creates a new action for a config page. */ QAction* createPageAction(QIcon img, QString text, QActionGroup *group); /** Adds a new action to the toolbar. */ void addAction(QAction *action, const char *slot = 0); - - void loadStyleSheet(const QString &sheetName); - - QSystemTrayIcon *trayIcon; - QAction *toggleVisibilityAction; - QMenu *menu; - + /** Qt Designer generated object */ Ui::ApplicationWindow ui; }; #endif - diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui b/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui index fb8be2949..21e91fe63 100644 --- a/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui @@ -1,7 +1,8 @@ - + + ApplicationWindow - - + + 0 0 @@ -9,1055 +10,67 @@ 542 - - - - - - - 0 - 0 - 0 - - - - - - - 208 - 208 - 208 - - - - - - - 255 - 255 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - 120 - 120 - 120 - - - - - - - 139 - 139 - 139 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - 0 - 0 - 0 - - - - - - - 10 - 36 - 106 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 255 - - - - - - - 255 - 0 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - - - 0 - 0 - 0 - - - - - - - 208 - 208 - 208 - - - - - - - 255 - 255 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - 120 - 120 - 120 - - - - - - - 139 - 139 - 139 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - 0 - 0 - 0 - - - - - - - 212 - 208 - 200 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 255 - - - - - - - 255 - 0 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - - - 120 - 120 - 120 - - - - - - - 208 - 208 - 208 - - - - - - - 255 - 255 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - 120 - 120 - 120 - - - - - - - 139 - 139 - 139 - - - - - - - 120 - 120 - 120 - - - - - - - 255 - 255 - 255 - - - - - - - 120 - 120 - 120 - - - - - - - 240 - 240 - 240 - - - - - - - 240 - 240 - 240 - - - - - - - 0 - 0 - 0 - - - - - - - 10 - 36 - 106 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 255 - - - - - - - 255 - 0 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - - Qt::CustomContextMenu - - + RetroShare - + 24 24 - + Qt::ToolButtonTextUnderIcon - - - - 0 - 12 - 679 - 509 - - - - + + + 6 - + 0 - + 6 - + 0 - + 0 - - - - - 120 - 0 - - - - - 120 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 208 - 208 - 208 - - - - - - - 255 - 255 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - 120 - 120 - 120 - - - - - - - 160 - 160 - 160 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - 0 - 0 - 0 - - - - - - - 10 - 36 - 106 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 255 - - - - - - - 255 - 0 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - - - 0 - 0 - 0 - - - - - - - 208 - 208 - 208 - - - - - - - 255 - 255 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - 120 - 120 - 120 - - - - - - - 160 - 160 - 160 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - 0 - 0 - 0 - - - - - - - 212 - 208 - 200 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 255 - - - - - - - 255 - 0 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - - - 120 - 120 - 120 - - - - - - - 208 - 208 - 208 - - - - - - - 255 - 255 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - 120 - 120 - 120 - - - - - - - 160 - 160 - 160 - - - - - - - 120 - 120 - 120 - - - - - - - 255 - 255 - 255 - - - - - - - 120 - 120 - 120 - - - - - - - 240 - 240 - 240 - - - - - - - 240 - 240 - 240 - - - - - - - 0 - 0 - 0 - - - - - - - 10 - 36 - 106 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 255 - - - - - - - 255 - 0 - 255 - - - - - - - 247 - 247 - 247 - - - - - - - - - 50 - false - - - - Qt::NoContextMenu - - + + - - - - 0 - 521 - 679 - 21 - + + + + Qt::CustomContextMenu - - - - - 0 - 0 - 679 - 12 - - - - Qt::NoContextMenu - - + true - + Qt::TopToolBarArea - + Qt::Horizontal - + 24 24 - + Qt::ToolButtonTextUnderIcon - + TopToolBarArea - + false @@ -1069,8 +82,6 @@
gui/mainpagestack.h
- - - + diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 53d1c984b..ba6f3a215 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -1,13 +1,21 @@ CONFIG += qt gui uic qrc resources uitools idle bitdht # Below is for GXS services. -#CONFIG += photoshare -#CONFIG += wikipoos -#CONFIG += thewire -#CONFIG += identities -#CONFIG += forumsv2 -#CONFIG += posted -#CONFIG += unfinished +# Should be disabled for releases. +#CONFIG += gxs + +gxs { + CONFIG += photoshare + CONFIG += wikipoos + CONFIG += identities + CONFIG += circles + CONFIG += gxsforums + CONFIG += posted + CONFIG += unfinished + CONFIG += gxsgui + # thewire is incomplete - dont enable + #CONFIG += thewire +} # Other Disabled Bits. @@ -53,6 +61,12 @@ linux-* { LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 LIBS += -lssl -lupnp -lixml -lXss -lgnome-keyring LIBS *= -lcrypto -ldl -lX11 -lz + + gxs { + LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + LIBS += -lsqlite3 + } + LIBS *= -rdynamic DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions DEFINES *= UBUNTU @@ -137,6 +151,12 @@ win32 { LIBS += -lole32 -lwinmm RC_FILE = gui/images/retroshare_win.rc + gxs { + LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\.libs\libsqlite3.a + #LIBS += -lsqlite3 + } + # export symbols for the plugins LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a @@ -164,6 +184,12 @@ macx { LIBS += -framework CoreFoundation LIBS += -framework Security + gxs { + LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + LIBS += -lsqlite3 + } + + INCLUDEPATH += . #DEFINES* = MAC_IDLE # for idle feature CONFIG -= uitools @@ -181,6 +207,12 @@ freebsd-* { LIBS *= -lupnp LIBS *= -lgnome-keyring PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + + gxs { + LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + LIBS += -lsqlite3 + } + } ############################## Common stuff ###################################### @@ -365,6 +397,7 @@ HEADERS += rshare.h \ gui/common/GroupDefs.h \ gui/common/Emoticons.h \ gui/common/RSListWidgetItem.h \ + gui/common/RSTreeWidget.h \ gui/common/RSTreeWidgetItem.h \ gui/common/RSTabWidget.h \ gui/common/RSItemDelegate.h \ @@ -631,6 +664,7 @@ SOURCES += main.cpp \ gui/common/GroupDefs.cpp \ gui/common/Emoticons.cpp \ gui/common/RSListWidgetItem.cpp \ + gui/common/RSTreeWidget.cpp \ gui/common/RSTreeWidgetItem.cpp \ gui/common/RSTabWidget.cpp \ gui/common/RSItemDelegate.cpp \ @@ -830,162 +864,239 @@ DEFINES *= CHANNELS_FRAME_CATCHER } + # BELOW IS GXS New Services. + unfinished { - -DEPENDPATH += gui/unfinished \ - -HEADERS += gui/unfinished/ApplicationWindow.h \ - gui/unfinished/CalDialog.h \ - gui/unfinished/ExampleDialog.h \ - gui/unfinished/GamesDialog.h \ - -# gui/unfinished/profile/ProfileView.h \ -# gui/unfinished/profile/ProfileEdit.h -# gui/unfinished/StatisticDialog.h \ -# gui/unfinished/PhotoDialog.h \ -# gui/unfinished/PhotoShow.h \ - -FORMS += gui/unfinished/ApplicationWindow.ui \ - gui/unfinished/CalDialog.ui \ - gui/unfinished/ExampleDialog.ui \ - gui/unfinished/GamesDialog.ui \ - -# gui/unfinished/profile/ProfileView.ui \ -# gui/unfinished/profile/ProfileEdit.ui -# gui/unfinished/StatisticDialog.ui \ -# gui/unfinished/PhotoDialog.ui \ -# gui/unfinished/PhotoShow.ui \ - -SOURCES += gui/unfinished/ApplicationWindow.cpp \ - gui/unfinished/CalDialog.cpp \ - gui/unfinished/ExampleDialog.cpp \ - gui/unfinished/GamesDialog.cpp \ - -# gui/unfinished/profile/ProfileView.cpp \ -# gui/unfinished/profile/ProfileEdit.cpp -# gui/unfinished/StatisticDialog.cpp \ -# gui/unfinished/PhotoDialog.cpp \ -# gui/unfinished/PhotoShow.cpp \ - - DEFINES *= UNFINISHED + + DEPENDPATH += gui/unfinished \ + + HEADERS += gui/unfinished/ApplicationWindow.h \ + gui/unfinished/CalDialog.h \ + gui/unfinished/ExampleDialog.h \ + gui/unfinished/GamesDialog.h \ + +# gui/unfinished/profile/ProfileView.h \ +# gui/unfinished/profile/ProfileEdit.h +# gui/unfinished/StatisticDialog.h \ +# gui/unfinished/PhotoDialog.h \ +# gui/unfinished/PhotoShow.h \ + + FORMS += gui/unfinished/ApplicationWindow.ui \ + gui/unfinished/CalDialog.ui \ + gui/unfinished/ExampleDialog.ui \ + gui/unfinished/GamesDialog.ui \ + +# gui/unfinished/profile/ProfileView.ui \ +# gui/unfinished/profile/ProfileEdit.ui +# gui/unfinished/StatisticDialog.ui \ +# gui/unfinished/PhotoDialog.ui \ +# gui/unfinished/PhotoShow.ui \ + + SOURCES += gui/unfinished/ApplicationWindow.cpp \ + gui/unfinished/CalDialog.cpp \ + gui/unfinished/ExampleDialog.cpp \ + gui/unfinished/GamesDialog.cpp \ + +# gui/unfinished/profile/ProfileView.cpp \ +# gui/unfinished/profile/ProfileEdit.cpp +# gui/unfinished/StatisticDialog.cpp \ +# gui/unfinished/PhotoDialog.cpp \ +# gui/unfinished/PhotoShow.cpp \ + + DEFINES *= UNFINISHED } - - + + photoshare { - - HEADERS += gui/PhotoShare/PhotoItem.h \ - gui/PhotoShare/PhotoDialog.h \ - gui/PhotoShare/PhotoAddDialog.h \ - gui/PhotoShare/PhotoDetailsDialog.h \ + + HEADERS += \ gui/PhotoShare/PhotoDrop.h \ + gui/PhotoShare/AlbumItem.h \ + gui/PhotoShare/AlbumDialog.h \ + gui/PhotoShare/AlbumCreateDialog.h \ + gui/PhotoShare/PhotoItem.h \ + gui/PhotoShare/PhotoShareItemHolder.h \ + gui/PhotoShare/PhotoShare.h \ gui/PhotoShare/PhotoSlideShow.h \ - - FORMS += gui/PhotoShare/PhotoItem.ui \ + gui/PhotoShare/PhotoDialog.h \ + gui/PhotoShare/PhotoCommentItem.h \ + gui/PhotoShare/AddCommentDialog.h + + FORMS += \ + gui/PhotoShare/PhotoItem.ui \ gui/PhotoShare/PhotoDialog.ui \ - gui/PhotoShare/PhotoAddDialog.ui \ - gui/PhotoShare/PhotoDetailsDialog.ui \ + gui/PhotoShare/AlbumItem.ui \ + gui/PhotoShare/AlbumDialog.ui \ + gui/PhotoShare/AlbumCreateDialog.ui \ + gui/PhotoShare/PhotoShare.ui \ gui/PhotoShare/PhotoSlideShow.ui \ - - SOURCES += gui/PhotoShare/PhotoItem.cpp \ + gui/PhotoShare/PhotoCommentItem.ui \ + gui/PhotoShare/AddCommentDialog.ui + + SOURCES += \ + gui/PhotoShare/PhotoItem.cpp \ gui/PhotoShare/PhotoDialog.cpp \ - gui/PhotoShare/PhotoAddDialog.cpp \ - gui/PhotoShare/PhotoDetailsDialog.cpp \ gui/PhotoShare/PhotoDrop.cpp \ + gui/PhotoShare/AlbumItem.cpp \ + gui/PhotoShare/AlbumDialog.cpp \ + gui/PhotoShare/AlbumCreateDialog.cpp \ + gui/PhotoShare/PhotoShareItemHolder.cpp \ + gui/PhotoShare/PhotoShare.cpp \ gui/PhotoShare/PhotoSlideShow.cpp \ + gui/PhotoShare/PhotoCommentItem.cpp \ + gui/PhotoShare/AddCommentDialog.cpp + + RESOURCES += gui/PhotoShare/Photo_images.qrc } - - + + wikipoos { - + + INCLUDEPATH += ../../supportlibs/pegmarkdown + HEADERS += gui/WikiPoos/WikiDialog.h \ gui/WikiPoos/WikiAddDialog.h \ gui/WikiPoos/WikiEditDialog.h \ - + FORMS += gui/WikiPoos/WikiDialog.ui \ gui/WikiPoos/WikiAddDialog.ui \ gui/WikiPoos/WikiEditDialog.ui \ - + SOURCES += gui/WikiPoos/WikiDialog.cpp \ gui/WikiPoos/WikiAddDialog.cpp \ gui/WikiPoos/WikiEditDialog.cpp \ - + + RESOURCES += gui/WikiPoos/Wiki_images.qrc } - - - + + + thewire { - + HEADERS += gui/TheWire/PulseItem.h \ gui/TheWire/WireDialog.h \ gui/TheWire/PulseAddDialog.h \ - + FORMS += gui/TheWire/PulseItem.ui \ gui/TheWire/WireDialog.ui \ gui/TheWire/PulseAddDialog.ui \ - + SOURCES += gui/TheWire/PulseItem.cpp \ gui/TheWire/WireDialog.cpp \ gui/TheWire/PulseAddDialog.cpp \ - + } - + identities { - - HEADERS += util/TokenQueue.h \ + + HEADERS += \ gui/Identity/IdDialog.h \ gui/Identity/IdEditDialog.h \ - + FORMS += gui/Identity/IdDialog.ui \ gui/Identity/IdEditDialog.ui \ - - SOURCES += util/TokenQueue.cpp \ + + SOURCES += \ gui/Identity/IdDialog.cpp \ gui/Identity/IdEditDialog.cpp \ - + } - - -forumsv2 { - - HEADERS += gui/ForumsV2Dialog.h \ - gui/forumsv2/ForumV2Details.h \ - gui/forumsv2/EditForumV2Details.h \ - gui/forumsv2/CreateForumV2.h \ - gui/forumsv2/CreateForumV2Msg.h \ - - FORMS += gui/ForumsV2Dialog.ui \ - gui/forumsv2/ForumV2Details.ui \ - gui/forumsv2/EditForumV2Details.ui \ - gui/forumsv2/CreateForumV2.ui \ - gui/forumsv2/CreateForumV2Msg.ui \ - - SOURCES += gui/ForumsV2Dialog.cpp \ - gui/forumsv2/ForumV2Details.cpp \ - gui/forumsv2/EditForumV2Details.cpp \ - gui/forumsv2/CreateForumV2.cpp \ - gui/forumsv2/CreateForumV2Msg.cpp \ - + +circles { + + HEADERS += \ + gui/Circles/CirclesDialog.h \ + + FORMS += gui/Circles/CirclesDialog.ui \ + + SOURCES += \ + gui/Circles/CirclesDialog.cpp \ + } - - + + +gxsforums { + + HEADERS += gui/GxsForumsDialog.h \ + gui/gxsforums/CreateGxsForumMsg.h \ + gui/gxsforums/GxsForumThreadWidget.h \ + gui/gxsforums/GxsForumsFillThread.h + + FORMS += gui/GxsForumsDialog.ui \ + gui/gxsforums/CreateGxsForumMsg.ui \ + gui/gxsforums/GxsForumThreadWidget.ui + + SOURCES += gui/GxsForumsDialog.cpp \ + gui/gxsforums/CreateGxsForumMsg.cpp \ + gui/gxsforums/GxsForumThreadWidget.cpp \ + gui/gxsforums/GxsForumsFillThread.cpp +} + + posted { - + HEADERS += gui/Posted/PostedDialog.h \ - gui/Posted/PostedListDialog.h \ - gui/Posted/PostedItem.h \ - gui/Posted/PostedComments.h \ - + gui/Posted/PostedListDialog.h \ + gui/Posted/PostedItem.h \ + gui/Posted/PostedComments.h \ + gui/Posted/PostedGroupDialog.h \ + gui/Posted/PostedCreatePostDialog.h \ + gui/Posted/PostedCreateCommentDialog.h \ + gui/Posted/PostedUserTypes.h + FORMS += gui/Posted/PostedDialog.ui \ - gui/Posted/PostedListDialog.ui \ - gui/Posted/PostedItem.ui \ - gui/Posted/PostedComments.ui \ - + gui/Posted/PostedListDialog.ui \ + gui/Posted/PostedItem.ui \ + gui/Posted/PostedComments.ui \ + gui/Posted/PostedCreatePostDialog.ui \ + gui/Posted/PostedCreateCommentDialog.ui + SOURCES += gui/Posted/PostedDialog.cpp \ - gui/Posted/PostedListDialog.cpp \ - gui/Posted/PostedItem.cpp \ - gui/Posted/PostedComments.cpp \ - + gui/Posted/PostedListDialog.cpp \ + gui/Posted/PostedItem.cpp \ + gui/Posted/PostedComments.cpp \ + gui/Posted/PostedGroupDialog.cpp \ + gui/Posted/PostedCreatePostDialog.cpp \ + gui/Posted/PostedCreateCommentDialog.cpp + + RESOURCES += gui/Posted/Posted_images.qrc +} + +gxsgui { + + HEADERS += gui/gxs/GxsGroupDialog.h \ + gui/gxs/GxsCommentTreeWidget.h \ + gui/gxs/WikiGroupDialog.h \ + gui/gxs/GxsForumGroupDialog.h \ + gui/gxs/GxsIdChooser.h \ + gui/gxs/GxsIdLabel.h \ + gui/gxs/GxsCircleChooser.h \ + gui/gxs/GxsCircleLabel.h \ + gui/gxs/GxsIdTreeWidgetItem.h \ + util/TokenQueue.h \ + +# gui/gxs/GxsMsgDialog.h \ + + FORMS += gui/gxs/GxsGroupDialog.ui \ + +# gui/gxs/GxsMsgDialog.ui \ +# gui/gxs/GxsCommentTreeWidget.ui \ + + SOURCES += gui/gxs/GxsGroupDialog.cpp \ + gui/gxs/GxsCommentTreeWidget.cpp \ + gui/gxs/WikiGroupDialog.cpp \ + gui/gxs/GxsForumGroupDialog.cpp \ + gui/gxs/GxsIdChooser.cpp \ + gui/gxs/GxsIdLabel.cpp \ + gui/gxs/GxsCircleChooser.cpp \ + gui/gxs/GxsCircleLabel.cpp \ + gui/gxs/GxsIdTreeWidgetItem.cpp \ + util/TokenQueue.cpp \ + +# gui/gxs/GxsMsgDialog.cpp \ + + } diff --git a/retroshare-gui/src/util/TokenQueue.cpp b/retroshare-gui/src/util/TokenQueue.cpp index 232e17bb4..8d114e95f 100644 --- a/retroshare-gui/src/util/TokenQueue.cpp +++ b/retroshare-gui/src/util/TokenQueue.cpp @@ -32,12 +32,11 @@ /** Constructor */ TokenQueue::TokenQueue(RsTokenService *service, TokenResponse *resp) -:QWidget(NULL), mService(service), mResponder(resp) + : QObject(NULL), mService(service), mResponder(resp) { - return; } -bool TokenQueue::requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, std::list ids, uint32_t usertype) +bool TokenQueue::requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, std::list& ids, uint32_t usertype) { uint32_t basictype = TOKENREQ_GROUPINFO; mService->requestGroupInfo(token, anstype, opts, ids); @@ -46,8 +45,16 @@ bool TokenQueue::requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTok return true; } +bool TokenQueue::requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, uint32_t usertype) +{ + uint32_t basictype = TOKENREQ_GROUPINFO; + mService->requestGroupInfo(token, anstype, opts); + queueRequest(token, basictype, anstype, usertype); -bool TokenQueue::requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, std::list ids, uint32_t usertype) + return true; +} + +bool TokenQueue::requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, const GxsMsgReq& ids, uint32_t usertype) { uint32_t basictype = TOKENREQ_MSGINFO; mService->requestMsgInfo(token, anstype, opts, ids); @@ -56,11 +63,20 @@ bool TokenQueue::requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokRe return true; } - -bool TokenQueue::requestMsgRelatedInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, std::list ids, uint32_t usertype) +bool TokenQueue::requestMsgRelatedInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, const std::vector &msgId, uint32_t usertype) { - uint32_t basictype = TOKENREQ_MSGRELATEDINFO; - mService->requestMsgRelatedInfo(token, anstype, opts, ids); + uint32_t basictype = TOKENREQ_MSGINFO; + mService->requestMsgRelatedInfo(token, anstype, opts, msgId); + queueRequest(token, basictype, anstype, usertype); + + return true; +} + +bool TokenQueue::requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, + const std::list &grpIds, uint32_t usertype) +{ + uint32_t basictype = TOKENREQ_MSGINFO; + mService->requestMsgInfo(token, anstype, opts, grpIds); queueRequest(token, basictype, anstype, usertype); return true; @@ -82,8 +98,10 @@ void TokenQueue::queueRequest(uint32_t token, uint32_t basictype, uint32_t ansty gettimeofday(&req.mRequestTs, NULL); req.mPollTs = req.mRequestTs; + mRequests.push_back(req); + if (mRequests.size() == 1) { /* start the timer */ @@ -98,27 +116,43 @@ void TokenQueue::doPoll(float dt) QTimer::singleShot((int) (dt * 1000.0), this, SLOT(pollRequests())); } - void TokenQueue::pollRequests() { - std::list::iterator it; - double pollPeriod = 1.0; // max poll period. - for(it = mRequests.begin(); it != mRequests.end(); it++) + + if (mRequests.empty()) { + return; + } + + TokenRequest req; + + + req = mRequests.front(); + mRequests.pop_front(); + + + if (checkForRequest(req.mToken)) { - if (checkForRequest(it->mToken)) + /* clean it up and handle */ + loadRequest(req); + } + else + { + +#define MAX_REQUEST_AGE 30 + + /* drop old requests too */ + if (time(NULL) - req.mRequestTs.tv_sec < MAX_REQUEST_AGE) { - /* clean it up and handle */ - loadRequest(*it); - it = mRequests.erase(it); + + mRequests.push_back(req); + } else { - /* calculate desired poll period */ - - /* if less then current poll period, adjust */ - - it++; + std::cerr << "TokenQueue::loadRequest(): "; + std::cerr << "Dropping old Token: " << req.mToken << " Type: " << req.mType; + std::cerr << std::endl; } } @@ -128,13 +162,52 @@ void TokenQueue::pollRequests() } } - bool TokenQueue::checkForRequest(uint32_t token) { /* check token */ - return (COMPLETED_REQUEST == mService->requestStatus(token)); + uint32_t status = mService->requestStatus(token); + return ( (RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == status) || + (RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == status) ); } +bool TokenQueue::activeRequestExist(const uint32_t& userType) const +{ + + + std::list::const_iterator lit = mRequests.begin(); + + for(; lit != mRequests.end(); lit++) + { + const TokenRequest& req = *lit; + + if(req.mUserType == userType) + { + + return true; + } + } + + + + return false; +} + +void TokenQueue::activeRequestTokens(const uint32_t& userType, std::list& tokens) const +{ + + + std::list::const_iterator lit = mRequests.begin(); + + for(; lit != mRequests.end(); lit++) + { + const TokenRequest& req = *lit; + + if(req.mUserType == userType) + tokens.push_back(req.mToken); + } + + +} void TokenQueue::loadRequest(const TokenRequest &req) { @@ -144,11 +217,8 @@ void TokenQueue::loadRequest(const TokenRequest &req) std::cerr << std::endl; mResponder->loadRequest(this, req); - - return; } - bool TokenQueue::cancelRequest(const uint32_t token) { /* cancel at lower level first */ @@ -156,6 +226,7 @@ bool TokenQueue::cancelRequest(const uint32_t token) std::list::iterator it; + for(it = mRequests.begin(); it != mRequests.end(); it++) { if (it->mToken == token) @@ -165,18 +236,15 @@ bool TokenQueue::cancelRequest(const uint32_t token) std::cerr << "TokenQueue::cancelRequest() Cleared Request: " << token; std::cerr << std::endl; + + return true; } } + std::cerr << "TokenQueue::cancelRequest() Failed to Find Request: " << token; std::cerr << std::endl; return false; } - - - - - - diff --git a/retroshare-gui/src/util/TokenQueue.h b/retroshare-gui/src/util/TokenQueue.h index 7a09ca806..dcf580b52 100644 --- a/retroshare-gui/src/util/TokenQueue.h +++ b/retroshare-gui/src/util/TokenQueue.h @@ -1,7 +1,7 @@ /* * Token Queue. * - * Copyright 2012-2012 by Robert Fernie. + * Copyright 2012-2012 by Robert Fernie, Christopher Evi-Parker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,8 +21,8 @@ * */ -#ifndef MRK_TOKEN_QUEUE_H -#define MRK_TOKEN_QUEUE_H +#ifndef MRK_TOKEN_QUEUE_V2_H +#define MRK_TOKEN_QUEUE_V2_H #include #include @@ -30,20 +30,21 @@ #include #include -#include +#include -#define COMPLETED_REQUEST 4 +#define COMPLETED_REQUEST 4 + +#define TOKENREQ_GROUPINFO 1 +#define TOKENREQ_MSGINFO 2 +#define TOKENREQ_MSGRELATEDINFO 3 -#define TOKENREQ_GROUPINFO 1 -#define TOKENREQ_MSGINFO 2 -#define TOKENREQ_MSGRELATEDINFO 3 class TokenQueue; class TokenRequest { - public: +public: uint32_t mToken; uint32_t mType; uint32_t mAnsType; @@ -54,33 +55,53 @@ class TokenRequest class TokenResponse { - public: +public: //virtual ~TokenResponse() { return; } // These Functions are overloaded to get results out. virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req) = 0; }; -class TokenQueue: public QWidget +/*! + * An important thing to note is that all requests are stacked (so FIFO) + * This is to prevent overlapped loads on GXS UIs + */ +class TokenQueue: public QObject { - Q_OBJECT + Q_OBJECT public: TokenQueue(RsTokenService *service, TokenResponse *resp); /* generic handling of token / response update behaviour */ - bool requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, - std::list ids, uint32_t usertype); - bool requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, - std::list ids, uint32_t usertype); - bool requestMsgRelatedInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, - std::list ids, uint32_t usertype); + + /*! + * + * @token the token to be redeem is assigned here + * + */ + bool requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, + std::list& ids, uint32_t usertype); + + bool requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, uint32_t usertype); + + bool requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, + const std::list& grpIds, uint32_t usertype); + + bool requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, + const GxsMsgReq& grpIds, uint32_t usertype); + + bool requestMsgRelatedInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptions &opts, const std::vector& msgId, uint32_t usertype); + bool cancelRequest(const uint32_t token); void queueRequest(uint32_t token, uint32_t basictype, uint32_t anstype, uint32_t usertype); bool checkForRequest(uint32_t token); void loadRequest(const TokenRequest &req); + bool activeRequestExist(const uint32_t& userType) const; + void activeRequestTokens(const uint32_t& userType, std::list& tokens) const; + protected: void doPoll(float dt); @@ -92,11 +113,9 @@ private: std::list mRequests; RsTokenService *mService; - TokenResponse *mResponder; + TokenResponse *mResponder; QTimer *mTrigger; }; #endif - - diff --git a/retroshare-gui/src/util/TokenQueueVEG.cpp b/retroshare-gui/src/util/TokenQueueVEG.cpp new file mode 100644 index 000000000..5c11dca31 --- /dev/null +++ b/retroshare-gui/src/util/TokenQueueVEG.cpp @@ -0,0 +1,182 @@ +/* + * Token Queue. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/TokenQueueVEG.h" +#include + +#include + +/****** + * #define ID_DEBUG 1 + *****/ + +/** Constructor */ +TokenQueueVEG::TokenQueueVEG(RsTokenServiceVEG *service, TokenResponseVEG *resp) +:QWidget(NULL), mService(service), mResponder(resp) +{ + return; +} + +bool TokenQueueVEG::requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptionsVEG &opts, std::list ids, uint32_t usertype) +{ + uint32_t basictype = TOKENREQ_GROUPINFO; + mService->requestGroupInfo(token, anstype, opts, ids); + queueRequest(token, basictype, anstype, usertype); + + return true; +} + + +bool TokenQueueVEG::requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptionsVEG &opts, std::list ids, uint32_t usertype) +{ + uint32_t basictype = TOKENREQ_MSGINFO; + mService->requestMsgInfo(token, anstype, opts, ids); + queueRequest(token, basictype, anstype, usertype); + + return true; +} + + +bool TokenQueueVEG::requestMsgRelatedInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptionsVEG &opts, std::list ids, uint32_t usertype) +{ + uint32_t basictype = TOKENREQ_MSGRELATEDINFO; + mService->requestMsgRelatedInfo(token, anstype, opts, ids); + queueRequest(token, basictype, anstype, usertype); + + return true; +} + + +void TokenQueueVEG::queueRequest(uint32_t token, uint32_t basictype, uint32_t anstype, uint32_t usertype) +{ + std::cerr << "TokenQueueVEG::queueRequest() Token: " << token << " Type: " << basictype; + std::cerr << " AnsType: " << anstype << " UserType: " << usertype; + std::cerr << std::endl; + + TokenRequestVEG req; + req.mToken = token; + req.mType = basictype; + req.mAnsType = anstype; + req.mUserType = usertype; + + gettimeofday(&req.mRequestTs, NULL); + req.mPollTs = req.mRequestTs; + + mRequests.push_back(req); + + if (mRequests.size() == 1) + { + /* start the timer */ + doPoll(0.1); + } +} + +void TokenQueueVEG::doPoll(float dt) +{ + /* single shot poll */ + //mTrigger->singlesshot(dt * 1000); + QTimer::singleShot((int) (dt * 1000.0), this, SLOT(pollRequests())); +} + + +void TokenQueueVEG::pollRequests() +{ + std::list::iterator it; + + double pollPeriod = 1.0; // max poll period. + for(it = mRequests.begin(); it != mRequests.end();) + { + if (checkForRequest(it->mToken)) + { + /* clean it up and handle */ + loadRequest(*it); + it = mRequests.erase(it); + } + else + { + /* calculate desired poll period */ + + /* if less then current poll period, adjust */ + + it++; + } + } + + if (mRequests.size() > 0) + { + doPoll(pollPeriod); + } +} + + +bool TokenQueueVEG::checkForRequest(uint32_t token) +{ + /* check token */ + return (COMPLETED_REQUEST == mService->requestStatus(token)); +} + + +void TokenQueueVEG::loadRequest(const TokenRequestVEG &req) +{ + std::cerr << "TokenQueueVEG::loadRequest(): "; + std::cerr << "Token: " << req.mToken << " Type: " << req.mType; + std::cerr << " AnsType: " << req.mAnsType << " UserType: " << req.mUserType; + std::cerr << std::endl; + + mResponder->loadRequest(this, req); + + return; +} + + +bool TokenQueueVEG::cancelRequest(const uint32_t token) +{ + /* cancel at lower level first */ + mService->cancelRequest(token); + + std::list::iterator it; + + for(it = mRequests.begin(); it != mRequests.end(); it++) + { + if (it->mToken == token) + { + mRequests.erase(it); + + std::cerr << "TokenQueueVEG::cancelRequest() Cleared Request: " << token; + std::cerr << std::endl; + + return true; + } + } + + std::cerr << "TokenQueueVEG::cancelRequest() Failed to Find Request: " << token; + std::cerr << std::endl; + + return false; +} + + + + + + diff --git a/retroshare-gui/src/util/TokenQueueVEG.h b/retroshare-gui/src/util/TokenQueueVEG.h new file mode 100644 index 000000000..eca5a431a --- /dev/null +++ b/retroshare-gui/src/util/TokenQueueVEG.h @@ -0,0 +1,101 @@ +/* + * Token Queue. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_VEG_TOKEN_QUEUE_H +#define MRK_VEG_TOKEN_QUEUE_H + +#include +#include +#include +#include +#include +#include +#include + +#define COMPLETED_REQUEST 4 + +#define TOKENREQ_GROUPINFO 1 +#define TOKENREQ_MSGINFO 2 +#define TOKENREQ_MSGRELATEDINFO 3 + +class TokenQueueVEG; + +class TokenRequestVEG +{ + public: + uint32_t mToken; + uint32_t mType; + uint32_t mAnsType; + uint32_t mUserType; + struct timeval mRequestTs; + struct timeval mPollTs; +}; + +class TokenResponseVEG +{ + public: + //virtual ~TokenResponse() { return; } + // These Functions are overloaded to get results out. + virtual void loadRequest(const TokenQueueVEG *queue, const TokenRequestVEG &req) = 0; +}; + + +class TokenQueueVEG: public QWidget +{ + Q_OBJECT + +public: + TokenQueueVEG(RsTokenServiceVEG *service, TokenResponseVEG *resp); + + /* generic handling of token / response update behaviour */ + bool requestGroupInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptionsVEG &opts, + std::list ids, uint32_t usertype); + bool requestMsgInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptionsVEG &opts, + std::list ids, uint32_t usertype); + bool requestMsgRelatedInfo(uint32_t &token, uint32_t anstype, const RsTokReqOptionsVEG &opts, + std::list ids, uint32_t usertype); + bool cancelRequest(const uint32_t token); + + void queueRequest(uint32_t token, uint32_t basictype, uint32_t anstype, uint32_t usertype); + bool checkForRequest(uint32_t token); + void loadRequest(const TokenRequestVEG &req); + +protected: + void doPoll(float dt); + +private slots: + void pollRequests(); + +private: + /* Info for Data Requests */ + std::list mRequests; + + RsTokenServiceVEG *mService; + TokenResponseVEG *mResponder; + + QTimer *mTrigger; +}; + +#endif + + diff --git a/retroshare-nogui/src/menu/menu.cc b/retroshare-nogui/src/menu/menu.cc new file mode 100644 index 000000000..39cdc1e9e --- /dev/null +++ b/retroshare-nogui/src/menu/menu.cc @@ -0,0 +1,907 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "menu/menu.h" +#include +#include +#include + +#include +#include + +#include "util/rsstring.h" + +#define MENU_DEBUG 1 + +/********************************************************** + * Menu Base Interface. + */ + + // RsTermServer Interface. +void MenuInterface::reset(uint32_t /* chan_id */) +{ + mBase->reset(); + mCurrentMenu = mBase; + mInputRequired = false; + mUpdateTime = 0; +} + + + +int MenuInterface::tick() +{ +#ifdef MENU_DEBUG + std::cerr << "MenuInterface::tick()"; + std::cerr << std::endl; +#endif // MENU_DEBUG + + /* try to read a char */ + bool haveInput = false; + uint8_t keypress; + std::string output; + + uint32_t chan_id = 1; // dummy - for menu system. + + int read = mComms->recv(chan_id, &keypress, 1); +#ifdef MENU_DEBUG + std::cerr << "MenuInterface::tick() read " << read << " bytes"; + std::cerr << std::endl; +#endif // MENU_DEBUG + + if (read == 0) + { + haveInput = false; + /* make a harmless key */ + keypress = ' '; + } + else if (read == 1) + { + haveInput = true; + } + else + { + /* error, NON BLOCKING is handled by recv returning 0 */ + mComms->error(chan_id, "Bad Input"); + return -1; + } + + + /**** Main logic bit ****/ + /**** slow down the updates / refresh ****/ + + time_t now = time(NULL); +#define UPDATE_TIME 5 + if (!haveInput) + { + // If Input is Required, + if (mInputRequired) + { + std::cerr << "MenuInterface::tick() No Input & Required-No Output"; + std::cerr << std::endl; + return 0; + } + + // Output will just almost the same, so occasionally. + if (now < mUpdateTime + UPDATE_TIME) + { + std::cerr << "MenuInterface::tick() No Input-Slow Update"; + std::cerr << std::endl; + return 0; + } + + std::cerr << "MenuInterface::tick() No Input - but doing update."; + std::cerr << std::endl; + } + + uint32_t rt = process(keypress, mDrawFlags, output); + mInputRequired = (rt == MENU_PROCESS_NEEDDATA); + mUpdateTime = now; + + if (rt == MENU_PROCESS_QUIT) + { + return -1; + } + + if (output.size() > 0) + { + mComms->send(chan_id, output); + } + + return (haveInput); +} + + +int tailrec_printparents(Menu *m, std::string &buffer) +{ + Menu *p = m->parent(); + if (p) + { + tailrec_printparents(p, buffer); + } + buffer += m->ShortFnDesc(); + buffer += " => "; + return 1; +} + + + +uint32_t MenuInterface::process(char key, uint32_t drawFlags, std::string &buffer) +{ + +#ifdef MENU_DEBUG + std::cout << "MenuInterface::process(" << key << ")"; + std::cout << std::endl; +#endif // MENU_DEBUG + + /* call process on current menu */ + uint32_t rt = mCurrentMenu->process(key); + bool doRedraw = true; + bool showError = false; + bool showHelp = false; + +#ifdef MENU_DEBUG + std::cout << "MenuInterface::process() currentMenu says: " << rt; + std::cout << std::endl; +#endif // MENU_DEBUG + + + uint32_t base_rt = (rt & MENU_PROCESS_MASK); + bool needData = (rt & MENU_PROCESS_NEEDDATA); + switch(base_rt) + { + case MENU_PROCESS_NONE: + if (needData) + { + /* no redraw, this could be called many times */ + doRedraw = false; + } + break; + + case MENU_PROCESS_DONE: + /* no changes - operation performed, or noop */ + break; + + case MENU_PROCESS_ERROR: + /* Show Error at top of Page */ + showError = true; + break; + + case MENU_PROCESS_HELP: + /* Show Help at top of Page */ + showHelp = true; + break; + + case MENU_PROCESS_MENU: + /* new menu to switch to */ + if (mCurrentMenu->selectedMenu()) + { + std::cout << "MenuInterface::process() Switching Menus"; + std::cout << std::endl; + mCurrentMenu = mCurrentMenu->selectedMenu(); + } + else + { + std::cout << "MenuInterface::process() ERROR"; + std::cout << " SelectedMenu == NULL"; + std::cout << std::endl; + } + break; + + case MENU_PROCESS_TOP: + /* switch to Base Menu */ + mCurrentMenu = mBase; + break; + + case MENU_PROCESS_QUIT: + return MENU_PROCESS_QUIT; + break; + } + + if (drawFlags & MENU_DRAW_FLAGS_ECHO) + { + buffer += key; + } + + /* now we redraw, and wait for next data */ + if (!doRedraw) + { + return MENU_PROCESS_NEEDDATA; + } + + /* HEADER */ + for(int i = 0; i < 20; i++) + { + buffer += "\r\n"; + } + + /* ERROR */ + if (showError) + { + mCurrentMenu->showError(); + } + /* HELP */ + else if (showHelp) + { + mCurrentMenu->showHelp(); + } + + /* MENU PAGE */ + drawHeader(drawFlags, buffer); + mCurrentMenu->drawPage(drawFlags, buffer); + + if (needData) + return MENU_PROCESS_NEEDDATA; + + return MENU_PROCESS_NONE; +} + + + + +uint32_t MenuInterface::drawHeader(uint32_t drawFlags, std::string &buffer) +{ + buffer += "=======================================================\r\n"; + buffer += "Retroshare Terminal Menu V2.xxxx ======================\r\n"; + + unsigned int nTotal = 0; + unsigned int nConnected = 0; + rsPeers->getPeerCount(&nTotal, &nConnected, false); + + uint32_t netState = rsConfig->getNetState(); + std::string natState("Unknown"); + switch(netState) + { + default: + case RSNET_NETSTATE_BAD_UNKNOWN: + natState = "YELLOW:Unknown"; + break; + + case RSNET_NETSTATE_BAD_OFFLINE: + natState = "GRAY:Offline"; + break; + + case RSNET_NETSTATE_BAD_NATSYM: + natState = "RED:Nasty Firewall"; + break; + + case RSNET_NETSTATE_BAD_NODHT_NAT: + natState = "RED:NoDht & Firewalled"; + break; + + case RSNET_NETSTATE_WARNING_RESTART: + natState = "YELLOW:Restarting"; + break; + + case RSNET_NETSTATE_WARNING_NATTED: + natState = "YELLOW:Firewalled"; + break; + + case RSNET_NETSTATE_WARNING_NODHT: + natState = "YELLOW:DHT Disabled"; + break; + + case RSNET_NETSTATE_GOOD: + natState = "GREEN:Good!"; + break; + + case RSNET_NETSTATE_ADV_FORWARD: + natState = "GREEN:Forwarded Port"; + break; + } + + float downKb = 0; + float upKb = 0; + rsicontrol -> ConfigGetDataRates(downKb, upKb); + + rs_sprintf_append(buffer, "Friends %d / %d Network: %s\r\n", + nConnected, nTotal, natState.c_str()); + + rs_sprintf_append(buffer, "Down: %2.2f Up %2.2f\r\n", downKb, upKb); + + std::string menuState; + tailrec_printparents(mCurrentMenu, menuState); + + buffer += "Menu State: "; + buffer += menuState; + buffer += "\r\n"; + + buffer += "=======================================================\r\n"; + + return 1; +} + +/********************************************************** + * Menu (Base) + */ + +Menu::~Menu() +{ + /* cleanup children */ + mParent = NULL; + mSelectedMenu = NULL; + std::map::iterator it; + + for(it = mChildren.begin(); it != mChildren.end(); it++) + { + delete (it->second); + } + + mChildren.clear(); +} + +int Menu::addMenuItem(char key, Menu *child) +{ + std::map::iterator it; + it = mChildren.find(key); + if (it != mChildren.end()) + { + std::cout << "Menu::addMenuItem() ERROR DUPLICATE MENU ITEM"; + std::cout << std::endl; + return 0; + } + mChildren[key] = child; + child->setParent(this); + + return 1; +} + +void Menu::reset() +{ + mSelectedMenu = NULL; + std::map::iterator it; + for(it = mChildren.begin(); it != mChildren.end(); it++) + { + it->second->reset(); + } +} + + +uint32_t Menu::process(char key) +{ + /* try standard list ones */ + uint32_t rt = std_process(key); + if (rt) + { + return rt; + } + + /* now try children */ + rt = process_children(key); + if (rt) + { + return rt; + } + + return MENU_PROCESS_NONE; +} + +uint32_t Menu::std_process(char key) +{ + switch(key) + { + case MENU_KEY_QUIT: + return MENU_PROCESS_QUIT; + break; + case MENU_KEY_HELP: + return MENU_PROCESS_HELP; + break; + case MENU_KEY_TOP: + return MENU_PROCESS_TOP; + break; + case MENU_KEY_UP: + setSelectedMenu(parent()); + return MENU_PROCESS_MENU; + break; + } + + return MENU_PROCESS_NONE; +} + + +uint32_t Menu::process_children(char key) +{ + std::map::iterator it; + it = mChildren.find(key); + + if (it == mChildren.end()) + { + return MENU_PROCESS_NONE; + } + + /* have a child */ + + /* now return, depending on type */ + switch(it->second->op()) + { + case MENU_OP_NEEDDATA: + setSelectedMenu(it->second); + return MENU_PROCESS_MENU | MENU_PROCESS_NEEDDATA; + break; + + case MENU_OP_SUBMENU: + setSelectedMenu(it->second); + return MENU_PROCESS_MENU; + break; + + default: + case MENU_OP_INSTANT: + /* done already! */ + setSelectedMenu(NULL); + return MENU_PROCESS_DONE; + break; + + case MENU_OP_ERROR: + /* done already! */ + setSelectedMenu(NULL); + return MENU_PROCESS_ERROR; + break; + } +} + + +uint32_t Menu::drawPage(uint32_t drawFlags, std::string &buffer) +{ + buffer += "Universal Commands ( "; + if (!(drawFlags & MENU_DRAW_FLAGS_NOQUIT)) + { + buffer += (char) MENU_KEY_QUIT; + buffer += ":Quit "; + } + buffer += (char) MENU_KEY_HELP; + buffer += ":Help "; + buffer += (char) MENU_KEY_TOP; + buffer += ":Top "; + buffer += (char) MENU_KEY_UP; + buffer += ":Up "; + buffer += ")"; + buffer += "\r\n"; + + buffer += "Specific Commands ( "; + std::map::iterator it; + for(it = mChildren.begin(); it != mChildren.end(); it++) + { + buffer += (char) it->first; + buffer += ":"; + buffer += it->second->ShortFnDesc(); + buffer += " "; + } + buffer += ")"; + buffer += "\r\n"; + + return 1; +} + + +uint32_t Menu::drawHelpPage(uint32_t drawFlags, std::string &buffer) +{ + std::cout << "Menu Help: Universal Commands are:"; + std::cout << std::endl; + std::cout << "\tKey: " << (char) MENU_KEY_QUIT << " => Quit"; + std::cout << std::endl; + std::cout << "\tKey: " << (char) MENU_KEY_HELP << " => Help"; + std::cout << std::endl; + std::cout << "\tKey: " << (char) MENU_KEY_TOP << " => Top Menu"; + std::cout << std::endl; + std::cout << "\tKey: " << (char) MENU_KEY_UP << " => Up a Menu"; + std::cout << std::endl; + + std::cout << "Specific Commands are:"; + std::cout << std::endl; + std::map::iterator it; + for(it = mChildren.begin(); it != mChildren.end(); it++) + { + std::cout << "\tKey: " << (char) it->first << " => "; + std::cout << it->second->ShortFnDesc(); + std::cout << std::endl; + } + + return 1; +} + + +/********************************************************** + * Menu List (Base) + */ + + +uint32_t MenuList::drawPage(uint32_t drawFlags, std::string &buffer) +{ + Menu::drawPage(drawFlags, buffer); + + buffer += "Navigation Commands ("; + buffer += (char) MENULIST_KEY_NEXT; + buffer += ":Next "; + buffer += (char) MENULIST_KEY_PREV; + buffer += ":Prev "; + buffer += ")"; + buffer += "\r\n"; + + rs_sprintf_append(buffer, "MenuList::Internals ListSize: %d, SelectIdx: %d Cursor: %d\r\n", + getListCount(), mSelectIdx, mCursor); + + int i = 0; + + int listCount = getListCount(); + int startCount = mCursor + 1; + int endCount = mCursor + 10; + if (endCount > listCount) + { + endCount = listCount; + } + + if (mSelectIdx >= 0) + { + + rs_sprintf_append(buffer, "Current Selection Idx: %d : ", mSelectIdx); + std::string desc; + if (getEntryDesc(mSelectIdx, desc) & (desc != "")) + { + buffer += desc; + } + else + { + buffer += "Missing Description"; + } + buffer += "\r\n"; + } + else + { + buffer += "No Current Selection: Use 0 - 9 to choose an Entry"; + buffer += "\r\n"; + } + + + rs_sprintf_append(buffer, "Showing %d to %d of %d Entries\r\n", + startCount, endCount, listCount); + + std::list::iterator it; + for (it = mList.begin(); it != mList.end(); it++, i++) + { + int curIdx = i - mCursor; + if ((curIdx >= 0) && (curIdx < 10)) + { + if (i == mSelectIdx) + { + rs_sprintf_append(buffer, "SELECTED (%d) ", curIdx); + } + else + { + rs_sprintf_append(buffer, "\t(%d) ", curIdx); + } + std::string desc; + if (getEntryDesc(i, desc) & (desc != "")) + { + buffer += desc; + } + else + { + buffer += *it; + buffer += " => "; + buffer += "Missing Description"; + } + buffer += "\r\n"; + } + } + buffer += "\r\n"; + buffer += "Make Your Choice > "; + + return 1; +} + +uint32_t MenuList::drawHelpPage(uint32_t drawFlags, std::string &buffer) +{ + Menu::drawHelpPage(drawFlags, buffer); + + std::cout << "MenuList Help: Navigation Commands are:"; + std::cout << std::endl; + //std::cout << "\tKey: " << (char) MENULIST_KEY_LIST << " => List"; + //std::cout << std::endl; + std::cout << "\tKey: " << (char) MENULIST_KEY_NEXT << " => Next Page"; + std::cout << std::endl; + std::cout << "\tKey: " << (char) MENULIST_KEY_PREV << " => Prev Page"; + std::cout << std::endl; + + std::cout << "MenuList::drawPage() Internal Details"; + std::cout << std::endl; + std::cout << "List Size: " << getListCount(); + std::cout << std::endl; + std::cout << "SelectIdx: " << mSelectIdx; + std::cout << std::endl; + std::cout << "Cursor: " << mCursor; + std::cout << std::endl; + return 1; +} + + +void MenuList::reset() +{ + Menu::reset(); // clears children too. + + mList.clear(); + mSelectIdx = -1; + mCursor = 0; +} + +uint32_t MenuList::op() +{ + mList.clear(); + mSelectIdx = -1; + mCursor = 0; + + return MENU_OP_ERROR; // SUBMENU -> only for inherited classes; +} + +uint32_t MenuList::getListCount() +{ + return mList.size(); +} + +int MenuList::getCurrentKey(std::string &key) +{ + return getListEntry(mSelectIdx, key); +} + +int MenuList::getCurrentIdx(int &idx) +{ + idx = mSelectIdx; + return 1; +} + +int MenuList::getListEntry(int idx, std::string &key) +{ + if (idx < 0) + { + return MENU_ENTRY_NONE; + } + + std::list::iterator it; + int i = 0; + for (it = mList.begin(); (i < idx) && (it != mList.end()); it++, i++) ; + + if (it != mList.end()) + { + key = *it; + return MENU_ENTRY_OKAY; + } + return MENU_ENTRY_NONE; +} + +int MenuList::getEntryDesc(int idx, std::string &desc) +{ + desc = "Entry Description"; + return MENU_ENTRY_OKAY; +} + +uint32_t MenuList::process(char key) +{ + /* try standard list ones */ + uint32_t rt = Menu::process(key); + if (rt) + { + return rt; + } + + rt = list_process(key); + return rt; +} + +uint32_t MenuList::list_process(char key) +{ + if (((key >= '0') && (key <= '9')) || + ((key >= 'a') && (key <= 'f'))) + { + int idx = 0; + /* select index */ + if ((key >= '0') && (key <= '9')) + { + idx = key - '0'; + } + else + { + idx = key - 'a' + 9; + } + + /* now change selection, dependent on pagination */ + if (mCursor + idx < getListCount()) + { + mSelectIdx = mCursor + idx; + std::cout << "MenuList::list_process() Selected Idx: " << mSelectIdx; + std::cout << std::endl; + } + else + { + std::cout << "MenuList::list_process() Idx Out of Range"; + std::cout << std::endl; + } + + return MENU_PROCESS_DONE; /* ready for next key stroke */ + } + + + switch(key) + { + case MENULIST_KEY_LIST: + /* send a list to output */ + + return MENU_PROCESS_DONE; /* ready for next key stroke */ + break; + case MENULIST_KEY_NEXT: + /* shift to next page */ + if (mCursor + 10 < getListCount()) + { + mCursor += 10; + } + + return MENU_PROCESS_DONE; + break; + case MENULIST_KEY_PREV: + /* shift to prev page */ + if (((int) mCursor) - 10 >= 0) + { + mCursor -= 10; + } + + return MENU_PROCESS_DONE; + break; + } + + return MENU_PROCESS_NONE; +} + + +uint32_t MenuOpBasicKey::op_basic(std::string key) +{ + parent()->setErrorMessage("MenuOpBasicKey Not Overloaded Correctly"); + return MENU_OP_ERROR; +} + + +uint32_t MenuOpBasicKey::op() +{ + std::string key; + Menu *Parent=parent(); + MenuList *p = dynamic_cast(Parent); + + if (!p) + { + if (Parent) + { + Parent->setErrorMessage("Invalid (Basic) Menu Structure"); + } + return MENU_OP_ERROR; + } + + if (p->getCurrentKey(key)) + { + return op_basic(key); + } + + if (Parent) + { + Parent->setErrorMessage("Invalid Current Keys"); + } + return MENU_OP_ERROR; +} + + + +uint32_t MenuOpTwoKeys::op_twokeys(std::string parentkey, std::string key) +{ + parent()->setErrorMessage("MenuOpTwoKeys Not Overloaded Correctly"); + return MENU_OP_ERROR; +} + + +uint32_t MenuOpTwoKeys::op() +{ + std::string parentkey; + std::string key; + Menu *Parent=parent(); + MenuList *p = dynamic_cast(Parent); + + Menu *grandParent=parent()->parent(); + MenuList *gp = dynamic_cast(grandParent); + + if ((!gp) || (!p)) + { + if (Parent) + { + Parent->setErrorMessage("Invalid (TwoKeys) Menu Structure"); + } + return MENU_OP_ERROR; + } + + if ((gp->getCurrentKey(parentkey)) && (p->getCurrentKey(key))) + { + return op_twokeys(parentkey, key); + } + + if (Parent) + { + Parent->setErrorMessage("Invalid Current Keys"); + } + return MENU_OP_ERROR; +} + + + +/********************************************************** + * Menu Op Line Input (Base) + */ + + +uint32_t MenuOpLineInput::op() +{ + return MENU_OP_NEEDDATA; +} + + +uint32_t MenuOpLineInput::process_lines(std::string input) +{ + std::cout << "MenuOpLineInput::process_lines() => SHOULD BE OVERLOADED"; + std::cout << "Input Was: "; + std::cout << std::endl; + std::cout << "=================================================="; + std::cout << std::endl; + std::cout << input; + std::cout << "=================================================="; + std::cout << std::endl; + + return MENU_PROCESS_ERROR; +} + + +uint32_t MenuOpLineInput::process(char key) +{ + /* read data in and add to buffer */ + mInput += key; + if ((key != '\n') && (key != '\r')) + { + return MENU_PROCESS_NEEDDATA; + } + + uint32_t rt = process_lines(mInput); + + switch(rt) + { + case MENU_PROCESS_NEEDDATA: + break; + case MENU_PROCESS_ERROR: + std::cout << "MenuOpLineInput::process() => ERROR"; + std::cout << std::endl; + case MENU_PROCESS_DONE: + /* cleanup for next command */ + std::cout << "MenuOpLineInput::process() Clearing Buffer"; + std::cout << std::endl; + mInput.clear(); + + /* go back to parent menu */ + rt = MENU_PROCESS_MENU; + setSelectedMenu(parent()); + break; + } + + return rt; +} + + diff --git a/retroshare-nogui/src/menu/menu.h b/retroshare-nogui/src/menu/menu.h new file mode 100644 index 000000000..c667e64dd --- /dev/null +++ b/retroshare-nogui/src/menu/menu.h @@ -0,0 +1,249 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef RSNOGUI_MENU_H +#define RSNOGUI_MENU_H + +#include + +#include +#include +#include + +#include "rpcsystem.h" // generic processing command. + +#define MENU_PROCESS_MASK 0x0fff + +#define MENU_PROCESS_NONE 0x0000 +#define MENU_PROCESS_TOP 0x0001 +#define MENU_PROCESS_MENU 0x0002 +#define MENU_PROCESS_DONE 0x0004 +#define MENU_PROCESS_QUIT 0x0008 +#define MENU_PROCESS_SHUTDOWN 0x0010 +#define MENU_PROCESS_HELP 0x0020 +#define MENU_PROCESS_ERROR 0x0040 + +#define MENU_PROCESS_NEEDDATA 0x1000 // Able to be OR'd with ANOTHER CASE. + +#define MENU_KEY_QUIT 'Q' +#define MENU_KEY_HELP 'h' +#define MENU_KEY_TOP 't' +#define MENU_KEY_REPEAT 'r' +#define MENU_KEY_UP 'u' + +#define MENULIST_KEY_LIST 'l' // Don't need this. +#define MENULIST_KEY_NEXT 'n' +#define MENULIST_KEY_PREV 'p' + +#define MENU_OP_ERROR 0 +#define MENU_OP_INSTANT 1 +#define MENU_OP_SUBMENU 2 +#define MENU_OP_NEEDDATA 3 + +#define MENU_ENTRY_NONE 0 +#define MENU_ENTRY_OKAY 1 + +#define MENU_DRAW_FLAGS_STD 0 +#define MENU_DRAW_FLAGS_HTML 1 +#define MENU_DRAW_FLAGS_ECHO 2 +#define MENU_DRAW_FLAGS_NOQUIT 4 + +class Menu; +class Screen; + +class Menu +{ +public: + Menu(std::string shortDesc): mParent(NULL), mShortDesc(shortDesc) { return; } +virtual ~Menu(); + + void setParent(Menu *p) { mParent = p; } + Menu *parent() { return mParent; } + Menu *selectedMenu() { return mSelectedMenu; } + int addMenuItem(char key, Menu *child); + +virtual void reset(); +virtual uint32_t op() { return MENU_OP_SUBMENU; } /* what type is it? returns SUBMENU, INSTANT, NEEDINPUT */ +virtual uint32_t process(char key); + + // THE BIT STILL TO BE DEFINED! + +std::string ShortFnDesc() { return mShortDesc; }// Menu Text (for Help). +virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer); +virtual uint32_t drawHelpPage(uint32_t drawFlags, std::string &buffer); + +//virtual std::string menuText() = 0; +//virtual std::string menuHelp() = 0; +virtual void setOpMessage(std::string msg) { return; } +virtual void setErrorMessage(std::string msg) { return; } +virtual uint32_t showError() { return 1; } //= 0; +virtual uint32_t showHelp() { return 1; } //= 0; + +protected: +virtual uint32_t std_process(char key); /* for H/T/R/Q */ +virtual uint32_t process_children(char key); /* check for children ops */ + + void setSelectedMenu(Menu *m) { mSelectedMenu = m; } + +private: + Menu *mParent; + Menu *mSelectedMenu; + std::string mShortDesc; + std::map mChildren; +}; + + +/********************************************************** + * Generic MenuList... provides a list of KEYS, which + * can be iterated through. + * + * Maintains: List + Current + Next / Previous. + * Single Child, which is called for all. + */ + +class MenuList: public Menu +{ +public: + MenuList(std::string shortDesc): Menu(shortDesc) { return; } + +virtual void reset(); +virtual uint32_t op(); +virtual uint32_t process(char key); + + // List Info. + uint32_t getListCount(); + int getCurrentIdx(int &idx); + int getCurrentKey(std::string &key); + int getListEntry(int idx, std::string &key); +virtual int getEntryDesc(int idx, std::string &desc); + + // Output. +virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer); +virtual uint32_t drawHelpPage(uint32_t drawFlags, std::string &buffer); + +protected: + virtual uint32_t list_process(char key); + + int32_t mSelectIdx; /* -1 => none */ + uint32_t mCursor; /* offset for list display */ + std::list mList; + +private: +}; + + + +class MenuOpBasicKey: public Menu +{ +public: + MenuOpBasicKey(std::string shortDesc): Menu(shortDesc) { return; } + virtual uint32_t op(); + +protected: + virtual uint32_t op_basic(std::string key); +}; + + + +class MenuOpTwoKeys: public Menu +{ + +public: + MenuOpTwoKeys(std::string shortDesc): Menu(shortDesc) { return; } + virtual uint32_t op(); + +protected: + virtual uint32_t op_twokeys(std::string parentkey, std::string key); + +}; + +/* Read input, line by line... + */ + +class MenuOpLineInput: public Menu +{ + +public: + MenuOpLineInput(std::string shortDesc): Menu(shortDesc) { return; } + virtual uint32_t op(); + virtual uint32_t process(char key); + +protected: + virtual uint32_t process_lines(std::string input); + + std::string mInput; +}; + + +#if 0 +class MenuInterface: public RsTermServer +{ +public: + + MenuInterface(Menu *b, uint32_t drawFlags) :mCurrentMenu(b), mBase(b), mDrawFlags(drawFlags), mInputRequired(false) { return; } + uint32_t process(char key, uint32_t drawFlags, std::string &buffer); + uint32_t drawHeader(uint32_t drawFlags, std::string &buffer); + + // RsTermServer Interface. + virtual void reset(); + virtual int tick(bool haveInput, char keypress, std::string &output); + + +private: + Menu *mCurrentMenu; + Menu *mBase; + uint32_t mDrawFlags; + bool mInputRequired; +}; + +#endif + + +class MenuInterface: public RpcSystem +{ +public: + + MenuInterface(RpcComms *c, Menu *b, uint32_t drawFlags) + :mComms(c), mCurrentMenu(b), mBase(b), mDrawFlags(drawFlags), mInputRequired(false) { return; } + + uint32_t process(char key, uint32_t drawFlags, std::string &buffer); + uint32_t drawHeader(uint32_t drawFlags, std::string &buffer); + + // RsSystem Interface. + virtual void reset(uint32_t chan_id); + virtual int tick(); + + +private: + RpcComms *mComms; + Menu *mCurrentMenu; + Menu *mBase; + uint32_t mDrawFlags; + bool mInputRequired; + time_t mUpdateTime; +}; + + +#endif diff --git a/retroshare-nogui/src/menu/menus.cc b/retroshare-nogui/src/menu/menus.cc new file mode 100644 index 000000000..46e044aa6 --- /dev/null +++ b/retroshare-nogui/src/menu/menus.cc @@ -0,0 +1,822 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include "util/rsstring.h" +#include "util/rsdir.h" + +#include "menu/menus.h" + +// Can't use: Q, H, T, U (universal) +// or L, N, P (list ops). +// or 0-9,a-f (list selection). + +#define MENU_FRIENDS_KEY_ADD 'a' +#define MENU_FRIENDS_KEY_VIEW 'v' +#define MENU_FRIENDS_KEY_REMOVE 'd' +#define MENU_FRIENDS_KEY_CHAT 'c' + +#define MENU_TRANSFER_KEY_STOP 's' +#define MENU_TRANSFER_KEY_CANCEL 'c' + +#define MENU_SEARCH_KEY_ADD 'a' +#define MENU_SEARCH_KEY_REMOVE 'd' +#define MENU_SEARCH_KEY_VIEW 'v' +#define MENU_SEARCH_KEY_DOWNLOAD 'g' + +#define MENU_FORUMS_KEY_ADD 'a' +#define MENU_FORUMS_KEY_VIEW 'v' +#define MENU_FORUMS_KEY_REMOVE 'd' +#define MENU_FORUMS_KEY_CHAT 'c' + +#define MENU_SHARED_KEY_EXPAND 'e' +#define MENU_SHARED_KEY_UNSHARE 's' +#define MENU_SHARED_KEY_ADD 'a' +#define MENU_SHARED_KEY_PUBLIC 'c' +#define MENU_SHARED_KEY_BROWSABLE 'b' + +#define MENU_TOPLEVEL_KEY_FRIENDS 'f' +#define MENU_TOPLEVEL_KEY_NETWORK 'w' +#define MENU_TOPLEVEL_KEY_TRANSFER 'd' +#define MENU_TOPLEVEL_KEY_SEARCH 's' +#define MENU_TOPLEVEL_KEY_FORUMS 'o' +#define MENU_TOPLEVEL_KEY_SHARED 'k' //If you know of a key which fits better, just change it ;-) +#define MENU_TOPLEVEL_KEY_UPLOADS 'e' + + +Menu *CreateMenuStructure(NotifyTxt *notify) +{ + /* construct Friends Menu */ + MenuList *friends = new MenuListFriends(); + // No Friends Operations Completed Yet! + //friends->addMenuItem(MENU_FRIENDS_KEY_ADD, new MenuOpFriendsAdd()); + //friends->addMenuItem(MENU_FRIENDS_KEY_VIEW, new MenuOpFriendsViewDetail()); + //friends->addMenuItem(MENU_FRIENDS_KEY_REMOVE, new MenuOpFriendsRemove()); + //friends->addMenuItem(MENU_FRIENDS_KEY_CHAT, new MenuOpFriendsChat()); + + MenuList *network = new MenuListNetwork(); + + MenuList *transfers = new MenuListTransfer(); + //transfers->addMenuItem(MENU_TRANSFER_KEY_STOP, new MenuOpTransferStop()); + transfers->addMenuItem(MENU_TRANSFER_KEY_CANCEL, new MenuOpTransferCancel()); + + MenuList *search = new MenuListSearch(notify); + MenuList *searchlist = new MenuListSearchList(notify); + search->addMenuItem(MENU_SEARCH_KEY_ADD, new MenuOpSearchNew(notify)); + //search->addMenuItem(MENU_SEARCH_KEY_REMOVE, new MenuOpSearchDelete()); + search->addMenuItem(MENU_SEARCH_KEY_VIEW, searchlist); + searchlist->addMenuItem(MENU_SEARCH_KEY_DOWNLOAD, new MenuOpSearchListDownload()); + + // Forums - TODO. + //MenuList *forums = new MenuListForums(); + //forums->addMenuItem(MENU_FRIENDS_KEY_ADD, new MenuOpFriendsAdd()); + //forums->addMenuItem(MENU_FRIENDS_KEY_VIEW, new MenuOpFriendsViewDetail()); + //forums->addMenuItem(MENU_FRIENDS_KEY_REMOVE, new MenuOpFriendsRemove()); + //forums->addMenuItem(MENU_FRIENDS_KEY_CHAT, new MenuOpFriendsChat()); + + // Shared folders Menu + MenuList *shared = new MenuListShared(); + shared->addMenuItem(MENU_SHARED_KEY_ADD , new MenuListSharedAddShare()); + shared->addMenuItem(MENU_SHARED_KEY_UNSHARE , new MenuListSharedUnshare()); + shared->addMenuItem(MENU_SHARED_KEY_PUBLIC , new MenuListSharedTogglePublic()); + shared->addMenuItem(MENU_SHARED_KEY_BROWSABLE , new MenuListSharedToggleBrowsable()); + + /* Top Level Menu */ + Menu *tlm = new Menu("Top Level Menu"); + + tlm->addMenuItem(MENU_TOPLEVEL_KEY_FRIENDS, friends); + tlm->addMenuItem(MENU_TOPLEVEL_KEY_NETWORK, network); + tlm->addMenuItem(MENU_TOPLEVEL_KEY_TRANSFER, transfers); + tlm->addMenuItem(MENU_TOPLEVEL_KEY_SEARCH, search); + //tlm->addMenuItem(MENU_TOPLEVEL_KEY_FORUMS, forums); + tlm->addMenuItem(MENU_TOPLEVEL_KEY_SHARED, shared); + + return tlm; +} + + +/************ + * Friends Menu + */ + + +uint32_t MenuListFriends::op() +{ + MenuList::op(); + + rsPeers->getGPGAcceptedList(mList); + //rsPeers->getGPGValidList(mList); + + return MENU_OP_SUBMENU; +} + +int MenuListFriends::getEntryDesc(int idx, std::string &desc) +{ + std::string gpgId; + + if (!getListEntry(idx, gpgId)) + { + /* error */ + return 0; + } + + RsPeerDetails details; + if (rsPeers->getPeerDetails(gpgId, details)) + { + if (details.accept_connection) + { + desc = "Friend: "; + } + else + { + desc = "Neighbour: "; + } + + desc += "<" + gpgId + "> "; + desc += details.name; + } + return 1; +} + + +uint32_t MenuListNetwork::op() +{ + MenuList::op(); + + rsPeers->getGPGValidList(mList); + //rsPeers->getGPGAcceptedList(mList); + + return MENU_OP_SUBMENU; +} + + +uint32_t MenuOpFriendsAdd::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + +uint32_t MenuOpFriendsViewDetail::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuOpFriendsRemove::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuOpFriendsChat::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +/************ + * Transfer Menu + */ + + +uint32_t MenuListTransfer::op() +{ + MenuList::op(); + + /* load friend list*/ + rsFiles->FileDownloads(mList); + + return MENU_OP_SUBMENU; +} + +int MenuListTransfer::getEntryDesc(int idx, std::string &desc) +{ + std::string hash; + if (!getListEntry(idx, hash)) + { + std::cout << "MenuListTransfer::getEntryDesc() No ListEntry"; + std::cout << std::endl; + return 0; + } + + FileInfo info; + if (!rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info)) + { + std::cout << "MenuListTransfer::getEntryDesc() No FileDetails"; + std::cout << std::endl; + return 0; + } + + float frac = 100.0 * (float) info.transfered / info.size; + + if (frac != 1.0) + { + if (info.tfRate > 0) + { + rs_sprintf(desc, "<%s> Downloading %3.2f%% from %d Peers @%3.1fKB/s. Name: %s", + info.hash.c_str(), frac, info.peers.size(), info.tfRate, info.fname.c_str()); + } + else + { + rs_sprintf(desc, "<%s> Stalled %3.2f%% Name: %s", + info.hash.c_str(), frac, info.fname.c_str()); + } + } + else + { + rs_sprintf(desc, "<%s> Done! Name: %s", info.hash.c_str(), info.fname.c_str()); + } + return MENU_OP_INSTANT; +} + +uint32_t MenuOpTransferStop::op_basic(std::string key) +{ + rsFiles->FileCancel(key); + parent()->setOpMessage("Stopped Transfer"); + return MENU_OP_INSTANT; +} + +uint32_t MenuOpTransferCancel::op_basic(std::string key) +{ + rsFiles->FileCancel(key); + parent()->setOpMessage("Stopped Transfer"); + return MENU_OP_INSTANT; +} + + +/************ + * Search Menu + */ + + + +uint32_t MenuListSearch::op() +{ + mSelectIdx = -1; + mCursor = 0; + + /* Don't reset List -> done dynamically */ + + return MENU_OP_SUBMENU; +} + +int MenuListSearch::getEntryDesc(int idx, std::string &desc) +{ + std::string strSearchId; + + if (!getListEntry(idx, strSearchId)) + { + /* error */ + return 0; + } + + std::map::iterator it; + std::map::iterator sit; + it = mSearchTerms.find(strSearchId); + sit = mSearchIds.find(strSearchId); + if ((it == mSearchTerms.end()) || (sit == mSearchIds.end())) + { + /* error */ + return 0; + } + + rs_sprintf(desc, "Search(\"%s\") Found %d matches so far", + it->second.c_str(), mNotify->getSearchResultCount(sit->second)); + return 1; +} + + +int MenuListSearch::getCurrentSearchId(uint32_t &id) +{ + std::string strSearchId; + + if (!getListEntry(mSelectIdx, strSearchId)) + { + /* error */ + return 0; + } + + std::map::iterator sit; + sit = mSearchIds.find(strSearchId); + if (sit == mSearchIds.end()) + { + /* error */ + return 0; + } + + id = sit->second; + return 1; +} + +int MenuListSearch::storeSearch(uint32_t searchId, std::string match_string) +{ + std::cout << "MenuListSearch::storeSearch(" << searchId << " => "; + std::cout << match_string; + std::cout << std::endl; + + std::string strSearchId; + rs_sprintf(strSearchId, "%lu", searchId); + mList.push_back(strSearchId); + + mSearchTerms[strSearchId] = match_string; + mSearchIds[strSearchId] = searchId; + + return 1; +} + +int MenuListSearch::removeSearch(std::string strSearchId) +{ + std::cout << "MenuListSearch::removeSearch(" << strSearchId << ")"; + std::cout << std::endl; + + std::map::iterator it; + it = mSearchIds.find(strSearchId); + if (it != mSearchIds.end()) + { + + /* cancel search */ + // CAN'T DO!!! + + /* clear results from Notify Collector */ + mNotify->clearSearchId(it->second); + + /* cleanup local maps */ + mSearchIds.erase(it); + + /* cleanup terms maps (TODO) */ + } + + return 1; +} + +uint32_t MenuOpSearchNew::drawPage(uint32_t drawFlags, std::string &buffer) +{ + buffer += "Enter New Search Term > "; + return 1; +} + + + +uint32_t MenuOpSearchNew::process_lines(std::string input) +{ + /* launch search */ + if (input.size() < 4) + { + std::cout << "MenuOpSearchNew::process_lines() ERROR Input too small"; + std::cout << std::endl; + return MENU_PROCESS_ERROR; + } + + std::string search = input.substr(0, input.size() - 1); // remove \n. + uint32_t searchId = (uint32_t) rsTurtle->turtleSearch(search); + mNotify->collectSearchResults(searchId); + + /* store request in parent */ + MenuListSearch *ms = dynamic_cast(parent()); + if (ms) + { + ms->storeSearch(searchId, search); + } + + return MENU_PROCESS_DONE; +} + +uint32_t MenuOpSearchDelete::op_basic(std::string key) +{ + + return MENU_OP_INSTANT; +} + + +uint32_t MenuListSearchList::op() +{ + MenuList::op(); + return refresh(); +} + +uint32_t MenuListSearchList::refresh() +{ + Menu* p = parent(); + MenuListSearch *mls = dynamic_cast(p); + if (!mls) + { + std::cout << "MenuListSearchList::refresh() mls not there"; + std::cout << std::endl; + return MENU_OP_ERROR; + } + + /* load friend list*/ + mList.clear(); + + uint32_t searchId; + if (!mls->getCurrentSearchId(searchId)) + { + std::cout << "MenuListSearchList::refresh() currentIdx invalid"; + std::cout << std::endl; + return MENU_OP_ERROR; + } + + std::cout << "MenuListSearchList::refresh() searchId: " << searchId; + std::cout << std::endl; + + std::list::iterator it; + mNotify->getSearchResults(searchId, mSearchResults); + + /* convert into useful list */ + for(it = mSearchResults.begin(); it != mSearchResults.end(); it++) + { + mList.push_back(it->hash); + } + + mSelectIdx = -1; + mCursor = 0; + return MENU_OP_SUBMENU; +} + +int MenuListSearchList::getEntryDesc(int idx, std::string &desc) +{ + std::list::iterator it; + int i = 0; + for (it = mSearchResults.begin(); + (i < idx) && (it != mSearchResults.end()); it++, i++) ; + + if (it != mSearchResults.end()) + { + rs_sprintf(desc, "<%s> Size: %llu Name:%s", + it->hash.c_str(), it->size, it->name.c_str()); + return MENU_ENTRY_OKAY; + } + return MENU_ENTRY_NONE; +} + + +int MenuListSearchList::downloadSelected() +{ + if (mSelectIdx < 0) + { + std::cout << "MenuListSearchList::downloadSelected() Invalid Selection"; + std::cout << std::endl; + return MENU_ENTRY_NONE; + } + + std::list::iterator it; + int i = 0; + for (it = mSearchResults.begin(); + (i < mSelectIdx) && (it != mSearchResults.end()); it++, i++) ; + + if (it != mSearchResults.end()) + { + std::list srcIds; + if (rsFiles -> FileRequest(it->name, it->hash, it->size, + "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) + { + std::cout << "MenuListSearchList::downloadSelected() Download Started"; + std::cout << std::endl; + } + else + { + std::cout << "MenuListSearchList::downloadSelected() Error Starting Download"; + std::cout << std::endl; + } + return MENU_ENTRY_OKAY; + } + return MENU_ENTRY_NONE; +} + + + +uint32_t MenuOpSearchListDownload::op_basic(std::string key) +{ + Menu* p = parent(); + MenuListSearchList *mlsl = dynamic_cast(p); + if (!mlsl) + { + std::cout << "MenuOpSearchListDownload::op_basic() ERROR"; + std::cout << std::endl; + return MENU_OP_ERROR; + } + + mlsl->downloadSelected(); + + return MENU_OP_INSTANT; +} + +/************ + * Forums Menu + */ + + + +uint32_t MenuListForums::op() +{ + /* load friend list*/ + mList.clear(); + rsPeers->getGPGAcceptedList(mList); + mSelectIdx = 0; + + return MENU_OP_SUBMENU; +} + + +int MenuListForums::getEntryDesc(int idx, std::string &desc) +{ + + + return MENU_OP_INSTANT; +} + +uint32_t MenuOpForumDetails::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuOpForumSubscribe::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuOpForumUnsubscribe::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuOpForumCreate::op_basic(std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuListForumMsgs::op() +{ + /* load friend list*/ + mList.clear(); + rsPeers->getGPGAcceptedList(mList); + mSelectIdx = 0; + + return MENU_OP_SUBMENU; +} + +int MenuListForumMsgs::getEntryDesc(int idx, std::string &desc) +{ + + + return MENU_OP_INSTANT; +} + +uint32_t MenuOpForumMsgView::op_twokeys(std::string parentkey, std::string key) +{ + + + return MENU_OP_INSTANT; +} + +uint32_t MenuOpForumMsgReply::op_twokeys(std::string parentkey, std::string key) +{ + + + return MENU_OP_INSTANT; +} + + +uint32_t MenuOpForumMsgWrite::op_twokeys(std::string parentkey, std::string key) +{ + + + return MENU_OP_INSTANT; +} + +/************ + * Shared folders Menu + */ + + +uint32_t MenuListShared::op() +{ + MenuList::op(); + + mList.clear(); + std::list dirs; + rsFiles->getSharedDirectories(dirs); + std::list::iterator it; + for(it = dirs.begin(); it != dirs.end(); it++) + { + mList.push_back ((*it).virtualname) ; + } + + return MENU_OP_SUBMENU; +} + +int MenuListShared::getEntryDesc(int idx, std::string &desc) +{ + std::list dirs; + rsFiles->getSharedDirectories(dirs); + std::list::iterator it; + std::string shareflag; + int i=0; + for (it = dirs.begin(); (i < idx) && (it != dirs.end()); it++, i++); + if (it != dirs.end()) + { + if (it->shareflags == (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE)) + shareflag = "networkwide - browsable"; + else if ((it->shareflags & RS_FILE_HINTS_BROWSABLE) == RS_FILE_HINTS_BROWSABLE) + shareflag = "private - browsable"; + else if ((it->shareflags & RS_FILE_HINTS_NETWORK_WIDE) == RS_FILE_HINTS_NETWORK_WIDE) + shareflag = "networkwide - anonymous"; + else + shareflag = "not shared"; + + rs_sprintf(desc, "Path: %s Share Type:%s", it->filename.c_str(), shareflag.c_str()); + return MENU_ENTRY_OKAY; + } + return MENU_ENTRY_NONE; +} + +int MenuListShared::unshareSelected() +{ + if (mSelectIdx < 0) + { + std::cout << "MenuListSearchList::unshareSelected() Invalid Selection"; + std::cout << std::endl; + return MENU_ENTRY_NONE; + } + std::list dirs; + rsFiles->getSharedDirectories(dirs); + std::list::iterator it; + int i=0; + for (it = dirs.begin(); (i < mSelectIdx) && (it != dirs.end()); it++, i++); + if (it != dirs.end()) + { + rsFiles->removeSharedDirectory(it->filename); + return MENU_ENTRY_OKAY; + } + return MENU_ENTRY_NONE; +} + +int MenuListShared::toggleFlagSelected(uint32_t shareflags) +{ + if (mSelectIdx < 0) + { + std::cout << "MenuListSearchList::unshareSelected() Invalid Selection"; + std::cout << std::endl; + return MENU_ENTRY_NONE; + } + std::list dirs; + rsFiles->getSharedDirectories(dirs); + std::list::iterator it; + int i=0; + for (it = dirs.begin(); (i < mSelectIdx) && (it != dirs.end()); it++, i++); + if (it != dirs.end()) + { + if((it->shareflags & shareflags) == shareflags) + { + it->shareflags = it->shareflags & ~shareflags; //disable shareflags + rsFiles->updateShareFlags(*it); + } else + { + it->shareflags = it->shareflags | shareflags; //anable shareflags + rsFiles->updateShareFlags(*it); + } + return MENU_ENTRY_OKAY; + } + return MENU_ENTRY_NONE; +} + +uint32_t MenuListSharedUnshare::op_basic(std::string key) +{ + Menu* p = parent(); + MenuListShared *mls = dynamic_cast(p); + if (!mls) + { + std::cout << "MenuListShared::op_basic() ERROR"; + std::cout << std::endl; + return MENU_OP_ERROR; + } + + mls->unshareSelected(); + + return MENU_OP_INSTANT; +} + +uint32_t MenuListSharedTogglePublic::op_basic(std::string key) +{ + Menu* p = parent(); + MenuListShared *mls = dynamic_cast(p); + if (!mls) + { + std::cout << "MenuListShared::op_basic() ERROR"; + std::cout << std::endl; + return MENU_OP_ERROR; + } + + mls->toggleFlagSelected(RS_FILE_HINTS_NETWORK_WIDE); + + return MENU_OP_INSTANT; +} + +uint32_t MenuListSharedToggleBrowsable::op_basic(std::string key) +{ + Menu* p = parent(); + MenuListShared *mls = dynamic_cast(p); + if (!mls) + { + std::cout << "MenuListShared::op_basic() ERROR"; + std::cout << std::endl; + return MENU_OP_ERROR; + } + + mls->toggleFlagSelected(RS_FILE_HINTS_BROWSABLE); + + return MENU_OP_INSTANT; +} + +uint32_t MenuListSharedAddShare::drawPage(uint32_t drawFlags, std::string &buffer) +{ + buffer += "Enter New path 'path' 'virtualfolder' > "; + return 1; +} + + + +uint32_t MenuListSharedAddShare::process_lines(std::string input) +{ + /* launch search */ + if (input.size() < 4) + { + std::cout << "MenuOpSearchNew::process_lines() ERROR Input too small"; + std::cout << std::endl; + return MENU_PROCESS_ERROR; + } + + std::string dir = input.substr(0, input.size() - 1); // remove \n. + + // check that the directory exists! + if (!RsDirUtil::checkDirectory(dir)) + { + std::cout << "MenuOpSearchNew::process_lines() ERROR Directory doesn't exist"; + std::cout << std::endl; + return MENU_PROCESS_ERROR; + } + + // extract top level as the virtual name. + std::string topdir = RsDirUtil::getTopDir(input); + if (topdir.size() < 1) + { + std::cout << "MenuOpSearchNew::process_lines() ERROR TopDir is invalid"; + std::cout << std::endl; + return MENU_PROCESS_ERROR; + } + + SharedDirInfo shareddir; + shareddir.filename = dir; + shareddir.virtualname = topdir; + shareddir.shareflags = 0x0; + + if (!rsFiles->addSharedDirectory(shareddir)) + { + std::cout << "MenuOpSearchNew::process_lines() ERROR Adding SharedDir"; + std::cout << std::endl; + return MENU_PROCESS_ERROR; + } + + return MENU_PROCESS_DONE; +} diff --git a/retroshare-nogui/src/menu/menus.h b/retroshare-nogui/src/menu/menus.h new file mode 100644 index 000000000..757ae208d --- /dev/null +++ b/retroshare-nogui/src/menu/menus.h @@ -0,0 +1,346 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "menu/menu.h" +#include +#include "notifytxt.h" /* needed to access search results */ +#include + +Menu *CreateMenuStructure(NotifyTxt *notify); + +/************ + * Friends Menu + */ + +class MenuListFriends: public MenuList +{ + +public: + MenuListFriends() :MenuList("Friends") { return; } + + virtual uint32_t op(); + int getEntryDesc(int idx, std::string &desc); + +protected: + MenuListFriends(std::string name) :MenuList(name) { return; } // For Network. +}; + + +class MenuListNetwork: public MenuListFriends +{ + +public: + MenuListNetwork() :MenuListFriends("Network") { return; } + + virtual uint32_t op(); +}; + + +class MenuOpFriendsAdd: public MenuOpBasicKey +{ + public: + + MenuOpFriendsAdd() :MenuOpBasicKey("Add") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuOpFriendsViewDetail: public MenuOpBasicKey +{ + public: + + MenuOpFriendsViewDetail() :MenuOpBasicKey("View") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuOpFriendsRemove: public MenuOpBasicKey +{ + public: + + MenuOpFriendsRemove() :MenuOpBasicKey("Remove") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuOpFriendsChat: public MenuOpBasicKey +{ + public: + + MenuOpFriendsChat() :MenuOpBasicKey("Chat") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + + +/************ + * Transfer Menu + */ + + +class MenuListTransfer: public MenuList +{ + public: + + MenuListTransfer() :MenuList("Downloads") { return; } + virtual uint32_t op(); + int getEntryDesc(int idx, std::string &desc); +}; + + +class MenuOpTransferStop: public MenuOpBasicKey +{ + public: + + MenuOpTransferStop() :MenuOpBasicKey("Stop") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + + +class MenuOpTransferCancel: public MenuOpBasicKey +{ + public: + + MenuOpTransferCancel() :MenuOpBasicKey("Cancel") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + + +/************ + * Search Menu + */ + + +class MenuListSearch: public MenuList +{ + public: + + MenuListSearch(NotifyTxt *notify) + :MenuList("Search"), mNotify(notify) { return; } + + virtual uint32_t op(); + int getEntryDesc(int idx, std::string &desc); + + /* specific Search Functions */ + int getCurrentSearchId(uint32_t &id); + int storeSearch(uint32_t searchId, std::string match_string); + int removeSearch(std::string strSearchId); + +private: + std::map mSearchIds; + std::map mSearchTerms; + NotifyTxt *mNotify; +}; + + +class MenuOpSearchNew: public MenuOpLineInput +{ + public: + + MenuOpSearchNew(NotifyTxt *notify) + :MenuOpLineInput("New"), mNotify(notify) { return; } + virtual uint32_t process_lines(std::string input); + virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer); + +private: + NotifyTxt *mNotify; +}; + + +class MenuOpSearchDelete: public MenuOpBasicKey +{ + public: + + MenuOpSearchDelete() :MenuOpBasicKey("Delete") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuListSearchList: public MenuList +{ + public: + + MenuListSearchList(NotifyTxt *notify) + :MenuList("Results"), mNotify(notify) { return; } + virtual uint32_t op(); + uint32_t refresh(); + int getEntryDesc(int idx, std::string &desc); + int downloadSelected(); + + private: + NotifyTxt *mNotify; + std::list mSearchResults; // local cache for consistency. +}; + + +class MenuOpSearchListDownload: public MenuOpBasicKey +{ + public: + + MenuOpSearchListDownload() :MenuOpBasicKey("Download") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + + +/************ + * Forums Menu + */ + + + +class MenuListForums: public MenuList +{ + public: + + MenuListForums() :MenuList("Forums SubMenu") { return; } + virtual uint32_t op(); + int getEntryDesc(int idx, std::string &desc); +}; + + +class MenuOpForumDetails: public MenuOpBasicKey +{ + public: + + MenuOpForumDetails() :MenuOpBasicKey("Show Forum Details") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuOpForumSubscribe: public MenuOpBasicKey +{ + public: + + MenuOpForumSubscribe() :MenuOpBasicKey("Subscribe To Forum") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuOpForumUnsubscribe: public MenuOpBasicKey +{ + public: + + MenuOpForumUnsubscribe() :MenuOpBasicKey("Unsubscribe To Forum") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + +class MenuOpForumCreate: public MenuOpBasicKey +{ + public: + + MenuOpForumCreate() :MenuOpBasicKey("Create Forum") { return; } + virtual uint32_t op_basic(std::string hash); +}; + + + +class MenuListForumMsgs: public MenuList +{ + public: + + MenuListForumMsgs() :MenuList("List Forum Msgs") { return; } + virtual uint32_t op(); + int getEntryDesc(int idx, std::string &desc); +}; + +class MenuOpForumMsgView: public MenuOpTwoKeys +{ + public: + + MenuOpForumMsgView() :MenuOpTwoKeys("View Message") { return; } + virtual uint32_t op_twokeys(std::string parentkey, std::string key); +}; + + +class MenuOpForumMsgReply: public MenuOpTwoKeys +{ + public: + + MenuOpForumMsgReply() :MenuOpTwoKeys("Reply to Message") { return; } + virtual uint32_t op_twokeys(std::string parentkey, std::string key); +}; + + +class MenuOpForumMsgWrite: public MenuOpTwoKeys +{ + public: + + MenuOpForumMsgWrite() :MenuOpTwoKeys("Write Message") { return; } + virtual uint32_t op_twokeys(std::string parentkey, std::string key); +}; + +/************ + * Shared folders Menu + */ + + +class MenuListShared: public MenuList +{ + public: + + MenuListShared() :MenuList("My Shared Directories") { return; } + virtual uint32_t op(); + int getEntryDesc(int idx, std::string &desc); + int unshareSelected(); + int toggleFlagSelected(uint32_t shareflags); +}; + + + +class MenuListSharedUnshare: public MenuOpBasicKey +{ + public: + + MenuListSharedUnshare() :MenuOpBasicKey("Stop Sharing Selected") { return; } + virtual uint32_t op_basic(std::string key); +}; + +class MenuListSharedTogglePublic: public MenuOpBasicKey +{ + public: + + MenuListSharedTogglePublic() :MenuOpBasicKey("Enable/Disable Networkwide Sharing") { return; } + virtual uint32_t op_basic(std::string key); +}; + +class MenuListSharedToggleBrowsable: public MenuOpBasicKey +{ + public: + + MenuListSharedToggleBrowsable() :MenuOpBasicKey("Enable/Disable Browsing Of Selected") { return; } + virtual uint32_t op_basic(std::string key); +}; + +class MenuListSharedAddShare: public MenuOpLineInput +{ + public: + + MenuListSharedAddShare() :MenuOpLineInput("Add new Share") { return; } + virtual uint32_t process_lines(std::string input); + virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer); +}; + diff --git a/retroshare-nogui/src/menu/menutest.h b/retroshare-nogui/src/menu/menutest.h new file mode 100644 index 000000000..94c58d4ee --- /dev/null +++ b/retroshare-nogui/src/menu/menutest.h @@ -0,0 +1,94 @@ + +#include +#include "menu/menu.h" + +class MenuTest +{ +public: + MenuTest(MenuInterface *i, std::istream &in, std::ostream &out) + :mMenus(i), mIn(in), mOut(out) + { + return; + } + +int tick() + { + int c = mIn.get(); + uint8_t key = (uint8_t) c; + uint32_t drawFlags = 0; + std::string buffer; + mMenus->process(key, drawFlags, buffer); + + return 1; + } + +private: + + + MenuInterface *mMenus; + std::istream &mIn; + std::ostream &mOut; +}; + +#include +#include + +#include "rstermserver.h" + +class RsConsole +{ + public: + + RsConsole(RsTermServer *s, int infd, int outfd) + :mServer(s), mIn(infd), mOut(outfd) + { + const int fcflags = fcntl(mIn,F_GETFL); + if (fcflags < 0) + { + std::cerr << "RsConsole() ERROR getting fcntl FLAGS"; + std::cerr << std::endl; + exit(1); + } + if (fcntl(mIn,F_SETFL,fcflags | O_NONBLOCK) <0) + { + std::cerr << "RsConsole() ERROR setting fcntl FLAGS"; + std::cerr << std::endl; + exit(1); + } + } + + int tick() + { + char buf; + std::string output; + int size = read(mIn, &buf, 1); + + bool haveInput = (size > 0); + + int rt = mServer->tick(haveInput, buf, output); + + if (output.size() > 0) + { + write(mOut, output.c_str(), output.size()); + } + + if (rt < 0) + { + std::cerr << "Exit Request"; + exit(1); + } + + if (!haveInput) + { + return 0; + } + + return 1; + } + +private: + + RsTermServer *mServer; + int mIn, mOut; +}; + diff --git a/retroshare-nogui/src/menu/stdiocomms.cc b/retroshare-nogui/src/menu/stdiocomms.cc new file mode 100644 index 000000000..132b8e89d --- /dev/null +++ b/retroshare-nogui/src/menu/stdiocomms.cc @@ -0,0 +1,183 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "menu/stdiocomms.h" + +#include +#include +#include +#include +#include + + +StdioComms::StdioComms(int infd, int outfd) + :mIn(infd), mOut(outfd) +{ +// fcntl not available on Windows, search alternative when needed +#ifndef WINDOWS_SYS +#if 1 +// THIS Code is strange... +// It seems to mess up stderr. +// But if you redirect it -> is comes out fine. Very Weird. +// HELP!!! + + std::cerr << "StdioComms() STDERR msg 0"; + std::cerr << std::endl; + const int fcflags = fcntl(mIn,F_GETFL); + if (fcflags < 0) + { + std::cerr << "StdioComms() ERROR getting fcntl FLAGS"; + std::cerr << std::endl; + exit(1); + } + if (fcntl(mIn,F_SETFL,fcflags | O_NONBLOCK) <0) + { + std::cerr << "StdioComms() ERROR setting fcntl FLAGS"; + std::cerr << std::endl; + exit(1); + } + std::cerr << "StdioComms() STDERR msg 1"; + std::cerr << std::endl; +#endif +#endif // WINDOWS_SYS +} + + +int StdioComms::isOkay() +{ + return 1; +} + + +int StdioComms::active_channels(std::list &chan_ids) +{ + if (isOkay()) + { + chan_ids.push_back(1); // only one possible here (stdin/stdout) + } + return 1; +} + +int StdioComms::error(uint32_t chan_id, std::string msg) +{ + std::cerr << "StdioComms::error(" << msg << ")"; + std::cerr << std::endl; + return 1; +} + + + +int StdioComms::recv_ready(uint32_t chan_id) +{ + /* should be proper poll / select! - but we don't use this at the moment */ + return 1; +} + + +int StdioComms::recv(uint32_t chan_id, uint8_t *buffer, int bytes) +{ + int size = read(mIn, buffer, bytes); + std::cerr << "StdioComms::recv() returned: " << size; + std::cerr << std::endl; + + if (size == -1) + { + std::cerr << "StdioComms::recv() ERROR: " << errno; + std::cerr << std::endl; + if (errno == EAGAIN) + { + return 0; // OKAY; + } + } + + return size; +} + + +int StdioComms::recv(uint32_t chan_id, std::string &buffer, int bytes) +{ + uint8_t tmpbuffer[bytes]; + int size = read(mIn, tmpbuffer, bytes); + for(int i = 0; i < size; i++) + { + buffer += tmpbuffer[i]; + } + return size; +} + + // these make it easier... +int StdioComms::recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes) +{ + int totalread = 0; + while(totalread < bytes) + { + int size = read(mIn, &(buffer[totalread]), bytes - totalread); + if (size < 0) + { + if (totalread) + break; // partial read. + else + return size; // error. + } + totalread += size; + usleep(1000); // minisleep - so we don't 100% CPU. + std::cerr << "StdioComms::recv_blocking() read so far: " << size; + std::cerr << " / " << totalread; + std::cerr << std::endl; + } + return totalread; +} + + +int StdioComms::recv_blocking(uint32_t chan_id, std::string &buffer, int bytes) +{ + uint8_t tmpbuffer[bytes]; + int size = recv_blocking(chan_id, tmpbuffer, bytes); + + if (size < 0) + return size; // error. + + for(int i = 0; i < size; i++) + buffer += tmpbuffer[i]; + + return size; +} + + +int StdioComms::send(uint32_t chan_id, uint8_t *buffer, int bytes) +{ + write(mOut, buffer, bytes); + return bytes; +} + + +int StdioComms::send(uint32_t chan_id, const std::string &output) +{ + if (output.size() > 0) + { + write(mOut, output.c_str(), output.size()); + } + return output.size(); +} + + diff --git a/retroshare-nogui/src/menu/stdiocomms.h b/retroshare-nogui/src/menu/stdiocomms.h new file mode 100644 index 000000000..bc559af4c --- /dev/null +++ b/retroshare-nogui/src/menu/stdiocomms.h @@ -0,0 +1,59 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef RS_STDIO_COMMS_H +#define RS_STDIO_COMMS_H + +#include "rpcsystem.h" + + + +class StdioComms: public RpcComms +{ +public: + StdioComms(int infd, int outfd); + + virtual int isOkay(); + virtual int error(uint32_t chan_id, std::string msg); + + virtual int active_channels(std::list &chan_ids); + + virtual int recv_ready(uint32_t chan_id); + virtual int recv(uint32_t chan_id, uint8_t *buffer, int bytes); + virtual int recv(uint32_t chan_id, std::string &buffer, int bytes); + + // these make it easier... + virtual int recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes); + virtual int recv_blocking(uint32_t chan_id, std::string &buffer, int bytes); + + virtual int send(uint32_t chan_id, uint8_t *buffer, int bytes); + virtual int send(uint32_t chan_id, const std::string &buffer); + +private: + int mIn, mOut; +}; + +#endif + diff --git a/retroshare-nogui/src/notifytxt.cc b/retroshare-nogui/src/notifytxt.cc index 01c98b753..429b370b6 100644 --- a/retroshare-nogui/src/notifytxt.cc +++ b/retroshare-nogui/src/notifytxt.cc @@ -112,7 +112,7 @@ bool NotifyTxt::askForPassword(const std::string& key_details, bool prev_is_bad, void NotifyTxt::notifyListChange(int list, int type) { - std::cerr << "NotifyTxt::notifyListChange()" << std::endl; + //std::cerr << "NotifyTxt::notifyListChange()" << std::endl; switch(list) { // case NOTIFY_LIST_NEIGHBOURS: @@ -231,3 +231,128 @@ void NotifyTxt::displayTransfers() iface->unlockData(); /* UnLock Interface */ } + + +/******************* Turtle Search Interface **********/ + +void NotifyTxt::notifyTurtleSearchResult(uint32_t search_id,const std::list& found_files) +{ +// std::cerr << "NotifyTxt::notifyTurtleSearchResult() " << found_files.size(); +// std::cerr << " new results for Id: " << search_id; +// std::cerr << std::endl; + + RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/ + + std::map >::iterator it; + it = mSearchResults.find(search_id); + if (it == mSearchResults.end()) + { + std::cerr << "NotifyTxt::notifyTurtleSearchResult() " << found_files.size(); + std::cerr << "ERROR: new results for Id: " << search_id; + std::cerr << std::endl; + std::cerr << "But list not installed..."; + std::cerr << " DROPPING SEARCH RESULTS"; + std::cerr << std::endl; + + /* new entry */ + //mSearchResults[search_id] = found_files; + return; + } + + /* add to existing entry */ + std::list::const_iterator fit; + for(fit = found_files.begin(); fit != found_files.end(); fit++) + { + it->second.push_back(*fit); + } + return; +} + + + /* interface for handling SearchResults */ +void NotifyTxt::getSearchIds(std::list &searchIds) +{ + RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/ + + std::map >::iterator it; + for(it = mSearchResults.begin(); it != mSearchResults.end(); it++) + { + searchIds.push_back(it->first); + } + return; +} + + +int NotifyTxt::getSearchResults(uint32_t id, std::list &searchResults) +{ + RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/ + + std::map >::iterator it; + it = mSearchResults.find(id); + if (it == mSearchResults.end()) + { + return 0; + } + + searchResults = it->second; + return 1; +} + + +int NotifyTxt::getSearchResultCount(uint32_t id) +{ + RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/ + + std::map >::iterator it; + it = mSearchResults.find(id); + if (it == mSearchResults.end()) + { + return 0; + } + return it->second.size(); +} + + // only collect results for selected searches. + // will drop others. +int NotifyTxt::collectSearchResults(uint32_t searchId) +{ + std::cerr << "NotifyTxt::collectSearchResult(" << searchId << ")"; + std::cerr << std::endl; + + RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/ + + std::map >::iterator it; + it = mSearchResults.find(searchId); + if (it == mSearchResults.end()) + { + std::list emptyList; + mSearchResults[searchId] = emptyList; + return 1; + } + + std::cerr << "NotifyTxt::collectSearchResult() ERROR Id exists"; + std::cerr << std::endl; + return 1; +} + +int NotifyTxt::clearSearchId(uint32_t searchId) +{ + std::cerr << "NotifyTxt::clearSearchId(" << searchId << ")"; + std::cerr << std::endl; + + RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/ + + std::map >::iterator it; + it = mSearchResults.find(searchId); + if (it == mSearchResults.end()) + { + std::cerr << "NotifyTxt::clearSearchId() ERROR Id not there"; + std::cerr << std::endl; + return 0; + } + + mSearchResults.erase(it); + return 1; +} + + diff --git a/retroshare-nogui/src/notifytxt.h b/retroshare-nogui/src/notifytxt.h index 82a019dc8..c3e63467e 100644 --- a/retroshare-nogui/src/notifytxt.h +++ b/retroshare-nogui/src/notifytxt.h @@ -27,13 +27,15 @@ #include +#include +#include "util/rsthreads.h" #include class NotifyTxt: public NotifyBase { public: - NotifyTxt() { return; } + NotifyTxt():mNotifyMtx("NotifyMtx") { return; } virtual ~NotifyTxt() { return; } void setRsIface(RsIface *i) { iface = i; } @@ -43,6 +45,20 @@ class NotifyTxt: public NotifyBase virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password); virtual bool askForPluginConfirmation(const std::string& plugin_file, const std::string& plugin_hash); + virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& found_files); + + /* interface for handling SearchResults */ + void getSearchIds(std::list &searchIds); + + int getSearchResultCount(uint32_t id); + int getSearchResults(uint32_t id, std::list &searchResults); + + // only collect results for selected searches. + // will drop others. + int collectSearchResults(uint32_t searchId); + int clearSearchId(uint32_t searchId); + + private: void displayNeighbours(); @@ -54,6 +70,12 @@ class NotifyTxt: public NotifyBase void displayTransfers(); RsIface *iface; /* so we can get the data */ + + + /* store TurtleSearchResults */ + RsMutex mNotifyMtx; + + std::map > mSearchResults; }; #endif diff --git a/retroshare-nogui/src/protobuf.pri b/retroshare-nogui/src/protobuf.pri new file mode 100644 index 000000000..b4c545774 --- /dev/null +++ b/retroshare-nogui/src/protobuf.pri @@ -0,0 +1,36 @@ +# +# Qt qmake integration with Google Protocol Buffers compiler protoc +# +# To compile protocol buffers with qt qmake, specify PROTOS variable and +# include this file +# +# Example: +# LIBS += /usr/local/lib/libprotobuf.so +# PROTOS = a.proto b.proto +# include(protobuf.pri) +# +# By default protoc looks for .proto files (including the imported ones) in +# the current directory where protoc is run. If you need to include additional +# paths specify the PROTOPATH variable +# + +PROTOPATH += . +PROTOPATH += ../Protocol +PROTOPATHS = +for(p, PROTOPATH):PROTOPATHS += --proto_path=$${p} + +protobuf_decl.name = protobuf header +protobuf_decl.input = PROTOS +protobuf_decl.output = ${QMAKE_FILE_BASE}.pb.h +protobuf_decl.commands = protoc --cpp_out="." $${PROTOPATHS} ${QMAKE_FILE_NAME} +protobuf_decl.variable_out = GENERATED_FILES +QMAKE_EXTRA_COMPILERS += protobuf_decl + +protobuf_impl.name = protobuf implementation +protobuf_impl.input = PROTOS +protobuf_impl.output = ${QMAKE_FILE_BASE}.pb.cc +protobuf_impl.depends = ${QMAKE_FILE_BASE}.pb.h +protobuf_impl.commands = $$escape_expand(\n) +protobuf_impl.variable_out = GENERATED_SOURCES +QMAKE_EXTRA_COMPILERS += protobuf_impl + diff --git a/retroshare-nogui/src/retroshare-nogui.pro b/retroshare-nogui/src/retroshare-nogui.pro index eef5a2fd0..2b6a53b04 100644 --- a/retroshare-nogui/src/retroshare-nogui.pro +++ b/retroshare-nogui/src/retroshare-nogui.pro @@ -2,6 +2,22 @@ TEMPLATE = app TARGET = retroshare-nogui CONFIG += bitdht #CONFIG += introserver +#CONFIG += sshserver + +# if you are linking against the libretroshare with gxs. +# this option links against the required sqlite library. +CONFIG += gxs + +CONFIG += debug +debug { + QMAKE_CFLAGS -= -O2 + QMAKE_CFLAGS += -O0 + QMAKE_CFLAGS += -g + + QMAKE_CXXFLAGS -= -O2 + QMAKE_CXXFLAGS += -O0 + QMAKE_CXXFLAGS += -g +} ################################# Linux ########################################## linux-* { @@ -12,6 +28,10 @@ linux-* { LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 LIBS += -lssl -lupnp -lixml -lgnome-keyring LIBS *= -lcrypto -ldl -lz + + gxs { + LIBS += -lsqlite3 + } } linux-g++ { @@ -65,6 +85,13 @@ win32 { RC_FILE = resources/retroshare_win.rc DEFINES *= WINDOWS_SYS + + SSH_DIR = ../../../libssh-0.5.2 + SSL_DIR = ../../../openssl-1.0.1c + + INCLUDEPATH += . $${SSH_DIR}/include $${SSL_DIR}/include + + } ##################################### MacOS ###################################### @@ -116,6 +143,116 @@ introserver { } +sshserver { + LIBSSH_DIR = ../../../lib/libssh-0.5.2 + + # This Requires libssh-0.5.* to compile. + # Modify path below to point at it. + # Probably will only work on Linux for the moment. + # + # Use the following commend to generate a Server RSA Key. + # Key should be in current directory - when run/ + # ssh-keygen -t rsa -f rs_ssh_host_rsa_key + # + # You can connect from a standard ssh, eg: ssh -p 7022 127.0.0.1 + # + # The Menu system is available from the command-line (-T) and SSH (-S) + # if it get covered by debug gunk, just press to refresh. + # + # ./retroshare-nogui -h provides some more instructions. + # + + INCLUDEPATH += $$LIBSSH_DIR/include/ + LIBS += $$LIBSSH_DIR/build/src/libssh.a + LIBS += $$LIBSSH_DIR/build/src/threads/libssh_threads.a + #LIBS += -lssh + #LIBS += -lssh_threads + HEADERS += ssh/rssshd.h + SOURCES += ssh/rssshd.cc + + # For the Menu System + HEADERS += menu/menu.h \ + menu/menus.h \ + menu/stdiocomms.h \ + + SOURCES += menu/menu.cc \ + menu/menus.cc \ + menu/stdiocomms.cc \ + + # For the RPC System + HEADERS += rpc/rpc.h \ + rpc/rpcserver.h \ + rpc/rpcsetup.h \ + rpc/rpcecho.h \ + rpcsystem.h \ + + SOURCES += rpc/rpc.cc \ + rpc/rpcserver.cc \ + rpc/rpcsetup.cc \ + rpc/rpcecho.cc \ + + # Actual protocol files to go here... + #HEADERS += rpc/proto/rpcecho.h \ + + #SOURCES += rpc/proto/rpcecho.cc \ + + DEFINES *= RS_SSH_SERVER + + # Include Protobuf classes. + CONFIG += protorpc +} + +protorpc { + # Proto Services + HEADERS += rpc/proto/rpcprotopeers.h \ + rpc/proto/rpcprotosystem.h \ + rpc/proto/rpcprotochat.h \ + rpc/proto/rpcprotosearch.h \ + rpc/proto/rpcprotofiles.h \ + + SOURCES += rpc/proto/rpcprotopeers.cc \ + rpc/proto/rpcprotosystem.cc \ + rpc/proto/rpcprotochat.cc \ + rpc/proto/rpcprotosearch.cc \ + rpc/proto/rpcprotofiles.cc \ + + # Offical Generated Code (protobuf 2.4.1) + HEADERS += rpc/proto/gencc/core.pb.h \ + rpc/proto/gencc/peers.pb.h \ + rpc/proto/gencc/system.pb.h \ + rpc/proto/gencc/chat.pb.h \ + rpc/proto/gencc/search.pb.h \ + rpc/proto/gencc/files.pb.h \ + + SOURCES += rpc/proto/gencc/core.pb.cc \ + rpc/proto/gencc/peers.pb.cc \ + rpc/proto/gencc/system.pb.cc \ + rpc/proto/gencc/chat.pb.cc \ + rpc/proto/gencc/search.pb.cc \ + rpc/proto/gencc/files.pb.cc \ + + # Generated ProtoBuf Code the RPC System + # If you are developing, or have a different version of protobuf + # you can use these ones (run make inside rsctrl/src/ to generate) + #HEADERS += ../../rsctrl/src/gencc/core.pb.h \ + # ../../rsctrl/src/gencc/peers.pb.h \ + # ../../rsctrl/src/gencc/system.pb.h \ + # ../../rsctrl/src/gencc/chat.pb.h \ + # ../../rsctrl/src/gencc/search.pb.h \ + # ../../rsctrl/src/gencc/files.pb.h \ + + #SOURCES += ../../rsctrl/src/gencc/core.pb.cc \ + # ../../rsctrl/src/gencc/peers.pb.cc \ + # ../../rsctrl/src/gencc/system.pb.cc \ + # ../../rsctrl/src/gencc/chat.pb.cc \ + # ../../rsctrl/src/gencc/search.pb.cc \ + # ../../rsctrl/src/gencc/files.pb.cc \ + + QMAKE_CFLAGS += -pthread + QMAKE_CXXFLAGS += -pthread + LIBS += -lprotobuf +} + diff --git a/retroshare-nogui/src/retroshare.cc b/retroshare-nogui/src/retroshare.cc index 5b054a925..d1b6a5abd 100644 --- a/retroshare-nogui/src/retroshare.cc +++ b/retroshare-nogui/src/retroshare.cc @@ -40,6 +40,16 @@ #include "introserver.h" #endif +#ifdef RS_SSH_SERVER +#include "ssh/rssshd.h" + +#include "menu/menus.h" +#include "menu/stdiocomms.h" + +#include "rpc/rpcsetup.h" + +#endif + /* Basic instructions for running libretroshare as background thread. * ******************************************************************* * * This allows your program to communicate with authenticated peers. @@ -74,8 +84,211 @@ int main(int argc, char **argv) * LoadPassword(...) set password for existing certificate. **/ + bool strictCheck = true; + +#ifdef RS_SSH_SERVER + /* parse commandline for additional nogui options */ + + int c; + // libretroshare's getopt str - so don't use any of these: "hesamui:p:c:w:l:d:U:r:R:" + // need options for + // enable SSH. (-S) + // set user/password for SSH. -L "user:pwdhash" + // accept RSA Key Auth. -K "RsaPubKeyFile" + // Terminal mode. -T + bool enableRpc = false; + bool enableSsh = false; + bool enableSshHtml = false; + bool enableSshPwd = false; + bool enableTerminal = false; + bool enableSshRsa = false; + bool genPwdHash = false; + std::string sshUser = "user"; + std::string sshPwdHash = ""; + std::string sshRsaFile = ""; + std::string sshPortStr = "7022"; + + while((c = getopt(argc, argv,"ChTL:P:K:GS::")) != -1) + { + switch(c) + { + case 'C': + enableRpc = true; + strictCheck = false; + break; + case 'S': + enableSsh = true; + if (optarg) + { + sshPortStr = optarg; // optional. + } + strictCheck = false; + break; + case 'H': + enableSshHtml = true; + strictCheck = false; + break; + case 'T': + enableTerminal = true; + strictCheck = false; + break; + case 'L': + sshUser = optarg; + strictCheck = false; + break; + case 'P': + enableSshPwd = true; + sshPwdHash = optarg; + strictCheck = false; + break; +#if 0 // NOT FINISHED YET. + case 'K': + enableSshRsa = true; + sshRsaFile = optarg; + strictCheck = false; + break; +#endif + case 'G': + genPwdHash = true; + break; + case 'h': + /* nogui help */ + std::cerr << argv[0] << std::endl; + std::cerr << "Specific Help Options: " << std::endl; + std::cerr << "\t-G Generate a Password Hash for SSH Server" << std::endl; + std::cerr << "\t-T Enable Terminal Interface" << std::endl; + std::cerr << "\t-S [port] Enable SSH Server, optionally specify port" << std::endl; + std::cerr << "\t-L Specify SSH login user (default:user)" << std::endl; + std::cerr << "\t-P Enable SSH login via Password" << std::endl; + std::cerr << "\t-C Enable RPC Protocol (requires -S too)" << std::endl; + //std::cerr << "\t-K [rsapubkeyfile] Enable SSH login via RSA key" << std::endl; + //std::cerr << "\t NB: Two Factor Auth, specify both -P & -K" << std::endl; + std::cerr << std::endl; + std::cerr << "\t To setup rs-nogui as a SSH Server is a three step process: " << std::endl; + std::cerr << "\t 1) \"ssh-keygen -t rsa -f rs_ssh_host_rsa_key\" " << std::endl; + std::cerr << "\t 2) \"./retroshare-nogui -G\" " << std::endl; + std::cerr << "\t 3) \"./retroshare-nogui -S [port] -L -P \" " << std::endl; + std::cerr << std::endl; + std::cerr << "Further Options "; + /* libretroshare will call exit(1) after printing its options */ + break; + + default: + /* let others through - for libretroshare */ + break; + } + } + // reset optind for Retroshare commandline arguments. + optind = 1; + + if (genPwdHash) + { + std::string saltBin; + std::string pwdHashRadix64; + std::string sshPwdForHash = ""; + + std::cout << "Type in your Password:" << std::flush; + char pwd[1024]; + if (!fgets(pwd, 1024, stdin)) + { + std::cerr << "Error Reading Password"; + std::cerr << std::endl; + exit(1); + } + + // strip newline. + for(int i = 0; (i < 1024) && (pwd[i] != '\n') && (pwd[i] != '\0'); i++) + { + sshPwdForHash += pwd[i]; + } + + std::cerr << "Chosen Password : " << sshPwdForHash; + std::cerr << std::endl; + + + GenerateSalt(saltBin); + if (!GeneratePasswordHash(saltBin, sshPwdForHash, pwdHashRadix64)) + { + std::cerr << "Error Generating Password Hash, password probably too short"; + std::cerr << pwdHashRadix64; + std::cerr << std::endl; + exit(1); + } + + std::cout << "Generated Password Hash for rs-nogui: "; + std::cout << pwdHashRadix64; + std::cout << std::endl; + std::cout << std::endl; + + /* checking match */ + if (CheckPasswordHash(pwdHashRadix64, sshPwdForHash)) + { + std::cerr << "Passed Check Okay!"; + std::cerr << std::endl; + } + else + { + std::cerr << "ERROR: Failed CheckPassword!"; + std::cerr << std::endl; + exit(1); + } + + + std::cerr << "Usage: ./retroshare-nogui -S [port] -L -P " << pwdHashRadix64; + std::cerr << std::endl; + exit(1); + } + + + /* enforce conditions */ + if (((enableSshRsa) || (enableSshPwd)) && (!enableSsh)) + { + std::cerr << "ERROR: SSH Server (-S) must be enabled to specify SSH Pwd (-P) or SSH RSA (-K)"; + std::cerr << std::endl; + exit(1); + } + + if (enableSsh && (!enableSshRsa) && (!enableSshPwd)) + { + std::cerr << "ERROR: One of (or both) SSH Pwd (-P) and SSH RSA (-K) must be specified with SSH Server (-S)"; + std::cerr << std::endl; + exit(1); + } + + if (enableRpc && (!enableSsh)) + { + std::cerr << "ERROR: RPC Mode (-C) requires SSH Server (-S) enabled"; + std::cerr << std::endl; + exit(1); + } + + + /* parse -S, -L & -K parameters */ + if (enableSshRsa) + { + /* check the file exists */ + /* TODO */ + + } + + if (enableSsh) + { + /* try parse it */ + /* TODO */ + + } + + if (enableSshPwd) + { + /* try parse it */ + /* TODO */ + + } +#endif + + RsInit::InitRsConfig(); - int initResult = RsInit::InitRetroShare(argc, argv); + int initResult = RsInit::InitRetroShare(argc, argv, strictCheck); if (initResult < 0) { /* Error occured */ @@ -132,6 +345,30 @@ int main(int argc, char **argv) return 1; } +#ifdef RS_SSH_SERVER + // Says it must be called before all the threads are launched! */ + // NB: this port number is not currently used. + RsSshd *ssh = NULL; + + if (enableSsh) + { + ssh = RsSshd::InitRsSshd(sshPortStr, "rs_ssh_host_rsa_key"); + // TODO Parse Option + if (enableSshRsa) + { + //ssh->adduser("anrsuser", "test"); + } + + if (enableSshPwd) + { + ssh->adduserpwdhash(sshUser, sshPwdHash); + } + + } + + +#endif + /* Start-up libretroshare server threads */ rsServer -> StartupRetroShare(); @@ -139,19 +376,77 @@ int main(int argc, char **argv) RsIntroServer rsIS; #endif +#ifdef RS_SSH_SERVER + uint32_t baseDrawFlags = 0; + if (enableSshHtml) + { + baseDrawFlags = MENU_DRAW_FLAGS_HTML; + } + + if (enableSsh) + { + if (enableRpc) + { + /* Build RPC Server */ + RpcMediator *med = CreateRpcSystem(ssh, notify); + ssh->setRpcSystem(med); + ssh->setSleepPeriods(0.01, 0.1); + } + else + { + /* create menu system for SSH */ + Menu *baseMenu = CreateMenuStructure(notify); + MenuInterface *menuInterface = new MenuInterface(ssh, baseMenu, baseDrawFlags | MENU_DRAW_FLAGS_ECHO); + ssh->setRpcSystem(menuInterface); + ssh->setSleepPeriods(0.05, 0.5); + } + + ssh->start(); + } + + MenuInterface *terminalMenu = NULL; + if (enableTerminal) + { + /* Terminal Version */ + RpcComms *stdioComms = new StdioComms(fileno(stdin), fileno(stdout)); + Menu *baseMenu = CreateMenuStructure(notify); + terminalMenu = new MenuInterface(stdioComms, baseMenu, baseDrawFlags | MENU_DRAW_FLAGS_NOQUIT); + //menuTerminal = new RsConsole(menuInterface, fileno(stdin), fileno(stdout)); + } + + +#endif + /* pass control to the GUI */ while(1) { - std::cerr << "GUI Tick()" << std::endl; -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif + //std::cerr << "GUI Tick()" << std::endl; #ifdef RS_INTRO_SERVER rsIS.tick(); #endif + + int rt = 0; +#ifdef RS_SSH_SERVER + if (terminalMenu) + { + rt = terminalMenu->tick(); + } +#endif + + // If we have a MenuTerminal ... + // only want to sleep if there is no input. (rt == 0). + if (rt == 0) + { +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif + } + + usleep(1000); + } return 1; } diff --git a/retroshare-nogui/src/rpc/proto/gencc/NOTES.txt b/retroshare-nogui/src/rpc/proto/gencc/NOTES.txt new file mode 100644 index 000000000..cdd79634d --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/NOTES.txt @@ -0,0 +1,4 @@ + +The files in this directory are auto generated by protobuf's protoc. +Don't add any other files in here!. + diff --git a/retroshare-nogui/src/rpc/proto/gencc/chat.pb.cc b/retroshare-nogui/src/rpc/proto/gencc/chat.pb.cc new file mode 100644 index 000000000..cff430bdb --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/chat.pb.cc @@ -0,0 +1,5019 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "chat.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace chat { + +namespace { + +const ::google::protobuf::Descriptor* ChatLobbyInfo_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ChatLobbyInfo_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* ChatLobbyInfo_LobbyState_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ChatId_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ChatId_reflection_ = NULL; +const ::google::protobuf::Descriptor* ChatMessage_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ChatMessage_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseChatLobbies_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseChatLobbies_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestChatLobbies_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestChatLobbies_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestChatLobbies_LobbySet_descriptor_ = NULL; +const ::google::protobuf::Descriptor* RequestCreateLobby_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestCreateLobby_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestJoinOrLeaveLobby_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestJoinOrLeaveLobby_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestJoinOrLeaveLobby_LobbyAction_descriptor_ = NULL; +const ::google::protobuf::Descriptor* RequestSetLobbyNickname_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestSetLobbyNickname_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseSetLobbyNickname_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseSetLobbyNickname_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestRegisterEvents_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestRegisterEvents_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestRegisterEvents_RegisterAction_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ResponseRegisterEvents_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseRegisterEvents_reflection_ = NULL; +const ::google::protobuf::Descriptor* EventLobbyInvite_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EventLobbyInvite_reflection_ = NULL; +const ::google::protobuf::Descriptor* EventChatMessage_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EventChatMessage_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestSendMessage_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestSendMessage_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseSendMessage_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseSendMessage_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* LobbyPrivacyLevel_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* ChatType_descriptor_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_chat_2eproto() { + protobuf_AddDesc_chat_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "chat.proto"); + GOOGLE_CHECK(file != NULL); + ChatLobbyInfo_descriptor_ = file->message_type(0); + static const int ChatLobbyInfo_offsets_[11] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, lobby_id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, lobby_topic_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, lobby_name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, lobby_nickname_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, privacy_level_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, lobby_state_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, no_peers_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, last_report_time_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, last_activity_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, participating_friends_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, nicknames_), + }; + ChatLobbyInfo_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ChatLobbyInfo_descriptor_, + ChatLobbyInfo::default_instance_, + ChatLobbyInfo_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatLobbyInfo, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ChatLobbyInfo)); + ChatLobbyInfo_LobbyState_descriptor_ = ChatLobbyInfo_descriptor_->enum_type(0); + ChatId_descriptor_ = file->message_type(1); + static const int ChatId_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatId, chat_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatId, chat_id_), + }; + ChatId_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ChatId_descriptor_, + ChatId::default_instance_, + ChatId_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatId, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatId, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ChatId)); + ChatMessage_descriptor_ = file->message_type(2); + static const int ChatMessage_offsets_[6] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, msg_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, peer_nickname_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, chat_flags_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, send_time_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, recv_time_), + }; + ChatMessage_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ChatMessage_descriptor_, + ChatMessage::default_instance_, + ChatMessage_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ChatMessage, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ChatMessage)); + ResponseChatLobbies_descriptor_ = file->message_type(3); + static const int ResponseChatLobbies_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseChatLobbies, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseChatLobbies, lobbies_), + }; + ResponseChatLobbies_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseChatLobbies_descriptor_, + ResponseChatLobbies::default_instance_, + ResponseChatLobbies_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseChatLobbies, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseChatLobbies, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseChatLobbies)); + RequestChatLobbies_descriptor_ = file->message_type(4); + static const int RequestChatLobbies_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestChatLobbies, lobby_set_), + }; + RequestChatLobbies_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestChatLobbies_descriptor_, + RequestChatLobbies::default_instance_, + RequestChatLobbies_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestChatLobbies, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestChatLobbies, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestChatLobbies)); + RequestChatLobbies_LobbySet_descriptor_ = RequestChatLobbies_descriptor_->enum_type(0); + RequestCreateLobby_descriptor_ = file->message_type(5); + static const int RequestCreateLobby_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCreateLobby, lobby_name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCreateLobby, lobby_topic_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCreateLobby, privacy_level_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCreateLobby, invited_friends_), + }; + RequestCreateLobby_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestCreateLobby_descriptor_, + RequestCreateLobby::default_instance_, + RequestCreateLobby_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCreateLobby, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCreateLobby, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestCreateLobby)); + RequestJoinOrLeaveLobby_descriptor_ = file->message_type(6); + static const int RequestJoinOrLeaveLobby_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestJoinOrLeaveLobby, lobby_id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestJoinOrLeaveLobby, action_), + }; + RequestJoinOrLeaveLobby_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestJoinOrLeaveLobby_descriptor_, + RequestJoinOrLeaveLobby::default_instance_, + RequestJoinOrLeaveLobby_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestJoinOrLeaveLobby, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestJoinOrLeaveLobby, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestJoinOrLeaveLobby)); + RequestJoinOrLeaveLobby_LobbyAction_descriptor_ = RequestJoinOrLeaveLobby_descriptor_->enum_type(0); + RequestSetLobbyNickname_descriptor_ = file->message_type(7); + static const int RequestSetLobbyNickname_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSetLobbyNickname, nickname_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSetLobbyNickname, lobby_ids_), + }; + RequestSetLobbyNickname_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestSetLobbyNickname_descriptor_, + RequestSetLobbyNickname::default_instance_, + RequestSetLobbyNickname_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSetLobbyNickname, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSetLobbyNickname, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestSetLobbyNickname)); + ResponseSetLobbyNickname_descriptor_ = file->message_type(8); + static const int ResponseSetLobbyNickname_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSetLobbyNickname, status_), + }; + ResponseSetLobbyNickname_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseSetLobbyNickname_descriptor_, + ResponseSetLobbyNickname::default_instance_, + ResponseSetLobbyNickname_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSetLobbyNickname, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSetLobbyNickname, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseSetLobbyNickname)); + RequestRegisterEvents_descriptor_ = file->message_type(9); + static const int RequestRegisterEvents_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestRegisterEvents, action_), + }; + RequestRegisterEvents_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestRegisterEvents_descriptor_, + RequestRegisterEvents::default_instance_, + RequestRegisterEvents_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestRegisterEvents, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestRegisterEvents, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestRegisterEvents)); + RequestRegisterEvents_RegisterAction_descriptor_ = RequestRegisterEvents_descriptor_->enum_type(0); + ResponseRegisterEvents_descriptor_ = file->message_type(10); + static const int ResponseRegisterEvents_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseRegisterEvents, status_), + }; + ResponseRegisterEvents_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseRegisterEvents_descriptor_, + ResponseRegisterEvents::default_instance_, + ResponseRegisterEvents_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseRegisterEvents, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseRegisterEvents, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseRegisterEvents)); + EventLobbyInvite_descriptor_ = file->message_type(11); + static const int EventLobbyInvite_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EventLobbyInvite, lobby_), + }; + EventLobbyInvite_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + EventLobbyInvite_descriptor_, + EventLobbyInvite::default_instance_, + EventLobbyInvite_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EventLobbyInvite, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EventLobbyInvite, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(EventLobbyInvite)); + EventChatMessage_descriptor_ = file->message_type(12); + static const int EventChatMessage_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EventChatMessage, msg_), + }; + EventChatMessage_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + EventChatMessage_descriptor_, + EventChatMessage::default_instance_, + EventChatMessage_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EventChatMessage, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EventChatMessage, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(EventChatMessage)); + RequestSendMessage_descriptor_ = file->message_type(13); + static const int RequestSendMessage_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSendMessage, msg_), + }; + RequestSendMessage_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestSendMessage_descriptor_, + RequestSendMessage::default_instance_, + RequestSendMessage_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSendMessage, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSendMessage, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestSendMessage)); + ResponseSendMessage_descriptor_ = file->message_type(14); + static const int ResponseSendMessage_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSendMessage, status_), + }; + ResponseSendMessage_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseSendMessage_descriptor_, + ResponseSendMessage::default_instance_, + ResponseSendMessage_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSendMessage, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSendMessage, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseSendMessage)); + RequestMsgIds_descriptor_ = file->enum_type(0); + ResponseMsgIds_descriptor_ = file->enum_type(1); + LobbyPrivacyLevel_descriptor_ = file->enum_type(2); + ChatType_descriptor_ = file->enum_type(3); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_chat_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ChatLobbyInfo_descriptor_, &ChatLobbyInfo::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ChatId_descriptor_, &ChatId::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ChatMessage_descriptor_, &ChatMessage::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseChatLobbies_descriptor_, &ResponseChatLobbies::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestChatLobbies_descriptor_, &RequestChatLobbies::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestCreateLobby_descriptor_, &RequestCreateLobby::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestJoinOrLeaveLobby_descriptor_, &RequestJoinOrLeaveLobby::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestSetLobbyNickname_descriptor_, &RequestSetLobbyNickname::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseSetLobbyNickname_descriptor_, &ResponseSetLobbyNickname::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestRegisterEvents_descriptor_, &RequestRegisterEvents::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseRegisterEvents_descriptor_, &ResponseRegisterEvents::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EventLobbyInvite_descriptor_, &EventLobbyInvite::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EventChatMessage_descriptor_, &EventChatMessage::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestSendMessage_descriptor_, &RequestSendMessage::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseSendMessage_descriptor_, &ResponseSendMessage::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_chat_2eproto() { + delete ChatLobbyInfo::default_instance_; + delete ChatLobbyInfo_reflection_; + delete ChatId::default_instance_; + delete ChatId_reflection_; + delete ChatMessage::default_instance_; + delete ChatMessage_reflection_; + delete ResponseChatLobbies::default_instance_; + delete ResponseChatLobbies_reflection_; + delete RequestChatLobbies::default_instance_; + delete RequestChatLobbies_reflection_; + delete RequestCreateLobby::default_instance_; + delete RequestCreateLobby_reflection_; + delete RequestJoinOrLeaveLobby::default_instance_; + delete RequestJoinOrLeaveLobby_reflection_; + delete RequestSetLobbyNickname::default_instance_; + delete RequestSetLobbyNickname_reflection_; + delete ResponseSetLobbyNickname::default_instance_; + delete ResponseSetLobbyNickname_reflection_; + delete RequestRegisterEvents::default_instance_; + delete RequestRegisterEvents_reflection_; + delete ResponseRegisterEvents::default_instance_; + delete ResponseRegisterEvents_reflection_; + delete EventLobbyInvite::default_instance_; + delete EventLobbyInvite_reflection_; + delete EventChatMessage::default_instance_; + delete EventChatMessage_reflection_; + delete RequestSendMessage::default_instance_; + delete RequestSendMessage_reflection_; + delete ResponseSendMessage::default_instance_; + delete ResponseSendMessage_reflection_; +} + +void protobuf_AddDesc_chat_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::rsctrl::core::protobuf_AddDesc_core_2eproto(); + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\nchat.proto\022\013rsctrl.chat\032\ncore.proto\"\236\003" + "\n\rChatLobbyInfo\022\020\n\010lobby_id\030\001 \002(\t\022\023\n\013lob" + "by_topic\030\002 \002(\t\022\022\n\nlobby_name\030\003 \002(\t\022\026\n\016lo" + "bby_nickname\030\004 \002(\t\0225\n\rprivacy_level\030\005 \002(" + "\0162\036.rsctrl.chat.LobbyPrivacyLevel\022:\n\013lob" + "by_state\030\006 \002(\0162%.rsctrl.chat.ChatLobbyIn" + "fo.LobbyState\022\020\n\010no_peers\030\007 \002(\r\022\030\n\020last_" + "report_time\030\010 \002(\r\022\025\n\rlast_activity\030\t \002(\r" + "\022\035\n\025participating_friends\030\n \003(\t\022\021\n\tnickn" + "ames\030\013 \003(\t\"R\n\nLobbyState\022\025\n\021LOBBYSTATE_J" + "OINED\020\001\022\026\n\022LOBBYSTATE_INVITED\020\002\022\025\n\021LOBBY" + "STATE_PUBLIC\020\003\"C\n\006ChatId\022(\n\tchat_type\030\001 " + "\002(\0162\025.rsctrl.chat.ChatType\022\017\n\007chat_id\030\002 " + "\002(\t\"\214\001\n\013ChatMessage\022\037\n\002id\030\001 \002(\0132\023.rsctrl" + ".chat.ChatId\022\013\n\003msg\030\002 \002(\t\022\025\n\rpeer_nickna" + "me\030\003 \001(\t\022\022\n\nchat_flags\030\004 \001(\r\022\021\n\tsend_tim" + "e\030\005 \001(\r\022\021\n\trecv_time\030\006 \001(\r\"g\n\023ResponseCh" + "atLobbies\022#\n\006status\030\001 \002(\0132\023.rsctrl.core." + "Status\022+\n\007lobbies\030\002 \003(\0132\032.rsctrl.chat.Ch" + "atLobbyInfo\"\257\001\n\022RequestChatLobbies\022;\n\tlo" + "bby_set\030\001 \002(\0162(.rsctrl.chat.RequestChatL" + "obbies.LobbySet\"\\\n\010LobbySet\022\020\n\014LOBBYSET_" + "ALL\020\001\022\023\n\017LOBBYSET_JOINED\020\002\022\024\n\020LOBBYSET_I" + "NVITED\020\003\022\023\n\017LOBBYSET_PUBLIC\020\004\"\215\001\n\022Reques" + "tCreateLobby\022\022\n\nlobby_name\030\001 \002(\t\022\023\n\013lobb" + "y_topic\030\002 \002(\t\0225\n\rprivacy_level\030\004 \002(\0162\036.r" + "sctrl.chat.LobbyPrivacyLevel\022\027\n\017invited_" + "friends\030\003 \003(\t\"\243\001\n\027RequestJoinOrLeaveLobb" + "y\022\020\n\010lobby_id\030\001 \002(\t\022@\n\006action\030\002 \002(\01620.rs" + "ctrl.chat.RequestJoinOrLeaveLobby.LobbyA" + "ction\"4\n\013LobbyAction\022\022\n\016JOIN_OR_ACCEPT\020\001" + "\022\021\n\rLEAVE_OR_DENY\020\002\">\n\027RequestSetLobbyNi" + "ckname\022\020\n\010nickname\030\001 \002(\t\022\021\n\tlobby_ids\030\002 " + "\003(\t\"\?\n\030ResponseSetLobbyNickname\022#\n\006statu" + "s\030\001 \002(\0132\023.rsctrl.core.Status\"\212\001\n\025Request" + "RegisterEvents\022A\n\006action\030\001 \002(\01621.rsctrl." + "chat.RequestRegisterEvents.RegisterActio" + "n\".\n\016RegisterAction\022\014\n\010REGISTER\020\001\022\016\n\nDER" + "EGISTER\020\002\"=\n\026ResponseRegisterEvents\022#\n\006s" + "tatus\030\001 \002(\0132\023.rsctrl.core.Status\"=\n\020Even" + "tLobbyInvite\022)\n\005lobby\030\001 \002(\0132\032.rsctrl.cha" + "t.ChatLobbyInfo\"9\n\020EventChatMessage\022%\n\003m" + "sg\030\001 \002(\0132\030.rsctrl.chat.ChatMessage\";\n\022Re" + "questSendMessage\022%\n\003msg\030\001 \002(\0132\030.rsctrl.c" + "hat.ChatMessage\":\n\023ResponseSendMessage\022#" + "\n\006status\030\001 \002(\0132\023.rsctrl.core.Status*\320\001\n\r" + "RequestMsgIds\022\034\n\030MsgId_RequestChatLobbie" + "s\020\001\022\034\n\030MsgId_RequestCreateLobby\020\002\022!\n\035Msg" + "Id_RequestJoinOrLeaveLobby\020\003\022!\n\035MsgId_Re" + "questSetLobbyNickname\020\004\022\037\n\033MsgId_Request" + "RegisterEvents\020\005\022\034\n\030MsgId_RequestSendMes" + "sage\020\006*\314\001\n\016ResponseMsgIds\022\035\n\031MsgId_Respo" + "nseChatLobbies\020\001\022\"\n\036MsgId_ResponseSetLob" + "byNickname\020\004\022 \n\034MsgId_ResponseRegisterEv" + "ents\020\005\022\035\n\031MsgId_ResponseSendMessage\020\006\022\032\n" + "\026MsgId_EventLobbyInvite\020e\022\032\n\026MsgId_Event" + "ChatMessage\020f*<\n\021LobbyPrivacyLevel\022\023\n\017PR" + "IVACY_PRIVATE\020\001\022\022\n\016PRIVACY_PUBLIC\020\002*<\n\010C" + "hatType\022\020\n\014TYPE_PRIVATE\020\001\022\016\n\nTYPE_LOBBY\020" + "\002\022\016\n\nTYPE_GROUP\020\003", 2377); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "chat.proto", &protobuf_RegisterTypes); + ChatLobbyInfo::default_instance_ = new ChatLobbyInfo(); + ChatId::default_instance_ = new ChatId(); + ChatMessage::default_instance_ = new ChatMessage(); + ResponseChatLobbies::default_instance_ = new ResponseChatLobbies(); + RequestChatLobbies::default_instance_ = new RequestChatLobbies(); + RequestCreateLobby::default_instance_ = new RequestCreateLobby(); + RequestJoinOrLeaveLobby::default_instance_ = new RequestJoinOrLeaveLobby(); + RequestSetLobbyNickname::default_instance_ = new RequestSetLobbyNickname(); + ResponseSetLobbyNickname::default_instance_ = new ResponseSetLobbyNickname(); + RequestRegisterEvents::default_instance_ = new RequestRegisterEvents(); + ResponseRegisterEvents::default_instance_ = new ResponseRegisterEvents(); + EventLobbyInvite::default_instance_ = new EventLobbyInvite(); + EventChatMessage::default_instance_ = new EventChatMessage(); + RequestSendMessage::default_instance_ = new RequestSendMessage(); + ResponseSendMessage::default_instance_ = new ResponseSendMessage(); + ChatLobbyInfo::default_instance_->InitAsDefaultInstance(); + ChatId::default_instance_->InitAsDefaultInstance(); + ChatMessage::default_instance_->InitAsDefaultInstance(); + ResponseChatLobbies::default_instance_->InitAsDefaultInstance(); + RequestChatLobbies::default_instance_->InitAsDefaultInstance(); + RequestCreateLobby::default_instance_->InitAsDefaultInstance(); + RequestJoinOrLeaveLobby::default_instance_->InitAsDefaultInstance(); + RequestSetLobbyNickname::default_instance_->InitAsDefaultInstance(); + ResponseSetLobbyNickname::default_instance_->InitAsDefaultInstance(); + RequestRegisterEvents::default_instance_->InitAsDefaultInstance(); + ResponseRegisterEvents::default_instance_->InitAsDefaultInstance(); + EventLobbyInvite::default_instance_->InitAsDefaultInstance(); + EventChatMessage::default_instance_->InitAsDefaultInstance(); + RequestSendMessage::default_instance_->InitAsDefaultInstance(); + ResponseSendMessage::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_chat_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_chat_2eproto { + StaticDescriptorInitializer_chat_2eproto() { + protobuf_AddDesc_chat_2eproto(); + } +} static_descriptor_initializer_chat_2eproto_; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestMsgIds_descriptor_; +} +bool RequestMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseMsgIds_descriptor_; +} +bool ResponseMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 4: + case 5: + case 6: + case 101: + case 102: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* LobbyPrivacyLevel_descriptor() { + protobuf_AssignDescriptorsOnce(); + return LobbyPrivacyLevel_descriptor_; +} +bool LobbyPrivacyLevel_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* ChatType_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ChatType_descriptor_; +} +bool ChatType_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* ChatLobbyInfo_LobbyState_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ChatLobbyInfo_LobbyState_descriptor_; +} +bool ChatLobbyInfo_LobbyState_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const ChatLobbyInfo_LobbyState ChatLobbyInfo::LOBBYSTATE_JOINED; +const ChatLobbyInfo_LobbyState ChatLobbyInfo::LOBBYSTATE_INVITED; +const ChatLobbyInfo_LobbyState ChatLobbyInfo::LOBBYSTATE_PUBLIC; +const ChatLobbyInfo_LobbyState ChatLobbyInfo::LobbyState_MIN; +const ChatLobbyInfo_LobbyState ChatLobbyInfo::LobbyState_MAX; +const int ChatLobbyInfo::LobbyState_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int ChatLobbyInfo::kLobbyIdFieldNumber; +const int ChatLobbyInfo::kLobbyTopicFieldNumber; +const int ChatLobbyInfo::kLobbyNameFieldNumber; +const int ChatLobbyInfo::kLobbyNicknameFieldNumber; +const int ChatLobbyInfo::kPrivacyLevelFieldNumber; +const int ChatLobbyInfo::kLobbyStateFieldNumber; +const int ChatLobbyInfo::kNoPeersFieldNumber; +const int ChatLobbyInfo::kLastReportTimeFieldNumber; +const int ChatLobbyInfo::kLastActivityFieldNumber; +const int ChatLobbyInfo::kParticipatingFriendsFieldNumber; +const int ChatLobbyInfo::kNicknamesFieldNumber; +#endif // !_MSC_VER + +ChatLobbyInfo::ChatLobbyInfo() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ChatLobbyInfo::InitAsDefaultInstance() { +} + +ChatLobbyInfo::ChatLobbyInfo(const ChatLobbyInfo& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ChatLobbyInfo::SharedCtor() { + _cached_size_ = 0; + lobby_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + lobby_topic_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + lobby_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + lobby_nickname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + privacy_level_ = 1; + lobby_state_ = 1; + no_peers_ = 0u; + last_report_time_ = 0u; + last_activity_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ChatLobbyInfo::~ChatLobbyInfo() { + SharedDtor(); +} + +void ChatLobbyInfo::SharedDtor() { + if (lobby_id_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_id_; + } + if (lobby_topic_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_topic_; + } + if (lobby_name_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_name_; + } + if (lobby_nickname_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_nickname_; + } + if (this != default_instance_) { + } +} + +void ChatLobbyInfo::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ChatLobbyInfo::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ChatLobbyInfo_descriptor_; +} + +const ChatLobbyInfo& ChatLobbyInfo::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ChatLobbyInfo* ChatLobbyInfo::default_instance_ = NULL; + +ChatLobbyInfo* ChatLobbyInfo::New() const { + return new ChatLobbyInfo; +} + +void ChatLobbyInfo::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_lobby_id()) { + if (lobby_id_ != &::google::protobuf::internal::kEmptyString) { + lobby_id_->clear(); + } + } + if (has_lobby_topic()) { + if (lobby_topic_ != &::google::protobuf::internal::kEmptyString) { + lobby_topic_->clear(); + } + } + if (has_lobby_name()) { + if (lobby_name_ != &::google::protobuf::internal::kEmptyString) { + lobby_name_->clear(); + } + } + if (has_lobby_nickname()) { + if (lobby_nickname_ != &::google::protobuf::internal::kEmptyString) { + lobby_nickname_->clear(); + } + } + privacy_level_ = 1; + lobby_state_ = 1; + no_peers_ = 0u; + last_report_time_ = 0u; + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + last_activity_ = 0u; + } + participating_friends_.Clear(); + nicknames_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ChatLobbyInfo::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string lobby_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_id())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_id().data(), this->lobby_id().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_lobby_topic; + break; + } + + // required string lobby_topic = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_lobby_topic: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_topic())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_topic().data(), this->lobby_topic().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_lobby_name; + break; + } + + // required string lobby_name = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_lobby_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_name().data(), this->lobby_name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_lobby_nickname; + break; + } + + // required string lobby_nickname = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_lobby_nickname: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_nickname())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_nickname().data(), this->lobby_nickname().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_privacy_level; + break; + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_privacy_level: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (rsctrl::chat::LobbyPrivacyLevel_IsValid(value)) { + set_privacy_level(static_cast< rsctrl::chat::LobbyPrivacyLevel >(value)); + } else { + mutable_unknown_fields()->AddVarint(5, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(48)) goto parse_lobby_state; + break; + } + + // required .rsctrl.chat.ChatLobbyInfo.LobbyState lobby_state = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_lobby_state: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::chat::ChatLobbyInfo_LobbyState_IsValid(value)) { + set_lobby_state(static_cast< ::rsctrl::chat::ChatLobbyInfo_LobbyState >(value)); + } else { + mutable_unknown_fields()->AddVarint(6, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(56)) goto parse_no_peers; + break; + } + + // required uint32 no_peers = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_no_peers: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &no_peers_))); + set_has_no_peers(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(64)) goto parse_last_report_time; + break; + } + + // required uint32 last_report_time = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_last_report_time: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &last_report_time_))); + set_has_last_report_time(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(72)) goto parse_last_activity; + break; + } + + // required uint32 last_activity = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_last_activity: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &last_activity_))); + set_has_last_activity(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(82)) goto parse_participating_friends; + break; + } + + // repeated string participating_friends = 10; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_participating_friends: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_participating_friends())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->participating_friends(0).data(), this->participating_friends(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(82)) goto parse_participating_friends; + if (input->ExpectTag(90)) goto parse_nicknames; + break; + } + + // repeated string nicknames = 11; + case 11: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_nicknames: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_nicknames())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->nicknames(0).data(), this->nicknames(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(90)) goto parse_nicknames; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ChatLobbyInfo::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string lobby_id = 1; + if (has_lobby_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_id().data(), this->lobby_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->lobby_id(), output); + } + + // required string lobby_topic = 2; + if (has_lobby_topic()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_topic().data(), this->lobby_topic().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->lobby_topic(), output); + } + + // required string lobby_name = 3; + if (has_lobby_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_name().data(), this->lobby_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->lobby_name(), output); + } + + // required string lobby_nickname = 4; + if (has_lobby_nickname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_nickname().data(), this->lobby_nickname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 4, this->lobby_nickname(), output); + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 5; + if (has_privacy_level()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 5, this->privacy_level(), output); + } + + // required .rsctrl.chat.ChatLobbyInfo.LobbyState lobby_state = 6; + if (has_lobby_state()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 6, this->lobby_state(), output); + } + + // required uint32 no_peers = 7; + if (has_no_peers()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(7, this->no_peers(), output); + } + + // required uint32 last_report_time = 8; + if (has_last_report_time()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(8, this->last_report_time(), output); + } + + // required uint32 last_activity = 9; + if (has_last_activity()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(9, this->last_activity(), output); + } + + // repeated string participating_friends = 10; + for (int i = 0; i < this->participating_friends_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->participating_friends(i).data(), this->participating_friends(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 10, this->participating_friends(i), output); + } + + // repeated string nicknames = 11; + for (int i = 0; i < this->nicknames_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->nicknames(i).data(), this->nicknames(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 11, this->nicknames(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ChatLobbyInfo::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string lobby_id = 1; + if (has_lobby_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_id().data(), this->lobby_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->lobby_id(), target); + } + + // required string lobby_topic = 2; + if (has_lobby_topic()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_topic().data(), this->lobby_topic().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->lobby_topic(), target); + } + + // required string lobby_name = 3; + if (has_lobby_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_name().data(), this->lobby_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->lobby_name(), target); + } + + // required string lobby_nickname = 4; + if (has_lobby_nickname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_nickname().data(), this->lobby_nickname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 4, this->lobby_nickname(), target); + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 5; + if (has_privacy_level()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 5, this->privacy_level(), target); + } + + // required .rsctrl.chat.ChatLobbyInfo.LobbyState lobby_state = 6; + if (has_lobby_state()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 6, this->lobby_state(), target); + } + + // required uint32 no_peers = 7; + if (has_no_peers()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(7, this->no_peers(), target); + } + + // required uint32 last_report_time = 8; + if (has_last_report_time()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(8, this->last_report_time(), target); + } + + // required uint32 last_activity = 9; + if (has_last_activity()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(9, this->last_activity(), target); + } + + // repeated string participating_friends = 10; + for (int i = 0; i < this->participating_friends_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->participating_friends(i).data(), this->participating_friends(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(10, this->participating_friends(i), target); + } + + // repeated string nicknames = 11; + for (int i = 0; i < this->nicknames_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->nicknames(i).data(), this->nicknames(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(11, this->nicknames(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ChatLobbyInfo::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string lobby_id = 1; + if (has_lobby_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_id()); + } + + // required string lobby_topic = 2; + if (has_lobby_topic()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_topic()); + } + + // required string lobby_name = 3; + if (has_lobby_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_name()); + } + + // required string lobby_nickname = 4; + if (has_lobby_nickname()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_nickname()); + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 5; + if (has_privacy_level()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->privacy_level()); + } + + // required .rsctrl.chat.ChatLobbyInfo.LobbyState lobby_state = 6; + if (has_lobby_state()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->lobby_state()); + } + + // required uint32 no_peers = 7; + if (has_no_peers()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->no_peers()); + } + + // required uint32 last_report_time = 8; + if (has_last_report_time()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->last_report_time()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // required uint32 last_activity = 9; + if (has_last_activity()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->last_activity()); + } + + } + // repeated string participating_friends = 10; + total_size += 1 * this->participating_friends_size(); + for (int i = 0; i < this->participating_friends_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->participating_friends(i)); + } + + // repeated string nicknames = 11; + total_size += 1 * this->nicknames_size(); + for (int i = 0; i < this->nicknames_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->nicknames(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ChatLobbyInfo::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ChatLobbyInfo* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ChatLobbyInfo::MergeFrom(const ChatLobbyInfo& from) { + GOOGLE_CHECK_NE(&from, this); + participating_friends_.MergeFrom(from.participating_friends_); + nicknames_.MergeFrom(from.nicknames_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_lobby_id()) { + set_lobby_id(from.lobby_id()); + } + if (from.has_lobby_topic()) { + set_lobby_topic(from.lobby_topic()); + } + if (from.has_lobby_name()) { + set_lobby_name(from.lobby_name()); + } + if (from.has_lobby_nickname()) { + set_lobby_nickname(from.lobby_nickname()); + } + if (from.has_privacy_level()) { + set_privacy_level(from.privacy_level()); + } + if (from.has_lobby_state()) { + set_lobby_state(from.lobby_state()); + } + if (from.has_no_peers()) { + set_no_peers(from.no_peers()); + } + if (from.has_last_report_time()) { + set_last_report_time(from.last_report_time()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_last_activity()) { + set_last_activity(from.last_activity()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ChatLobbyInfo::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ChatLobbyInfo::CopyFrom(const ChatLobbyInfo& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ChatLobbyInfo::IsInitialized() const { + if ((_has_bits_[0] & 0x000001ff) != 0x000001ff) return false; + + return true; +} + +void ChatLobbyInfo::Swap(ChatLobbyInfo* other) { + if (other != this) { + std::swap(lobby_id_, other->lobby_id_); + std::swap(lobby_topic_, other->lobby_topic_); + std::swap(lobby_name_, other->lobby_name_); + std::swap(lobby_nickname_, other->lobby_nickname_); + std::swap(privacy_level_, other->privacy_level_); + std::swap(lobby_state_, other->lobby_state_); + std::swap(no_peers_, other->no_peers_); + std::swap(last_report_time_, other->last_report_time_); + std::swap(last_activity_, other->last_activity_); + participating_friends_.Swap(&other->participating_friends_); + nicknames_.Swap(&other->nicknames_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ChatLobbyInfo::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ChatLobbyInfo_descriptor_; + metadata.reflection = ChatLobbyInfo_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ChatId::kChatTypeFieldNumber; +const int ChatId::kChatIdFieldNumber; +#endif // !_MSC_VER + +ChatId::ChatId() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ChatId::InitAsDefaultInstance() { +} + +ChatId::ChatId(const ChatId& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ChatId::SharedCtor() { + _cached_size_ = 0; + chat_type_ = 1; + chat_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ChatId::~ChatId() { + SharedDtor(); +} + +void ChatId::SharedDtor() { + if (chat_id_ != &::google::protobuf::internal::kEmptyString) { + delete chat_id_; + } + if (this != default_instance_) { + } +} + +void ChatId::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ChatId::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ChatId_descriptor_; +} + +const ChatId& ChatId::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ChatId* ChatId::default_instance_ = NULL; + +ChatId* ChatId::New() const { + return new ChatId; +} + +void ChatId::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + chat_type_ = 1; + if (has_chat_id()) { + if (chat_id_ != &::google::protobuf::internal::kEmptyString) { + chat_id_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ChatId::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.ChatType chat_type = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (rsctrl::chat::ChatType_IsValid(value)) { + set_chat_type(static_cast< rsctrl::chat::ChatType >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_chat_id; + break; + } + + // required string chat_id = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_chat_id: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_chat_id())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->chat_id().data(), this->chat_id().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ChatId::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.ChatType chat_type = 1; + if (has_chat_type()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->chat_type(), output); + } + + // required string chat_id = 2; + if (has_chat_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->chat_id().data(), this->chat_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->chat_id(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ChatId::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.ChatType chat_type = 1; + if (has_chat_type()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->chat_type(), target); + } + + // required string chat_id = 2; + if (has_chat_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->chat_id().data(), this->chat_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->chat_id(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ChatId::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.ChatType chat_type = 1; + if (has_chat_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->chat_type()); + } + + // required string chat_id = 2; + if (has_chat_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->chat_id()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ChatId::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ChatId* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ChatId::MergeFrom(const ChatId& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_chat_type()) { + set_chat_type(from.chat_type()); + } + if (from.has_chat_id()) { + set_chat_id(from.chat_id()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ChatId::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ChatId::CopyFrom(const ChatId& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ChatId::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void ChatId::Swap(ChatId* other) { + if (other != this) { + std::swap(chat_type_, other->chat_type_); + std::swap(chat_id_, other->chat_id_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ChatId::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ChatId_descriptor_; + metadata.reflection = ChatId_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ChatMessage::kIdFieldNumber; +const int ChatMessage::kMsgFieldNumber; +const int ChatMessage::kPeerNicknameFieldNumber; +const int ChatMessage::kChatFlagsFieldNumber; +const int ChatMessage::kSendTimeFieldNumber; +const int ChatMessage::kRecvTimeFieldNumber; +#endif // !_MSC_VER + +ChatMessage::ChatMessage() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ChatMessage::InitAsDefaultInstance() { + id_ = const_cast< ::rsctrl::chat::ChatId*>(&::rsctrl::chat::ChatId::default_instance()); +} + +ChatMessage::ChatMessage(const ChatMessage& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ChatMessage::SharedCtor() { + _cached_size_ = 0; + id_ = NULL; + msg_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + peer_nickname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + chat_flags_ = 0u; + send_time_ = 0u; + recv_time_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ChatMessage::~ChatMessage() { + SharedDtor(); +} + +void ChatMessage::SharedDtor() { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + delete msg_; + } + if (peer_nickname_ != &::google::protobuf::internal::kEmptyString) { + delete peer_nickname_; + } + if (this != default_instance_) { + delete id_; + } +} + +void ChatMessage::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ChatMessage::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ChatMessage_descriptor_; +} + +const ChatMessage& ChatMessage::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ChatMessage* ChatMessage::default_instance_ = NULL; + +ChatMessage* ChatMessage::New() const { + return new ChatMessage; +} + +void ChatMessage::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_id()) { + if (id_ != NULL) id_->::rsctrl::chat::ChatId::Clear(); + } + if (has_msg()) { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + msg_->clear(); + } + } + if (has_peer_nickname()) { + if (peer_nickname_ != &::google::protobuf::internal::kEmptyString) { + peer_nickname_->clear(); + } + } + chat_flags_ = 0u; + send_time_ = 0u; + recv_time_ = 0u; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ChatMessage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.ChatId id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_id())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_msg; + break; + } + + // required string msg = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_msg: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_msg())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_peer_nickname; + break; + } + + // optional string peer_nickname = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_peer_nickname: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_peer_nickname())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->peer_nickname().data(), this->peer_nickname().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_chat_flags; + break; + } + + // optional uint32 chat_flags = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_chat_flags: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &chat_flags_))); + set_has_chat_flags(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_send_time; + break; + } + + // optional uint32 send_time = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_send_time: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &send_time_))); + set_has_send_time(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(48)) goto parse_recv_time; + break; + } + + // optional uint32 recv_time = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_recv_time: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &recv_time_))); + set_has_recv_time(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ChatMessage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.ChatId id = 1; + if (has_id()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->id(), output); + } + + // required string msg = 2; + if (has_msg()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->msg(), output); + } + + // optional string peer_nickname = 3; + if (has_peer_nickname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->peer_nickname().data(), this->peer_nickname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->peer_nickname(), output); + } + + // optional uint32 chat_flags = 4; + if (has_chat_flags()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->chat_flags(), output); + } + + // optional uint32 send_time = 5; + if (has_send_time()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(5, this->send_time(), output); + } + + // optional uint32 recv_time = 6; + if (has_recv_time()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(6, this->recv_time(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ChatMessage::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.ChatId id = 1; + if (has_id()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->id(), target); + } + + // required string msg = 2; + if (has_msg()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->msg(), target); + } + + // optional string peer_nickname = 3; + if (has_peer_nickname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->peer_nickname().data(), this->peer_nickname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->peer_nickname(), target); + } + + // optional uint32 chat_flags = 4; + if (has_chat_flags()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(4, this->chat_flags(), target); + } + + // optional uint32 send_time = 5; + if (has_send_time()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(5, this->send_time(), target); + } + + // optional uint32 recv_time = 6; + if (has_recv_time()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(6, this->recv_time(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ChatMessage::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.ChatId id = 1; + if (has_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->id()); + } + + // required string msg = 2; + if (has_msg()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->msg()); + } + + // optional string peer_nickname = 3; + if (has_peer_nickname()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->peer_nickname()); + } + + // optional uint32 chat_flags = 4; + if (has_chat_flags()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->chat_flags()); + } + + // optional uint32 send_time = 5; + if (has_send_time()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->send_time()); + } + + // optional uint32 recv_time = 6; + if (has_recv_time()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->recv_time()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ChatMessage::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ChatMessage* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ChatMessage::MergeFrom(const ChatMessage& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_id()) { + mutable_id()->::rsctrl::chat::ChatId::MergeFrom(from.id()); + } + if (from.has_msg()) { + set_msg(from.msg()); + } + if (from.has_peer_nickname()) { + set_peer_nickname(from.peer_nickname()); + } + if (from.has_chat_flags()) { + set_chat_flags(from.chat_flags()); + } + if (from.has_send_time()) { + set_send_time(from.send_time()); + } + if (from.has_recv_time()) { + set_recv_time(from.recv_time()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ChatMessage::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ChatMessage::CopyFrom(const ChatMessage& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ChatMessage::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + if (has_id()) { + if (!this->id().IsInitialized()) return false; + } + return true; +} + +void ChatMessage::Swap(ChatMessage* other) { + if (other != this) { + std::swap(id_, other->id_); + std::swap(msg_, other->msg_); + std::swap(peer_nickname_, other->peer_nickname_); + std::swap(chat_flags_, other->chat_flags_); + std::swap(send_time_, other->send_time_); + std::swap(recv_time_, other->recv_time_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ChatMessage::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ChatMessage_descriptor_; + metadata.reflection = ChatMessage_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseChatLobbies::kStatusFieldNumber; +const int ResponseChatLobbies::kLobbiesFieldNumber; +#endif // !_MSC_VER + +ResponseChatLobbies::ResponseChatLobbies() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseChatLobbies::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseChatLobbies::ResponseChatLobbies(const ResponseChatLobbies& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseChatLobbies::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseChatLobbies::~ResponseChatLobbies() { + SharedDtor(); +} + +void ResponseChatLobbies::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseChatLobbies::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseChatLobbies::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseChatLobbies_descriptor_; +} + +const ResponseChatLobbies& ResponseChatLobbies::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ResponseChatLobbies* ResponseChatLobbies::default_instance_ = NULL; + +ResponseChatLobbies* ResponseChatLobbies::New() const { + return new ResponseChatLobbies; +} + +void ResponseChatLobbies::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + lobbies_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseChatLobbies::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_lobbies; + break; + } + + // repeated .rsctrl.chat.ChatLobbyInfo lobbies = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_lobbies: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_lobbies())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_lobbies; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseChatLobbies::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated .rsctrl.chat.ChatLobbyInfo lobbies = 2; + for (int i = 0; i < this->lobbies_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->lobbies(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseChatLobbies::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated .rsctrl.chat.ChatLobbyInfo lobbies = 2; + for (int i = 0; i < this->lobbies_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->lobbies(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseChatLobbies::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated .rsctrl.chat.ChatLobbyInfo lobbies = 2; + total_size += 1 * this->lobbies_size(); + for (int i = 0; i < this->lobbies_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->lobbies(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseChatLobbies::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseChatLobbies* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseChatLobbies::MergeFrom(const ResponseChatLobbies& from) { + GOOGLE_CHECK_NE(&from, this); + lobbies_.MergeFrom(from.lobbies_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseChatLobbies::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseChatLobbies::CopyFrom(const ResponseChatLobbies& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseChatLobbies::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + for (int i = 0; i < lobbies_size(); i++) { + if (!this->lobbies(i).IsInitialized()) return false; + } + return true; +} + +void ResponseChatLobbies::Swap(ResponseChatLobbies* other) { + if (other != this) { + std::swap(status_, other->status_); + lobbies_.Swap(&other->lobbies_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseChatLobbies::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseChatLobbies_descriptor_; + metadata.reflection = ResponseChatLobbies_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestChatLobbies_LobbySet_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestChatLobbies_LobbySet_descriptor_; +} +bool RequestChatLobbies_LobbySet_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestChatLobbies_LobbySet RequestChatLobbies::LOBBYSET_ALL; +const RequestChatLobbies_LobbySet RequestChatLobbies::LOBBYSET_JOINED; +const RequestChatLobbies_LobbySet RequestChatLobbies::LOBBYSET_INVITED; +const RequestChatLobbies_LobbySet RequestChatLobbies::LOBBYSET_PUBLIC; +const RequestChatLobbies_LobbySet RequestChatLobbies::LobbySet_MIN; +const RequestChatLobbies_LobbySet RequestChatLobbies::LobbySet_MAX; +const int RequestChatLobbies::LobbySet_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestChatLobbies::kLobbySetFieldNumber; +#endif // !_MSC_VER + +RequestChatLobbies::RequestChatLobbies() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestChatLobbies::InitAsDefaultInstance() { +} + +RequestChatLobbies::RequestChatLobbies(const RequestChatLobbies& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestChatLobbies::SharedCtor() { + _cached_size_ = 0; + lobby_set_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestChatLobbies::~RequestChatLobbies() { + SharedDtor(); +} + +void RequestChatLobbies::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestChatLobbies::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestChatLobbies::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestChatLobbies_descriptor_; +} + +const RequestChatLobbies& RequestChatLobbies::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +RequestChatLobbies* RequestChatLobbies::default_instance_ = NULL; + +RequestChatLobbies* RequestChatLobbies::New() const { + return new RequestChatLobbies; +} + +void RequestChatLobbies::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + lobby_set_ = 1; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestChatLobbies::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.RequestChatLobbies.LobbySet lobby_set = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::chat::RequestChatLobbies_LobbySet_IsValid(value)) { + set_lobby_set(static_cast< ::rsctrl::chat::RequestChatLobbies_LobbySet >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestChatLobbies::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.RequestChatLobbies.LobbySet lobby_set = 1; + if (has_lobby_set()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->lobby_set(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestChatLobbies::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.RequestChatLobbies.LobbySet lobby_set = 1; + if (has_lobby_set()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->lobby_set(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestChatLobbies::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.RequestChatLobbies.LobbySet lobby_set = 1; + if (has_lobby_set()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->lobby_set()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestChatLobbies::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestChatLobbies* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestChatLobbies::MergeFrom(const RequestChatLobbies& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_lobby_set()) { + set_lobby_set(from.lobby_set()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestChatLobbies::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestChatLobbies::CopyFrom(const RequestChatLobbies& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestChatLobbies::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void RequestChatLobbies::Swap(RequestChatLobbies* other) { + if (other != this) { + std::swap(lobby_set_, other->lobby_set_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestChatLobbies::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestChatLobbies_descriptor_; + metadata.reflection = RequestChatLobbies_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestCreateLobby::kLobbyNameFieldNumber; +const int RequestCreateLobby::kLobbyTopicFieldNumber; +const int RequestCreateLobby::kPrivacyLevelFieldNumber; +const int RequestCreateLobby::kInvitedFriendsFieldNumber; +#endif // !_MSC_VER + +RequestCreateLobby::RequestCreateLobby() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestCreateLobby::InitAsDefaultInstance() { +} + +RequestCreateLobby::RequestCreateLobby(const RequestCreateLobby& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestCreateLobby::SharedCtor() { + _cached_size_ = 0; + lobby_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + lobby_topic_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + privacy_level_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestCreateLobby::~RequestCreateLobby() { + SharedDtor(); +} + +void RequestCreateLobby::SharedDtor() { + if (lobby_name_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_name_; + } + if (lobby_topic_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_topic_; + } + if (this != default_instance_) { + } +} + +void RequestCreateLobby::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestCreateLobby::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestCreateLobby_descriptor_; +} + +const RequestCreateLobby& RequestCreateLobby::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +RequestCreateLobby* RequestCreateLobby::default_instance_ = NULL; + +RequestCreateLobby* RequestCreateLobby::New() const { + return new RequestCreateLobby; +} + +void RequestCreateLobby::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_lobby_name()) { + if (lobby_name_ != &::google::protobuf::internal::kEmptyString) { + lobby_name_->clear(); + } + } + if (has_lobby_topic()) { + if (lobby_topic_ != &::google::protobuf::internal::kEmptyString) { + lobby_topic_->clear(); + } + } + privacy_level_ = 1; + } + invited_friends_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestCreateLobby::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string lobby_name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_name().data(), this->lobby_name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_lobby_topic; + break; + } + + // required string lobby_topic = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_lobby_topic: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_topic())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_topic().data(), this->lobby_topic().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_invited_friends; + break; + } + + // repeated string invited_friends = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_invited_friends: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_invited_friends())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->invited_friends(0).data(), this->invited_friends(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_invited_friends; + if (input->ExpectTag(32)) goto parse_privacy_level; + break; + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_privacy_level: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (rsctrl::chat::LobbyPrivacyLevel_IsValid(value)) { + set_privacy_level(static_cast< rsctrl::chat::LobbyPrivacyLevel >(value)); + } else { + mutable_unknown_fields()->AddVarint(4, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestCreateLobby::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string lobby_name = 1; + if (has_lobby_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_name().data(), this->lobby_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->lobby_name(), output); + } + + // required string lobby_topic = 2; + if (has_lobby_topic()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_topic().data(), this->lobby_topic().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->lobby_topic(), output); + } + + // repeated string invited_friends = 3; + for (int i = 0; i < this->invited_friends_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->invited_friends(i).data(), this->invited_friends(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->invited_friends(i), output); + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 4; + if (has_privacy_level()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 4, this->privacy_level(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestCreateLobby::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string lobby_name = 1; + if (has_lobby_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_name().data(), this->lobby_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->lobby_name(), target); + } + + // required string lobby_topic = 2; + if (has_lobby_topic()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_topic().data(), this->lobby_topic().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->lobby_topic(), target); + } + + // repeated string invited_friends = 3; + for (int i = 0; i < this->invited_friends_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->invited_friends(i).data(), this->invited_friends(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(3, this->invited_friends(i), target); + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 4; + if (has_privacy_level()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 4, this->privacy_level(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestCreateLobby::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string lobby_name = 1; + if (has_lobby_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_name()); + } + + // required string lobby_topic = 2; + if (has_lobby_topic()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_topic()); + } + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 4; + if (has_privacy_level()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->privacy_level()); + } + + } + // repeated string invited_friends = 3; + total_size += 1 * this->invited_friends_size(); + for (int i = 0; i < this->invited_friends_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->invited_friends(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestCreateLobby::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestCreateLobby* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestCreateLobby::MergeFrom(const RequestCreateLobby& from) { + GOOGLE_CHECK_NE(&from, this); + invited_friends_.MergeFrom(from.invited_friends_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_lobby_name()) { + set_lobby_name(from.lobby_name()); + } + if (from.has_lobby_topic()) { + set_lobby_topic(from.lobby_topic()); + } + if (from.has_privacy_level()) { + set_privacy_level(from.privacy_level()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestCreateLobby::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestCreateLobby::CopyFrom(const RequestCreateLobby& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestCreateLobby::IsInitialized() const { + if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; + + return true; +} + +void RequestCreateLobby::Swap(RequestCreateLobby* other) { + if (other != this) { + std::swap(lobby_name_, other->lobby_name_); + std::swap(lobby_topic_, other->lobby_topic_); + std::swap(privacy_level_, other->privacy_level_); + invited_friends_.Swap(&other->invited_friends_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestCreateLobby::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestCreateLobby_descriptor_; + metadata.reflection = RequestCreateLobby_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestJoinOrLeaveLobby_LobbyAction_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestJoinOrLeaveLobby_LobbyAction_descriptor_; +} +bool RequestJoinOrLeaveLobby_LobbyAction_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby::JOIN_OR_ACCEPT; +const RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby::LEAVE_OR_DENY; +const RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby::LobbyAction_MIN; +const RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby::LobbyAction_MAX; +const int RequestJoinOrLeaveLobby::LobbyAction_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestJoinOrLeaveLobby::kLobbyIdFieldNumber; +const int RequestJoinOrLeaveLobby::kActionFieldNumber; +#endif // !_MSC_VER + +RequestJoinOrLeaveLobby::RequestJoinOrLeaveLobby() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestJoinOrLeaveLobby::InitAsDefaultInstance() { +} + +RequestJoinOrLeaveLobby::RequestJoinOrLeaveLobby(const RequestJoinOrLeaveLobby& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestJoinOrLeaveLobby::SharedCtor() { + _cached_size_ = 0; + lobby_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + action_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestJoinOrLeaveLobby::~RequestJoinOrLeaveLobby() { + SharedDtor(); +} + +void RequestJoinOrLeaveLobby::SharedDtor() { + if (lobby_id_ != &::google::protobuf::internal::kEmptyString) { + delete lobby_id_; + } + if (this != default_instance_) { + } +} + +void RequestJoinOrLeaveLobby::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestJoinOrLeaveLobby::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestJoinOrLeaveLobby_descriptor_; +} + +const RequestJoinOrLeaveLobby& RequestJoinOrLeaveLobby::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +RequestJoinOrLeaveLobby* RequestJoinOrLeaveLobby::default_instance_ = NULL; + +RequestJoinOrLeaveLobby* RequestJoinOrLeaveLobby::New() const { + return new RequestJoinOrLeaveLobby; +} + +void RequestJoinOrLeaveLobby::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_lobby_id()) { + if (lobby_id_ != &::google::protobuf::internal::kEmptyString) { + lobby_id_->clear(); + } + } + action_ = 1; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestJoinOrLeaveLobby::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string lobby_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_lobby_id())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_id().data(), this->lobby_id().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_action; + break; + } + + // required .rsctrl.chat.RequestJoinOrLeaveLobby.LobbyAction action = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_action: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction_IsValid(value)) { + set_action(static_cast< ::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction >(value)); + } else { + mutable_unknown_fields()->AddVarint(2, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestJoinOrLeaveLobby::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string lobby_id = 1; + if (has_lobby_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_id().data(), this->lobby_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->lobby_id(), output); + } + + // required .rsctrl.chat.RequestJoinOrLeaveLobby.LobbyAction action = 2; + if (has_action()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 2, this->action(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestJoinOrLeaveLobby::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string lobby_id = 1; + if (has_lobby_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_id().data(), this->lobby_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->lobby_id(), target); + } + + // required .rsctrl.chat.RequestJoinOrLeaveLobby.LobbyAction action = 2; + if (has_action()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 2, this->action(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestJoinOrLeaveLobby::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string lobby_id = 1; + if (has_lobby_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_id()); + } + + // required .rsctrl.chat.RequestJoinOrLeaveLobby.LobbyAction action = 2; + if (has_action()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->action()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestJoinOrLeaveLobby::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestJoinOrLeaveLobby* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestJoinOrLeaveLobby::MergeFrom(const RequestJoinOrLeaveLobby& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_lobby_id()) { + set_lobby_id(from.lobby_id()); + } + if (from.has_action()) { + set_action(from.action()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestJoinOrLeaveLobby::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestJoinOrLeaveLobby::CopyFrom(const RequestJoinOrLeaveLobby& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestJoinOrLeaveLobby::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void RequestJoinOrLeaveLobby::Swap(RequestJoinOrLeaveLobby* other) { + if (other != this) { + std::swap(lobby_id_, other->lobby_id_); + std::swap(action_, other->action_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestJoinOrLeaveLobby::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestJoinOrLeaveLobby_descriptor_; + metadata.reflection = RequestJoinOrLeaveLobby_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestSetLobbyNickname::kNicknameFieldNumber; +const int RequestSetLobbyNickname::kLobbyIdsFieldNumber; +#endif // !_MSC_VER + +RequestSetLobbyNickname::RequestSetLobbyNickname() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestSetLobbyNickname::InitAsDefaultInstance() { +} + +RequestSetLobbyNickname::RequestSetLobbyNickname(const RequestSetLobbyNickname& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestSetLobbyNickname::SharedCtor() { + _cached_size_ = 0; + nickname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestSetLobbyNickname::~RequestSetLobbyNickname() { + SharedDtor(); +} + +void RequestSetLobbyNickname::SharedDtor() { + if (nickname_ != &::google::protobuf::internal::kEmptyString) { + delete nickname_; + } + if (this != default_instance_) { + } +} + +void RequestSetLobbyNickname::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestSetLobbyNickname::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestSetLobbyNickname_descriptor_; +} + +const RequestSetLobbyNickname& RequestSetLobbyNickname::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +RequestSetLobbyNickname* RequestSetLobbyNickname::default_instance_ = NULL; + +RequestSetLobbyNickname* RequestSetLobbyNickname::New() const { + return new RequestSetLobbyNickname; +} + +void RequestSetLobbyNickname::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_nickname()) { + if (nickname_ != &::google::protobuf::internal::kEmptyString) { + nickname_->clear(); + } + } + } + lobby_ids_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestSetLobbyNickname::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string nickname = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_nickname())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->nickname().data(), this->nickname().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_lobby_ids; + break; + } + + // repeated string lobby_ids = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_lobby_ids: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_lobby_ids())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_ids(0).data(), this->lobby_ids(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_lobby_ids; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestSetLobbyNickname::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string nickname = 1; + if (has_nickname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->nickname().data(), this->nickname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->nickname(), output); + } + + // repeated string lobby_ids = 2; + for (int i = 0; i < this->lobby_ids_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_ids(i).data(), this->lobby_ids(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->lobby_ids(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestSetLobbyNickname::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string nickname = 1; + if (has_nickname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->nickname().data(), this->nickname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->nickname(), target); + } + + // repeated string lobby_ids = 2; + for (int i = 0; i < this->lobby_ids_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->lobby_ids(i).data(), this->lobby_ids(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(2, this->lobby_ids(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestSetLobbyNickname::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string nickname = 1; + if (has_nickname()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->nickname()); + } + + } + // repeated string lobby_ids = 2; + total_size += 1 * this->lobby_ids_size(); + for (int i = 0; i < this->lobby_ids_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->lobby_ids(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestSetLobbyNickname::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestSetLobbyNickname* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestSetLobbyNickname::MergeFrom(const RequestSetLobbyNickname& from) { + GOOGLE_CHECK_NE(&from, this); + lobby_ids_.MergeFrom(from.lobby_ids_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_nickname()) { + set_nickname(from.nickname()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestSetLobbyNickname::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestSetLobbyNickname::CopyFrom(const RequestSetLobbyNickname& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestSetLobbyNickname::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void RequestSetLobbyNickname::Swap(RequestSetLobbyNickname* other) { + if (other != this) { + std::swap(nickname_, other->nickname_); + lobby_ids_.Swap(&other->lobby_ids_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestSetLobbyNickname::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestSetLobbyNickname_descriptor_; + metadata.reflection = RequestSetLobbyNickname_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseSetLobbyNickname::kStatusFieldNumber; +#endif // !_MSC_VER + +ResponseSetLobbyNickname::ResponseSetLobbyNickname() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseSetLobbyNickname::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseSetLobbyNickname::ResponseSetLobbyNickname(const ResponseSetLobbyNickname& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseSetLobbyNickname::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseSetLobbyNickname::~ResponseSetLobbyNickname() { + SharedDtor(); +} + +void ResponseSetLobbyNickname::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseSetLobbyNickname::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseSetLobbyNickname::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSetLobbyNickname_descriptor_; +} + +const ResponseSetLobbyNickname& ResponseSetLobbyNickname::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ResponseSetLobbyNickname* ResponseSetLobbyNickname::default_instance_ = NULL; + +ResponseSetLobbyNickname* ResponseSetLobbyNickname::New() const { + return new ResponseSetLobbyNickname; +} + +void ResponseSetLobbyNickname::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseSetLobbyNickname::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseSetLobbyNickname::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseSetLobbyNickname::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseSetLobbyNickname::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseSetLobbyNickname::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseSetLobbyNickname* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseSetLobbyNickname::MergeFrom(const ResponseSetLobbyNickname& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseSetLobbyNickname::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseSetLobbyNickname::CopyFrom(const ResponseSetLobbyNickname& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseSetLobbyNickname::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + return true; +} + +void ResponseSetLobbyNickname::Swap(ResponseSetLobbyNickname* other) { + if (other != this) { + std::swap(status_, other->status_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseSetLobbyNickname::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseSetLobbyNickname_descriptor_; + metadata.reflection = ResponseSetLobbyNickname_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestRegisterEvents_RegisterAction_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestRegisterEvents_RegisterAction_descriptor_; +} +bool RequestRegisterEvents_RegisterAction_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestRegisterEvents_RegisterAction RequestRegisterEvents::REGISTER; +const RequestRegisterEvents_RegisterAction RequestRegisterEvents::DEREGISTER; +const RequestRegisterEvents_RegisterAction RequestRegisterEvents::RegisterAction_MIN; +const RequestRegisterEvents_RegisterAction RequestRegisterEvents::RegisterAction_MAX; +const int RequestRegisterEvents::RegisterAction_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestRegisterEvents::kActionFieldNumber; +#endif // !_MSC_VER + +RequestRegisterEvents::RequestRegisterEvents() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestRegisterEvents::InitAsDefaultInstance() { +} + +RequestRegisterEvents::RequestRegisterEvents(const RequestRegisterEvents& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestRegisterEvents::SharedCtor() { + _cached_size_ = 0; + action_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestRegisterEvents::~RequestRegisterEvents() { + SharedDtor(); +} + +void RequestRegisterEvents::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestRegisterEvents::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestRegisterEvents::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestRegisterEvents_descriptor_; +} + +const RequestRegisterEvents& RequestRegisterEvents::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +RequestRegisterEvents* RequestRegisterEvents::default_instance_ = NULL; + +RequestRegisterEvents* RequestRegisterEvents::New() const { + return new RequestRegisterEvents; +} + +void RequestRegisterEvents::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + action_ = 1; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestRegisterEvents::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.RequestRegisterEvents.RegisterAction action = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::chat::RequestRegisterEvents_RegisterAction_IsValid(value)) { + set_action(static_cast< ::rsctrl::chat::RequestRegisterEvents_RegisterAction >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestRegisterEvents::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.RequestRegisterEvents.RegisterAction action = 1; + if (has_action()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->action(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestRegisterEvents::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.RequestRegisterEvents.RegisterAction action = 1; + if (has_action()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->action(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestRegisterEvents::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.RequestRegisterEvents.RegisterAction action = 1; + if (has_action()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->action()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestRegisterEvents::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestRegisterEvents* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestRegisterEvents::MergeFrom(const RequestRegisterEvents& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_action()) { + set_action(from.action()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestRegisterEvents::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestRegisterEvents::CopyFrom(const RequestRegisterEvents& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestRegisterEvents::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void RequestRegisterEvents::Swap(RequestRegisterEvents* other) { + if (other != this) { + std::swap(action_, other->action_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestRegisterEvents::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestRegisterEvents_descriptor_; + metadata.reflection = RequestRegisterEvents_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseRegisterEvents::kStatusFieldNumber; +#endif // !_MSC_VER + +ResponseRegisterEvents::ResponseRegisterEvents() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseRegisterEvents::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseRegisterEvents::ResponseRegisterEvents(const ResponseRegisterEvents& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseRegisterEvents::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseRegisterEvents::~ResponseRegisterEvents() { + SharedDtor(); +} + +void ResponseRegisterEvents::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseRegisterEvents::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseRegisterEvents::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseRegisterEvents_descriptor_; +} + +const ResponseRegisterEvents& ResponseRegisterEvents::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ResponseRegisterEvents* ResponseRegisterEvents::default_instance_ = NULL; + +ResponseRegisterEvents* ResponseRegisterEvents::New() const { + return new ResponseRegisterEvents; +} + +void ResponseRegisterEvents::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseRegisterEvents::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseRegisterEvents::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseRegisterEvents::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseRegisterEvents::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseRegisterEvents::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseRegisterEvents* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseRegisterEvents::MergeFrom(const ResponseRegisterEvents& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseRegisterEvents::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseRegisterEvents::CopyFrom(const ResponseRegisterEvents& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseRegisterEvents::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + return true; +} + +void ResponseRegisterEvents::Swap(ResponseRegisterEvents* other) { + if (other != this) { + std::swap(status_, other->status_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseRegisterEvents::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseRegisterEvents_descriptor_; + metadata.reflection = ResponseRegisterEvents_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int EventLobbyInvite::kLobbyFieldNumber; +#endif // !_MSC_VER + +EventLobbyInvite::EventLobbyInvite() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void EventLobbyInvite::InitAsDefaultInstance() { + lobby_ = const_cast< ::rsctrl::chat::ChatLobbyInfo*>(&::rsctrl::chat::ChatLobbyInfo::default_instance()); +} + +EventLobbyInvite::EventLobbyInvite(const EventLobbyInvite& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void EventLobbyInvite::SharedCtor() { + _cached_size_ = 0; + lobby_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +EventLobbyInvite::~EventLobbyInvite() { + SharedDtor(); +} + +void EventLobbyInvite::SharedDtor() { + if (this != default_instance_) { + delete lobby_; + } +} + +void EventLobbyInvite::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EventLobbyInvite::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EventLobbyInvite_descriptor_; +} + +const EventLobbyInvite& EventLobbyInvite::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +EventLobbyInvite* EventLobbyInvite::default_instance_ = NULL; + +EventLobbyInvite* EventLobbyInvite::New() const { + return new EventLobbyInvite; +} + +void EventLobbyInvite::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_lobby()) { + if (lobby_ != NULL) lobby_->::rsctrl::chat::ChatLobbyInfo::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool EventLobbyInvite::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.ChatLobbyInfo lobby = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_lobby())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void EventLobbyInvite::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.ChatLobbyInfo lobby = 1; + if (has_lobby()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->lobby(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* EventLobbyInvite::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.ChatLobbyInfo lobby = 1; + if (has_lobby()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->lobby(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int EventLobbyInvite::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.ChatLobbyInfo lobby = 1; + if (has_lobby()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->lobby()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EventLobbyInvite::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const EventLobbyInvite* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EventLobbyInvite::MergeFrom(const EventLobbyInvite& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_lobby()) { + mutable_lobby()->::rsctrl::chat::ChatLobbyInfo::MergeFrom(from.lobby()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void EventLobbyInvite::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EventLobbyInvite::CopyFrom(const EventLobbyInvite& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EventLobbyInvite::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_lobby()) { + if (!this->lobby().IsInitialized()) return false; + } + return true; +} + +void EventLobbyInvite::Swap(EventLobbyInvite* other) { + if (other != this) { + std::swap(lobby_, other->lobby_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata EventLobbyInvite::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EventLobbyInvite_descriptor_; + metadata.reflection = EventLobbyInvite_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int EventChatMessage::kMsgFieldNumber; +#endif // !_MSC_VER + +EventChatMessage::EventChatMessage() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void EventChatMessage::InitAsDefaultInstance() { + msg_ = const_cast< ::rsctrl::chat::ChatMessage*>(&::rsctrl::chat::ChatMessage::default_instance()); +} + +EventChatMessage::EventChatMessage(const EventChatMessage& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void EventChatMessage::SharedCtor() { + _cached_size_ = 0; + msg_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +EventChatMessage::~EventChatMessage() { + SharedDtor(); +} + +void EventChatMessage::SharedDtor() { + if (this != default_instance_) { + delete msg_; + } +} + +void EventChatMessage::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EventChatMessage::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EventChatMessage_descriptor_; +} + +const EventChatMessage& EventChatMessage::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +EventChatMessage* EventChatMessage::default_instance_ = NULL; + +EventChatMessage* EventChatMessage::New() const { + return new EventChatMessage; +} + +void EventChatMessage::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_msg()) { + if (msg_ != NULL) msg_->::rsctrl::chat::ChatMessage::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool EventChatMessage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.ChatMessage msg = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_msg())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void EventChatMessage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.ChatMessage msg = 1; + if (has_msg()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->msg(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* EventChatMessage::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.ChatMessage msg = 1; + if (has_msg()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->msg(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int EventChatMessage::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.ChatMessage msg = 1; + if (has_msg()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->msg()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EventChatMessage::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const EventChatMessage* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EventChatMessage::MergeFrom(const EventChatMessage& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_msg()) { + mutable_msg()->::rsctrl::chat::ChatMessage::MergeFrom(from.msg()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void EventChatMessage::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EventChatMessage::CopyFrom(const EventChatMessage& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EventChatMessage::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_msg()) { + if (!this->msg().IsInitialized()) return false; + } + return true; +} + +void EventChatMessage::Swap(EventChatMessage* other) { + if (other != this) { + std::swap(msg_, other->msg_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata EventChatMessage::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EventChatMessage_descriptor_; + metadata.reflection = EventChatMessage_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestSendMessage::kMsgFieldNumber; +#endif // !_MSC_VER + +RequestSendMessage::RequestSendMessage() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestSendMessage::InitAsDefaultInstance() { + msg_ = const_cast< ::rsctrl::chat::ChatMessage*>(&::rsctrl::chat::ChatMessage::default_instance()); +} + +RequestSendMessage::RequestSendMessage(const RequestSendMessage& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestSendMessage::SharedCtor() { + _cached_size_ = 0; + msg_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestSendMessage::~RequestSendMessage() { + SharedDtor(); +} + +void RequestSendMessage::SharedDtor() { + if (this != default_instance_) { + delete msg_; + } +} + +void RequestSendMessage::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestSendMessage::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestSendMessage_descriptor_; +} + +const RequestSendMessage& RequestSendMessage::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +RequestSendMessage* RequestSendMessage::default_instance_ = NULL; + +RequestSendMessage* RequestSendMessage::New() const { + return new RequestSendMessage; +} + +void RequestSendMessage::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_msg()) { + if (msg_ != NULL) msg_->::rsctrl::chat::ChatMessage::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestSendMessage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.chat.ChatMessage msg = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_msg())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestSendMessage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.chat.ChatMessage msg = 1; + if (has_msg()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->msg(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestSendMessage::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.chat.ChatMessage msg = 1; + if (has_msg()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->msg(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestSendMessage::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.chat.ChatMessage msg = 1; + if (has_msg()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->msg()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestSendMessage::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestSendMessage* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestSendMessage::MergeFrom(const RequestSendMessage& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_msg()) { + mutable_msg()->::rsctrl::chat::ChatMessage::MergeFrom(from.msg()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestSendMessage::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestSendMessage::CopyFrom(const RequestSendMessage& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestSendMessage::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_msg()) { + if (!this->msg().IsInitialized()) return false; + } + return true; +} + +void RequestSendMessage::Swap(RequestSendMessage* other) { + if (other != this) { + std::swap(msg_, other->msg_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestSendMessage::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestSendMessage_descriptor_; + metadata.reflection = RequestSendMessage_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseSendMessage::kStatusFieldNumber; +#endif // !_MSC_VER + +ResponseSendMessage::ResponseSendMessage() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseSendMessage::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseSendMessage::ResponseSendMessage(const ResponseSendMessage& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseSendMessage::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseSendMessage::~ResponseSendMessage() { + SharedDtor(); +} + +void ResponseSendMessage::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseSendMessage::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseSendMessage::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSendMessage_descriptor_; +} + +const ResponseSendMessage& ResponseSendMessage::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_chat_2eproto(); return *default_instance_; +} + +ResponseSendMessage* ResponseSendMessage::default_instance_ = NULL; + +ResponseSendMessage* ResponseSendMessage::New() const { + return new ResponseSendMessage; +} + +void ResponseSendMessage::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseSendMessage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseSendMessage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseSendMessage::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseSendMessage::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseSendMessage::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseSendMessage* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseSendMessage::MergeFrom(const ResponseSendMessage& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseSendMessage::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseSendMessage::CopyFrom(const ResponseSendMessage& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseSendMessage::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + return true; +} + +void ResponseSendMessage::Swap(ResponseSendMessage* other) { + if (other != this) { + std::swap(status_, other->status_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseSendMessage::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseSendMessage_descriptor_; + metadata.reflection = ResponseSendMessage_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace chat +} // namespace rsctrl + +// @@protoc_insertion_point(global_scope) diff --git a/retroshare-nogui/src/rpc/proto/gencc/chat.pb.h b/retroshare-nogui/src/rpc/proto/gencc/chat.pb.h new file mode 100644 index 000000000..d6ebc3adf --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/chat.pb.h @@ -0,0 +1,3325 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: chat.proto + +#ifndef PROTOBUF_chat_2eproto__INCLUDED +#define PROTOBUF_chat_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include "core.pb.h" +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace chat { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_chat_2eproto(); +void protobuf_AssignDesc_chat_2eproto(); +void protobuf_ShutdownFile_chat_2eproto(); + +class ChatLobbyInfo; +class ChatId; +class ChatMessage; +class ResponseChatLobbies; +class RequestChatLobbies; +class RequestCreateLobby; +class RequestJoinOrLeaveLobby; +class RequestSetLobbyNickname; +class ResponseSetLobbyNickname; +class RequestRegisterEvents; +class ResponseRegisterEvents; +class EventLobbyInvite; +class EventChatMessage; +class RequestSendMessage; +class ResponseSendMessage; + +enum ChatLobbyInfo_LobbyState { + ChatLobbyInfo_LobbyState_LOBBYSTATE_JOINED = 1, + ChatLobbyInfo_LobbyState_LOBBYSTATE_INVITED = 2, + ChatLobbyInfo_LobbyState_LOBBYSTATE_PUBLIC = 3 +}; +bool ChatLobbyInfo_LobbyState_IsValid(int value); +const ChatLobbyInfo_LobbyState ChatLobbyInfo_LobbyState_LobbyState_MIN = ChatLobbyInfo_LobbyState_LOBBYSTATE_JOINED; +const ChatLobbyInfo_LobbyState ChatLobbyInfo_LobbyState_LobbyState_MAX = ChatLobbyInfo_LobbyState_LOBBYSTATE_PUBLIC; +const int ChatLobbyInfo_LobbyState_LobbyState_ARRAYSIZE = ChatLobbyInfo_LobbyState_LobbyState_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ChatLobbyInfo_LobbyState_descriptor(); +inline const ::std::string& ChatLobbyInfo_LobbyState_Name(ChatLobbyInfo_LobbyState value) { + return ::google::protobuf::internal::NameOfEnum( + ChatLobbyInfo_LobbyState_descriptor(), value); +} +inline bool ChatLobbyInfo_LobbyState_Parse( + const ::std::string& name, ChatLobbyInfo_LobbyState* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ChatLobbyInfo_LobbyState_descriptor(), name, value); +} +enum RequestChatLobbies_LobbySet { + RequestChatLobbies_LobbySet_LOBBYSET_ALL = 1, + RequestChatLobbies_LobbySet_LOBBYSET_JOINED = 2, + RequestChatLobbies_LobbySet_LOBBYSET_INVITED = 3, + RequestChatLobbies_LobbySet_LOBBYSET_PUBLIC = 4 +}; +bool RequestChatLobbies_LobbySet_IsValid(int value); +const RequestChatLobbies_LobbySet RequestChatLobbies_LobbySet_LobbySet_MIN = RequestChatLobbies_LobbySet_LOBBYSET_ALL; +const RequestChatLobbies_LobbySet RequestChatLobbies_LobbySet_LobbySet_MAX = RequestChatLobbies_LobbySet_LOBBYSET_PUBLIC; +const int RequestChatLobbies_LobbySet_LobbySet_ARRAYSIZE = RequestChatLobbies_LobbySet_LobbySet_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestChatLobbies_LobbySet_descriptor(); +inline const ::std::string& RequestChatLobbies_LobbySet_Name(RequestChatLobbies_LobbySet value) { + return ::google::protobuf::internal::NameOfEnum( + RequestChatLobbies_LobbySet_descriptor(), value); +} +inline bool RequestChatLobbies_LobbySet_Parse( + const ::std::string& name, RequestChatLobbies_LobbySet* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestChatLobbies_LobbySet_descriptor(), name, value); +} +enum RequestJoinOrLeaveLobby_LobbyAction { + RequestJoinOrLeaveLobby_LobbyAction_JOIN_OR_ACCEPT = 1, + RequestJoinOrLeaveLobby_LobbyAction_LEAVE_OR_DENY = 2 +}; +bool RequestJoinOrLeaveLobby_LobbyAction_IsValid(int value); +const RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_MIN = RequestJoinOrLeaveLobby_LobbyAction_JOIN_OR_ACCEPT; +const RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_MAX = RequestJoinOrLeaveLobby_LobbyAction_LEAVE_OR_DENY; +const int RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_ARRAYSIZE = RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestJoinOrLeaveLobby_LobbyAction_descriptor(); +inline const ::std::string& RequestJoinOrLeaveLobby_LobbyAction_Name(RequestJoinOrLeaveLobby_LobbyAction value) { + return ::google::protobuf::internal::NameOfEnum( + RequestJoinOrLeaveLobby_LobbyAction_descriptor(), value); +} +inline bool RequestJoinOrLeaveLobby_LobbyAction_Parse( + const ::std::string& name, RequestJoinOrLeaveLobby_LobbyAction* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestJoinOrLeaveLobby_LobbyAction_descriptor(), name, value); +} +enum RequestRegisterEvents_RegisterAction { + RequestRegisterEvents_RegisterAction_REGISTER = 1, + RequestRegisterEvents_RegisterAction_DEREGISTER = 2 +}; +bool RequestRegisterEvents_RegisterAction_IsValid(int value); +const RequestRegisterEvents_RegisterAction RequestRegisterEvents_RegisterAction_RegisterAction_MIN = RequestRegisterEvents_RegisterAction_REGISTER; +const RequestRegisterEvents_RegisterAction RequestRegisterEvents_RegisterAction_RegisterAction_MAX = RequestRegisterEvents_RegisterAction_DEREGISTER; +const int RequestRegisterEvents_RegisterAction_RegisterAction_ARRAYSIZE = RequestRegisterEvents_RegisterAction_RegisterAction_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestRegisterEvents_RegisterAction_descriptor(); +inline const ::std::string& RequestRegisterEvents_RegisterAction_Name(RequestRegisterEvents_RegisterAction value) { + return ::google::protobuf::internal::NameOfEnum( + RequestRegisterEvents_RegisterAction_descriptor(), value); +} +inline bool RequestRegisterEvents_RegisterAction_Parse( + const ::std::string& name, RequestRegisterEvents_RegisterAction* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestRegisterEvents_RegisterAction_descriptor(), name, value); +} +enum RequestMsgIds { + MsgId_RequestChatLobbies = 1, + MsgId_RequestCreateLobby = 2, + MsgId_RequestJoinOrLeaveLobby = 3, + MsgId_RequestSetLobbyNickname = 4, + MsgId_RequestRegisterEvents = 5, + MsgId_RequestSendMessage = 6 +}; +bool RequestMsgIds_IsValid(int value); +const RequestMsgIds RequestMsgIds_MIN = MsgId_RequestChatLobbies; +const RequestMsgIds RequestMsgIds_MAX = MsgId_RequestSendMessage; +const int RequestMsgIds_ARRAYSIZE = RequestMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor(); +inline const ::std::string& RequestMsgIds_Name(RequestMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + RequestMsgIds_descriptor(), value); +} +inline bool RequestMsgIds_Parse( + const ::std::string& name, RequestMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestMsgIds_descriptor(), name, value); +} +enum ResponseMsgIds { + MsgId_ResponseChatLobbies = 1, + MsgId_ResponseSetLobbyNickname = 4, + MsgId_ResponseRegisterEvents = 5, + MsgId_ResponseSendMessage = 6, + MsgId_EventLobbyInvite = 101, + MsgId_EventChatMessage = 102 +}; +bool ResponseMsgIds_IsValid(int value); +const ResponseMsgIds ResponseMsgIds_MIN = MsgId_ResponseChatLobbies; +const ResponseMsgIds ResponseMsgIds_MAX = MsgId_EventChatMessage; +const int ResponseMsgIds_ARRAYSIZE = ResponseMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor(); +inline const ::std::string& ResponseMsgIds_Name(ResponseMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + ResponseMsgIds_descriptor(), value); +} +inline bool ResponseMsgIds_Parse( + const ::std::string& name, ResponseMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ResponseMsgIds_descriptor(), name, value); +} +enum LobbyPrivacyLevel { + PRIVACY_PRIVATE = 1, + PRIVACY_PUBLIC = 2 +}; +bool LobbyPrivacyLevel_IsValid(int value); +const LobbyPrivacyLevel LobbyPrivacyLevel_MIN = PRIVACY_PRIVATE; +const LobbyPrivacyLevel LobbyPrivacyLevel_MAX = PRIVACY_PUBLIC; +const int LobbyPrivacyLevel_ARRAYSIZE = LobbyPrivacyLevel_MAX + 1; + +const ::google::protobuf::EnumDescriptor* LobbyPrivacyLevel_descriptor(); +inline const ::std::string& LobbyPrivacyLevel_Name(LobbyPrivacyLevel value) { + return ::google::protobuf::internal::NameOfEnum( + LobbyPrivacyLevel_descriptor(), value); +} +inline bool LobbyPrivacyLevel_Parse( + const ::std::string& name, LobbyPrivacyLevel* value) { + return ::google::protobuf::internal::ParseNamedEnum( + LobbyPrivacyLevel_descriptor(), name, value); +} +enum ChatType { + TYPE_PRIVATE = 1, + TYPE_LOBBY = 2, + TYPE_GROUP = 3 +}; +bool ChatType_IsValid(int value); +const ChatType ChatType_MIN = TYPE_PRIVATE; +const ChatType ChatType_MAX = TYPE_GROUP; +const int ChatType_ARRAYSIZE = ChatType_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ChatType_descriptor(); +inline const ::std::string& ChatType_Name(ChatType value) { + return ::google::protobuf::internal::NameOfEnum( + ChatType_descriptor(), value); +} +inline bool ChatType_Parse( + const ::std::string& name, ChatType* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ChatType_descriptor(), name, value); +} +// =================================================================== + +class ChatLobbyInfo : public ::google::protobuf::Message { + public: + ChatLobbyInfo(); + virtual ~ChatLobbyInfo(); + + ChatLobbyInfo(const ChatLobbyInfo& from); + + inline ChatLobbyInfo& operator=(const ChatLobbyInfo& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ChatLobbyInfo& default_instance(); + + void Swap(ChatLobbyInfo* other); + + // implements Message ---------------------------------------------- + + ChatLobbyInfo* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ChatLobbyInfo& from); + void MergeFrom(const ChatLobbyInfo& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef ChatLobbyInfo_LobbyState LobbyState; + static const LobbyState LOBBYSTATE_JOINED = ChatLobbyInfo_LobbyState_LOBBYSTATE_JOINED; + static const LobbyState LOBBYSTATE_INVITED = ChatLobbyInfo_LobbyState_LOBBYSTATE_INVITED; + static const LobbyState LOBBYSTATE_PUBLIC = ChatLobbyInfo_LobbyState_LOBBYSTATE_PUBLIC; + static inline bool LobbyState_IsValid(int value) { + return ChatLobbyInfo_LobbyState_IsValid(value); + } + static const LobbyState LobbyState_MIN = + ChatLobbyInfo_LobbyState_LobbyState_MIN; + static const LobbyState LobbyState_MAX = + ChatLobbyInfo_LobbyState_LobbyState_MAX; + static const int LobbyState_ARRAYSIZE = + ChatLobbyInfo_LobbyState_LobbyState_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + LobbyState_descriptor() { + return ChatLobbyInfo_LobbyState_descriptor(); + } + static inline const ::std::string& LobbyState_Name(LobbyState value) { + return ChatLobbyInfo_LobbyState_Name(value); + } + static inline bool LobbyState_Parse(const ::std::string& name, + LobbyState* value) { + return ChatLobbyInfo_LobbyState_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required string lobby_id = 1; + inline bool has_lobby_id() const; + inline void clear_lobby_id(); + static const int kLobbyIdFieldNumber = 1; + inline const ::std::string& lobby_id() const; + inline void set_lobby_id(const ::std::string& value); + inline void set_lobby_id(const char* value); + inline void set_lobby_id(const char* value, size_t size); + inline ::std::string* mutable_lobby_id(); + inline ::std::string* release_lobby_id(); + + // required string lobby_topic = 2; + inline bool has_lobby_topic() const; + inline void clear_lobby_topic(); + static const int kLobbyTopicFieldNumber = 2; + inline const ::std::string& lobby_topic() const; + inline void set_lobby_topic(const ::std::string& value); + inline void set_lobby_topic(const char* value); + inline void set_lobby_topic(const char* value, size_t size); + inline ::std::string* mutable_lobby_topic(); + inline ::std::string* release_lobby_topic(); + + // required string lobby_name = 3; + inline bool has_lobby_name() const; + inline void clear_lobby_name(); + static const int kLobbyNameFieldNumber = 3; + inline const ::std::string& lobby_name() const; + inline void set_lobby_name(const ::std::string& value); + inline void set_lobby_name(const char* value); + inline void set_lobby_name(const char* value, size_t size); + inline ::std::string* mutable_lobby_name(); + inline ::std::string* release_lobby_name(); + + // required string lobby_nickname = 4; + inline bool has_lobby_nickname() const; + inline void clear_lobby_nickname(); + static const int kLobbyNicknameFieldNumber = 4; + inline const ::std::string& lobby_nickname() const; + inline void set_lobby_nickname(const ::std::string& value); + inline void set_lobby_nickname(const char* value); + inline void set_lobby_nickname(const char* value, size_t size); + inline ::std::string* mutable_lobby_nickname(); + inline ::std::string* release_lobby_nickname(); + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 5; + inline bool has_privacy_level() const; + inline void clear_privacy_level(); + static const int kPrivacyLevelFieldNumber = 5; + inline rsctrl::chat::LobbyPrivacyLevel privacy_level() const; + inline void set_privacy_level(rsctrl::chat::LobbyPrivacyLevel value); + + // required .rsctrl.chat.ChatLobbyInfo.LobbyState lobby_state = 6; + inline bool has_lobby_state() const; + inline void clear_lobby_state(); + static const int kLobbyStateFieldNumber = 6; + inline ::rsctrl::chat::ChatLobbyInfo_LobbyState lobby_state() const; + inline void set_lobby_state(::rsctrl::chat::ChatLobbyInfo_LobbyState value); + + // required uint32 no_peers = 7; + inline bool has_no_peers() const; + inline void clear_no_peers(); + static const int kNoPeersFieldNumber = 7; + inline ::google::protobuf::uint32 no_peers() const; + inline void set_no_peers(::google::protobuf::uint32 value); + + // required uint32 last_report_time = 8; + inline bool has_last_report_time() const; + inline void clear_last_report_time(); + static const int kLastReportTimeFieldNumber = 8; + inline ::google::protobuf::uint32 last_report_time() const; + inline void set_last_report_time(::google::protobuf::uint32 value); + + // required uint32 last_activity = 9; + inline bool has_last_activity() const; + inline void clear_last_activity(); + static const int kLastActivityFieldNumber = 9; + inline ::google::protobuf::uint32 last_activity() const; + inline void set_last_activity(::google::protobuf::uint32 value); + + // repeated string participating_friends = 10; + inline int participating_friends_size() const; + inline void clear_participating_friends(); + static const int kParticipatingFriendsFieldNumber = 10; + inline const ::std::string& participating_friends(int index) const; + inline ::std::string* mutable_participating_friends(int index); + inline void set_participating_friends(int index, const ::std::string& value); + inline void set_participating_friends(int index, const char* value); + inline void set_participating_friends(int index, const char* value, size_t size); + inline ::std::string* add_participating_friends(); + inline void add_participating_friends(const ::std::string& value); + inline void add_participating_friends(const char* value); + inline void add_participating_friends(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& participating_friends() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_participating_friends(); + + // repeated string nicknames = 11; + inline int nicknames_size() const; + inline void clear_nicknames(); + static const int kNicknamesFieldNumber = 11; + inline const ::std::string& nicknames(int index) const; + inline ::std::string* mutable_nicknames(int index); + inline void set_nicknames(int index, const ::std::string& value); + inline void set_nicknames(int index, const char* value); + inline void set_nicknames(int index, const char* value, size_t size); + inline ::std::string* add_nicknames(); + inline void add_nicknames(const ::std::string& value); + inline void add_nicknames(const char* value); + inline void add_nicknames(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& nicknames() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_nicknames(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ChatLobbyInfo) + private: + inline void set_has_lobby_id(); + inline void clear_has_lobby_id(); + inline void set_has_lobby_topic(); + inline void clear_has_lobby_topic(); + inline void set_has_lobby_name(); + inline void clear_has_lobby_name(); + inline void set_has_lobby_nickname(); + inline void clear_has_lobby_nickname(); + inline void set_has_privacy_level(); + inline void clear_has_privacy_level(); + inline void set_has_lobby_state(); + inline void clear_has_lobby_state(); + inline void set_has_no_peers(); + inline void clear_has_no_peers(); + inline void set_has_last_report_time(); + inline void clear_has_last_report_time(); + inline void set_has_last_activity(); + inline void clear_has_last_activity(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* lobby_id_; + ::std::string* lobby_topic_; + ::std::string* lobby_name_; + ::std::string* lobby_nickname_; + int privacy_level_; + int lobby_state_; + ::google::protobuf::uint32 no_peers_; + ::google::protobuf::uint32 last_report_time_; + ::google::protobuf::RepeatedPtrField< ::std::string> participating_friends_; + ::google::protobuf::RepeatedPtrField< ::std::string> nicknames_; + ::google::protobuf::uint32 last_activity_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ChatLobbyInfo* default_instance_; +}; +// ------------------------------------------------------------------- + +class ChatId : public ::google::protobuf::Message { + public: + ChatId(); + virtual ~ChatId(); + + ChatId(const ChatId& from); + + inline ChatId& operator=(const ChatId& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ChatId& default_instance(); + + void Swap(ChatId* other); + + // implements Message ---------------------------------------------- + + ChatId* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ChatId& from); + void MergeFrom(const ChatId& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.ChatType chat_type = 1; + inline bool has_chat_type() const; + inline void clear_chat_type(); + static const int kChatTypeFieldNumber = 1; + inline rsctrl::chat::ChatType chat_type() const; + inline void set_chat_type(rsctrl::chat::ChatType value); + + // required string chat_id = 2; + inline bool has_chat_id() const; + inline void clear_chat_id(); + static const int kChatIdFieldNumber = 2; + inline const ::std::string& chat_id() const; + inline void set_chat_id(const ::std::string& value); + inline void set_chat_id(const char* value); + inline void set_chat_id(const char* value, size_t size); + inline ::std::string* mutable_chat_id(); + inline ::std::string* release_chat_id(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ChatId) + private: + inline void set_has_chat_type(); + inline void clear_has_chat_type(); + inline void set_has_chat_id(); + inline void clear_has_chat_id(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* chat_id_; + int chat_type_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ChatId* default_instance_; +}; +// ------------------------------------------------------------------- + +class ChatMessage : public ::google::protobuf::Message { + public: + ChatMessage(); + virtual ~ChatMessage(); + + ChatMessage(const ChatMessage& from); + + inline ChatMessage& operator=(const ChatMessage& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ChatMessage& default_instance(); + + void Swap(ChatMessage* other); + + // implements Message ---------------------------------------------- + + ChatMessage* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ChatMessage& from); + void MergeFrom(const ChatMessage& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.ChatId id = 1; + inline bool has_id() const; + inline void clear_id(); + static const int kIdFieldNumber = 1; + inline const ::rsctrl::chat::ChatId& id() const; + inline ::rsctrl::chat::ChatId* mutable_id(); + inline ::rsctrl::chat::ChatId* release_id(); + + // required string msg = 2; + inline bool has_msg() const; + inline void clear_msg(); + static const int kMsgFieldNumber = 2; + inline const ::std::string& msg() const; + inline void set_msg(const ::std::string& value); + inline void set_msg(const char* value); + inline void set_msg(const char* value, size_t size); + inline ::std::string* mutable_msg(); + inline ::std::string* release_msg(); + + // optional string peer_nickname = 3; + inline bool has_peer_nickname() const; + inline void clear_peer_nickname(); + static const int kPeerNicknameFieldNumber = 3; + inline const ::std::string& peer_nickname() const; + inline void set_peer_nickname(const ::std::string& value); + inline void set_peer_nickname(const char* value); + inline void set_peer_nickname(const char* value, size_t size); + inline ::std::string* mutable_peer_nickname(); + inline ::std::string* release_peer_nickname(); + + // optional uint32 chat_flags = 4; + inline bool has_chat_flags() const; + inline void clear_chat_flags(); + static const int kChatFlagsFieldNumber = 4; + inline ::google::protobuf::uint32 chat_flags() const; + inline void set_chat_flags(::google::protobuf::uint32 value); + + // optional uint32 send_time = 5; + inline bool has_send_time() const; + inline void clear_send_time(); + static const int kSendTimeFieldNumber = 5; + inline ::google::protobuf::uint32 send_time() const; + inline void set_send_time(::google::protobuf::uint32 value); + + // optional uint32 recv_time = 6; + inline bool has_recv_time() const; + inline void clear_recv_time(); + static const int kRecvTimeFieldNumber = 6; + inline ::google::protobuf::uint32 recv_time() const; + inline void set_recv_time(::google::protobuf::uint32 value); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ChatMessage) + private: + inline void set_has_id(); + inline void clear_has_id(); + inline void set_has_msg(); + inline void clear_has_msg(); + inline void set_has_peer_nickname(); + inline void clear_has_peer_nickname(); + inline void set_has_chat_flags(); + inline void clear_has_chat_flags(); + inline void set_has_send_time(); + inline void clear_has_send_time(); + inline void set_has_recv_time(); + inline void clear_has_recv_time(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::chat::ChatId* id_; + ::std::string* msg_; + ::std::string* peer_nickname_; + ::google::protobuf::uint32 chat_flags_; + ::google::protobuf::uint32 send_time_; + ::google::protobuf::uint32 recv_time_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ChatMessage* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseChatLobbies : public ::google::protobuf::Message { + public: + ResponseChatLobbies(); + virtual ~ResponseChatLobbies(); + + ResponseChatLobbies(const ResponseChatLobbies& from); + + inline ResponseChatLobbies& operator=(const ResponseChatLobbies& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseChatLobbies& default_instance(); + + void Swap(ResponseChatLobbies* other); + + // implements Message ---------------------------------------------- + + ResponseChatLobbies* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseChatLobbies& from); + void MergeFrom(const ResponseChatLobbies& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated .rsctrl.chat.ChatLobbyInfo lobbies = 2; + inline int lobbies_size() const; + inline void clear_lobbies(); + static const int kLobbiesFieldNumber = 2; + inline const ::rsctrl::chat::ChatLobbyInfo& lobbies(int index) const; + inline ::rsctrl::chat::ChatLobbyInfo* mutable_lobbies(int index); + inline ::rsctrl::chat::ChatLobbyInfo* add_lobbies(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::chat::ChatLobbyInfo >& + lobbies() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::chat::ChatLobbyInfo >* + mutable_lobbies(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ResponseChatLobbies) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::chat::ChatLobbyInfo > lobbies_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ResponseChatLobbies* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestChatLobbies : public ::google::protobuf::Message { + public: + RequestChatLobbies(); + virtual ~RequestChatLobbies(); + + RequestChatLobbies(const RequestChatLobbies& from); + + inline RequestChatLobbies& operator=(const RequestChatLobbies& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestChatLobbies& default_instance(); + + void Swap(RequestChatLobbies* other); + + // implements Message ---------------------------------------------- + + RequestChatLobbies* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestChatLobbies& from); + void MergeFrom(const RequestChatLobbies& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestChatLobbies_LobbySet LobbySet; + static const LobbySet LOBBYSET_ALL = RequestChatLobbies_LobbySet_LOBBYSET_ALL; + static const LobbySet LOBBYSET_JOINED = RequestChatLobbies_LobbySet_LOBBYSET_JOINED; + static const LobbySet LOBBYSET_INVITED = RequestChatLobbies_LobbySet_LOBBYSET_INVITED; + static const LobbySet LOBBYSET_PUBLIC = RequestChatLobbies_LobbySet_LOBBYSET_PUBLIC; + static inline bool LobbySet_IsValid(int value) { + return RequestChatLobbies_LobbySet_IsValid(value); + } + static const LobbySet LobbySet_MIN = + RequestChatLobbies_LobbySet_LobbySet_MIN; + static const LobbySet LobbySet_MAX = + RequestChatLobbies_LobbySet_LobbySet_MAX; + static const int LobbySet_ARRAYSIZE = + RequestChatLobbies_LobbySet_LobbySet_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + LobbySet_descriptor() { + return RequestChatLobbies_LobbySet_descriptor(); + } + static inline const ::std::string& LobbySet_Name(LobbySet value) { + return RequestChatLobbies_LobbySet_Name(value); + } + static inline bool LobbySet_Parse(const ::std::string& name, + LobbySet* value) { + return RequestChatLobbies_LobbySet_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.RequestChatLobbies.LobbySet lobby_set = 1; + inline bool has_lobby_set() const; + inline void clear_lobby_set(); + static const int kLobbySetFieldNumber = 1; + inline ::rsctrl::chat::RequestChatLobbies_LobbySet lobby_set() const; + inline void set_lobby_set(::rsctrl::chat::RequestChatLobbies_LobbySet value); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.RequestChatLobbies) + private: + inline void set_has_lobby_set(); + inline void clear_has_lobby_set(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + int lobby_set_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static RequestChatLobbies* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestCreateLobby : public ::google::protobuf::Message { + public: + RequestCreateLobby(); + virtual ~RequestCreateLobby(); + + RequestCreateLobby(const RequestCreateLobby& from); + + inline RequestCreateLobby& operator=(const RequestCreateLobby& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestCreateLobby& default_instance(); + + void Swap(RequestCreateLobby* other); + + // implements Message ---------------------------------------------- + + RequestCreateLobby* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestCreateLobby& from); + void MergeFrom(const RequestCreateLobby& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required string lobby_name = 1; + inline bool has_lobby_name() const; + inline void clear_lobby_name(); + static const int kLobbyNameFieldNumber = 1; + inline const ::std::string& lobby_name() const; + inline void set_lobby_name(const ::std::string& value); + inline void set_lobby_name(const char* value); + inline void set_lobby_name(const char* value, size_t size); + inline ::std::string* mutable_lobby_name(); + inline ::std::string* release_lobby_name(); + + // required string lobby_topic = 2; + inline bool has_lobby_topic() const; + inline void clear_lobby_topic(); + static const int kLobbyTopicFieldNumber = 2; + inline const ::std::string& lobby_topic() const; + inline void set_lobby_topic(const ::std::string& value); + inline void set_lobby_topic(const char* value); + inline void set_lobby_topic(const char* value, size_t size); + inline ::std::string* mutable_lobby_topic(); + inline ::std::string* release_lobby_topic(); + + // required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 4; + inline bool has_privacy_level() const; + inline void clear_privacy_level(); + static const int kPrivacyLevelFieldNumber = 4; + inline rsctrl::chat::LobbyPrivacyLevel privacy_level() const; + inline void set_privacy_level(rsctrl::chat::LobbyPrivacyLevel value); + + // repeated string invited_friends = 3; + inline int invited_friends_size() const; + inline void clear_invited_friends(); + static const int kInvitedFriendsFieldNumber = 3; + inline const ::std::string& invited_friends(int index) const; + inline ::std::string* mutable_invited_friends(int index); + inline void set_invited_friends(int index, const ::std::string& value); + inline void set_invited_friends(int index, const char* value); + inline void set_invited_friends(int index, const char* value, size_t size); + inline ::std::string* add_invited_friends(); + inline void add_invited_friends(const ::std::string& value); + inline void add_invited_friends(const char* value); + inline void add_invited_friends(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& invited_friends() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_invited_friends(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.RequestCreateLobby) + private: + inline void set_has_lobby_name(); + inline void clear_has_lobby_name(); + inline void set_has_lobby_topic(); + inline void clear_has_lobby_topic(); + inline void set_has_privacy_level(); + inline void clear_has_privacy_level(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* lobby_name_; + ::std::string* lobby_topic_; + ::google::protobuf::RepeatedPtrField< ::std::string> invited_friends_; + int privacy_level_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static RequestCreateLobby* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestJoinOrLeaveLobby : public ::google::protobuf::Message { + public: + RequestJoinOrLeaveLobby(); + virtual ~RequestJoinOrLeaveLobby(); + + RequestJoinOrLeaveLobby(const RequestJoinOrLeaveLobby& from); + + inline RequestJoinOrLeaveLobby& operator=(const RequestJoinOrLeaveLobby& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestJoinOrLeaveLobby& default_instance(); + + void Swap(RequestJoinOrLeaveLobby* other); + + // implements Message ---------------------------------------------- + + RequestJoinOrLeaveLobby* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestJoinOrLeaveLobby& from); + void MergeFrom(const RequestJoinOrLeaveLobby& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestJoinOrLeaveLobby_LobbyAction LobbyAction; + static const LobbyAction JOIN_OR_ACCEPT = RequestJoinOrLeaveLobby_LobbyAction_JOIN_OR_ACCEPT; + static const LobbyAction LEAVE_OR_DENY = RequestJoinOrLeaveLobby_LobbyAction_LEAVE_OR_DENY; + static inline bool LobbyAction_IsValid(int value) { + return RequestJoinOrLeaveLobby_LobbyAction_IsValid(value); + } + static const LobbyAction LobbyAction_MIN = + RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_MIN; + static const LobbyAction LobbyAction_MAX = + RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_MAX; + static const int LobbyAction_ARRAYSIZE = + RequestJoinOrLeaveLobby_LobbyAction_LobbyAction_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + LobbyAction_descriptor() { + return RequestJoinOrLeaveLobby_LobbyAction_descriptor(); + } + static inline const ::std::string& LobbyAction_Name(LobbyAction value) { + return RequestJoinOrLeaveLobby_LobbyAction_Name(value); + } + static inline bool LobbyAction_Parse(const ::std::string& name, + LobbyAction* value) { + return RequestJoinOrLeaveLobby_LobbyAction_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required string lobby_id = 1; + inline bool has_lobby_id() const; + inline void clear_lobby_id(); + static const int kLobbyIdFieldNumber = 1; + inline const ::std::string& lobby_id() const; + inline void set_lobby_id(const ::std::string& value); + inline void set_lobby_id(const char* value); + inline void set_lobby_id(const char* value, size_t size); + inline ::std::string* mutable_lobby_id(); + inline ::std::string* release_lobby_id(); + + // required .rsctrl.chat.RequestJoinOrLeaveLobby.LobbyAction action = 2; + inline bool has_action() const; + inline void clear_action(); + static const int kActionFieldNumber = 2; + inline ::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction action() const; + inline void set_action(::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction value); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.RequestJoinOrLeaveLobby) + private: + inline void set_has_lobby_id(); + inline void clear_has_lobby_id(); + inline void set_has_action(); + inline void clear_has_action(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* lobby_id_; + int action_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static RequestJoinOrLeaveLobby* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestSetLobbyNickname : public ::google::protobuf::Message { + public: + RequestSetLobbyNickname(); + virtual ~RequestSetLobbyNickname(); + + RequestSetLobbyNickname(const RequestSetLobbyNickname& from); + + inline RequestSetLobbyNickname& operator=(const RequestSetLobbyNickname& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestSetLobbyNickname& default_instance(); + + void Swap(RequestSetLobbyNickname* other); + + // implements Message ---------------------------------------------- + + RequestSetLobbyNickname* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestSetLobbyNickname& from); + void MergeFrom(const RequestSetLobbyNickname& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required string nickname = 1; + inline bool has_nickname() const; + inline void clear_nickname(); + static const int kNicknameFieldNumber = 1; + inline const ::std::string& nickname() const; + inline void set_nickname(const ::std::string& value); + inline void set_nickname(const char* value); + inline void set_nickname(const char* value, size_t size); + inline ::std::string* mutable_nickname(); + inline ::std::string* release_nickname(); + + // repeated string lobby_ids = 2; + inline int lobby_ids_size() const; + inline void clear_lobby_ids(); + static const int kLobbyIdsFieldNumber = 2; + inline const ::std::string& lobby_ids(int index) const; + inline ::std::string* mutable_lobby_ids(int index); + inline void set_lobby_ids(int index, const ::std::string& value); + inline void set_lobby_ids(int index, const char* value); + inline void set_lobby_ids(int index, const char* value, size_t size); + inline ::std::string* add_lobby_ids(); + inline void add_lobby_ids(const ::std::string& value); + inline void add_lobby_ids(const char* value); + inline void add_lobby_ids(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& lobby_ids() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_lobby_ids(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.RequestSetLobbyNickname) + private: + inline void set_has_nickname(); + inline void clear_has_nickname(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* nickname_; + ::google::protobuf::RepeatedPtrField< ::std::string> lobby_ids_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static RequestSetLobbyNickname* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseSetLobbyNickname : public ::google::protobuf::Message { + public: + ResponseSetLobbyNickname(); + virtual ~ResponseSetLobbyNickname(); + + ResponseSetLobbyNickname(const ResponseSetLobbyNickname& from); + + inline ResponseSetLobbyNickname& operator=(const ResponseSetLobbyNickname& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseSetLobbyNickname& default_instance(); + + void Swap(ResponseSetLobbyNickname* other); + + // implements Message ---------------------------------------------- + + ResponseSetLobbyNickname* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseSetLobbyNickname& from); + void MergeFrom(const ResponseSetLobbyNickname& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ResponseSetLobbyNickname) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ResponseSetLobbyNickname* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestRegisterEvents : public ::google::protobuf::Message { + public: + RequestRegisterEvents(); + virtual ~RequestRegisterEvents(); + + RequestRegisterEvents(const RequestRegisterEvents& from); + + inline RequestRegisterEvents& operator=(const RequestRegisterEvents& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestRegisterEvents& default_instance(); + + void Swap(RequestRegisterEvents* other); + + // implements Message ---------------------------------------------- + + RequestRegisterEvents* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestRegisterEvents& from); + void MergeFrom(const RequestRegisterEvents& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestRegisterEvents_RegisterAction RegisterAction; + static const RegisterAction REGISTER = RequestRegisterEvents_RegisterAction_REGISTER; + static const RegisterAction DEREGISTER = RequestRegisterEvents_RegisterAction_DEREGISTER; + static inline bool RegisterAction_IsValid(int value) { + return RequestRegisterEvents_RegisterAction_IsValid(value); + } + static const RegisterAction RegisterAction_MIN = + RequestRegisterEvents_RegisterAction_RegisterAction_MIN; + static const RegisterAction RegisterAction_MAX = + RequestRegisterEvents_RegisterAction_RegisterAction_MAX; + static const int RegisterAction_ARRAYSIZE = + RequestRegisterEvents_RegisterAction_RegisterAction_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + RegisterAction_descriptor() { + return RequestRegisterEvents_RegisterAction_descriptor(); + } + static inline const ::std::string& RegisterAction_Name(RegisterAction value) { + return RequestRegisterEvents_RegisterAction_Name(value); + } + static inline bool RegisterAction_Parse(const ::std::string& name, + RegisterAction* value) { + return RequestRegisterEvents_RegisterAction_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.RequestRegisterEvents.RegisterAction action = 1; + inline bool has_action() const; + inline void clear_action(); + static const int kActionFieldNumber = 1; + inline ::rsctrl::chat::RequestRegisterEvents_RegisterAction action() const; + inline void set_action(::rsctrl::chat::RequestRegisterEvents_RegisterAction value); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.RequestRegisterEvents) + private: + inline void set_has_action(); + inline void clear_has_action(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + int action_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static RequestRegisterEvents* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseRegisterEvents : public ::google::protobuf::Message { + public: + ResponseRegisterEvents(); + virtual ~ResponseRegisterEvents(); + + ResponseRegisterEvents(const ResponseRegisterEvents& from); + + inline ResponseRegisterEvents& operator=(const ResponseRegisterEvents& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseRegisterEvents& default_instance(); + + void Swap(ResponseRegisterEvents* other); + + // implements Message ---------------------------------------------- + + ResponseRegisterEvents* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseRegisterEvents& from); + void MergeFrom(const ResponseRegisterEvents& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ResponseRegisterEvents) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ResponseRegisterEvents* default_instance_; +}; +// ------------------------------------------------------------------- + +class EventLobbyInvite : public ::google::protobuf::Message { + public: + EventLobbyInvite(); + virtual ~EventLobbyInvite(); + + EventLobbyInvite(const EventLobbyInvite& from); + + inline EventLobbyInvite& operator=(const EventLobbyInvite& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EventLobbyInvite& default_instance(); + + void Swap(EventLobbyInvite* other); + + // implements Message ---------------------------------------------- + + EventLobbyInvite* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EventLobbyInvite& from); + void MergeFrom(const EventLobbyInvite& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.ChatLobbyInfo lobby = 1; + inline bool has_lobby() const; + inline void clear_lobby(); + static const int kLobbyFieldNumber = 1; + inline const ::rsctrl::chat::ChatLobbyInfo& lobby() const; + inline ::rsctrl::chat::ChatLobbyInfo* mutable_lobby(); + inline ::rsctrl::chat::ChatLobbyInfo* release_lobby(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.EventLobbyInvite) + private: + inline void set_has_lobby(); + inline void clear_has_lobby(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::chat::ChatLobbyInfo* lobby_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static EventLobbyInvite* default_instance_; +}; +// ------------------------------------------------------------------- + +class EventChatMessage : public ::google::protobuf::Message { + public: + EventChatMessage(); + virtual ~EventChatMessage(); + + EventChatMessage(const EventChatMessage& from); + + inline EventChatMessage& operator=(const EventChatMessage& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EventChatMessage& default_instance(); + + void Swap(EventChatMessage* other); + + // implements Message ---------------------------------------------- + + EventChatMessage* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EventChatMessage& from); + void MergeFrom(const EventChatMessage& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.ChatMessage msg = 1; + inline bool has_msg() const; + inline void clear_msg(); + static const int kMsgFieldNumber = 1; + inline const ::rsctrl::chat::ChatMessage& msg() const; + inline ::rsctrl::chat::ChatMessage* mutable_msg(); + inline ::rsctrl::chat::ChatMessage* release_msg(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.EventChatMessage) + private: + inline void set_has_msg(); + inline void clear_has_msg(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::chat::ChatMessage* msg_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static EventChatMessage* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestSendMessage : public ::google::protobuf::Message { + public: + RequestSendMessage(); + virtual ~RequestSendMessage(); + + RequestSendMessage(const RequestSendMessage& from); + + inline RequestSendMessage& operator=(const RequestSendMessage& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestSendMessage& default_instance(); + + void Swap(RequestSendMessage* other); + + // implements Message ---------------------------------------------- + + RequestSendMessage* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestSendMessage& from); + void MergeFrom(const RequestSendMessage& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.chat.ChatMessage msg = 1; + inline bool has_msg() const; + inline void clear_msg(); + static const int kMsgFieldNumber = 1; + inline const ::rsctrl::chat::ChatMessage& msg() const; + inline ::rsctrl::chat::ChatMessage* mutable_msg(); + inline ::rsctrl::chat::ChatMessage* release_msg(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.RequestSendMessage) + private: + inline void set_has_msg(); + inline void clear_has_msg(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::chat::ChatMessage* msg_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static RequestSendMessage* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseSendMessage : public ::google::protobuf::Message { + public: + ResponseSendMessage(); + virtual ~ResponseSendMessage(); + + ResponseSendMessage(const ResponseSendMessage& from); + + inline ResponseSendMessage& operator=(const ResponseSendMessage& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseSendMessage& default_instance(); + + void Swap(ResponseSendMessage* other); + + // implements Message ---------------------------------------------- + + ResponseSendMessage* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseSendMessage& from); + void MergeFrom(const ResponseSendMessage& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // @@protoc_insertion_point(class_scope:rsctrl.chat.ResponseSendMessage) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_chat_2eproto(); + friend void protobuf_AssignDesc_chat_2eproto(); + friend void protobuf_ShutdownFile_chat_2eproto(); + + void InitAsDefaultInstance(); + static ResponseSendMessage* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// ChatLobbyInfo + +// required string lobby_id = 1; +inline bool ChatLobbyInfo::has_lobby_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ChatLobbyInfo::set_has_lobby_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void ChatLobbyInfo::clear_has_lobby_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ChatLobbyInfo::clear_lobby_id() { + if (lobby_id_ != &::google::protobuf::internal::kEmptyString) { + lobby_id_->clear(); + } + clear_has_lobby_id(); +} +inline const ::std::string& ChatLobbyInfo::lobby_id() const { + return *lobby_id_; +} +inline void ChatLobbyInfo::set_lobby_id(const ::std::string& value) { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + lobby_id_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_id(const char* value) { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + lobby_id_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_id(const char* value, size_t size) { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + lobby_id_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatLobbyInfo::mutable_lobby_id() { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + return lobby_id_; +} +inline ::std::string* ChatLobbyInfo::release_lobby_id() { + clear_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_id_; + lobby_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string lobby_topic = 2; +inline bool ChatLobbyInfo::has_lobby_topic() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void ChatLobbyInfo::set_has_lobby_topic() { + _has_bits_[0] |= 0x00000002u; +} +inline void ChatLobbyInfo::clear_has_lobby_topic() { + _has_bits_[0] &= ~0x00000002u; +} +inline void ChatLobbyInfo::clear_lobby_topic() { + if (lobby_topic_ != &::google::protobuf::internal::kEmptyString) { + lobby_topic_->clear(); + } + clear_has_lobby_topic(); +} +inline const ::std::string& ChatLobbyInfo::lobby_topic() const { + return *lobby_topic_; +} +inline void ChatLobbyInfo::set_lobby_topic(const ::std::string& value) { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + lobby_topic_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_topic(const char* value) { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + lobby_topic_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_topic(const char* value, size_t size) { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + lobby_topic_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatLobbyInfo::mutable_lobby_topic() { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + return lobby_topic_; +} +inline ::std::string* ChatLobbyInfo::release_lobby_topic() { + clear_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_topic_; + lobby_topic_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string lobby_name = 3; +inline bool ChatLobbyInfo::has_lobby_name() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ChatLobbyInfo::set_has_lobby_name() { + _has_bits_[0] |= 0x00000004u; +} +inline void ChatLobbyInfo::clear_has_lobby_name() { + _has_bits_[0] &= ~0x00000004u; +} +inline void ChatLobbyInfo::clear_lobby_name() { + if (lobby_name_ != &::google::protobuf::internal::kEmptyString) { + lobby_name_->clear(); + } + clear_has_lobby_name(); +} +inline const ::std::string& ChatLobbyInfo::lobby_name() const { + return *lobby_name_; +} +inline void ChatLobbyInfo::set_lobby_name(const ::std::string& value) { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + lobby_name_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_name(const char* value) { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + lobby_name_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_name(const char* value, size_t size) { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + lobby_name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatLobbyInfo::mutable_lobby_name() { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + return lobby_name_; +} +inline ::std::string* ChatLobbyInfo::release_lobby_name() { + clear_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_name_; + lobby_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string lobby_nickname = 4; +inline bool ChatLobbyInfo::has_lobby_nickname() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void ChatLobbyInfo::set_has_lobby_nickname() { + _has_bits_[0] |= 0x00000008u; +} +inline void ChatLobbyInfo::clear_has_lobby_nickname() { + _has_bits_[0] &= ~0x00000008u; +} +inline void ChatLobbyInfo::clear_lobby_nickname() { + if (lobby_nickname_ != &::google::protobuf::internal::kEmptyString) { + lobby_nickname_->clear(); + } + clear_has_lobby_nickname(); +} +inline const ::std::string& ChatLobbyInfo::lobby_nickname() const { + return *lobby_nickname_; +} +inline void ChatLobbyInfo::set_lobby_nickname(const ::std::string& value) { + set_has_lobby_nickname(); + if (lobby_nickname_ == &::google::protobuf::internal::kEmptyString) { + lobby_nickname_ = new ::std::string; + } + lobby_nickname_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_nickname(const char* value) { + set_has_lobby_nickname(); + if (lobby_nickname_ == &::google::protobuf::internal::kEmptyString) { + lobby_nickname_ = new ::std::string; + } + lobby_nickname_->assign(value); +} +inline void ChatLobbyInfo::set_lobby_nickname(const char* value, size_t size) { + set_has_lobby_nickname(); + if (lobby_nickname_ == &::google::protobuf::internal::kEmptyString) { + lobby_nickname_ = new ::std::string; + } + lobby_nickname_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatLobbyInfo::mutable_lobby_nickname() { + set_has_lobby_nickname(); + if (lobby_nickname_ == &::google::protobuf::internal::kEmptyString) { + lobby_nickname_ = new ::std::string; + } + return lobby_nickname_; +} +inline ::std::string* ChatLobbyInfo::release_lobby_nickname() { + clear_has_lobby_nickname(); + if (lobby_nickname_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_nickname_; + lobby_nickname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 5; +inline bool ChatLobbyInfo::has_privacy_level() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void ChatLobbyInfo::set_has_privacy_level() { + _has_bits_[0] |= 0x00000010u; +} +inline void ChatLobbyInfo::clear_has_privacy_level() { + _has_bits_[0] &= ~0x00000010u; +} +inline void ChatLobbyInfo::clear_privacy_level() { + privacy_level_ = 1; + clear_has_privacy_level(); +} +inline rsctrl::chat::LobbyPrivacyLevel ChatLobbyInfo::privacy_level() const { + return static_cast< rsctrl::chat::LobbyPrivacyLevel >(privacy_level_); +} +inline void ChatLobbyInfo::set_privacy_level(rsctrl::chat::LobbyPrivacyLevel value) { + GOOGLE_DCHECK(rsctrl::chat::LobbyPrivacyLevel_IsValid(value)); + set_has_privacy_level(); + privacy_level_ = value; +} + +// required .rsctrl.chat.ChatLobbyInfo.LobbyState lobby_state = 6; +inline bool ChatLobbyInfo::has_lobby_state() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void ChatLobbyInfo::set_has_lobby_state() { + _has_bits_[0] |= 0x00000020u; +} +inline void ChatLobbyInfo::clear_has_lobby_state() { + _has_bits_[0] &= ~0x00000020u; +} +inline void ChatLobbyInfo::clear_lobby_state() { + lobby_state_ = 1; + clear_has_lobby_state(); +} +inline ::rsctrl::chat::ChatLobbyInfo_LobbyState ChatLobbyInfo::lobby_state() const { + return static_cast< ::rsctrl::chat::ChatLobbyInfo_LobbyState >(lobby_state_); +} +inline void ChatLobbyInfo::set_lobby_state(::rsctrl::chat::ChatLobbyInfo_LobbyState value) { + GOOGLE_DCHECK(::rsctrl::chat::ChatLobbyInfo_LobbyState_IsValid(value)); + set_has_lobby_state(); + lobby_state_ = value; +} + +// required uint32 no_peers = 7; +inline bool ChatLobbyInfo::has_no_peers() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void ChatLobbyInfo::set_has_no_peers() { + _has_bits_[0] |= 0x00000040u; +} +inline void ChatLobbyInfo::clear_has_no_peers() { + _has_bits_[0] &= ~0x00000040u; +} +inline void ChatLobbyInfo::clear_no_peers() { + no_peers_ = 0u; + clear_has_no_peers(); +} +inline ::google::protobuf::uint32 ChatLobbyInfo::no_peers() const { + return no_peers_; +} +inline void ChatLobbyInfo::set_no_peers(::google::protobuf::uint32 value) { + set_has_no_peers(); + no_peers_ = value; +} + +// required uint32 last_report_time = 8; +inline bool ChatLobbyInfo::has_last_report_time() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void ChatLobbyInfo::set_has_last_report_time() { + _has_bits_[0] |= 0x00000080u; +} +inline void ChatLobbyInfo::clear_has_last_report_time() { + _has_bits_[0] &= ~0x00000080u; +} +inline void ChatLobbyInfo::clear_last_report_time() { + last_report_time_ = 0u; + clear_has_last_report_time(); +} +inline ::google::protobuf::uint32 ChatLobbyInfo::last_report_time() const { + return last_report_time_; +} +inline void ChatLobbyInfo::set_last_report_time(::google::protobuf::uint32 value) { + set_has_last_report_time(); + last_report_time_ = value; +} + +// required uint32 last_activity = 9; +inline bool ChatLobbyInfo::has_last_activity() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void ChatLobbyInfo::set_has_last_activity() { + _has_bits_[0] |= 0x00000100u; +} +inline void ChatLobbyInfo::clear_has_last_activity() { + _has_bits_[0] &= ~0x00000100u; +} +inline void ChatLobbyInfo::clear_last_activity() { + last_activity_ = 0u; + clear_has_last_activity(); +} +inline ::google::protobuf::uint32 ChatLobbyInfo::last_activity() const { + return last_activity_; +} +inline void ChatLobbyInfo::set_last_activity(::google::protobuf::uint32 value) { + set_has_last_activity(); + last_activity_ = value; +} + +// repeated string participating_friends = 10; +inline int ChatLobbyInfo::participating_friends_size() const { + return participating_friends_.size(); +} +inline void ChatLobbyInfo::clear_participating_friends() { + participating_friends_.Clear(); +} +inline const ::std::string& ChatLobbyInfo::participating_friends(int index) const { + return participating_friends_.Get(index); +} +inline ::std::string* ChatLobbyInfo::mutable_participating_friends(int index) { + return participating_friends_.Mutable(index); +} +inline void ChatLobbyInfo::set_participating_friends(int index, const ::std::string& value) { + participating_friends_.Mutable(index)->assign(value); +} +inline void ChatLobbyInfo::set_participating_friends(int index, const char* value) { + participating_friends_.Mutable(index)->assign(value); +} +inline void ChatLobbyInfo::set_participating_friends(int index, const char* value, size_t size) { + participating_friends_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* ChatLobbyInfo::add_participating_friends() { + return participating_friends_.Add(); +} +inline void ChatLobbyInfo::add_participating_friends(const ::std::string& value) { + participating_friends_.Add()->assign(value); +} +inline void ChatLobbyInfo::add_participating_friends(const char* value) { + participating_friends_.Add()->assign(value); +} +inline void ChatLobbyInfo::add_participating_friends(const char* value, size_t size) { + participating_friends_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +ChatLobbyInfo::participating_friends() const { + return participating_friends_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +ChatLobbyInfo::mutable_participating_friends() { + return &participating_friends_; +} + +// repeated string nicknames = 11; +inline int ChatLobbyInfo::nicknames_size() const { + return nicknames_.size(); +} +inline void ChatLobbyInfo::clear_nicknames() { + nicknames_.Clear(); +} +inline const ::std::string& ChatLobbyInfo::nicknames(int index) const { + return nicknames_.Get(index); +} +inline ::std::string* ChatLobbyInfo::mutable_nicknames(int index) { + return nicknames_.Mutable(index); +} +inline void ChatLobbyInfo::set_nicknames(int index, const ::std::string& value) { + nicknames_.Mutable(index)->assign(value); +} +inline void ChatLobbyInfo::set_nicknames(int index, const char* value) { + nicknames_.Mutable(index)->assign(value); +} +inline void ChatLobbyInfo::set_nicknames(int index, const char* value, size_t size) { + nicknames_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* ChatLobbyInfo::add_nicknames() { + return nicknames_.Add(); +} +inline void ChatLobbyInfo::add_nicknames(const ::std::string& value) { + nicknames_.Add()->assign(value); +} +inline void ChatLobbyInfo::add_nicknames(const char* value) { + nicknames_.Add()->assign(value); +} +inline void ChatLobbyInfo::add_nicknames(const char* value, size_t size) { + nicknames_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +ChatLobbyInfo::nicknames() const { + return nicknames_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +ChatLobbyInfo::mutable_nicknames() { + return &nicknames_; +} + +// ------------------------------------------------------------------- + +// ChatId + +// required .rsctrl.chat.ChatType chat_type = 1; +inline bool ChatId::has_chat_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ChatId::set_has_chat_type() { + _has_bits_[0] |= 0x00000001u; +} +inline void ChatId::clear_has_chat_type() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ChatId::clear_chat_type() { + chat_type_ = 1; + clear_has_chat_type(); +} +inline rsctrl::chat::ChatType ChatId::chat_type() const { + return static_cast< rsctrl::chat::ChatType >(chat_type_); +} +inline void ChatId::set_chat_type(rsctrl::chat::ChatType value) { + GOOGLE_DCHECK(rsctrl::chat::ChatType_IsValid(value)); + set_has_chat_type(); + chat_type_ = value; +} + +// required string chat_id = 2; +inline bool ChatId::has_chat_id() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void ChatId::set_has_chat_id() { + _has_bits_[0] |= 0x00000002u; +} +inline void ChatId::clear_has_chat_id() { + _has_bits_[0] &= ~0x00000002u; +} +inline void ChatId::clear_chat_id() { + if (chat_id_ != &::google::protobuf::internal::kEmptyString) { + chat_id_->clear(); + } + clear_has_chat_id(); +} +inline const ::std::string& ChatId::chat_id() const { + return *chat_id_; +} +inline void ChatId::set_chat_id(const ::std::string& value) { + set_has_chat_id(); + if (chat_id_ == &::google::protobuf::internal::kEmptyString) { + chat_id_ = new ::std::string; + } + chat_id_->assign(value); +} +inline void ChatId::set_chat_id(const char* value) { + set_has_chat_id(); + if (chat_id_ == &::google::protobuf::internal::kEmptyString) { + chat_id_ = new ::std::string; + } + chat_id_->assign(value); +} +inline void ChatId::set_chat_id(const char* value, size_t size) { + set_has_chat_id(); + if (chat_id_ == &::google::protobuf::internal::kEmptyString) { + chat_id_ = new ::std::string; + } + chat_id_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatId::mutable_chat_id() { + set_has_chat_id(); + if (chat_id_ == &::google::protobuf::internal::kEmptyString) { + chat_id_ = new ::std::string; + } + return chat_id_; +} +inline ::std::string* ChatId::release_chat_id() { + clear_has_chat_id(); + if (chat_id_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = chat_id_; + chat_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// ChatMessage + +// required .rsctrl.chat.ChatId id = 1; +inline bool ChatMessage::has_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ChatMessage::set_has_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void ChatMessage::clear_has_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ChatMessage::clear_id() { + if (id_ != NULL) id_->::rsctrl::chat::ChatId::Clear(); + clear_has_id(); +} +inline const ::rsctrl::chat::ChatId& ChatMessage::id() const { + return id_ != NULL ? *id_ : *default_instance_->id_; +} +inline ::rsctrl::chat::ChatId* ChatMessage::mutable_id() { + set_has_id(); + if (id_ == NULL) id_ = new ::rsctrl::chat::ChatId; + return id_; +} +inline ::rsctrl::chat::ChatId* ChatMessage::release_id() { + clear_has_id(); + ::rsctrl::chat::ChatId* temp = id_; + id_ = NULL; + return temp; +} + +// required string msg = 2; +inline bool ChatMessage::has_msg() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void ChatMessage::set_has_msg() { + _has_bits_[0] |= 0x00000002u; +} +inline void ChatMessage::clear_has_msg() { + _has_bits_[0] &= ~0x00000002u; +} +inline void ChatMessage::clear_msg() { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + msg_->clear(); + } + clear_has_msg(); +} +inline const ::std::string& ChatMessage::msg() const { + return *msg_; +} +inline void ChatMessage::set_msg(const ::std::string& value) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(value); +} +inline void ChatMessage::set_msg(const char* value) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(value); +} +inline void ChatMessage::set_msg(const char* value, size_t size) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatMessage::mutable_msg() { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + return msg_; +} +inline ::std::string* ChatMessage::release_msg() { + clear_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = msg_; + msg_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional string peer_nickname = 3; +inline bool ChatMessage::has_peer_nickname() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ChatMessage::set_has_peer_nickname() { + _has_bits_[0] |= 0x00000004u; +} +inline void ChatMessage::clear_has_peer_nickname() { + _has_bits_[0] &= ~0x00000004u; +} +inline void ChatMessage::clear_peer_nickname() { + if (peer_nickname_ != &::google::protobuf::internal::kEmptyString) { + peer_nickname_->clear(); + } + clear_has_peer_nickname(); +} +inline const ::std::string& ChatMessage::peer_nickname() const { + return *peer_nickname_; +} +inline void ChatMessage::set_peer_nickname(const ::std::string& value) { + set_has_peer_nickname(); + if (peer_nickname_ == &::google::protobuf::internal::kEmptyString) { + peer_nickname_ = new ::std::string; + } + peer_nickname_->assign(value); +} +inline void ChatMessage::set_peer_nickname(const char* value) { + set_has_peer_nickname(); + if (peer_nickname_ == &::google::protobuf::internal::kEmptyString) { + peer_nickname_ = new ::std::string; + } + peer_nickname_->assign(value); +} +inline void ChatMessage::set_peer_nickname(const char* value, size_t size) { + set_has_peer_nickname(); + if (peer_nickname_ == &::google::protobuf::internal::kEmptyString) { + peer_nickname_ = new ::std::string; + } + peer_nickname_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ChatMessage::mutable_peer_nickname() { + set_has_peer_nickname(); + if (peer_nickname_ == &::google::protobuf::internal::kEmptyString) { + peer_nickname_ = new ::std::string; + } + return peer_nickname_; +} +inline ::std::string* ChatMessage::release_peer_nickname() { + clear_has_peer_nickname(); + if (peer_nickname_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = peer_nickname_; + peer_nickname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional uint32 chat_flags = 4; +inline bool ChatMessage::has_chat_flags() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void ChatMessage::set_has_chat_flags() { + _has_bits_[0] |= 0x00000008u; +} +inline void ChatMessage::clear_has_chat_flags() { + _has_bits_[0] &= ~0x00000008u; +} +inline void ChatMessage::clear_chat_flags() { + chat_flags_ = 0u; + clear_has_chat_flags(); +} +inline ::google::protobuf::uint32 ChatMessage::chat_flags() const { + return chat_flags_; +} +inline void ChatMessage::set_chat_flags(::google::protobuf::uint32 value) { + set_has_chat_flags(); + chat_flags_ = value; +} + +// optional uint32 send_time = 5; +inline bool ChatMessage::has_send_time() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void ChatMessage::set_has_send_time() { + _has_bits_[0] |= 0x00000010u; +} +inline void ChatMessage::clear_has_send_time() { + _has_bits_[0] &= ~0x00000010u; +} +inline void ChatMessage::clear_send_time() { + send_time_ = 0u; + clear_has_send_time(); +} +inline ::google::protobuf::uint32 ChatMessage::send_time() const { + return send_time_; +} +inline void ChatMessage::set_send_time(::google::protobuf::uint32 value) { + set_has_send_time(); + send_time_ = value; +} + +// optional uint32 recv_time = 6; +inline bool ChatMessage::has_recv_time() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void ChatMessage::set_has_recv_time() { + _has_bits_[0] |= 0x00000020u; +} +inline void ChatMessage::clear_has_recv_time() { + _has_bits_[0] &= ~0x00000020u; +} +inline void ChatMessage::clear_recv_time() { + recv_time_ = 0u; + clear_has_recv_time(); +} +inline ::google::protobuf::uint32 ChatMessage::recv_time() const { + return recv_time_; +} +inline void ChatMessage::set_recv_time(::google::protobuf::uint32 value) { + set_has_recv_time(); + recv_time_ = value; +} + +// ------------------------------------------------------------------- + +// ResponseChatLobbies + +// required .rsctrl.core.Status status = 1; +inline bool ResponseChatLobbies::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseChatLobbies::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseChatLobbies::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseChatLobbies::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseChatLobbies::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseChatLobbies::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseChatLobbies::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated .rsctrl.chat.ChatLobbyInfo lobbies = 2; +inline int ResponseChatLobbies::lobbies_size() const { + return lobbies_.size(); +} +inline void ResponseChatLobbies::clear_lobbies() { + lobbies_.Clear(); +} +inline const ::rsctrl::chat::ChatLobbyInfo& ResponseChatLobbies::lobbies(int index) const { + return lobbies_.Get(index); +} +inline ::rsctrl::chat::ChatLobbyInfo* ResponseChatLobbies::mutable_lobbies(int index) { + return lobbies_.Mutable(index); +} +inline ::rsctrl::chat::ChatLobbyInfo* ResponseChatLobbies::add_lobbies() { + return lobbies_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::chat::ChatLobbyInfo >& +ResponseChatLobbies::lobbies() const { + return lobbies_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::chat::ChatLobbyInfo >* +ResponseChatLobbies::mutable_lobbies() { + return &lobbies_; +} + +// ------------------------------------------------------------------- + +// RequestChatLobbies + +// required .rsctrl.chat.RequestChatLobbies.LobbySet lobby_set = 1; +inline bool RequestChatLobbies::has_lobby_set() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestChatLobbies::set_has_lobby_set() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestChatLobbies::clear_has_lobby_set() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestChatLobbies::clear_lobby_set() { + lobby_set_ = 1; + clear_has_lobby_set(); +} +inline ::rsctrl::chat::RequestChatLobbies_LobbySet RequestChatLobbies::lobby_set() const { + return static_cast< ::rsctrl::chat::RequestChatLobbies_LobbySet >(lobby_set_); +} +inline void RequestChatLobbies::set_lobby_set(::rsctrl::chat::RequestChatLobbies_LobbySet value) { + GOOGLE_DCHECK(::rsctrl::chat::RequestChatLobbies_LobbySet_IsValid(value)); + set_has_lobby_set(); + lobby_set_ = value; +} + +// ------------------------------------------------------------------- + +// RequestCreateLobby + +// required string lobby_name = 1; +inline bool RequestCreateLobby::has_lobby_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestCreateLobby::set_has_lobby_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestCreateLobby::clear_has_lobby_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestCreateLobby::clear_lobby_name() { + if (lobby_name_ != &::google::protobuf::internal::kEmptyString) { + lobby_name_->clear(); + } + clear_has_lobby_name(); +} +inline const ::std::string& RequestCreateLobby::lobby_name() const { + return *lobby_name_; +} +inline void RequestCreateLobby::set_lobby_name(const ::std::string& value) { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + lobby_name_->assign(value); +} +inline void RequestCreateLobby::set_lobby_name(const char* value) { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + lobby_name_->assign(value); +} +inline void RequestCreateLobby::set_lobby_name(const char* value, size_t size) { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + lobby_name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RequestCreateLobby::mutable_lobby_name() { + set_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + lobby_name_ = new ::std::string; + } + return lobby_name_; +} +inline ::std::string* RequestCreateLobby::release_lobby_name() { + clear_has_lobby_name(); + if (lobby_name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_name_; + lobby_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string lobby_topic = 2; +inline bool RequestCreateLobby::has_lobby_topic() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RequestCreateLobby::set_has_lobby_topic() { + _has_bits_[0] |= 0x00000002u; +} +inline void RequestCreateLobby::clear_has_lobby_topic() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RequestCreateLobby::clear_lobby_topic() { + if (lobby_topic_ != &::google::protobuf::internal::kEmptyString) { + lobby_topic_->clear(); + } + clear_has_lobby_topic(); +} +inline const ::std::string& RequestCreateLobby::lobby_topic() const { + return *lobby_topic_; +} +inline void RequestCreateLobby::set_lobby_topic(const ::std::string& value) { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + lobby_topic_->assign(value); +} +inline void RequestCreateLobby::set_lobby_topic(const char* value) { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + lobby_topic_->assign(value); +} +inline void RequestCreateLobby::set_lobby_topic(const char* value, size_t size) { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + lobby_topic_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RequestCreateLobby::mutable_lobby_topic() { + set_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + lobby_topic_ = new ::std::string; + } + return lobby_topic_; +} +inline ::std::string* RequestCreateLobby::release_lobby_topic() { + clear_has_lobby_topic(); + if (lobby_topic_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_topic_; + lobby_topic_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required .rsctrl.chat.LobbyPrivacyLevel privacy_level = 4; +inline bool RequestCreateLobby::has_privacy_level() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void RequestCreateLobby::set_has_privacy_level() { + _has_bits_[0] |= 0x00000004u; +} +inline void RequestCreateLobby::clear_has_privacy_level() { + _has_bits_[0] &= ~0x00000004u; +} +inline void RequestCreateLobby::clear_privacy_level() { + privacy_level_ = 1; + clear_has_privacy_level(); +} +inline rsctrl::chat::LobbyPrivacyLevel RequestCreateLobby::privacy_level() const { + return static_cast< rsctrl::chat::LobbyPrivacyLevel >(privacy_level_); +} +inline void RequestCreateLobby::set_privacy_level(rsctrl::chat::LobbyPrivacyLevel value) { + GOOGLE_DCHECK(rsctrl::chat::LobbyPrivacyLevel_IsValid(value)); + set_has_privacy_level(); + privacy_level_ = value; +} + +// repeated string invited_friends = 3; +inline int RequestCreateLobby::invited_friends_size() const { + return invited_friends_.size(); +} +inline void RequestCreateLobby::clear_invited_friends() { + invited_friends_.Clear(); +} +inline const ::std::string& RequestCreateLobby::invited_friends(int index) const { + return invited_friends_.Get(index); +} +inline ::std::string* RequestCreateLobby::mutable_invited_friends(int index) { + return invited_friends_.Mutable(index); +} +inline void RequestCreateLobby::set_invited_friends(int index, const ::std::string& value) { + invited_friends_.Mutable(index)->assign(value); +} +inline void RequestCreateLobby::set_invited_friends(int index, const char* value) { + invited_friends_.Mutable(index)->assign(value); +} +inline void RequestCreateLobby::set_invited_friends(int index, const char* value, size_t size) { + invited_friends_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* RequestCreateLobby::add_invited_friends() { + return invited_friends_.Add(); +} +inline void RequestCreateLobby::add_invited_friends(const ::std::string& value) { + invited_friends_.Add()->assign(value); +} +inline void RequestCreateLobby::add_invited_friends(const char* value) { + invited_friends_.Add()->assign(value); +} +inline void RequestCreateLobby::add_invited_friends(const char* value, size_t size) { + invited_friends_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +RequestCreateLobby::invited_friends() const { + return invited_friends_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +RequestCreateLobby::mutable_invited_friends() { + return &invited_friends_; +} + +// ------------------------------------------------------------------- + +// RequestJoinOrLeaveLobby + +// required string lobby_id = 1; +inline bool RequestJoinOrLeaveLobby::has_lobby_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestJoinOrLeaveLobby::set_has_lobby_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestJoinOrLeaveLobby::clear_has_lobby_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestJoinOrLeaveLobby::clear_lobby_id() { + if (lobby_id_ != &::google::protobuf::internal::kEmptyString) { + lobby_id_->clear(); + } + clear_has_lobby_id(); +} +inline const ::std::string& RequestJoinOrLeaveLobby::lobby_id() const { + return *lobby_id_; +} +inline void RequestJoinOrLeaveLobby::set_lobby_id(const ::std::string& value) { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + lobby_id_->assign(value); +} +inline void RequestJoinOrLeaveLobby::set_lobby_id(const char* value) { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + lobby_id_->assign(value); +} +inline void RequestJoinOrLeaveLobby::set_lobby_id(const char* value, size_t size) { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + lobby_id_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RequestJoinOrLeaveLobby::mutable_lobby_id() { + set_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + lobby_id_ = new ::std::string; + } + return lobby_id_; +} +inline ::std::string* RequestJoinOrLeaveLobby::release_lobby_id() { + clear_has_lobby_id(); + if (lobby_id_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = lobby_id_; + lobby_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required .rsctrl.chat.RequestJoinOrLeaveLobby.LobbyAction action = 2; +inline bool RequestJoinOrLeaveLobby::has_action() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RequestJoinOrLeaveLobby::set_has_action() { + _has_bits_[0] |= 0x00000002u; +} +inline void RequestJoinOrLeaveLobby::clear_has_action() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RequestJoinOrLeaveLobby::clear_action() { + action_ = 1; + clear_has_action(); +} +inline ::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction RequestJoinOrLeaveLobby::action() const { + return static_cast< ::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction >(action_); +} +inline void RequestJoinOrLeaveLobby::set_action(::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction value) { + GOOGLE_DCHECK(::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction_IsValid(value)); + set_has_action(); + action_ = value; +} + +// ------------------------------------------------------------------- + +// RequestSetLobbyNickname + +// required string nickname = 1; +inline bool RequestSetLobbyNickname::has_nickname() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestSetLobbyNickname::set_has_nickname() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestSetLobbyNickname::clear_has_nickname() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestSetLobbyNickname::clear_nickname() { + if (nickname_ != &::google::protobuf::internal::kEmptyString) { + nickname_->clear(); + } + clear_has_nickname(); +} +inline const ::std::string& RequestSetLobbyNickname::nickname() const { + return *nickname_; +} +inline void RequestSetLobbyNickname::set_nickname(const ::std::string& value) { + set_has_nickname(); + if (nickname_ == &::google::protobuf::internal::kEmptyString) { + nickname_ = new ::std::string; + } + nickname_->assign(value); +} +inline void RequestSetLobbyNickname::set_nickname(const char* value) { + set_has_nickname(); + if (nickname_ == &::google::protobuf::internal::kEmptyString) { + nickname_ = new ::std::string; + } + nickname_->assign(value); +} +inline void RequestSetLobbyNickname::set_nickname(const char* value, size_t size) { + set_has_nickname(); + if (nickname_ == &::google::protobuf::internal::kEmptyString) { + nickname_ = new ::std::string; + } + nickname_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RequestSetLobbyNickname::mutable_nickname() { + set_has_nickname(); + if (nickname_ == &::google::protobuf::internal::kEmptyString) { + nickname_ = new ::std::string; + } + return nickname_; +} +inline ::std::string* RequestSetLobbyNickname::release_nickname() { + clear_has_nickname(); + if (nickname_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = nickname_; + nickname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// repeated string lobby_ids = 2; +inline int RequestSetLobbyNickname::lobby_ids_size() const { + return lobby_ids_.size(); +} +inline void RequestSetLobbyNickname::clear_lobby_ids() { + lobby_ids_.Clear(); +} +inline const ::std::string& RequestSetLobbyNickname::lobby_ids(int index) const { + return lobby_ids_.Get(index); +} +inline ::std::string* RequestSetLobbyNickname::mutable_lobby_ids(int index) { + return lobby_ids_.Mutable(index); +} +inline void RequestSetLobbyNickname::set_lobby_ids(int index, const ::std::string& value) { + lobby_ids_.Mutable(index)->assign(value); +} +inline void RequestSetLobbyNickname::set_lobby_ids(int index, const char* value) { + lobby_ids_.Mutable(index)->assign(value); +} +inline void RequestSetLobbyNickname::set_lobby_ids(int index, const char* value, size_t size) { + lobby_ids_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* RequestSetLobbyNickname::add_lobby_ids() { + return lobby_ids_.Add(); +} +inline void RequestSetLobbyNickname::add_lobby_ids(const ::std::string& value) { + lobby_ids_.Add()->assign(value); +} +inline void RequestSetLobbyNickname::add_lobby_ids(const char* value) { + lobby_ids_.Add()->assign(value); +} +inline void RequestSetLobbyNickname::add_lobby_ids(const char* value, size_t size) { + lobby_ids_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +RequestSetLobbyNickname::lobby_ids() const { + return lobby_ids_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +RequestSetLobbyNickname::mutable_lobby_ids() { + return &lobby_ids_; +} + +// ------------------------------------------------------------------- + +// ResponseSetLobbyNickname + +// required .rsctrl.core.Status status = 1; +inline bool ResponseSetLobbyNickname::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseSetLobbyNickname::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseSetLobbyNickname::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseSetLobbyNickname::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseSetLobbyNickname::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseSetLobbyNickname::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseSetLobbyNickname::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// ------------------------------------------------------------------- + +// RequestRegisterEvents + +// required .rsctrl.chat.RequestRegisterEvents.RegisterAction action = 1; +inline bool RequestRegisterEvents::has_action() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestRegisterEvents::set_has_action() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestRegisterEvents::clear_has_action() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestRegisterEvents::clear_action() { + action_ = 1; + clear_has_action(); +} +inline ::rsctrl::chat::RequestRegisterEvents_RegisterAction RequestRegisterEvents::action() const { + return static_cast< ::rsctrl::chat::RequestRegisterEvents_RegisterAction >(action_); +} +inline void RequestRegisterEvents::set_action(::rsctrl::chat::RequestRegisterEvents_RegisterAction value) { + GOOGLE_DCHECK(::rsctrl::chat::RequestRegisterEvents_RegisterAction_IsValid(value)); + set_has_action(); + action_ = value; +} + +// ------------------------------------------------------------------- + +// ResponseRegisterEvents + +// required .rsctrl.core.Status status = 1; +inline bool ResponseRegisterEvents::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseRegisterEvents::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseRegisterEvents::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseRegisterEvents::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseRegisterEvents::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseRegisterEvents::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseRegisterEvents::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// ------------------------------------------------------------------- + +// EventLobbyInvite + +// required .rsctrl.chat.ChatLobbyInfo lobby = 1; +inline bool EventLobbyInvite::has_lobby() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EventLobbyInvite::set_has_lobby() { + _has_bits_[0] |= 0x00000001u; +} +inline void EventLobbyInvite::clear_has_lobby() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EventLobbyInvite::clear_lobby() { + if (lobby_ != NULL) lobby_->::rsctrl::chat::ChatLobbyInfo::Clear(); + clear_has_lobby(); +} +inline const ::rsctrl::chat::ChatLobbyInfo& EventLobbyInvite::lobby() const { + return lobby_ != NULL ? *lobby_ : *default_instance_->lobby_; +} +inline ::rsctrl::chat::ChatLobbyInfo* EventLobbyInvite::mutable_lobby() { + set_has_lobby(); + if (lobby_ == NULL) lobby_ = new ::rsctrl::chat::ChatLobbyInfo; + return lobby_; +} +inline ::rsctrl::chat::ChatLobbyInfo* EventLobbyInvite::release_lobby() { + clear_has_lobby(); + ::rsctrl::chat::ChatLobbyInfo* temp = lobby_; + lobby_ = NULL; + return temp; +} + +// ------------------------------------------------------------------- + +// EventChatMessage + +// required .rsctrl.chat.ChatMessage msg = 1; +inline bool EventChatMessage::has_msg() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EventChatMessage::set_has_msg() { + _has_bits_[0] |= 0x00000001u; +} +inline void EventChatMessage::clear_has_msg() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EventChatMessage::clear_msg() { + if (msg_ != NULL) msg_->::rsctrl::chat::ChatMessage::Clear(); + clear_has_msg(); +} +inline const ::rsctrl::chat::ChatMessage& EventChatMessage::msg() const { + return msg_ != NULL ? *msg_ : *default_instance_->msg_; +} +inline ::rsctrl::chat::ChatMessage* EventChatMessage::mutable_msg() { + set_has_msg(); + if (msg_ == NULL) msg_ = new ::rsctrl::chat::ChatMessage; + return msg_; +} +inline ::rsctrl::chat::ChatMessage* EventChatMessage::release_msg() { + clear_has_msg(); + ::rsctrl::chat::ChatMessage* temp = msg_; + msg_ = NULL; + return temp; +} + +// ------------------------------------------------------------------- + +// RequestSendMessage + +// required .rsctrl.chat.ChatMessage msg = 1; +inline bool RequestSendMessage::has_msg() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestSendMessage::set_has_msg() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestSendMessage::clear_has_msg() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestSendMessage::clear_msg() { + if (msg_ != NULL) msg_->::rsctrl::chat::ChatMessage::Clear(); + clear_has_msg(); +} +inline const ::rsctrl::chat::ChatMessage& RequestSendMessage::msg() const { + return msg_ != NULL ? *msg_ : *default_instance_->msg_; +} +inline ::rsctrl::chat::ChatMessage* RequestSendMessage::mutable_msg() { + set_has_msg(); + if (msg_ == NULL) msg_ = new ::rsctrl::chat::ChatMessage; + return msg_; +} +inline ::rsctrl::chat::ChatMessage* RequestSendMessage::release_msg() { + clear_has_msg(); + ::rsctrl::chat::ChatMessage* temp = msg_; + msg_ = NULL; + return temp; +} + +// ------------------------------------------------------------------- + +// ResponseSendMessage + +// required .rsctrl.core.Status status = 1; +inline bool ResponseSendMessage::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseSendMessage::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseSendMessage::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseSendMessage::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseSendMessage::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseSendMessage::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseSendMessage::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace chat +} // namespace rsctrl + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::chat::ChatLobbyInfo_LobbyState>() { + return ::rsctrl::chat::ChatLobbyInfo_LobbyState_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::chat::RequestChatLobbies_LobbySet>() { + return ::rsctrl::chat::RequestChatLobbies_LobbySet_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction>() { + return ::rsctrl::chat::RequestJoinOrLeaveLobby_LobbyAction_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::chat::RequestRegisterEvents_RegisterAction>() { + return ::rsctrl::chat::RequestRegisterEvents_RegisterAction_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::chat::RequestMsgIds>() { + return rsctrl::chat::RequestMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::chat::ResponseMsgIds>() { + return rsctrl::chat::ResponseMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::chat::LobbyPrivacyLevel>() { + return rsctrl::chat::LobbyPrivacyLevel_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::chat::ChatType>() { + return rsctrl::chat::ChatType_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_chat_2eproto__INCLUDED diff --git a/retroshare-nogui/src/rpc/proto/gencc/core.pb.cc b/retroshare-nogui/src/rpc/proto/gencc/core.pb.cc new file mode 100644 index 000000000..cb1061f88 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/core.pb.cc @@ -0,0 +1,3288 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "core.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace core { + +namespace { + +const ::google::protobuf::Descriptor* Status_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Status_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* Status_StatusCode_descriptor_ = NULL; +const ::google::protobuf::Descriptor* IpAddr_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + IpAddr_reflection_ = NULL; +const ::google::protobuf::Descriptor* Location_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Location_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* Location_StateFlags_descriptor_ = NULL; +const ::google::protobuf::Descriptor* Person_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Person_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* Person_Relationship_descriptor_ = NULL; +const ::google::protobuf::Descriptor* File_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + File_reflection_ = NULL; +const ::google::protobuf::Descriptor* Dir_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Dir_reflection_ = NULL; +const ::google::protobuf::Descriptor* SystemStatus_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SystemStatus_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* SystemStatus_NetCode_descriptor_ = NULL; +const ::google::protobuf::Descriptor* Bandwidth_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + Bandwidth_reflection_ = NULL; +const ::google::protobuf::Descriptor* BandwidthSet_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + BandwidthSet_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* ExtensionId_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* PackageId_descriptor_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_core_2eproto() { + protobuf_AddDesc_core_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "core.proto"); + GOOGLE_CHECK(file != NULL); + Status_descriptor_ = file->message_type(0); + static const int Status_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Status, code_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Status, msg_), + }; + Status_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Status_descriptor_, + Status::default_instance_, + Status_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Status, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Status, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Status)); + Status_StatusCode_descriptor_ = Status_descriptor_->enum_type(0); + IpAddr_descriptor_ = file->message_type(1); + static const int IpAddr_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(IpAddr, addr_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(IpAddr, port_), + }; + IpAddr_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + IpAddr_descriptor_, + IpAddr::default_instance_, + IpAddr_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(IpAddr, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(IpAddr, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(IpAddr)); + Location_descriptor_ = file->message_type(2); + static const int Location_offsets_[5] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, ssl_id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, location_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, localaddr_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, extaddr_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, state_), + }; + Location_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Location_descriptor_, + Location::default_instance_, + Location_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Location, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Location)); + Location_StateFlags_descriptor_ = Location_descriptor_->enum_type(0); + Person_descriptor_ = file->message_type(3); + static const int Person_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, gpg_id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, relation_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, locations_), + }; + Person_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Person_descriptor_, + Person::default_instance_, + Person_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Person)); + Person_Relationship_descriptor_ = Person_descriptor_->enum_type(0); + File_descriptor_ = file->message_type(4); + static const int File_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(File, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(File, hash_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(File, size_), + }; + File_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + File_descriptor_, + File::default_instance_, + File_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(File, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(File, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(File)); + Dir_descriptor_ = file->message_type(5); + static const int Dir_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Dir, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Dir, path_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Dir, subdirs_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Dir, files_), + }; + Dir_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Dir_descriptor_, + Dir::default_instance_, + Dir_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Dir, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Dir, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Dir)); + SystemStatus_descriptor_ = file->message_type(6); + static const int SystemStatus_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SystemStatus, net_status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SystemStatus, msg_), + }; + SystemStatus_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SystemStatus_descriptor_, + SystemStatus::default_instance_, + SystemStatus_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SystemStatus, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SystemStatus, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SystemStatus)); + SystemStatus_NetCode_descriptor_ = SystemStatus_descriptor_->enum_type(0); + Bandwidth_descriptor_ = file->message_type(7); + static const int Bandwidth_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Bandwidth, up_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Bandwidth, down_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Bandwidth, name_), + }; + Bandwidth_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + Bandwidth_descriptor_, + Bandwidth::default_instance_, + Bandwidth_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Bandwidth, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Bandwidth, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(Bandwidth)); + BandwidthSet_descriptor_ = file->message_type(8); + static const int BandwidthSet_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BandwidthSet, bandwidths_), + }; + BandwidthSet_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + BandwidthSet_descriptor_, + BandwidthSet::default_instance_, + BandwidthSet_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BandwidthSet, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BandwidthSet, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(BandwidthSet)); + ExtensionId_descriptor_ = file->enum_type(0); + PackageId_descriptor_ = file->enum_type(1); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_core_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Status_descriptor_, &Status::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + IpAddr_descriptor_, &IpAddr::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Location_descriptor_, &Location::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Person_descriptor_, &Person::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + File_descriptor_, &File::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Dir_descriptor_, &Dir::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SystemStatus_descriptor_, &SystemStatus::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + Bandwidth_descriptor_, &Bandwidth::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + BandwidthSet_descriptor_, &BandwidthSet::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_core_2eproto() { + delete Status::default_instance_; + delete Status_reflection_; + delete IpAddr::default_instance_; + delete IpAddr_reflection_; + delete Location::default_instance_; + delete Location_reflection_; + delete Person::default_instance_; + delete Person_reflection_; + delete File::default_instance_; + delete File_reflection_; + delete Dir::default_instance_; + delete Dir_reflection_; + delete SystemStatus::default_instance_; + delete SystemStatus_reflection_; + delete Bandwidth::default_instance_; + delete Bandwidth_reflection_; + delete BandwidthSet::default_instance_; + delete BandwidthSet_reflection_; +} + +void protobuf_AddDesc_core_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\ncore.proto\022\013rsctrl.core\"\260\001\n\006Status\022,\n\004" + "code\030\001 \002(\0162\036.rsctrl.core.Status.StatusCo" + "de\022\013\n\003msg\030\002 \001(\t\"k\n\nStatusCode\022\n\n\006FAILED\020" + "\000\022\017\n\013NO_IMPL_YET\020\001\022\021\n\rINVALID_QUERY\020\002\022\023\n" + "\017PARTIAL_SUCCESS\020\003\022\013\n\007SUCCESS\020\004\022\013\n\007READM" + "SG\020\005\")\n\006IpAddr\022\016\n\004addr\030\001 \002(\t:\000\022\017\n\004port\030\002" + " \002(\r:\0010\"\303\001\n\010Location\022\016\n\006ssl_id\030\001 \002(\t\022\020\n\010" + "location\030\002 \002(\t\022&\n\tlocaladdr\030\003 \002(\0132\023.rsct" + "rl.core.IpAddr\022$\n\007extaddr\030\004 \002(\0132\023.rsctrl" + ".core.IpAddr\022\r\n\005state\030\005 \002(\r\"8\n\nStateFlag" + "s\022\n\n\006ONLINE\020\001\022\r\n\tCONNECTED\020\002\022\017\n\013UNREACHA" + "BLE\020\004\"\340\001\n\006Person\022\016\n\006gpg_id\030\001 \002(\t\022\014\n\004name" + "\030\002 \002(\t\0222\n\010relation\030\003 \002(\0162 .rsctrl.core.P" + "erson.Relationship\022(\n\tlocations\030\004 \003(\0132\025." + "rsctrl.core.Location\"Z\n\014Relationship\022\n\n\006" + "FRIEND\020\001\022\032\n\026FRIEND_OF_MANY_FRIENDS\020\002\022\025\n\021" + "FRIEND_OF_FRIENDS\020\003\022\013\n\007UNKNOWN\020\004\"0\n\004File" + "\022\014\n\004name\030\001 \002(\t\022\014\n\004hash\030\002 \002(\t\022\014\n\004size\030\003 \002" + "(\004\"f\n\003Dir\022\014\n\004name\030\001 \002(\t\022\014\n\004path\030\002 \002(\t\022!\n" + "\007subdirs\030\003 \003(\0132\020.rsctrl.core.Dir\022 \n\005file" + "s\030\004 \003(\0132\021.rsctrl.core.File\"\372\001\n\014SystemSta" + "tus\0225\n\nnet_status\030\001 \002(\0162!.rsctrl.core.Sy" + "stemStatus.NetCode\022\013\n\003msg\030\002 \001(\t\"\245\001\n\007NetC" + "ode\022\017\n\013BAD_UNKNOWN\020\000\022\017\n\013BAD_OFFLINE\020\001\022\016\n" + "\nBAD_NATSYM\020\002\022\021\n\rBAD_NODHT_NAT\020\003\022\023\n\017WARN" + "ING_RESTART\020\004\022\022\n\016WARNING_NATTED\020\005\022\021\n\rWAR" + "NING_NODHT\020\006\022\010\n\004GOOD\020\007\022\017\n\013ADV_FORWARD\020\010\"" + "3\n\tBandwidth\022\n\n\002up\030\001 \002(\002\022\014\n\004down\030\002 \002(\002\022\014" + "\n\004name\030\003 \001(\t\":\n\014BandwidthSet\022*\n\nbandwidt" + "hs\030\001 \003(\0132\026.rsctrl.core.Bandwidth*\027\n\013Exte" + "nsionId\022\010\n\004CORE\020\000*M\n\tPackageId\022\t\n\005PEERS\020" + "\001\022\n\n\006SYSTEM\020\002\022\010\n\004CHAT\020\003\022\n\n\006SEARCH\020\004\022\t\n\005F" + "ILES\020\005\022\010\n\003GXS\020\350\007", 1296); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "core.proto", &protobuf_RegisterTypes); + Status::default_instance_ = new Status(); + IpAddr::default_instance_ = new IpAddr(); + Location::default_instance_ = new Location(); + Person::default_instance_ = new Person(); + File::default_instance_ = new File(); + Dir::default_instance_ = new Dir(); + SystemStatus::default_instance_ = new SystemStatus(); + Bandwidth::default_instance_ = new Bandwidth(); + BandwidthSet::default_instance_ = new BandwidthSet(); + Status::default_instance_->InitAsDefaultInstance(); + IpAddr::default_instance_->InitAsDefaultInstance(); + Location::default_instance_->InitAsDefaultInstance(); + Person::default_instance_->InitAsDefaultInstance(); + File::default_instance_->InitAsDefaultInstance(); + Dir::default_instance_->InitAsDefaultInstance(); + SystemStatus::default_instance_->InitAsDefaultInstance(); + Bandwidth::default_instance_->InitAsDefaultInstance(); + BandwidthSet::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_core_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_core_2eproto { + StaticDescriptorInitializer_core_2eproto() { + protobuf_AddDesc_core_2eproto(); + } +} static_descriptor_initializer_core_2eproto_; + +const ::google::protobuf::EnumDescriptor* ExtensionId_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ExtensionId_descriptor_; +} +bool ExtensionId_IsValid(int value) { + switch(value) { + case 0: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* PackageId_descriptor() { + protobuf_AssignDescriptorsOnce(); + return PackageId_descriptor_; +} +bool PackageId_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 1000: + return true; + default: + return false; + } +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* Status_StatusCode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return Status_StatusCode_descriptor_; +} +bool Status_StatusCode_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const Status_StatusCode Status::FAILED; +const Status_StatusCode Status::NO_IMPL_YET; +const Status_StatusCode Status::INVALID_QUERY; +const Status_StatusCode Status::PARTIAL_SUCCESS; +const Status_StatusCode Status::SUCCESS; +const Status_StatusCode Status::READMSG; +const Status_StatusCode Status::StatusCode_MIN; +const Status_StatusCode Status::StatusCode_MAX; +const int Status::StatusCode_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int Status::kCodeFieldNumber; +const int Status::kMsgFieldNumber; +#endif // !_MSC_VER + +Status::Status() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Status::InitAsDefaultInstance() { +} + +Status::Status(const Status& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Status::SharedCtor() { + _cached_size_ = 0; + code_ = 0; + msg_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Status::~Status() { + SharedDtor(); +} + +void Status::SharedDtor() { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + delete msg_; + } + if (this != default_instance_) { + } +} + +void Status::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Status::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Status_descriptor_; +} + +const Status& Status::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +Status* Status::default_instance_ = NULL; + +Status* Status::New() const { + return new Status; +} + +void Status::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + code_ = 0; + if (has_msg()) { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + msg_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Status::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status.StatusCode code = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::core::Status_StatusCode_IsValid(value)) { + set_code(static_cast< ::rsctrl::core::Status_StatusCode >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_msg; + break; + } + + // optional string msg = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_msg: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_msg())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Status::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status.StatusCode code = 1; + if (has_code()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->code(), output); + } + + // optional string msg = 2; + if (has_msg()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->msg(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Status::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status.StatusCode code = 1; + if (has_code()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->code(), target); + } + + // optional string msg = 2; + if (has_msg()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->msg(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Status::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status.StatusCode code = 1; + if (has_code()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->code()); + } + + // optional string msg = 2; + if (has_msg()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->msg()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Status::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Status* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Status::MergeFrom(const Status& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_code()) { + set_code(from.code()); + } + if (from.has_msg()) { + set_msg(from.msg()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Status::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Status::CopyFrom(const Status& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Status::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void Status::Swap(Status* other) { + if (other != this) { + std::swap(code_, other->code_); + std::swap(msg_, other->msg_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Status::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Status_descriptor_; + metadata.reflection = Status_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int IpAddr::kAddrFieldNumber; +const int IpAddr::kPortFieldNumber; +#endif // !_MSC_VER + +IpAddr::IpAddr() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void IpAddr::InitAsDefaultInstance() { +} + +IpAddr::IpAddr(const IpAddr& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void IpAddr::SharedCtor() { + _cached_size_ = 0; + addr_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + port_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +IpAddr::~IpAddr() { + SharedDtor(); +} + +void IpAddr::SharedDtor() { + if (addr_ != &::google::protobuf::internal::kEmptyString) { + delete addr_; + } + if (this != default_instance_) { + } +} + +void IpAddr::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* IpAddr::descriptor() { + protobuf_AssignDescriptorsOnce(); + return IpAddr_descriptor_; +} + +const IpAddr& IpAddr::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +IpAddr* IpAddr::default_instance_ = NULL; + +IpAddr* IpAddr::New() const { + return new IpAddr; +} + +void IpAddr::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_addr()) { + if (addr_ != &::google::protobuf::internal::kEmptyString) { + addr_->clear(); + } + } + port_ = 0u; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool IpAddr::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string addr = 1 [default = ""]; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_addr())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->addr().data(), this->addr().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_port; + break; + } + + // required uint32 port = 2 [default = 0]; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_port: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &port_))); + set_has_port(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void IpAddr::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string addr = 1 [default = ""]; + if (has_addr()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->addr().data(), this->addr().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->addr(), output); + } + + // required uint32 port = 2 [default = 0]; + if (has_port()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->port(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* IpAddr::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string addr = 1 [default = ""]; + if (has_addr()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->addr().data(), this->addr().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->addr(), target); + } + + // required uint32 port = 2 [default = 0]; + if (has_port()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->port(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int IpAddr::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string addr = 1 [default = ""]; + if (has_addr()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->addr()); + } + + // required uint32 port = 2 [default = 0]; + if (has_port()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->port()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void IpAddr::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const IpAddr* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void IpAddr::MergeFrom(const IpAddr& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_addr()) { + set_addr(from.addr()); + } + if (from.has_port()) { + set_port(from.port()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void IpAddr::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void IpAddr::CopyFrom(const IpAddr& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool IpAddr::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void IpAddr::Swap(IpAddr* other) { + if (other != this) { + std::swap(addr_, other->addr_); + std::swap(port_, other->port_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata IpAddr::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = IpAddr_descriptor_; + metadata.reflection = IpAddr_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* Location_StateFlags_descriptor() { + protobuf_AssignDescriptorsOnce(); + return Location_StateFlags_descriptor_; +} +bool Location_StateFlags_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 4: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const Location_StateFlags Location::ONLINE; +const Location_StateFlags Location::CONNECTED; +const Location_StateFlags Location::UNREACHABLE; +const Location_StateFlags Location::StateFlags_MIN; +const Location_StateFlags Location::StateFlags_MAX; +const int Location::StateFlags_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int Location::kSslIdFieldNumber; +const int Location::kLocationFieldNumber; +const int Location::kLocaladdrFieldNumber; +const int Location::kExtaddrFieldNumber; +const int Location::kStateFieldNumber; +#endif // !_MSC_VER + +Location::Location() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Location::InitAsDefaultInstance() { + localaddr_ = const_cast< ::rsctrl::core::IpAddr*>(&::rsctrl::core::IpAddr::default_instance()); + extaddr_ = const_cast< ::rsctrl::core::IpAddr*>(&::rsctrl::core::IpAddr::default_instance()); +} + +Location::Location(const Location& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Location::SharedCtor() { + _cached_size_ = 0; + ssl_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + location_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + localaddr_ = NULL; + extaddr_ = NULL; + state_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Location::~Location() { + SharedDtor(); +} + +void Location::SharedDtor() { + if (ssl_id_ != &::google::protobuf::internal::kEmptyString) { + delete ssl_id_; + } + if (location_ != &::google::protobuf::internal::kEmptyString) { + delete location_; + } + if (this != default_instance_) { + delete localaddr_; + delete extaddr_; + } +} + +void Location::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Location::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Location_descriptor_; +} + +const Location& Location::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +Location* Location::default_instance_ = NULL; + +Location* Location::New() const { + return new Location; +} + +void Location::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_ssl_id()) { + if (ssl_id_ != &::google::protobuf::internal::kEmptyString) { + ssl_id_->clear(); + } + } + if (has_location()) { + if (location_ != &::google::protobuf::internal::kEmptyString) { + location_->clear(); + } + } + if (has_localaddr()) { + if (localaddr_ != NULL) localaddr_->::rsctrl::core::IpAddr::Clear(); + } + if (has_extaddr()) { + if (extaddr_ != NULL) extaddr_->::rsctrl::core::IpAddr::Clear(); + } + state_ = 0u; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Location::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string ssl_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_ssl_id())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->ssl_id().data(), this->ssl_id().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_location; + break; + } + + // required string location = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_location: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_location())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->location().data(), this->location().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_localaddr; + break; + } + + // required .rsctrl.core.IpAddr localaddr = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_localaddr: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_localaddr())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_extaddr; + break; + } + + // required .rsctrl.core.IpAddr extaddr = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_extaddr: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_extaddr())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_state; + break; + } + + // required uint32 state = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_state: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &state_))); + set_has_state(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Location::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string ssl_id = 1; + if (has_ssl_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->ssl_id().data(), this->ssl_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->ssl_id(), output); + } + + // required string location = 2; + if (has_location()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->location().data(), this->location().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->location(), output); + } + + // required .rsctrl.core.IpAddr localaddr = 3; + if (has_localaddr()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 3, this->localaddr(), output); + } + + // required .rsctrl.core.IpAddr extaddr = 4; + if (has_extaddr()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->extaddr(), output); + } + + // required uint32 state = 5; + if (has_state()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(5, this->state(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Location::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string ssl_id = 1; + if (has_ssl_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->ssl_id().data(), this->ssl_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->ssl_id(), target); + } + + // required string location = 2; + if (has_location()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->location().data(), this->location().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->location(), target); + } + + // required .rsctrl.core.IpAddr localaddr = 3; + if (has_localaddr()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->localaddr(), target); + } + + // required .rsctrl.core.IpAddr extaddr = 4; + if (has_extaddr()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->extaddr(), target); + } + + // required uint32 state = 5; + if (has_state()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(5, this->state(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Location::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string ssl_id = 1; + if (has_ssl_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->ssl_id()); + } + + // required string location = 2; + if (has_location()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->location()); + } + + // required .rsctrl.core.IpAddr localaddr = 3; + if (has_localaddr()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->localaddr()); + } + + // required .rsctrl.core.IpAddr extaddr = 4; + if (has_extaddr()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->extaddr()); + } + + // required uint32 state = 5; + if (has_state()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->state()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Location::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Location* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Location::MergeFrom(const Location& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_ssl_id()) { + set_ssl_id(from.ssl_id()); + } + if (from.has_location()) { + set_location(from.location()); + } + if (from.has_localaddr()) { + mutable_localaddr()->::rsctrl::core::IpAddr::MergeFrom(from.localaddr()); + } + if (from.has_extaddr()) { + mutable_extaddr()->::rsctrl::core::IpAddr::MergeFrom(from.extaddr()); + } + if (from.has_state()) { + set_state(from.state()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Location::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Location::CopyFrom(const Location& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Location::IsInitialized() const { + if ((_has_bits_[0] & 0x0000001f) != 0x0000001f) return false; + + if (has_localaddr()) { + if (!this->localaddr().IsInitialized()) return false; + } + if (has_extaddr()) { + if (!this->extaddr().IsInitialized()) return false; + } + return true; +} + +void Location::Swap(Location* other) { + if (other != this) { + std::swap(ssl_id_, other->ssl_id_); + std::swap(location_, other->location_); + std::swap(localaddr_, other->localaddr_); + std::swap(extaddr_, other->extaddr_); + std::swap(state_, other->state_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Location::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Location_descriptor_; + metadata.reflection = Location_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* Person_Relationship_descriptor() { + protobuf_AssignDescriptorsOnce(); + return Person_Relationship_descriptor_; +} +bool Person_Relationship_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const Person_Relationship Person::FRIEND; +const Person_Relationship Person::FRIEND_OF_MANY_FRIENDS; +const Person_Relationship Person::FRIEND_OF_FRIENDS; +const Person_Relationship Person::UNKNOWN; +const Person_Relationship Person::Relationship_MIN; +const Person_Relationship Person::Relationship_MAX; +const int Person::Relationship_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int Person::kGpgIdFieldNumber; +const int Person::kNameFieldNumber; +const int Person::kRelationFieldNumber; +const int Person::kLocationsFieldNumber; +#endif // !_MSC_VER + +Person::Person() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Person::InitAsDefaultInstance() { +} + +Person::Person(const Person& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Person::SharedCtor() { + _cached_size_ = 0; + gpg_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + relation_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Person::~Person() { + SharedDtor(); +} + +void Person::SharedDtor() { + if (gpg_id_ != &::google::protobuf::internal::kEmptyString) { + delete gpg_id_; + } + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (this != default_instance_) { + } +} + +void Person::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Person::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Person_descriptor_; +} + +const Person& Person::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +Person* Person::default_instance_ = NULL; + +Person* Person::New() const { + return new Person; +} + +void Person::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_gpg_id()) { + if (gpg_id_ != &::google::protobuf::internal::kEmptyString) { + gpg_id_->clear(); + } + } + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + relation_ = 1; + } + locations_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Person::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string gpg_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_gpg_id())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_id().data(), this->gpg_id().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_name; + break; + } + + // required string name = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_relation; + break; + } + + // required .rsctrl.core.Person.Relationship relation = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_relation: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::core::Person_Relationship_IsValid(value)) { + set_relation(static_cast< ::rsctrl::core::Person_Relationship >(value)); + } else { + mutable_unknown_fields()->AddVarint(3, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_locations; + break; + } + + // repeated .rsctrl.core.Location locations = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_locations: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_locations())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_locations; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Person::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string gpg_id = 1; + if (has_gpg_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_id().data(), this->gpg_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->gpg_id(), output); + } + + // required string name = 2; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->name(), output); + } + + // required .rsctrl.core.Person.Relationship relation = 3; + if (has_relation()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 3, this->relation(), output); + } + + // repeated .rsctrl.core.Location locations = 4; + for (int i = 0; i < this->locations_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->locations(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Person::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string gpg_id = 1; + if (has_gpg_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_id().data(), this->gpg_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->gpg_id(), target); + } + + // required string name = 2; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->name(), target); + } + + // required .rsctrl.core.Person.Relationship relation = 3; + if (has_relation()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 3, this->relation(), target); + } + + // repeated .rsctrl.core.Location locations = 4; + for (int i = 0; i < this->locations_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->locations(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Person::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string gpg_id = 1; + if (has_gpg_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->gpg_id()); + } + + // required string name = 2; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // required .rsctrl.core.Person.Relationship relation = 3; + if (has_relation()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->relation()); + } + + } + // repeated .rsctrl.core.Location locations = 4; + total_size += 1 * this->locations_size(); + for (int i = 0; i < this->locations_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->locations(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Person::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Person* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Person::MergeFrom(const Person& from) { + GOOGLE_CHECK_NE(&from, this); + locations_.MergeFrom(from.locations_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_gpg_id()) { + set_gpg_id(from.gpg_id()); + } + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_relation()) { + set_relation(from.relation()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Person::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Person::CopyFrom(const Person& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Person::IsInitialized() const { + if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; + + for (int i = 0; i < locations_size(); i++) { + if (!this->locations(i).IsInitialized()) return false; + } + return true; +} + +void Person::Swap(Person* other) { + if (other != this) { + std::swap(gpg_id_, other->gpg_id_); + std::swap(name_, other->name_); + std::swap(relation_, other->relation_); + locations_.Swap(&other->locations_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Person::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Person_descriptor_; + metadata.reflection = Person_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int File::kNameFieldNumber; +const int File::kHashFieldNumber; +const int File::kSizeFieldNumber; +#endif // !_MSC_VER + +File::File() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void File::InitAsDefaultInstance() { +} + +File::File(const File& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void File::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + hash_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + size_ = GOOGLE_ULONGLONG(0); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +File::~File() { + SharedDtor(); +} + +void File::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (hash_ != &::google::protobuf::internal::kEmptyString) { + delete hash_; + } + if (this != default_instance_) { + } +} + +void File::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* File::descriptor() { + protobuf_AssignDescriptorsOnce(); + return File_descriptor_; +} + +const File& File::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +File* File::default_instance_ = NULL; + +File* File::New() const { + return new File; +} + +void File::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_hash()) { + if (hash_ != &::google::protobuf::internal::kEmptyString) { + hash_->clear(); + } + } + size_ = GOOGLE_ULONGLONG(0); + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool File::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_hash; + break; + } + + // required string hash = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_hash: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_hash())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->hash().data(), this->hash().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_size; + break; + } + + // required uint64 size = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_size: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( + input, &size_))); + set_has_size(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void File::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // required string hash = 2; + if (has_hash()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->hash().data(), this->hash().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->hash(), output); + } + + // required uint64 size = 3; + if (has_size()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt64(3, this->size(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* File::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // required string hash = 2; + if (has_hash()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->hash().data(), this->hash().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->hash(), target); + } + + // required uint64 size = 3; + if (has_size()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(3, this->size(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int File::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // required string hash = 2; + if (has_hash()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->hash()); + } + + // required uint64 size = 3; + if (has_size()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt64Size( + this->size()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void File::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const File* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void File::MergeFrom(const File& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_hash()) { + set_hash(from.hash()); + } + if (from.has_size()) { + set_size(from.size()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void File::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void File::CopyFrom(const File& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool File::IsInitialized() const { + if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; + + return true; +} + +void File::Swap(File* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(hash_, other->hash_); + std::swap(size_, other->size_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata File::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = File_descriptor_; + metadata.reflection = File_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Dir::kNameFieldNumber; +const int Dir::kPathFieldNumber; +const int Dir::kSubdirsFieldNumber; +const int Dir::kFilesFieldNumber; +#endif // !_MSC_VER + +Dir::Dir() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Dir::InitAsDefaultInstance() { +} + +Dir::Dir(const Dir& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Dir::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + path_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Dir::~Dir() { + SharedDtor(); +} + +void Dir::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (path_ != &::google::protobuf::internal::kEmptyString) { + delete path_; + } + if (this != default_instance_) { + } +} + +void Dir::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Dir::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Dir_descriptor_; +} + +const Dir& Dir::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +Dir* Dir::default_instance_ = NULL; + +Dir* Dir::New() const { + return new Dir; +} + +void Dir::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_path()) { + if (path_ != &::google::protobuf::internal::kEmptyString) { + path_->clear(); + } + } + } + subdirs_.Clear(); + files_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Dir::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_path; + break; + } + + // required string path = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_path: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_path())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->path().data(), this->path().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_subdirs; + break; + } + + // repeated .rsctrl.core.Dir subdirs = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_subdirs: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_subdirs())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_subdirs; + if (input->ExpectTag(34)) goto parse_files; + break; + } + + // repeated .rsctrl.core.File files = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_files: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_files())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_files; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Dir::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // required string path = 2; + if (has_path()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->path().data(), this->path().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->path(), output); + } + + // repeated .rsctrl.core.Dir subdirs = 3; + for (int i = 0; i < this->subdirs_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 3, this->subdirs(i), output); + } + + // repeated .rsctrl.core.File files = 4; + for (int i = 0; i < this->files_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->files(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Dir::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // required string path = 2; + if (has_path()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->path().data(), this->path().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->path(), target); + } + + // repeated .rsctrl.core.Dir subdirs = 3; + for (int i = 0; i < this->subdirs_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->subdirs(i), target); + } + + // repeated .rsctrl.core.File files = 4; + for (int i = 0; i < this->files_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->files(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Dir::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // required string path = 2; + if (has_path()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->path()); + } + + } + // repeated .rsctrl.core.Dir subdirs = 3; + total_size += 1 * this->subdirs_size(); + for (int i = 0; i < this->subdirs_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->subdirs(i)); + } + + // repeated .rsctrl.core.File files = 4; + total_size += 1 * this->files_size(); + for (int i = 0; i < this->files_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->files(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Dir::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Dir* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Dir::MergeFrom(const Dir& from) { + GOOGLE_CHECK_NE(&from, this); + subdirs_.MergeFrom(from.subdirs_); + files_.MergeFrom(from.files_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_path()) { + set_path(from.path()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Dir::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Dir::CopyFrom(const Dir& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Dir::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + for (int i = 0; i < subdirs_size(); i++) { + if (!this->subdirs(i).IsInitialized()) return false; + } + for (int i = 0; i < files_size(); i++) { + if (!this->files(i).IsInitialized()) return false; + } + return true; +} + +void Dir::Swap(Dir* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(path_, other->path_); + subdirs_.Swap(&other->subdirs_); + files_.Swap(&other->files_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Dir::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Dir_descriptor_; + metadata.reflection = Dir_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* SystemStatus_NetCode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return SystemStatus_NetCode_descriptor_; +} +bool SystemStatus_NetCode_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const SystemStatus_NetCode SystemStatus::BAD_UNKNOWN; +const SystemStatus_NetCode SystemStatus::BAD_OFFLINE; +const SystemStatus_NetCode SystemStatus::BAD_NATSYM; +const SystemStatus_NetCode SystemStatus::BAD_NODHT_NAT; +const SystemStatus_NetCode SystemStatus::WARNING_RESTART; +const SystemStatus_NetCode SystemStatus::WARNING_NATTED; +const SystemStatus_NetCode SystemStatus::WARNING_NODHT; +const SystemStatus_NetCode SystemStatus::GOOD; +const SystemStatus_NetCode SystemStatus::ADV_FORWARD; +const SystemStatus_NetCode SystemStatus::NetCode_MIN; +const SystemStatus_NetCode SystemStatus::NetCode_MAX; +const int SystemStatus::NetCode_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int SystemStatus::kNetStatusFieldNumber; +const int SystemStatus::kMsgFieldNumber; +#endif // !_MSC_VER + +SystemStatus::SystemStatus() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SystemStatus::InitAsDefaultInstance() { +} + +SystemStatus::SystemStatus(const SystemStatus& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SystemStatus::SharedCtor() { + _cached_size_ = 0; + net_status_ = 0; + msg_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SystemStatus::~SystemStatus() { + SharedDtor(); +} + +void SystemStatus::SharedDtor() { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + delete msg_; + } + if (this != default_instance_) { + } +} + +void SystemStatus::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SystemStatus::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SystemStatus_descriptor_; +} + +const SystemStatus& SystemStatus::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +SystemStatus* SystemStatus::default_instance_ = NULL; + +SystemStatus* SystemStatus::New() const { + return new SystemStatus; +} + +void SystemStatus::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + net_status_ = 0; + if (has_msg()) { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + msg_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SystemStatus::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.SystemStatus.NetCode net_status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::core::SystemStatus_NetCode_IsValid(value)) { + set_net_status(static_cast< ::rsctrl::core::SystemStatus_NetCode >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_msg; + break; + } + + // optional string msg = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_msg: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_msg())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SystemStatus::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.SystemStatus.NetCode net_status = 1; + if (has_net_status()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->net_status(), output); + } + + // optional string msg = 2; + if (has_msg()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->msg(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SystemStatus::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.SystemStatus.NetCode net_status = 1; + if (has_net_status()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->net_status(), target); + } + + // optional string msg = 2; + if (has_msg()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->msg().data(), this->msg().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->msg(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SystemStatus::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.SystemStatus.NetCode net_status = 1; + if (has_net_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->net_status()); + } + + // optional string msg = 2; + if (has_msg()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->msg()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SystemStatus::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SystemStatus* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SystemStatus::MergeFrom(const SystemStatus& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_net_status()) { + set_net_status(from.net_status()); + } + if (from.has_msg()) { + set_msg(from.msg()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SystemStatus::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SystemStatus::CopyFrom(const SystemStatus& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SystemStatus::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void SystemStatus::Swap(SystemStatus* other) { + if (other != this) { + std::swap(net_status_, other->net_status_); + std::swap(msg_, other->msg_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SystemStatus::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SystemStatus_descriptor_; + metadata.reflection = SystemStatus_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int Bandwidth::kUpFieldNumber; +const int Bandwidth::kDownFieldNumber; +const int Bandwidth::kNameFieldNumber; +#endif // !_MSC_VER + +Bandwidth::Bandwidth() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void Bandwidth::InitAsDefaultInstance() { +} + +Bandwidth::Bandwidth(const Bandwidth& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void Bandwidth::SharedCtor() { + _cached_size_ = 0; + up_ = 0; + down_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +Bandwidth::~Bandwidth() { + SharedDtor(); +} + +void Bandwidth::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (this != default_instance_) { + } +} + +void Bandwidth::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Bandwidth::descriptor() { + protobuf_AssignDescriptorsOnce(); + return Bandwidth_descriptor_; +} + +const Bandwidth& Bandwidth::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +Bandwidth* Bandwidth::default_instance_ = NULL; + +Bandwidth* Bandwidth::New() const { + return new Bandwidth; +} + +void Bandwidth::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + up_ = 0; + down_ = 0; + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool Bandwidth::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float up = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &up_))); + set_has_up(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_down; + break; + } + + // required float down = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_down: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &down_))); + set_has_down(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_name; + break; + } + + // optional string name = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void Bandwidth::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float up = 1; + if (has_up()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->up(), output); + } + + // required float down = 2; + if (has_down()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->down(), output); + } + + // optional string name = 3; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->name(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* Bandwidth::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required float up = 1; + if (has_up()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->up(), target); + } + + // required float down = 2; + if (has_down()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(2, this->down(), target); + } + + // optional string name = 3; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->name(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int Bandwidth::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float up = 1; + if (has_up()) { + total_size += 1 + 4; + } + + // required float down = 2; + if (has_down()) { + total_size += 1 + 4; + } + + // optional string name = 3; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Bandwidth::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const Bandwidth* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void Bandwidth::MergeFrom(const Bandwidth& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_up()) { + set_up(from.up()); + } + if (from.has_down()) { + set_down(from.down()); + } + if (from.has_name()) { + set_name(from.name()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void Bandwidth::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Bandwidth::CopyFrom(const Bandwidth& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Bandwidth::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void Bandwidth::Swap(Bandwidth* other) { + if (other != this) { + std::swap(up_, other->up_); + std::swap(down_, other->down_); + std::swap(name_, other->name_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata Bandwidth::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = Bandwidth_descriptor_; + metadata.reflection = Bandwidth_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int BandwidthSet::kBandwidthsFieldNumber; +#endif // !_MSC_VER + +BandwidthSet::BandwidthSet() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void BandwidthSet::InitAsDefaultInstance() { +} + +BandwidthSet::BandwidthSet(const BandwidthSet& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void BandwidthSet::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +BandwidthSet::~BandwidthSet() { + SharedDtor(); +} + +void BandwidthSet::SharedDtor() { + if (this != default_instance_) { + } +} + +void BandwidthSet::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* BandwidthSet::descriptor() { + protobuf_AssignDescriptorsOnce(); + return BandwidthSet_descriptor_; +} + +const BandwidthSet& BandwidthSet::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_core_2eproto(); return *default_instance_; +} + +BandwidthSet* BandwidthSet::default_instance_ = NULL; + +BandwidthSet* BandwidthSet::New() const { + return new BandwidthSet; +} + +void BandwidthSet::Clear() { + bandwidths_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool BandwidthSet::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .rsctrl.core.Bandwidth bandwidths = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_bandwidths: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_bandwidths())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_bandwidths; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void BandwidthSet::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .rsctrl.core.Bandwidth bandwidths = 1; + for (int i = 0; i < this->bandwidths_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->bandwidths(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* BandwidthSet::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .rsctrl.core.Bandwidth bandwidths = 1; + for (int i = 0; i < this->bandwidths_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->bandwidths(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int BandwidthSet::ByteSize() const { + int total_size = 0; + + // repeated .rsctrl.core.Bandwidth bandwidths = 1; + total_size += 1 * this->bandwidths_size(); + for (int i = 0; i < this->bandwidths_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->bandwidths(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void BandwidthSet::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const BandwidthSet* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void BandwidthSet::MergeFrom(const BandwidthSet& from) { + GOOGLE_CHECK_NE(&from, this); + bandwidths_.MergeFrom(from.bandwidths_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void BandwidthSet::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void BandwidthSet::CopyFrom(const BandwidthSet& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool BandwidthSet::IsInitialized() const { + + for (int i = 0; i < bandwidths_size(); i++) { + if (!this->bandwidths(i).IsInitialized()) return false; + } + return true; +} + +void BandwidthSet::Swap(BandwidthSet* other) { + if (other != this) { + bandwidths_.Swap(&other->bandwidths_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata BandwidthSet::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = BandwidthSet_descriptor_; + metadata.reflection = BandwidthSet_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace core +} // namespace rsctrl + +// @@protoc_insertion_point(global_scope) diff --git a/retroshare-nogui/src/rpc/proto/gencc/core.pb.h b/retroshare-nogui/src/rpc/proto/gencc/core.pb.h new file mode 100644 index 000000000..fda22264a --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/core.pb.h @@ -0,0 +1,2370 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: core.proto + +#ifndef PROTOBUF_core_2eproto__INCLUDED +#define PROTOBUF_core_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace core { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_core_2eproto(); +void protobuf_AssignDesc_core_2eproto(); +void protobuf_ShutdownFile_core_2eproto(); + +class Status; +class IpAddr; +class Location; +class Person; +class File; +class Dir; +class SystemStatus; +class Bandwidth; +class BandwidthSet; + +enum Status_StatusCode { + Status_StatusCode_FAILED = 0, + Status_StatusCode_NO_IMPL_YET = 1, + Status_StatusCode_INVALID_QUERY = 2, + Status_StatusCode_PARTIAL_SUCCESS = 3, + Status_StatusCode_SUCCESS = 4, + Status_StatusCode_READMSG = 5 +}; +bool Status_StatusCode_IsValid(int value); +const Status_StatusCode Status_StatusCode_StatusCode_MIN = Status_StatusCode_FAILED; +const Status_StatusCode Status_StatusCode_StatusCode_MAX = Status_StatusCode_READMSG; +const int Status_StatusCode_StatusCode_ARRAYSIZE = Status_StatusCode_StatusCode_MAX + 1; + +const ::google::protobuf::EnumDescriptor* Status_StatusCode_descriptor(); +inline const ::std::string& Status_StatusCode_Name(Status_StatusCode value) { + return ::google::protobuf::internal::NameOfEnum( + Status_StatusCode_descriptor(), value); +} +inline bool Status_StatusCode_Parse( + const ::std::string& name, Status_StatusCode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + Status_StatusCode_descriptor(), name, value); +} +enum Location_StateFlags { + Location_StateFlags_ONLINE = 1, + Location_StateFlags_CONNECTED = 2, + Location_StateFlags_UNREACHABLE = 4 +}; +bool Location_StateFlags_IsValid(int value); +const Location_StateFlags Location_StateFlags_StateFlags_MIN = Location_StateFlags_ONLINE; +const Location_StateFlags Location_StateFlags_StateFlags_MAX = Location_StateFlags_UNREACHABLE; +const int Location_StateFlags_StateFlags_ARRAYSIZE = Location_StateFlags_StateFlags_MAX + 1; + +const ::google::protobuf::EnumDescriptor* Location_StateFlags_descriptor(); +inline const ::std::string& Location_StateFlags_Name(Location_StateFlags value) { + return ::google::protobuf::internal::NameOfEnum( + Location_StateFlags_descriptor(), value); +} +inline bool Location_StateFlags_Parse( + const ::std::string& name, Location_StateFlags* value) { + return ::google::protobuf::internal::ParseNamedEnum( + Location_StateFlags_descriptor(), name, value); +} +enum Person_Relationship { + Person_Relationship_FRIEND = 1, + Person_Relationship_FRIEND_OF_MANY_FRIENDS = 2, + Person_Relationship_FRIEND_OF_FRIENDS = 3, + Person_Relationship_UNKNOWN = 4 +}; +bool Person_Relationship_IsValid(int value); +const Person_Relationship Person_Relationship_Relationship_MIN = Person_Relationship_FRIEND; +const Person_Relationship Person_Relationship_Relationship_MAX = Person_Relationship_UNKNOWN; +const int Person_Relationship_Relationship_ARRAYSIZE = Person_Relationship_Relationship_MAX + 1; + +const ::google::protobuf::EnumDescriptor* Person_Relationship_descriptor(); +inline const ::std::string& Person_Relationship_Name(Person_Relationship value) { + return ::google::protobuf::internal::NameOfEnum( + Person_Relationship_descriptor(), value); +} +inline bool Person_Relationship_Parse( + const ::std::string& name, Person_Relationship* value) { + return ::google::protobuf::internal::ParseNamedEnum( + Person_Relationship_descriptor(), name, value); +} +enum SystemStatus_NetCode { + SystemStatus_NetCode_BAD_UNKNOWN = 0, + SystemStatus_NetCode_BAD_OFFLINE = 1, + SystemStatus_NetCode_BAD_NATSYM = 2, + SystemStatus_NetCode_BAD_NODHT_NAT = 3, + SystemStatus_NetCode_WARNING_RESTART = 4, + SystemStatus_NetCode_WARNING_NATTED = 5, + SystemStatus_NetCode_WARNING_NODHT = 6, + SystemStatus_NetCode_GOOD = 7, + SystemStatus_NetCode_ADV_FORWARD = 8 +}; +bool SystemStatus_NetCode_IsValid(int value); +const SystemStatus_NetCode SystemStatus_NetCode_NetCode_MIN = SystemStatus_NetCode_BAD_UNKNOWN; +const SystemStatus_NetCode SystemStatus_NetCode_NetCode_MAX = SystemStatus_NetCode_ADV_FORWARD; +const int SystemStatus_NetCode_NetCode_ARRAYSIZE = SystemStatus_NetCode_NetCode_MAX + 1; + +const ::google::protobuf::EnumDescriptor* SystemStatus_NetCode_descriptor(); +inline const ::std::string& SystemStatus_NetCode_Name(SystemStatus_NetCode value) { + return ::google::protobuf::internal::NameOfEnum( + SystemStatus_NetCode_descriptor(), value); +} +inline bool SystemStatus_NetCode_Parse( + const ::std::string& name, SystemStatus_NetCode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + SystemStatus_NetCode_descriptor(), name, value); +} +enum ExtensionId { + CORE = 0 +}; +bool ExtensionId_IsValid(int value); +const ExtensionId ExtensionId_MIN = CORE; +const ExtensionId ExtensionId_MAX = CORE; +const int ExtensionId_ARRAYSIZE = ExtensionId_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ExtensionId_descriptor(); +inline const ::std::string& ExtensionId_Name(ExtensionId value) { + return ::google::protobuf::internal::NameOfEnum( + ExtensionId_descriptor(), value); +} +inline bool ExtensionId_Parse( + const ::std::string& name, ExtensionId* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ExtensionId_descriptor(), name, value); +} +enum PackageId { + PEERS = 1, + SYSTEM = 2, + CHAT = 3, + SEARCH = 4, + FILES = 5, + GXS = 1000 +}; +bool PackageId_IsValid(int value); +const PackageId PackageId_MIN = PEERS; +const PackageId PackageId_MAX = GXS; +const int PackageId_ARRAYSIZE = PackageId_MAX + 1; + +const ::google::protobuf::EnumDescriptor* PackageId_descriptor(); +inline const ::std::string& PackageId_Name(PackageId value) { + return ::google::protobuf::internal::NameOfEnum( + PackageId_descriptor(), value); +} +inline bool PackageId_Parse( + const ::std::string& name, PackageId* value) { + return ::google::protobuf::internal::ParseNamedEnum( + PackageId_descriptor(), name, value); +} +// =================================================================== + +class Status : public ::google::protobuf::Message { + public: + Status(); + virtual ~Status(); + + Status(const Status& from); + + inline Status& operator=(const Status& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Status& default_instance(); + + void Swap(Status* other); + + // implements Message ---------------------------------------------- + + Status* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Status& from); + void MergeFrom(const Status& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef Status_StatusCode StatusCode; + static const StatusCode FAILED = Status_StatusCode_FAILED; + static const StatusCode NO_IMPL_YET = Status_StatusCode_NO_IMPL_YET; + static const StatusCode INVALID_QUERY = Status_StatusCode_INVALID_QUERY; + static const StatusCode PARTIAL_SUCCESS = Status_StatusCode_PARTIAL_SUCCESS; + static const StatusCode SUCCESS = Status_StatusCode_SUCCESS; + static const StatusCode READMSG = Status_StatusCode_READMSG; + static inline bool StatusCode_IsValid(int value) { + return Status_StatusCode_IsValid(value); + } + static const StatusCode StatusCode_MIN = + Status_StatusCode_StatusCode_MIN; + static const StatusCode StatusCode_MAX = + Status_StatusCode_StatusCode_MAX; + static const int StatusCode_ARRAYSIZE = + Status_StatusCode_StatusCode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + StatusCode_descriptor() { + return Status_StatusCode_descriptor(); + } + static inline const ::std::string& StatusCode_Name(StatusCode value) { + return Status_StatusCode_Name(value); + } + static inline bool StatusCode_Parse(const ::std::string& name, + StatusCode* value) { + return Status_StatusCode_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status.StatusCode code = 1; + inline bool has_code() const; + inline void clear_code(); + static const int kCodeFieldNumber = 1; + inline ::rsctrl::core::Status_StatusCode code() const; + inline void set_code(::rsctrl::core::Status_StatusCode value); + + // optional string msg = 2; + inline bool has_msg() const; + inline void clear_msg(); + static const int kMsgFieldNumber = 2; + inline const ::std::string& msg() const; + inline void set_msg(const ::std::string& value); + inline void set_msg(const char* value); + inline void set_msg(const char* value, size_t size); + inline ::std::string* mutable_msg(); + inline ::std::string* release_msg(); + + // @@protoc_insertion_point(class_scope:rsctrl.core.Status) + private: + inline void set_has_code(); + inline void clear_has_code(); + inline void set_has_msg(); + inline void clear_has_msg(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* msg_; + int code_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static Status* default_instance_; +}; +// ------------------------------------------------------------------- + +class IpAddr : public ::google::protobuf::Message { + public: + IpAddr(); + virtual ~IpAddr(); + + IpAddr(const IpAddr& from); + + inline IpAddr& operator=(const IpAddr& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const IpAddr& default_instance(); + + void Swap(IpAddr* other); + + // implements Message ---------------------------------------------- + + IpAddr* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const IpAddr& from); + void MergeFrom(const IpAddr& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required string addr = 1 [default = ""]; + inline bool has_addr() const; + inline void clear_addr(); + static const int kAddrFieldNumber = 1; + inline const ::std::string& addr() const; + inline void set_addr(const ::std::string& value); + inline void set_addr(const char* value); + inline void set_addr(const char* value, size_t size); + inline ::std::string* mutable_addr(); + inline ::std::string* release_addr(); + + // required uint32 port = 2 [default = 0]; + inline bool has_port() const; + inline void clear_port(); + static const int kPortFieldNumber = 2; + inline ::google::protobuf::uint32 port() const; + inline void set_port(::google::protobuf::uint32 value); + + // @@protoc_insertion_point(class_scope:rsctrl.core.IpAddr) + private: + inline void set_has_addr(); + inline void clear_has_addr(); + inline void set_has_port(); + inline void clear_has_port(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* addr_; + ::google::protobuf::uint32 port_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static IpAddr* default_instance_; +}; +// ------------------------------------------------------------------- + +class Location : public ::google::protobuf::Message { + public: + Location(); + virtual ~Location(); + + Location(const Location& from); + + inline Location& operator=(const Location& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Location& default_instance(); + + void Swap(Location* other); + + // implements Message ---------------------------------------------- + + Location* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Location& from); + void MergeFrom(const Location& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef Location_StateFlags StateFlags; + static const StateFlags ONLINE = Location_StateFlags_ONLINE; + static const StateFlags CONNECTED = Location_StateFlags_CONNECTED; + static const StateFlags UNREACHABLE = Location_StateFlags_UNREACHABLE; + static inline bool StateFlags_IsValid(int value) { + return Location_StateFlags_IsValid(value); + } + static const StateFlags StateFlags_MIN = + Location_StateFlags_StateFlags_MIN; + static const StateFlags StateFlags_MAX = + Location_StateFlags_StateFlags_MAX; + static const int StateFlags_ARRAYSIZE = + Location_StateFlags_StateFlags_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + StateFlags_descriptor() { + return Location_StateFlags_descriptor(); + } + static inline const ::std::string& StateFlags_Name(StateFlags value) { + return Location_StateFlags_Name(value); + } + static inline bool StateFlags_Parse(const ::std::string& name, + StateFlags* value) { + return Location_StateFlags_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required string ssl_id = 1; + inline bool has_ssl_id() const; + inline void clear_ssl_id(); + static const int kSslIdFieldNumber = 1; + inline const ::std::string& ssl_id() const; + inline void set_ssl_id(const ::std::string& value); + inline void set_ssl_id(const char* value); + inline void set_ssl_id(const char* value, size_t size); + inline ::std::string* mutable_ssl_id(); + inline ::std::string* release_ssl_id(); + + // required string location = 2; + inline bool has_location() const; + inline void clear_location(); + static const int kLocationFieldNumber = 2; + inline const ::std::string& location() const; + inline void set_location(const ::std::string& value); + inline void set_location(const char* value); + inline void set_location(const char* value, size_t size); + inline ::std::string* mutable_location(); + inline ::std::string* release_location(); + + // required .rsctrl.core.IpAddr localaddr = 3; + inline bool has_localaddr() const; + inline void clear_localaddr(); + static const int kLocaladdrFieldNumber = 3; + inline const ::rsctrl::core::IpAddr& localaddr() const; + inline ::rsctrl::core::IpAddr* mutable_localaddr(); + inline ::rsctrl::core::IpAddr* release_localaddr(); + + // required .rsctrl.core.IpAddr extaddr = 4; + inline bool has_extaddr() const; + inline void clear_extaddr(); + static const int kExtaddrFieldNumber = 4; + inline const ::rsctrl::core::IpAddr& extaddr() const; + inline ::rsctrl::core::IpAddr* mutable_extaddr(); + inline ::rsctrl::core::IpAddr* release_extaddr(); + + // required uint32 state = 5; + inline bool has_state() const; + inline void clear_state(); + static const int kStateFieldNumber = 5; + inline ::google::protobuf::uint32 state() const; + inline void set_state(::google::protobuf::uint32 value); + + // @@protoc_insertion_point(class_scope:rsctrl.core.Location) + private: + inline void set_has_ssl_id(); + inline void clear_has_ssl_id(); + inline void set_has_location(); + inline void clear_has_location(); + inline void set_has_localaddr(); + inline void clear_has_localaddr(); + inline void set_has_extaddr(); + inline void clear_has_extaddr(); + inline void set_has_state(); + inline void clear_has_state(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* ssl_id_; + ::std::string* location_; + ::rsctrl::core::IpAddr* localaddr_; + ::rsctrl::core::IpAddr* extaddr_; + ::google::protobuf::uint32 state_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static Location* default_instance_; +}; +// ------------------------------------------------------------------- + +class Person : public ::google::protobuf::Message { + public: + Person(); + virtual ~Person(); + + Person(const Person& from); + + inline Person& operator=(const Person& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Person& default_instance(); + + void Swap(Person* other); + + // implements Message ---------------------------------------------- + + Person* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Person& from); + void MergeFrom(const Person& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef Person_Relationship Relationship; + static const Relationship FRIEND = Person_Relationship_FRIEND; + static const Relationship FRIEND_OF_MANY_FRIENDS = Person_Relationship_FRIEND_OF_MANY_FRIENDS; + static const Relationship FRIEND_OF_FRIENDS = Person_Relationship_FRIEND_OF_FRIENDS; + static const Relationship UNKNOWN = Person_Relationship_UNKNOWN; + static inline bool Relationship_IsValid(int value) { + return Person_Relationship_IsValid(value); + } + static const Relationship Relationship_MIN = + Person_Relationship_Relationship_MIN; + static const Relationship Relationship_MAX = + Person_Relationship_Relationship_MAX; + static const int Relationship_ARRAYSIZE = + Person_Relationship_Relationship_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Relationship_descriptor() { + return Person_Relationship_descriptor(); + } + static inline const ::std::string& Relationship_Name(Relationship value) { + return Person_Relationship_Name(value); + } + static inline bool Relationship_Parse(const ::std::string& name, + Relationship* value) { + return Person_Relationship_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required string gpg_id = 1; + inline bool has_gpg_id() const; + inline void clear_gpg_id(); + static const int kGpgIdFieldNumber = 1; + inline const ::std::string& gpg_id() const; + inline void set_gpg_id(const ::std::string& value); + inline void set_gpg_id(const char* value); + inline void set_gpg_id(const char* value, size_t size); + inline ::std::string* mutable_gpg_id(); + inline ::std::string* release_gpg_id(); + + // required string name = 2; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 2; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + + // required .rsctrl.core.Person.Relationship relation = 3; + inline bool has_relation() const; + inline void clear_relation(); + static const int kRelationFieldNumber = 3; + inline ::rsctrl::core::Person_Relationship relation() const; + inline void set_relation(::rsctrl::core::Person_Relationship value); + + // repeated .rsctrl.core.Location locations = 4; + inline int locations_size() const; + inline void clear_locations(); + static const int kLocationsFieldNumber = 4; + inline const ::rsctrl::core::Location& locations(int index) const; + inline ::rsctrl::core::Location* mutable_locations(int index); + inline ::rsctrl::core::Location* add_locations(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Location >& + locations() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Location >* + mutable_locations(); + + // @@protoc_insertion_point(class_scope:rsctrl.core.Person) + private: + inline void set_has_gpg_id(); + inline void clear_has_gpg_id(); + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_relation(); + inline void clear_has_relation(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* gpg_id_; + ::std::string* name_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Location > locations_; + int relation_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static Person* default_instance_; +}; +// ------------------------------------------------------------------- + +class File : public ::google::protobuf::Message { + public: + File(); + virtual ~File(); + + File(const File& from); + + inline File& operator=(const File& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const File& default_instance(); + + void Swap(File* other); + + // implements Message ---------------------------------------------- + + File* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const File& from); + void MergeFrom(const File& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + + // required string hash = 2; + inline bool has_hash() const; + inline void clear_hash(); + static const int kHashFieldNumber = 2; + inline const ::std::string& hash() const; + inline void set_hash(const ::std::string& value); + inline void set_hash(const char* value); + inline void set_hash(const char* value, size_t size); + inline ::std::string* mutable_hash(); + inline ::std::string* release_hash(); + + // required uint64 size = 3; + inline bool has_size() const; + inline void clear_size(); + static const int kSizeFieldNumber = 3; + inline ::google::protobuf::uint64 size() const; + inline void set_size(::google::protobuf::uint64 value); + + // @@protoc_insertion_point(class_scope:rsctrl.core.File) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_hash(); + inline void clear_has_hash(); + inline void set_has_size(); + inline void clear_has_size(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::std::string* hash_; + ::google::protobuf::uint64 size_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static File* default_instance_; +}; +// ------------------------------------------------------------------- + +class Dir : public ::google::protobuf::Message { + public: + Dir(); + virtual ~Dir(); + + Dir(const Dir& from); + + inline Dir& operator=(const Dir& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Dir& default_instance(); + + void Swap(Dir* other); + + // implements Message ---------------------------------------------- + + Dir* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Dir& from); + void MergeFrom(const Dir& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + + // required string path = 2; + inline bool has_path() const; + inline void clear_path(); + static const int kPathFieldNumber = 2; + inline const ::std::string& path() const; + inline void set_path(const ::std::string& value); + inline void set_path(const char* value); + inline void set_path(const char* value, size_t size); + inline ::std::string* mutable_path(); + inline ::std::string* release_path(); + + // repeated .rsctrl.core.Dir subdirs = 3; + inline int subdirs_size() const; + inline void clear_subdirs(); + static const int kSubdirsFieldNumber = 3; + inline const ::rsctrl::core::Dir& subdirs(int index) const; + inline ::rsctrl::core::Dir* mutable_subdirs(int index); + inline ::rsctrl::core::Dir* add_subdirs(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Dir >& + subdirs() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Dir >* + mutable_subdirs(); + + // repeated .rsctrl.core.File files = 4; + inline int files_size() const; + inline void clear_files(); + static const int kFilesFieldNumber = 4; + inline const ::rsctrl::core::File& files(int index) const; + inline ::rsctrl::core::File* mutable_files(int index); + inline ::rsctrl::core::File* add_files(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::File >& + files() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::File >* + mutable_files(); + + // @@protoc_insertion_point(class_scope:rsctrl.core.Dir) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_path(); + inline void clear_has_path(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::std::string* path_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Dir > subdirs_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::File > files_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static Dir* default_instance_; +}; +// ------------------------------------------------------------------- + +class SystemStatus : public ::google::protobuf::Message { + public: + SystemStatus(); + virtual ~SystemStatus(); + + SystemStatus(const SystemStatus& from); + + inline SystemStatus& operator=(const SystemStatus& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const SystemStatus& default_instance(); + + void Swap(SystemStatus* other); + + // implements Message ---------------------------------------------- + + SystemStatus* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SystemStatus& from); + void MergeFrom(const SystemStatus& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef SystemStatus_NetCode NetCode; + static const NetCode BAD_UNKNOWN = SystemStatus_NetCode_BAD_UNKNOWN; + static const NetCode BAD_OFFLINE = SystemStatus_NetCode_BAD_OFFLINE; + static const NetCode BAD_NATSYM = SystemStatus_NetCode_BAD_NATSYM; + static const NetCode BAD_NODHT_NAT = SystemStatus_NetCode_BAD_NODHT_NAT; + static const NetCode WARNING_RESTART = SystemStatus_NetCode_WARNING_RESTART; + static const NetCode WARNING_NATTED = SystemStatus_NetCode_WARNING_NATTED; + static const NetCode WARNING_NODHT = SystemStatus_NetCode_WARNING_NODHT; + static const NetCode GOOD = SystemStatus_NetCode_GOOD; + static const NetCode ADV_FORWARD = SystemStatus_NetCode_ADV_FORWARD; + static inline bool NetCode_IsValid(int value) { + return SystemStatus_NetCode_IsValid(value); + } + static const NetCode NetCode_MIN = + SystemStatus_NetCode_NetCode_MIN; + static const NetCode NetCode_MAX = + SystemStatus_NetCode_NetCode_MAX; + static const int NetCode_ARRAYSIZE = + SystemStatus_NetCode_NetCode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + NetCode_descriptor() { + return SystemStatus_NetCode_descriptor(); + } + static inline const ::std::string& NetCode_Name(NetCode value) { + return SystemStatus_NetCode_Name(value); + } + static inline bool NetCode_Parse(const ::std::string& name, + NetCode* value) { + return SystemStatus_NetCode_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.SystemStatus.NetCode net_status = 1; + inline bool has_net_status() const; + inline void clear_net_status(); + static const int kNetStatusFieldNumber = 1; + inline ::rsctrl::core::SystemStatus_NetCode net_status() const; + inline void set_net_status(::rsctrl::core::SystemStatus_NetCode value); + + // optional string msg = 2; + inline bool has_msg() const; + inline void clear_msg(); + static const int kMsgFieldNumber = 2; + inline const ::std::string& msg() const; + inline void set_msg(const ::std::string& value); + inline void set_msg(const char* value); + inline void set_msg(const char* value, size_t size); + inline ::std::string* mutable_msg(); + inline ::std::string* release_msg(); + + // @@protoc_insertion_point(class_scope:rsctrl.core.SystemStatus) + private: + inline void set_has_net_status(); + inline void clear_has_net_status(); + inline void set_has_msg(); + inline void clear_has_msg(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* msg_; + int net_status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static SystemStatus* default_instance_; +}; +// ------------------------------------------------------------------- + +class Bandwidth : public ::google::protobuf::Message { + public: + Bandwidth(); + virtual ~Bandwidth(); + + Bandwidth(const Bandwidth& from); + + inline Bandwidth& operator=(const Bandwidth& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const Bandwidth& default_instance(); + + void Swap(Bandwidth* other); + + // implements Message ---------------------------------------------- + + Bandwidth* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const Bandwidth& from); + void MergeFrom(const Bandwidth& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required float up = 1; + inline bool has_up() const; + inline void clear_up(); + static const int kUpFieldNumber = 1; + inline float up() const; + inline void set_up(float value); + + // required float down = 2; + inline bool has_down() const; + inline void clear_down(); + static const int kDownFieldNumber = 2; + inline float down() const; + inline void set_down(float value); + + // optional string name = 3; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 3; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + + // @@protoc_insertion_point(class_scope:rsctrl.core.Bandwidth) + private: + inline void set_has_up(); + inline void clear_has_up(); + inline void set_has_down(); + inline void clear_has_down(); + inline void set_has_name(); + inline void clear_has_name(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + float up_; + float down_; + ::std::string* name_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static Bandwidth* default_instance_; +}; +// ------------------------------------------------------------------- + +class BandwidthSet : public ::google::protobuf::Message { + public: + BandwidthSet(); + virtual ~BandwidthSet(); + + BandwidthSet(const BandwidthSet& from); + + inline BandwidthSet& operator=(const BandwidthSet& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const BandwidthSet& default_instance(); + + void Swap(BandwidthSet* other); + + // implements Message ---------------------------------------------- + + BandwidthSet* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const BandwidthSet& from); + void MergeFrom(const BandwidthSet& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated .rsctrl.core.Bandwidth bandwidths = 1; + inline int bandwidths_size() const; + inline void clear_bandwidths(); + static const int kBandwidthsFieldNumber = 1; + inline const ::rsctrl::core::Bandwidth& bandwidths(int index) const; + inline ::rsctrl::core::Bandwidth* mutable_bandwidths(int index); + inline ::rsctrl::core::Bandwidth* add_bandwidths(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Bandwidth >& + bandwidths() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Bandwidth >* + mutable_bandwidths(); + + // @@protoc_insertion_point(class_scope:rsctrl.core.BandwidthSet) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Bandwidth > bandwidths_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_core_2eproto(); + friend void protobuf_AssignDesc_core_2eproto(); + friend void protobuf_ShutdownFile_core_2eproto(); + + void InitAsDefaultInstance(); + static BandwidthSet* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// Status + +// required .rsctrl.core.Status.StatusCode code = 1; +inline bool Status::has_code() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Status::set_has_code() { + _has_bits_[0] |= 0x00000001u; +} +inline void Status::clear_has_code() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Status::clear_code() { + code_ = 0; + clear_has_code(); +} +inline ::rsctrl::core::Status_StatusCode Status::code() const { + return static_cast< ::rsctrl::core::Status_StatusCode >(code_); +} +inline void Status::set_code(::rsctrl::core::Status_StatusCode value) { + GOOGLE_DCHECK(::rsctrl::core::Status_StatusCode_IsValid(value)); + set_has_code(); + code_ = value; +} + +// optional string msg = 2; +inline bool Status::has_msg() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Status::set_has_msg() { + _has_bits_[0] |= 0x00000002u; +} +inline void Status::clear_has_msg() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Status::clear_msg() { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + msg_->clear(); + } + clear_has_msg(); +} +inline const ::std::string& Status::msg() const { + return *msg_; +} +inline void Status::set_msg(const ::std::string& value) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(value); +} +inline void Status::set_msg(const char* value) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(value); +} +inline void Status::set_msg(const char* value, size_t size) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Status::mutable_msg() { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + return msg_; +} +inline ::std::string* Status::release_msg() { + clear_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = msg_; + msg_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// IpAddr + +// required string addr = 1 [default = ""]; +inline bool IpAddr::has_addr() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void IpAddr::set_has_addr() { + _has_bits_[0] |= 0x00000001u; +} +inline void IpAddr::clear_has_addr() { + _has_bits_[0] &= ~0x00000001u; +} +inline void IpAddr::clear_addr() { + if (addr_ != &::google::protobuf::internal::kEmptyString) { + addr_->clear(); + } + clear_has_addr(); +} +inline const ::std::string& IpAddr::addr() const { + return *addr_; +} +inline void IpAddr::set_addr(const ::std::string& value) { + set_has_addr(); + if (addr_ == &::google::protobuf::internal::kEmptyString) { + addr_ = new ::std::string; + } + addr_->assign(value); +} +inline void IpAddr::set_addr(const char* value) { + set_has_addr(); + if (addr_ == &::google::protobuf::internal::kEmptyString) { + addr_ = new ::std::string; + } + addr_->assign(value); +} +inline void IpAddr::set_addr(const char* value, size_t size) { + set_has_addr(); + if (addr_ == &::google::protobuf::internal::kEmptyString) { + addr_ = new ::std::string; + } + addr_->assign(reinterpret_cast(value), size); +} +inline ::std::string* IpAddr::mutable_addr() { + set_has_addr(); + if (addr_ == &::google::protobuf::internal::kEmptyString) { + addr_ = new ::std::string; + } + return addr_; +} +inline ::std::string* IpAddr::release_addr() { + clear_has_addr(); + if (addr_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = addr_; + addr_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required uint32 port = 2 [default = 0]; +inline bool IpAddr::has_port() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void IpAddr::set_has_port() { + _has_bits_[0] |= 0x00000002u; +} +inline void IpAddr::clear_has_port() { + _has_bits_[0] &= ~0x00000002u; +} +inline void IpAddr::clear_port() { + port_ = 0u; + clear_has_port(); +} +inline ::google::protobuf::uint32 IpAddr::port() const { + return port_; +} +inline void IpAddr::set_port(::google::protobuf::uint32 value) { + set_has_port(); + port_ = value; +} + +// ------------------------------------------------------------------- + +// Location + +// required string ssl_id = 1; +inline bool Location::has_ssl_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Location::set_has_ssl_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void Location::clear_has_ssl_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Location::clear_ssl_id() { + if (ssl_id_ != &::google::protobuf::internal::kEmptyString) { + ssl_id_->clear(); + } + clear_has_ssl_id(); +} +inline const ::std::string& Location::ssl_id() const { + return *ssl_id_; +} +inline void Location::set_ssl_id(const ::std::string& value) { + set_has_ssl_id(); + if (ssl_id_ == &::google::protobuf::internal::kEmptyString) { + ssl_id_ = new ::std::string; + } + ssl_id_->assign(value); +} +inline void Location::set_ssl_id(const char* value) { + set_has_ssl_id(); + if (ssl_id_ == &::google::protobuf::internal::kEmptyString) { + ssl_id_ = new ::std::string; + } + ssl_id_->assign(value); +} +inline void Location::set_ssl_id(const char* value, size_t size) { + set_has_ssl_id(); + if (ssl_id_ == &::google::protobuf::internal::kEmptyString) { + ssl_id_ = new ::std::string; + } + ssl_id_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Location::mutable_ssl_id() { + set_has_ssl_id(); + if (ssl_id_ == &::google::protobuf::internal::kEmptyString) { + ssl_id_ = new ::std::string; + } + return ssl_id_; +} +inline ::std::string* Location::release_ssl_id() { + clear_has_ssl_id(); + if (ssl_id_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = ssl_id_; + ssl_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string location = 2; +inline bool Location::has_location() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Location::set_has_location() { + _has_bits_[0] |= 0x00000002u; +} +inline void Location::clear_has_location() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Location::clear_location() { + if (location_ != &::google::protobuf::internal::kEmptyString) { + location_->clear(); + } + clear_has_location(); +} +inline const ::std::string& Location::location() const { + return *location_; +} +inline void Location::set_location(const ::std::string& value) { + set_has_location(); + if (location_ == &::google::protobuf::internal::kEmptyString) { + location_ = new ::std::string; + } + location_->assign(value); +} +inline void Location::set_location(const char* value) { + set_has_location(); + if (location_ == &::google::protobuf::internal::kEmptyString) { + location_ = new ::std::string; + } + location_->assign(value); +} +inline void Location::set_location(const char* value, size_t size) { + set_has_location(); + if (location_ == &::google::protobuf::internal::kEmptyString) { + location_ = new ::std::string; + } + location_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Location::mutable_location() { + set_has_location(); + if (location_ == &::google::protobuf::internal::kEmptyString) { + location_ = new ::std::string; + } + return location_; +} +inline ::std::string* Location::release_location() { + clear_has_location(); + if (location_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = location_; + location_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required .rsctrl.core.IpAddr localaddr = 3; +inline bool Location::has_localaddr() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Location::set_has_localaddr() { + _has_bits_[0] |= 0x00000004u; +} +inline void Location::clear_has_localaddr() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Location::clear_localaddr() { + if (localaddr_ != NULL) localaddr_->::rsctrl::core::IpAddr::Clear(); + clear_has_localaddr(); +} +inline const ::rsctrl::core::IpAddr& Location::localaddr() const { + return localaddr_ != NULL ? *localaddr_ : *default_instance_->localaddr_; +} +inline ::rsctrl::core::IpAddr* Location::mutable_localaddr() { + set_has_localaddr(); + if (localaddr_ == NULL) localaddr_ = new ::rsctrl::core::IpAddr; + return localaddr_; +} +inline ::rsctrl::core::IpAddr* Location::release_localaddr() { + clear_has_localaddr(); + ::rsctrl::core::IpAddr* temp = localaddr_; + localaddr_ = NULL; + return temp; +} + +// required .rsctrl.core.IpAddr extaddr = 4; +inline bool Location::has_extaddr() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void Location::set_has_extaddr() { + _has_bits_[0] |= 0x00000008u; +} +inline void Location::clear_has_extaddr() { + _has_bits_[0] &= ~0x00000008u; +} +inline void Location::clear_extaddr() { + if (extaddr_ != NULL) extaddr_->::rsctrl::core::IpAddr::Clear(); + clear_has_extaddr(); +} +inline const ::rsctrl::core::IpAddr& Location::extaddr() const { + return extaddr_ != NULL ? *extaddr_ : *default_instance_->extaddr_; +} +inline ::rsctrl::core::IpAddr* Location::mutable_extaddr() { + set_has_extaddr(); + if (extaddr_ == NULL) extaddr_ = new ::rsctrl::core::IpAddr; + return extaddr_; +} +inline ::rsctrl::core::IpAddr* Location::release_extaddr() { + clear_has_extaddr(); + ::rsctrl::core::IpAddr* temp = extaddr_; + extaddr_ = NULL; + return temp; +} + +// required uint32 state = 5; +inline bool Location::has_state() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void Location::set_has_state() { + _has_bits_[0] |= 0x00000010u; +} +inline void Location::clear_has_state() { + _has_bits_[0] &= ~0x00000010u; +} +inline void Location::clear_state() { + state_ = 0u; + clear_has_state(); +} +inline ::google::protobuf::uint32 Location::state() const { + return state_; +} +inline void Location::set_state(::google::protobuf::uint32 value) { + set_has_state(); + state_ = value; +} + +// ------------------------------------------------------------------- + +// Person + +// required string gpg_id = 1; +inline bool Person::has_gpg_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Person::set_has_gpg_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void Person::clear_has_gpg_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Person::clear_gpg_id() { + if (gpg_id_ != &::google::protobuf::internal::kEmptyString) { + gpg_id_->clear(); + } + clear_has_gpg_id(); +} +inline const ::std::string& Person::gpg_id() const { + return *gpg_id_; +} +inline void Person::set_gpg_id(const ::std::string& value) { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + gpg_id_->assign(value); +} +inline void Person::set_gpg_id(const char* value) { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + gpg_id_->assign(value); +} +inline void Person::set_gpg_id(const char* value, size_t size) { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + gpg_id_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Person::mutable_gpg_id() { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + return gpg_id_; +} +inline ::std::string* Person::release_gpg_id() { + clear_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = gpg_id_; + gpg_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string name = 2; +inline bool Person::has_name() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Person::set_has_name() { + _has_bits_[0] |= 0x00000002u; +} +inline void Person::clear_has_name() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Person::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& Person::name() const { + return *name_; +} +inline void Person::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void Person::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void Person::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Person::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* Person::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required .rsctrl.core.Person.Relationship relation = 3; +inline bool Person::has_relation() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Person::set_has_relation() { + _has_bits_[0] |= 0x00000004u; +} +inline void Person::clear_has_relation() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Person::clear_relation() { + relation_ = 1; + clear_has_relation(); +} +inline ::rsctrl::core::Person_Relationship Person::relation() const { + return static_cast< ::rsctrl::core::Person_Relationship >(relation_); +} +inline void Person::set_relation(::rsctrl::core::Person_Relationship value) { + GOOGLE_DCHECK(::rsctrl::core::Person_Relationship_IsValid(value)); + set_has_relation(); + relation_ = value; +} + +// repeated .rsctrl.core.Location locations = 4; +inline int Person::locations_size() const { + return locations_.size(); +} +inline void Person::clear_locations() { + locations_.Clear(); +} +inline const ::rsctrl::core::Location& Person::locations(int index) const { + return locations_.Get(index); +} +inline ::rsctrl::core::Location* Person::mutable_locations(int index) { + return locations_.Mutable(index); +} +inline ::rsctrl::core::Location* Person::add_locations() { + return locations_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Location >& +Person::locations() const { + return locations_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Location >* +Person::mutable_locations() { + return &locations_; +} + +// ------------------------------------------------------------------- + +// File + +// required string name = 1; +inline bool File::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void File::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void File::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void File::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& File::name() const { + return *name_; +} +inline void File::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void File::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void File::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* File::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* File::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string hash = 2; +inline bool File::has_hash() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void File::set_has_hash() { + _has_bits_[0] |= 0x00000002u; +} +inline void File::clear_has_hash() { + _has_bits_[0] &= ~0x00000002u; +} +inline void File::clear_hash() { + if (hash_ != &::google::protobuf::internal::kEmptyString) { + hash_->clear(); + } + clear_has_hash(); +} +inline const ::std::string& File::hash() const { + return *hash_; +} +inline void File::set_hash(const ::std::string& value) { + set_has_hash(); + if (hash_ == &::google::protobuf::internal::kEmptyString) { + hash_ = new ::std::string; + } + hash_->assign(value); +} +inline void File::set_hash(const char* value) { + set_has_hash(); + if (hash_ == &::google::protobuf::internal::kEmptyString) { + hash_ = new ::std::string; + } + hash_->assign(value); +} +inline void File::set_hash(const char* value, size_t size) { + set_has_hash(); + if (hash_ == &::google::protobuf::internal::kEmptyString) { + hash_ = new ::std::string; + } + hash_->assign(reinterpret_cast(value), size); +} +inline ::std::string* File::mutable_hash() { + set_has_hash(); + if (hash_ == &::google::protobuf::internal::kEmptyString) { + hash_ = new ::std::string; + } + return hash_; +} +inline ::std::string* File::release_hash() { + clear_has_hash(); + if (hash_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = hash_; + hash_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required uint64 size = 3; +inline bool File::has_size() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void File::set_has_size() { + _has_bits_[0] |= 0x00000004u; +} +inline void File::clear_has_size() { + _has_bits_[0] &= ~0x00000004u; +} +inline void File::clear_size() { + size_ = GOOGLE_ULONGLONG(0); + clear_has_size(); +} +inline ::google::protobuf::uint64 File::size() const { + return size_; +} +inline void File::set_size(::google::protobuf::uint64 value) { + set_has_size(); + size_ = value; +} + +// ------------------------------------------------------------------- + +// Dir + +// required string name = 1; +inline bool Dir::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Dir::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void Dir::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Dir::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& Dir::name() const { + return *name_; +} +inline void Dir::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void Dir::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void Dir::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Dir::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* Dir::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required string path = 2; +inline bool Dir::has_path() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Dir::set_has_path() { + _has_bits_[0] |= 0x00000002u; +} +inline void Dir::clear_has_path() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Dir::clear_path() { + if (path_ != &::google::protobuf::internal::kEmptyString) { + path_->clear(); + } + clear_has_path(); +} +inline const ::std::string& Dir::path() const { + return *path_; +} +inline void Dir::set_path(const ::std::string& value) { + set_has_path(); + if (path_ == &::google::protobuf::internal::kEmptyString) { + path_ = new ::std::string; + } + path_->assign(value); +} +inline void Dir::set_path(const char* value) { + set_has_path(); + if (path_ == &::google::protobuf::internal::kEmptyString) { + path_ = new ::std::string; + } + path_->assign(value); +} +inline void Dir::set_path(const char* value, size_t size) { + set_has_path(); + if (path_ == &::google::protobuf::internal::kEmptyString) { + path_ = new ::std::string; + } + path_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Dir::mutable_path() { + set_has_path(); + if (path_ == &::google::protobuf::internal::kEmptyString) { + path_ = new ::std::string; + } + return path_; +} +inline ::std::string* Dir::release_path() { + clear_has_path(); + if (path_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = path_; + path_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// repeated .rsctrl.core.Dir subdirs = 3; +inline int Dir::subdirs_size() const { + return subdirs_.size(); +} +inline void Dir::clear_subdirs() { + subdirs_.Clear(); +} +inline const ::rsctrl::core::Dir& Dir::subdirs(int index) const { + return subdirs_.Get(index); +} +inline ::rsctrl::core::Dir* Dir::mutable_subdirs(int index) { + return subdirs_.Mutable(index); +} +inline ::rsctrl::core::Dir* Dir::add_subdirs() { + return subdirs_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Dir >& +Dir::subdirs() const { + return subdirs_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Dir >* +Dir::mutable_subdirs() { + return &subdirs_; +} + +// repeated .rsctrl.core.File files = 4; +inline int Dir::files_size() const { + return files_.size(); +} +inline void Dir::clear_files() { + files_.Clear(); +} +inline const ::rsctrl::core::File& Dir::files(int index) const { + return files_.Get(index); +} +inline ::rsctrl::core::File* Dir::mutable_files(int index) { + return files_.Mutable(index); +} +inline ::rsctrl::core::File* Dir::add_files() { + return files_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::File >& +Dir::files() const { + return files_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::File >* +Dir::mutable_files() { + return &files_; +} + +// ------------------------------------------------------------------- + +// SystemStatus + +// required .rsctrl.core.SystemStatus.NetCode net_status = 1; +inline bool SystemStatus::has_net_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void SystemStatus::set_has_net_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void SystemStatus::clear_has_net_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void SystemStatus::clear_net_status() { + net_status_ = 0; + clear_has_net_status(); +} +inline ::rsctrl::core::SystemStatus_NetCode SystemStatus::net_status() const { + return static_cast< ::rsctrl::core::SystemStatus_NetCode >(net_status_); +} +inline void SystemStatus::set_net_status(::rsctrl::core::SystemStatus_NetCode value) { + GOOGLE_DCHECK(::rsctrl::core::SystemStatus_NetCode_IsValid(value)); + set_has_net_status(); + net_status_ = value; +} + +// optional string msg = 2; +inline bool SystemStatus::has_msg() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void SystemStatus::set_has_msg() { + _has_bits_[0] |= 0x00000002u; +} +inline void SystemStatus::clear_has_msg() { + _has_bits_[0] &= ~0x00000002u; +} +inline void SystemStatus::clear_msg() { + if (msg_ != &::google::protobuf::internal::kEmptyString) { + msg_->clear(); + } + clear_has_msg(); +} +inline const ::std::string& SystemStatus::msg() const { + return *msg_; +} +inline void SystemStatus::set_msg(const ::std::string& value) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(value); +} +inline void SystemStatus::set_msg(const char* value) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(value); +} +inline void SystemStatus::set_msg(const char* value, size_t size) { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + msg_->assign(reinterpret_cast(value), size); +} +inline ::std::string* SystemStatus::mutable_msg() { + set_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + msg_ = new ::std::string; + } + return msg_; +} +inline ::std::string* SystemStatus::release_msg() { + clear_has_msg(); + if (msg_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = msg_; + msg_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// Bandwidth + +// required float up = 1; +inline bool Bandwidth::has_up() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void Bandwidth::set_has_up() { + _has_bits_[0] |= 0x00000001u; +} +inline void Bandwidth::clear_has_up() { + _has_bits_[0] &= ~0x00000001u; +} +inline void Bandwidth::clear_up() { + up_ = 0; + clear_has_up(); +} +inline float Bandwidth::up() const { + return up_; +} +inline void Bandwidth::set_up(float value) { + set_has_up(); + up_ = value; +} + +// required float down = 2; +inline bool Bandwidth::has_down() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void Bandwidth::set_has_down() { + _has_bits_[0] |= 0x00000002u; +} +inline void Bandwidth::clear_has_down() { + _has_bits_[0] &= ~0x00000002u; +} +inline void Bandwidth::clear_down() { + down_ = 0; + clear_has_down(); +} +inline float Bandwidth::down() const { + return down_; +} +inline void Bandwidth::set_down(float value) { + set_has_down(); + down_ = value; +} + +// optional string name = 3; +inline bool Bandwidth::has_name() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void Bandwidth::set_has_name() { + _has_bits_[0] |= 0x00000004u; +} +inline void Bandwidth::clear_has_name() { + _has_bits_[0] &= ~0x00000004u; +} +inline void Bandwidth::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& Bandwidth::name() const { + return *name_; +} +inline void Bandwidth::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void Bandwidth::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void Bandwidth::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* Bandwidth::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* Bandwidth::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// BandwidthSet + +// repeated .rsctrl.core.Bandwidth bandwidths = 1; +inline int BandwidthSet::bandwidths_size() const { + return bandwidths_.size(); +} +inline void BandwidthSet::clear_bandwidths() { + bandwidths_.Clear(); +} +inline const ::rsctrl::core::Bandwidth& BandwidthSet::bandwidths(int index) const { + return bandwidths_.Get(index); +} +inline ::rsctrl::core::Bandwidth* BandwidthSet::mutable_bandwidths(int index) { + return bandwidths_.Mutable(index); +} +inline ::rsctrl::core::Bandwidth* BandwidthSet::add_bandwidths() { + return bandwidths_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Bandwidth >& +BandwidthSet::bandwidths() const { + return bandwidths_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Bandwidth >* +BandwidthSet::mutable_bandwidths() { + return &bandwidths_; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace core +} // namespace rsctrl + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::core::Status_StatusCode>() { + return ::rsctrl::core::Status_StatusCode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::core::Location_StateFlags>() { + return ::rsctrl::core::Location_StateFlags_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::core::Person_Relationship>() { + return ::rsctrl::core::Person_Relationship_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::core::SystemStatus_NetCode>() { + return ::rsctrl::core::SystemStatus_NetCode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::core::ExtensionId>() { + return rsctrl::core::ExtensionId_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::core::PackageId>() { + return rsctrl::core::PackageId_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_core_2eproto__INCLUDED diff --git a/retroshare-nogui/src/rpc/proto/gencc/files.pb.cc b/retroshare-nogui/src/rpc/proto/gencc/files.pb.cc new file mode 100644 index 000000000..692a89dec --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/files.pb.cc @@ -0,0 +1,1594 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "files.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace files { + +namespace { + +const ::google::protobuf::Descriptor* FileTransfer_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + FileTransfer_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestTransferList_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestTransferList_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseTransferList_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseTransferList_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestControlDownload_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestControlDownload_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestControlDownload_Action_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ResponseControlDownload_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseControlDownload_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* Direction_descriptor_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_files_2eproto() { + protobuf_AddDesc_files_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "files.proto"); + GOOGLE_CHECK(file != NULL); + FileTransfer_descriptor_ = file->message_type(0); + static const int FileTransfer_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileTransfer, file_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileTransfer, direction_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileTransfer, fraction_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileTransfer, rate_kbs_), + }; + FileTransfer_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + FileTransfer_descriptor_, + FileTransfer::default_instance_, + FileTransfer_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileTransfer, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileTransfer, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(FileTransfer)); + RequestTransferList_descriptor_ = file->message_type(1); + static const int RequestTransferList_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestTransferList, direction_), + }; + RequestTransferList_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestTransferList_descriptor_, + RequestTransferList::default_instance_, + RequestTransferList_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestTransferList, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestTransferList, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestTransferList)); + ResponseTransferList_descriptor_ = file->message_type(2); + static const int ResponseTransferList_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseTransferList, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseTransferList, transfers_), + }; + ResponseTransferList_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseTransferList_descriptor_, + ResponseTransferList::default_instance_, + ResponseTransferList_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseTransferList, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseTransferList, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseTransferList)); + RequestControlDownload_descriptor_ = file->message_type(3); + static const int RequestControlDownload_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestControlDownload, file_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestControlDownload, action_), + }; + RequestControlDownload_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestControlDownload_descriptor_, + RequestControlDownload::default_instance_, + RequestControlDownload_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestControlDownload, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestControlDownload, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestControlDownload)); + RequestControlDownload_Action_descriptor_ = RequestControlDownload_descriptor_->enum_type(0); + ResponseControlDownload_descriptor_ = file->message_type(4); + static const int ResponseControlDownload_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseControlDownload, status_), + }; + ResponseControlDownload_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseControlDownload_descriptor_, + ResponseControlDownload::default_instance_, + ResponseControlDownload_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseControlDownload, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseControlDownload, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseControlDownload)); + RequestMsgIds_descriptor_ = file->enum_type(0); + ResponseMsgIds_descriptor_ = file->enum_type(1); + Direction_descriptor_ = file->enum_type(2); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_files_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + FileTransfer_descriptor_, &FileTransfer::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestTransferList_descriptor_, &RequestTransferList::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseTransferList_descriptor_, &ResponseTransferList::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestControlDownload_descriptor_, &RequestControlDownload::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseControlDownload_descriptor_, &ResponseControlDownload::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_files_2eproto() { + delete FileTransfer::default_instance_; + delete FileTransfer_reflection_; + delete RequestTransferList::default_instance_; + delete RequestTransferList_reflection_; + delete ResponseTransferList::default_instance_; + delete ResponseTransferList_reflection_; + delete RequestControlDownload::default_instance_; + delete RequestControlDownload_reflection_; + delete ResponseControlDownload::default_instance_; + delete ResponseControlDownload_reflection_; +} + +void protobuf_AddDesc_files_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::rsctrl::core::protobuf_AddDesc_core_2eproto(); + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\013files.proto\022\014rsctrl.files\032\ncore.proto\"" + "\177\n\014FileTransfer\022\037\n\004file\030\001 \002(\0132\021.rsctrl.c" + "ore.File\022*\n\tdirection\030\002 \002(\0162\027.rsctrl.fil" + "es.Direction\022\020\n\010fraction\030\003 \002(\002\022\020\n\010rate_k" + "Bs\030\004 \002(\002\"A\n\023RequestTransferList\022*\n\tdirec" + "tion\030\001 \002(\0162\027.rsctrl.files.Direction\"j\n\024R" + "esponseTransferList\022#\n\006status\030\001 \002(\0132\023.rs" + "ctrl.core.Status\022-\n\ttransfers\030\002 \003(\0132\032.rs" + "ctrl.files.FileTransfer\"\204\002\n\026RequestContr" + "olDownload\022\037\n\004file\030\001 \002(\0132\021.rsctrl.core.F" + "ile\022;\n\006action\030\002 \002(\0162+.rsctrl.files.Reque" + "stControlDownload.Action\"\213\001\n\006Action\022\020\n\014A" + "CTION_START\020\001\022\023\n\017ACTION_CONTINUE\020\002\022\017\n\013AC" + "TION_WAIT\020\003\022\020\n\014ACTION_PAUSE\020\004\022\022\n\016ACTION_" + "RESTART\020\005\022\020\n\014ACTION_CHECK\020\006\022\021\n\rACTION_CA" + "NCEL\020\007\">\n\027ResponseControlDownload\022#\n\006sta" + "tus\030\001 \002(\0132\023.rsctrl.core.Status*P\n\rReques" + "tMsgIds\022\035\n\031MsgId_RequestTransferList\020\001\022 " + "\n\034MsgId_RequestControlDownload\020\002*S\n\016Resp" + "onseMsgIds\022\036\n\032MsgId_ResponseTransferList" + "\020\001\022!\n\035MsgId_ResponseControlDownload\020\002*9\n" + "\tDirection\022\024\n\020DIRECTION_UPLOAD\020\001\022\026\n\022DIRE" + "CTION_DOWNLOAD\020\002", 896); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "files.proto", &protobuf_RegisterTypes); + FileTransfer::default_instance_ = new FileTransfer(); + RequestTransferList::default_instance_ = new RequestTransferList(); + ResponseTransferList::default_instance_ = new ResponseTransferList(); + RequestControlDownload::default_instance_ = new RequestControlDownload(); + ResponseControlDownload::default_instance_ = new ResponseControlDownload(); + FileTransfer::default_instance_->InitAsDefaultInstance(); + RequestTransferList::default_instance_->InitAsDefaultInstance(); + ResponseTransferList::default_instance_->InitAsDefaultInstance(); + RequestControlDownload::default_instance_->InitAsDefaultInstance(); + ResponseControlDownload::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_files_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_files_2eproto { + StaticDescriptorInitializer_files_2eproto() { + protobuf_AddDesc_files_2eproto(); + } +} static_descriptor_initializer_files_2eproto_; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestMsgIds_descriptor_; +} +bool RequestMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseMsgIds_descriptor_; +} +bool ResponseMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* Direction_descriptor() { + protobuf_AssignDescriptorsOnce(); + return Direction_descriptor_; +} +bool Direction_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + + +// =================================================================== + +#ifndef _MSC_VER +const int FileTransfer::kFileFieldNumber; +const int FileTransfer::kDirectionFieldNumber; +const int FileTransfer::kFractionFieldNumber; +const int FileTransfer::kRateKBsFieldNumber; +#endif // !_MSC_VER + +FileTransfer::FileTransfer() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void FileTransfer::InitAsDefaultInstance() { + file_ = const_cast< ::rsctrl::core::File*>(&::rsctrl::core::File::default_instance()); +} + +FileTransfer::FileTransfer(const FileTransfer& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void FileTransfer::SharedCtor() { + _cached_size_ = 0; + file_ = NULL; + direction_ = 1; + fraction_ = 0; + rate_kbs_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +FileTransfer::~FileTransfer() { + SharedDtor(); +} + +void FileTransfer::SharedDtor() { + if (this != default_instance_) { + delete file_; + } +} + +void FileTransfer::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* FileTransfer::descriptor() { + protobuf_AssignDescriptorsOnce(); + return FileTransfer_descriptor_; +} + +const FileTransfer& FileTransfer::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_files_2eproto(); return *default_instance_; +} + +FileTransfer* FileTransfer::default_instance_ = NULL; + +FileTransfer* FileTransfer::New() const { + return new FileTransfer; +} + +void FileTransfer::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_file()) { + if (file_ != NULL) file_->::rsctrl::core::File::Clear(); + } + direction_ = 1; + fraction_ = 0; + rate_kbs_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool FileTransfer::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.File file = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_file())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_direction; + break; + } + + // required .rsctrl.files.Direction direction = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_direction: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (rsctrl::files::Direction_IsValid(value)) { + set_direction(static_cast< rsctrl::files::Direction >(value)); + } else { + mutable_unknown_fields()->AddVarint(2, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_fraction; + break; + } + + // required float fraction = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_fraction: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &fraction_))); + set_has_fraction(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_rate_kBs; + break; + } + + // required float rate_kBs = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_rate_kBs: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &rate_kbs_))); + set_has_rate_kbs(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void FileTransfer::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.File file = 1; + if (has_file()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->file(), output); + } + + // required .rsctrl.files.Direction direction = 2; + if (has_direction()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 2, this->direction(), output); + } + + // required float fraction = 3; + if (has_fraction()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->fraction(), output); + } + + // required float rate_kBs = 4; + if (has_rate_kbs()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->rate_kbs(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* FileTransfer::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.File file = 1; + if (has_file()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->file(), target); + } + + // required .rsctrl.files.Direction direction = 2; + if (has_direction()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 2, this->direction(), target); + } + + // required float fraction = 3; + if (has_fraction()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->fraction(), target); + } + + // required float rate_kBs = 4; + if (has_rate_kbs()) { + target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(4, this->rate_kbs(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int FileTransfer::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.File file = 1; + if (has_file()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->file()); + } + + // required .rsctrl.files.Direction direction = 2; + if (has_direction()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->direction()); + } + + // required float fraction = 3; + if (has_fraction()) { + total_size += 1 + 4; + } + + // required float rate_kBs = 4; + if (has_rate_kbs()) { + total_size += 1 + 4; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void FileTransfer::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const FileTransfer* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void FileTransfer::MergeFrom(const FileTransfer& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_file()) { + mutable_file()->::rsctrl::core::File::MergeFrom(from.file()); + } + if (from.has_direction()) { + set_direction(from.direction()); + } + if (from.has_fraction()) { + set_fraction(from.fraction()); + } + if (from.has_rate_kbs()) { + set_rate_kbs(from.rate_kbs()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void FileTransfer::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void FileTransfer::CopyFrom(const FileTransfer& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileTransfer::IsInitialized() const { + if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false; + + if (has_file()) { + if (!this->file().IsInitialized()) return false; + } + return true; +} + +void FileTransfer::Swap(FileTransfer* other) { + if (other != this) { + std::swap(file_, other->file_); + std::swap(direction_, other->direction_); + std::swap(fraction_, other->fraction_); + std::swap(rate_kbs_, other->rate_kbs_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata FileTransfer::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileTransfer_descriptor_; + metadata.reflection = FileTransfer_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestTransferList::kDirectionFieldNumber; +#endif // !_MSC_VER + +RequestTransferList::RequestTransferList() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestTransferList::InitAsDefaultInstance() { +} + +RequestTransferList::RequestTransferList(const RequestTransferList& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestTransferList::SharedCtor() { + _cached_size_ = 0; + direction_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestTransferList::~RequestTransferList() { + SharedDtor(); +} + +void RequestTransferList::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestTransferList::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestTransferList::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestTransferList_descriptor_; +} + +const RequestTransferList& RequestTransferList::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_files_2eproto(); return *default_instance_; +} + +RequestTransferList* RequestTransferList::default_instance_ = NULL; + +RequestTransferList* RequestTransferList::New() const { + return new RequestTransferList; +} + +void RequestTransferList::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + direction_ = 1; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestTransferList::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.files.Direction direction = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (rsctrl::files::Direction_IsValid(value)) { + set_direction(static_cast< rsctrl::files::Direction >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestTransferList::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.files.Direction direction = 1; + if (has_direction()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->direction(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestTransferList::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.files.Direction direction = 1; + if (has_direction()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->direction(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestTransferList::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.files.Direction direction = 1; + if (has_direction()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->direction()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestTransferList::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestTransferList* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestTransferList::MergeFrom(const RequestTransferList& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_direction()) { + set_direction(from.direction()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestTransferList::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestTransferList::CopyFrom(const RequestTransferList& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestTransferList::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void RequestTransferList::Swap(RequestTransferList* other) { + if (other != this) { + std::swap(direction_, other->direction_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestTransferList::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestTransferList_descriptor_; + metadata.reflection = RequestTransferList_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseTransferList::kStatusFieldNumber; +const int ResponseTransferList::kTransfersFieldNumber; +#endif // !_MSC_VER + +ResponseTransferList::ResponseTransferList() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseTransferList::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseTransferList::ResponseTransferList(const ResponseTransferList& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseTransferList::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseTransferList::~ResponseTransferList() { + SharedDtor(); +} + +void ResponseTransferList::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseTransferList::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseTransferList::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseTransferList_descriptor_; +} + +const ResponseTransferList& ResponseTransferList::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_files_2eproto(); return *default_instance_; +} + +ResponseTransferList* ResponseTransferList::default_instance_ = NULL; + +ResponseTransferList* ResponseTransferList::New() const { + return new ResponseTransferList; +} + +void ResponseTransferList::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + transfers_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseTransferList::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_transfers; + break; + } + + // repeated .rsctrl.files.FileTransfer transfers = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_transfers: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_transfers())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_transfers; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseTransferList::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated .rsctrl.files.FileTransfer transfers = 2; + for (int i = 0; i < this->transfers_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->transfers(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseTransferList::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated .rsctrl.files.FileTransfer transfers = 2; + for (int i = 0; i < this->transfers_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->transfers(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseTransferList::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated .rsctrl.files.FileTransfer transfers = 2; + total_size += 1 * this->transfers_size(); + for (int i = 0; i < this->transfers_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->transfers(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseTransferList::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseTransferList* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseTransferList::MergeFrom(const ResponseTransferList& from) { + GOOGLE_CHECK_NE(&from, this); + transfers_.MergeFrom(from.transfers_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseTransferList::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseTransferList::CopyFrom(const ResponseTransferList& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseTransferList::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + for (int i = 0; i < transfers_size(); i++) { + if (!this->transfers(i).IsInitialized()) return false; + } + return true; +} + +void ResponseTransferList::Swap(ResponseTransferList* other) { + if (other != this) { + std::swap(status_, other->status_); + transfers_.Swap(&other->transfers_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseTransferList::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseTransferList_descriptor_; + metadata.reflection = ResponseTransferList_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestControlDownload_Action_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestControlDownload_Action_descriptor_; +} +bool RequestControlDownload_Action_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestControlDownload_Action RequestControlDownload::ACTION_START; +const RequestControlDownload_Action RequestControlDownload::ACTION_CONTINUE; +const RequestControlDownload_Action RequestControlDownload::ACTION_WAIT; +const RequestControlDownload_Action RequestControlDownload::ACTION_PAUSE; +const RequestControlDownload_Action RequestControlDownload::ACTION_RESTART; +const RequestControlDownload_Action RequestControlDownload::ACTION_CHECK; +const RequestControlDownload_Action RequestControlDownload::ACTION_CANCEL; +const RequestControlDownload_Action RequestControlDownload::Action_MIN; +const RequestControlDownload_Action RequestControlDownload::Action_MAX; +const int RequestControlDownload::Action_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestControlDownload::kFileFieldNumber; +const int RequestControlDownload::kActionFieldNumber; +#endif // !_MSC_VER + +RequestControlDownload::RequestControlDownload() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestControlDownload::InitAsDefaultInstance() { + file_ = const_cast< ::rsctrl::core::File*>(&::rsctrl::core::File::default_instance()); +} + +RequestControlDownload::RequestControlDownload(const RequestControlDownload& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestControlDownload::SharedCtor() { + _cached_size_ = 0; + file_ = NULL; + action_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestControlDownload::~RequestControlDownload() { + SharedDtor(); +} + +void RequestControlDownload::SharedDtor() { + if (this != default_instance_) { + delete file_; + } +} + +void RequestControlDownload::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestControlDownload::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestControlDownload_descriptor_; +} + +const RequestControlDownload& RequestControlDownload::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_files_2eproto(); return *default_instance_; +} + +RequestControlDownload* RequestControlDownload::default_instance_ = NULL; + +RequestControlDownload* RequestControlDownload::New() const { + return new RequestControlDownload; +} + +void RequestControlDownload::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_file()) { + if (file_ != NULL) file_->::rsctrl::core::File::Clear(); + } + action_ = 1; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestControlDownload::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.File file = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_file())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_action; + break; + } + + // required .rsctrl.files.RequestControlDownload.Action action = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_action: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::files::RequestControlDownload_Action_IsValid(value)) { + set_action(static_cast< ::rsctrl::files::RequestControlDownload_Action >(value)); + } else { + mutable_unknown_fields()->AddVarint(2, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestControlDownload::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.File file = 1; + if (has_file()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->file(), output); + } + + // required .rsctrl.files.RequestControlDownload.Action action = 2; + if (has_action()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 2, this->action(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestControlDownload::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.File file = 1; + if (has_file()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->file(), target); + } + + // required .rsctrl.files.RequestControlDownload.Action action = 2; + if (has_action()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 2, this->action(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestControlDownload::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.File file = 1; + if (has_file()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->file()); + } + + // required .rsctrl.files.RequestControlDownload.Action action = 2; + if (has_action()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->action()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestControlDownload::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestControlDownload* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestControlDownload::MergeFrom(const RequestControlDownload& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_file()) { + mutable_file()->::rsctrl::core::File::MergeFrom(from.file()); + } + if (from.has_action()) { + set_action(from.action()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestControlDownload::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestControlDownload::CopyFrom(const RequestControlDownload& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestControlDownload::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + if (has_file()) { + if (!this->file().IsInitialized()) return false; + } + return true; +} + +void RequestControlDownload::Swap(RequestControlDownload* other) { + if (other != this) { + std::swap(file_, other->file_); + std::swap(action_, other->action_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestControlDownload::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestControlDownload_descriptor_; + metadata.reflection = RequestControlDownload_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseControlDownload::kStatusFieldNumber; +#endif // !_MSC_VER + +ResponseControlDownload::ResponseControlDownload() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseControlDownload::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseControlDownload::ResponseControlDownload(const ResponseControlDownload& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseControlDownload::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseControlDownload::~ResponseControlDownload() { + SharedDtor(); +} + +void ResponseControlDownload::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseControlDownload::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseControlDownload::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseControlDownload_descriptor_; +} + +const ResponseControlDownload& ResponseControlDownload::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_files_2eproto(); return *default_instance_; +} + +ResponseControlDownload* ResponseControlDownload::default_instance_ = NULL; + +ResponseControlDownload* ResponseControlDownload::New() const { + return new ResponseControlDownload; +} + +void ResponseControlDownload::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseControlDownload::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseControlDownload::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseControlDownload::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseControlDownload::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseControlDownload::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseControlDownload* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseControlDownload::MergeFrom(const ResponseControlDownload& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseControlDownload::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseControlDownload::CopyFrom(const ResponseControlDownload& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseControlDownload::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + return true; +} + +void ResponseControlDownload::Swap(ResponseControlDownload* other) { + if (other != this) { + std::swap(status_, other->status_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseControlDownload::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseControlDownload_descriptor_; + metadata.reflection = ResponseControlDownload_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace files +} // namespace rsctrl + +// @@protoc_insertion_point(global_scope) diff --git a/retroshare-nogui/src/rpc/proto/gencc/files.pb.h b/retroshare-nogui/src/rpc/proto/gencc/files.pb.h new file mode 100644 index 000000000..39a7b8c44 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/files.pb.h @@ -0,0 +1,930 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: files.proto + +#ifndef PROTOBUF_files_2eproto__INCLUDED +#define PROTOBUF_files_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include "core.pb.h" +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace files { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_files_2eproto(); +void protobuf_AssignDesc_files_2eproto(); +void protobuf_ShutdownFile_files_2eproto(); + +class FileTransfer; +class RequestTransferList; +class ResponseTransferList; +class RequestControlDownload; +class ResponseControlDownload; + +enum RequestControlDownload_Action { + RequestControlDownload_Action_ACTION_START = 1, + RequestControlDownload_Action_ACTION_CONTINUE = 2, + RequestControlDownload_Action_ACTION_WAIT = 3, + RequestControlDownload_Action_ACTION_PAUSE = 4, + RequestControlDownload_Action_ACTION_RESTART = 5, + RequestControlDownload_Action_ACTION_CHECK = 6, + RequestControlDownload_Action_ACTION_CANCEL = 7 +}; +bool RequestControlDownload_Action_IsValid(int value); +const RequestControlDownload_Action RequestControlDownload_Action_Action_MIN = RequestControlDownload_Action_ACTION_START; +const RequestControlDownload_Action RequestControlDownload_Action_Action_MAX = RequestControlDownload_Action_ACTION_CANCEL; +const int RequestControlDownload_Action_Action_ARRAYSIZE = RequestControlDownload_Action_Action_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestControlDownload_Action_descriptor(); +inline const ::std::string& RequestControlDownload_Action_Name(RequestControlDownload_Action value) { + return ::google::protobuf::internal::NameOfEnum( + RequestControlDownload_Action_descriptor(), value); +} +inline bool RequestControlDownload_Action_Parse( + const ::std::string& name, RequestControlDownload_Action* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestControlDownload_Action_descriptor(), name, value); +} +enum RequestMsgIds { + MsgId_RequestTransferList = 1, + MsgId_RequestControlDownload = 2 +}; +bool RequestMsgIds_IsValid(int value); +const RequestMsgIds RequestMsgIds_MIN = MsgId_RequestTransferList; +const RequestMsgIds RequestMsgIds_MAX = MsgId_RequestControlDownload; +const int RequestMsgIds_ARRAYSIZE = RequestMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor(); +inline const ::std::string& RequestMsgIds_Name(RequestMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + RequestMsgIds_descriptor(), value); +} +inline bool RequestMsgIds_Parse( + const ::std::string& name, RequestMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestMsgIds_descriptor(), name, value); +} +enum ResponseMsgIds { + MsgId_ResponseTransferList = 1, + MsgId_ResponseControlDownload = 2 +}; +bool ResponseMsgIds_IsValid(int value); +const ResponseMsgIds ResponseMsgIds_MIN = MsgId_ResponseTransferList; +const ResponseMsgIds ResponseMsgIds_MAX = MsgId_ResponseControlDownload; +const int ResponseMsgIds_ARRAYSIZE = ResponseMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor(); +inline const ::std::string& ResponseMsgIds_Name(ResponseMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + ResponseMsgIds_descriptor(), value); +} +inline bool ResponseMsgIds_Parse( + const ::std::string& name, ResponseMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ResponseMsgIds_descriptor(), name, value); +} +enum Direction { + DIRECTION_UPLOAD = 1, + DIRECTION_DOWNLOAD = 2 +}; +bool Direction_IsValid(int value); +const Direction Direction_MIN = DIRECTION_UPLOAD; +const Direction Direction_MAX = DIRECTION_DOWNLOAD; +const int Direction_ARRAYSIZE = Direction_MAX + 1; + +const ::google::protobuf::EnumDescriptor* Direction_descriptor(); +inline const ::std::string& Direction_Name(Direction value) { + return ::google::protobuf::internal::NameOfEnum( + Direction_descriptor(), value); +} +inline bool Direction_Parse( + const ::std::string& name, Direction* value) { + return ::google::protobuf::internal::ParseNamedEnum( + Direction_descriptor(), name, value); +} +// =================================================================== + +class FileTransfer : public ::google::protobuf::Message { + public: + FileTransfer(); + virtual ~FileTransfer(); + + FileTransfer(const FileTransfer& from); + + inline FileTransfer& operator=(const FileTransfer& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const FileTransfer& default_instance(); + + void Swap(FileTransfer* other); + + // implements Message ---------------------------------------------- + + FileTransfer* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const FileTransfer& from); + void MergeFrom(const FileTransfer& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.File file = 1; + inline bool has_file() const; + inline void clear_file(); + static const int kFileFieldNumber = 1; + inline const ::rsctrl::core::File& file() const; + inline ::rsctrl::core::File* mutable_file(); + inline ::rsctrl::core::File* release_file(); + + // required .rsctrl.files.Direction direction = 2; + inline bool has_direction() const; + inline void clear_direction(); + static const int kDirectionFieldNumber = 2; + inline rsctrl::files::Direction direction() const; + inline void set_direction(rsctrl::files::Direction value); + + // required float fraction = 3; + inline bool has_fraction() const; + inline void clear_fraction(); + static const int kFractionFieldNumber = 3; + inline float fraction() const; + inline void set_fraction(float value); + + // required float rate_kBs = 4; + inline bool has_rate_kbs() const; + inline void clear_rate_kbs(); + static const int kRateKBsFieldNumber = 4; + inline float rate_kbs() const; + inline void set_rate_kbs(float value); + + // @@protoc_insertion_point(class_scope:rsctrl.files.FileTransfer) + private: + inline void set_has_file(); + inline void clear_has_file(); + inline void set_has_direction(); + inline void clear_has_direction(); + inline void set_has_fraction(); + inline void clear_has_fraction(); + inline void set_has_rate_kbs(); + inline void clear_has_rate_kbs(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::File* file_; + int direction_; + float fraction_; + float rate_kbs_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_files_2eproto(); + friend void protobuf_AssignDesc_files_2eproto(); + friend void protobuf_ShutdownFile_files_2eproto(); + + void InitAsDefaultInstance(); + static FileTransfer* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestTransferList : public ::google::protobuf::Message { + public: + RequestTransferList(); + virtual ~RequestTransferList(); + + RequestTransferList(const RequestTransferList& from); + + inline RequestTransferList& operator=(const RequestTransferList& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestTransferList& default_instance(); + + void Swap(RequestTransferList* other); + + // implements Message ---------------------------------------------- + + RequestTransferList* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestTransferList& from); + void MergeFrom(const RequestTransferList& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.files.Direction direction = 1; + inline bool has_direction() const; + inline void clear_direction(); + static const int kDirectionFieldNumber = 1; + inline rsctrl::files::Direction direction() const; + inline void set_direction(rsctrl::files::Direction value); + + // @@protoc_insertion_point(class_scope:rsctrl.files.RequestTransferList) + private: + inline void set_has_direction(); + inline void clear_has_direction(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + int direction_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_files_2eproto(); + friend void protobuf_AssignDesc_files_2eproto(); + friend void protobuf_ShutdownFile_files_2eproto(); + + void InitAsDefaultInstance(); + static RequestTransferList* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseTransferList : public ::google::protobuf::Message { + public: + ResponseTransferList(); + virtual ~ResponseTransferList(); + + ResponseTransferList(const ResponseTransferList& from); + + inline ResponseTransferList& operator=(const ResponseTransferList& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseTransferList& default_instance(); + + void Swap(ResponseTransferList* other); + + // implements Message ---------------------------------------------- + + ResponseTransferList* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseTransferList& from); + void MergeFrom(const ResponseTransferList& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated .rsctrl.files.FileTransfer transfers = 2; + inline int transfers_size() const; + inline void clear_transfers(); + static const int kTransfersFieldNumber = 2; + inline const ::rsctrl::files::FileTransfer& transfers(int index) const; + inline ::rsctrl::files::FileTransfer* mutable_transfers(int index); + inline ::rsctrl::files::FileTransfer* add_transfers(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::files::FileTransfer >& + transfers() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::files::FileTransfer >* + mutable_transfers(); + + // @@protoc_insertion_point(class_scope:rsctrl.files.ResponseTransferList) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::files::FileTransfer > transfers_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_files_2eproto(); + friend void protobuf_AssignDesc_files_2eproto(); + friend void protobuf_ShutdownFile_files_2eproto(); + + void InitAsDefaultInstance(); + static ResponseTransferList* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestControlDownload : public ::google::protobuf::Message { + public: + RequestControlDownload(); + virtual ~RequestControlDownload(); + + RequestControlDownload(const RequestControlDownload& from); + + inline RequestControlDownload& operator=(const RequestControlDownload& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestControlDownload& default_instance(); + + void Swap(RequestControlDownload* other); + + // implements Message ---------------------------------------------- + + RequestControlDownload* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestControlDownload& from); + void MergeFrom(const RequestControlDownload& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestControlDownload_Action Action; + static const Action ACTION_START = RequestControlDownload_Action_ACTION_START; + static const Action ACTION_CONTINUE = RequestControlDownload_Action_ACTION_CONTINUE; + static const Action ACTION_WAIT = RequestControlDownload_Action_ACTION_WAIT; + static const Action ACTION_PAUSE = RequestControlDownload_Action_ACTION_PAUSE; + static const Action ACTION_RESTART = RequestControlDownload_Action_ACTION_RESTART; + static const Action ACTION_CHECK = RequestControlDownload_Action_ACTION_CHECK; + static const Action ACTION_CANCEL = RequestControlDownload_Action_ACTION_CANCEL; + static inline bool Action_IsValid(int value) { + return RequestControlDownload_Action_IsValid(value); + } + static const Action Action_MIN = + RequestControlDownload_Action_Action_MIN; + static const Action Action_MAX = + RequestControlDownload_Action_Action_MAX; + static const int Action_ARRAYSIZE = + RequestControlDownload_Action_Action_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Action_descriptor() { + return RequestControlDownload_Action_descriptor(); + } + static inline const ::std::string& Action_Name(Action value) { + return RequestControlDownload_Action_Name(value); + } + static inline bool Action_Parse(const ::std::string& name, + Action* value) { + return RequestControlDownload_Action_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.File file = 1; + inline bool has_file() const; + inline void clear_file(); + static const int kFileFieldNumber = 1; + inline const ::rsctrl::core::File& file() const; + inline ::rsctrl::core::File* mutable_file(); + inline ::rsctrl::core::File* release_file(); + + // required .rsctrl.files.RequestControlDownload.Action action = 2; + inline bool has_action() const; + inline void clear_action(); + static const int kActionFieldNumber = 2; + inline ::rsctrl::files::RequestControlDownload_Action action() const; + inline void set_action(::rsctrl::files::RequestControlDownload_Action value); + + // @@protoc_insertion_point(class_scope:rsctrl.files.RequestControlDownload) + private: + inline void set_has_file(); + inline void clear_has_file(); + inline void set_has_action(); + inline void clear_has_action(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::File* file_; + int action_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_files_2eproto(); + friend void protobuf_AssignDesc_files_2eproto(); + friend void protobuf_ShutdownFile_files_2eproto(); + + void InitAsDefaultInstance(); + static RequestControlDownload* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseControlDownload : public ::google::protobuf::Message { + public: + ResponseControlDownload(); + virtual ~ResponseControlDownload(); + + ResponseControlDownload(const ResponseControlDownload& from); + + inline ResponseControlDownload& operator=(const ResponseControlDownload& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseControlDownload& default_instance(); + + void Swap(ResponseControlDownload* other); + + // implements Message ---------------------------------------------- + + ResponseControlDownload* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseControlDownload& from); + void MergeFrom(const ResponseControlDownload& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // @@protoc_insertion_point(class_scope:rsctrl.files.ResponseControlDownload) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_files_2eproto(); + friend void protobuf_AssignDesc_files_2eproto(); + friend void protobuf_ShutdownFile_files_2eproto(); + + void InitAsDefaultInstance(); + static ResponseControlDownload* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// FileTransfer + +// required .rsctrl.core.File file = 1; +inline bool FileTransfer::has_file() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileTransfer::set_has_file() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileTransfer::clear_has_file() { + _has_bits_[0] &= ~0x00000001u; +} +inline void FileTransfer::clear_file() { + if (file_ != NULL) file_->::rsctrl::core::File::Clear(); + clear_has_file(); +} +inline const ::rsctrl::core::File& FileTransfer::file() const { + return file_ != NULL ? *file_ : *default_instance_->file_; +} +inline ::rsctrl::core::File* FileTransfer::mutable_file() { + set_has_file(); + if (file_ == NULL) file_ = new ::rsctrl::core::File; + return file_; +} +inline ::rsctrl::core::File* FileTransfer::release_file() { + clear_has_file(); + ::rsctrl::core::File* temp = file_; + file_ = NULL; + return temp; +} + +// required .rsctrl.files.Direction direction = 2; +inline bool FileTransfer::has_direction() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileTransfer::set_has_direction() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileTransfer::clear_has_direction() { + _has_bits_[0] &= ~0x00000002u; +} +inline void FileTransfer::clear_direction() { + direction_ = 1; + clear_has_direction(); +} +inline rsctrl::files::Direction FileTransfer::direction() const { + return static_cast< rsctrl::files::Direction >(direction_); +} +inline void FileTransfer::set_direction(rsctrl::files::Direction value) { + GOOGLE_DCHECK(rsctrl::files::Direction_IsValid(value)); + set_has_direction(); + direction_ = value; +} + +// required float fraction = 3; +inline bool FileTransfer::has_fraction() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FileTransfer::set_has_fraction() { + _has_bits_[0] |= 0x00000004u; +} +inline void FileTransfer::clear_has_fraction() { + _has_bits_[0] &= ~0x00000004u; +} +inline void FileTransfer::clear_fraction() { + fraction_ = 0; + clear_has_fraction(); +} +inline float FileTransfer::fraction() const { + return fraction_; +} +inline void FileTransfer::set_fraction(float value) { + set_has_fraction(); + fraction_ = value; +} + +// required float rate_kBs = 4; +inline bool FileTransfer::has_rate_kbs() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FileTransfer::set_has_rate_kbs() { + _has_bits_[0] |= 0x00000008u; +} +inline void FileTransfer::clear_has_rate_kbs() { + _has_bits_[0] &= ~0x00000008u; +} +inline void FileTransfer::clear_rate_kbs() { + rate_kbs_ = 0; + clear_has_rate_kbs(); +} +inline float FileTransfer::rate_kbs() const { + return rate_kbs_; +} +inline void FileTransfer::set_rate_kbs(float value) { + set_has_rate_kbs(); + rate_kbs_ = value; +} + +// ------------------------------------------------------------------- + +// RequestTransferList + +// required .rsctrl.files.Direction direction = 1; +inline bool RequestTransferList::has_direction() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestTransferList::set_has_direction() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestTransferList::clear_has_direction() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestTransferList::clear_direction() { + direction_ = 1; + clear_has_direction(); +} +inline rsctrl::files::Direction RequestTransferList::direction() const { + return static_cast< rsctrl::files::Direction >(direction_); +} +inline void RequestTransferList::set_direction(rsctrl::files::Direction value) { + GOOGLE_DCHECK(rsctrl::files::Direction_IsValid(value)); + set_has_direction(); + direction_ = value; +} + +// ------------------------------------------------------------------- + +// ResponseTransferList + +// required .rsctrl.core.Status status = 1; +inline bool ResponseTransferList::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseTransferList::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseTransferList::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseTransferList::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseTransferList::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseTransferList::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseTransferList::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated .rsctrl.files.FileTransfer transfers = 2; +inline int ResponseTransferList::transfers_size() const { + return transfers_.size(); +} +inline void ResponseTransferList::clear_transfers() { + transfers_.Clear(); +} +inline const ::rsctrl::files::FileTransfer& ResponseTransferList::transfers(int index) const { + return transfers_.Get(index); +} +inline ::rsctrl::files::FileTransfer* ResponseTransferList::mutable_transfers(int index) { + return transfers_.Mutable(index); +} +inline ::rsctrl::files::FileTransfer* ResponseTransferList::add_transfers() { + return transfers_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::files::FileTransfer >& +ResponseTransferList::transfers() const { + return transfers_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::files::FileTransfer >* +ResponseTransferList::mutable_transfers() { + return &transfers_; +} + +// ------------------------------------------------------------------- + +// RequestControlDownload + +// required .rsctrl.core.File file = 1; +inline bool RequestControlDownload::has_file() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestControlDownload::set_has_file() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestControlDownload::clear_has_file() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestControlDownload::clear_file() { + if (file_ != NULL) file_->::rsctrl::core::File::Clear(); + clear_has_file(); +} +inline const ::rsctrl::core::File& RequestControlDownload::file() const { + return file_ != NULL ? *file_ : *default_instance_->file_; +} +inline ::rsctrl::core::File* RequestControlDownload::mutable_file() { + set_has_file(); + if (file_ == NULL) file_ = new ::rsctrl::core::File; + return file_; +} +inline ::rsctrl::core::File* RequestControlDownload::release_file() { + clear_has_file(); + ::rsctrl::core::File* temp = file_; + file_ = NULL; + return temp; +} + +// required .rsctrl.files.RequestControlDownload.Action action = 2; +inline bool RequestControlDownload::has_action() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RequestControlDownload::set_has_action() { + _has_bits_[0] |= 0x00000002u; +} +inline void RequestControlDownload::clear_has_action() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RequestControlDownload::clear_action() { + action_ = 1; + clear_has_action(); +} +inline ::rsctrl::files::RequestControlDownload_Action RequestControlDownload::action() const { + return static_cast< ::rsctrl::files::RequestControlDownload_Action >(action_); +} +inline void RequestControlDownload::set_action(::rsctrl::files::RequestControlDownload_Action value) { + GOOGLE_DCHECK(::rsctrl::files::RequestControlDownload_Action_IsValid(value)); + set_has_action(); + action_ = value; +} + +// ------------------------------------------------------------------- + +// ResponseControlDownload + +// required .rsctrl.core.Status status = 1; +inline bool ResponseControlDownload::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseControlDownload::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseControlDownload::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseControlDownload::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseControlDownload::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseControlDownload::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseControlDownload::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace files +} // namespace rsctrl + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::files::RequestControlDownload_Action>() { + return ::rsctrl::files::RequestControlDownload_Action_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::files::RequestMsgIds>() { + return rsctrl::files::RequestMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::files::ResponseMsgIds>() { + return rsctrl::files::ResponseMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::files::Direction>() { + return rsctrl::files::Direction_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_files_2eproto__INCLUDED diff --git a/retroshare-nogui/src/rpc/proto/gencc/peers.pb.cc b/retroshare-nogui/src/rpc/proto/gencc/peers.pb.cc new file mode 100644 index 000000000..948feed64 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/peers.pb.cc @@ -0,0 +1,2074 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "peers.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace peers { + +namespace { + +const ::google::protobuf::Descriptor* RequestPeers_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestPeers_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestPeers_SetOption_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestPeers_InfoOption_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ResponsePeerList_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponsePeerList_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestAddPeer_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestAddPeer_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestAddPeer_AddCmd_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ResponseAddPeer_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseAddPeer_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestModifyPeer_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestModifyPeer_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestModifyPeer_ModCmd_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ResponseModifyPeer_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseModifyPeer_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_peers_2eproto() { + protobuf_AddDesc_peers_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "peers.proto"); + GOOGLE_CHECK(file != NULL); + RequestPeers_descriptor_ = file->message_type(0); + static const int RequestPeers_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestPeers, set_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestPeers, info_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestPeers, gpg_ids_), + }; + RequestPeers_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestPeers_descriptor_, + RequestPeers::default_instance_, + RequestPeers_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestPeers, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestPeers, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestPeers)); + RequestPeers_SetOption_descriptor_ = RequestPeers_descriptor_->enum_type(0); + RequestPeers_InfoOption_descriptor_ = RequestPeers_descriptor_->enum_type(1); + ResponsePeerList_descriptor_ = file->message_type(1); + static const int ResponsePeerList_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponsePeerList, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponsePeerList, peers_), + }; + ResponsePeerList_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponsePeerList_descriptor_, + ResponsePeerList::default_instance_, + ResponsePeerList_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponsePeerList, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponsePeerList, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponsePeerList)); + RequestAddPeer_descriptor_ = file->message_type(2); + static const int RequestAddPeer_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAddPeer, gpg_id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAddPeer, cmd_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAddPeer, cert_), + }; + RequestAddPeer_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestAddPeer_descriptor_, + RequestAddPeer::default_instance_, + RequestAddPeer_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAddPeer, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAddPeer, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestAddPeer)); + RequestAddPeer_AddCmd_descriptor_ = RequestAddPeer_descriptor_->enum_type(0); + ResponseAddPeer_descriptor_ = file->message_type(3); + static const int ResponseAddPeer_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseAddPeer, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseAddPeer, peers_), + }; + ResponseAddPeer_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseAddPeer_descriptor_, + ResponseAddPeer::default_instance_, + ResponseAddPeer_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseAddPeer, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseAddPeer, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseAddPeer)); + RequestModifyPeer_descriptor_ = file->message_type(4); + static const int RequestModifyPeer_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestModifyPeer, cmd_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestModifyPeer, peers_), + }; + RequestModifyPeer_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestModifyPeer_descriptor_, + RequestModifyPeer::default_instance_, + RequestModifyPeer_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestModifyPeer, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestModifyPeer, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestModifyPeer)); + RequestModifyPeer_ModCmd_descriptor_ = RequestModifyPeer_descriptor_->enum_type(0); + ResponseModifyPeer_descriptor_ = file->message_type(5); + static const int ResponseModifyPeer_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseModifyPeer, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseModifyPeer, peers_), + }; + ResponseModifyPeer_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseModifyPeer_descriptor_, + ResponseModifyPeer::default_instance_, + ResponseModifyPeer_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseModifyPeer, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseModifyPeer, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseModifyPeer)); + RequestMsgIds_descriptor_ = file->enum_type(0); + ResponseMsgIds_descriptor_ = file->enum_type(1); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_peers_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestPeers_descriptor_, &RequestPeers::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponsePeerList_descriptor_, &ResponsePeerList::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestAddPeer_descriptor_, &RequestAddPeer::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseAddPeer_descriptor_, &ResponseAddPeer::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestModifyPeer_descriptor_, &RequestModifyPeer::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseModifyPeer_descriptor_, &ResponseModifyPeer::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_peers_2eproto() { + delete RequestPeers::default_instance_; + delete RequestPeers_reflection_; + delete ResponsePeerList::default_instance_; + delete ResponsePeerList_reflection_; + delete RequestAddPeer::default_instance_; + delete RequestAddPeer_reflection_; + delete ResponseAddPeer::default_instance_; + delete ResponseAddPeer_reflection_; + delete RequestModifyPeer::default_instance_; + delete RequestModifyPeer_reflection_; + delete ResponseModifyPeer::default_instance_; + delete ResponseModifyPeer_reflection_; +} + +void protobuf_AddDesc_peers_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::rsctrl::core::protobuf_AddDesc_core_2eproto(); + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\013peers.proto\022\014rsctrl.peers\032\ncore.proto\"" + "\251\002\n\014RequestPeers\0221\n\003set\030\001 \002(\0162$.rsctrl.p" + "eers.RequestPeers.SetOption\0223\n\004info\030\002 \002(" + "\0162%.rsctrl.peers.RequestPeers.InfoOption" + "\022\017\n\007gpg_ids\030\003 \003(\t\"^\n\tSetOption\022\t\n\005OWNID\020" + "\001\022\n\n\006LISTED\020\002\022\r\n\tCONNECTED\020\003\022\013\n\007FRIENDS\020" + "\004\022\t\n\005VALID\020\005\022\n\n\006SIGNED\020\006\022\007\n\003ALL\020\007\"@\n\nInf" + "oOption\022\014\n\010NAMEONLY\020\001\022\t\n\005BASIC\020\002\022\014\n\010LOCA" + "TION\020\003\022\013\n\007ALLINFO\020\004\"[\n\020ResponsePeerList\022" + "#\n\006status\030\001 \002(\0132\023.rsctrl.core.Status\022\"\n\005" + "peers\030\002 \003(\0132\023.rsctrl.core.Person\"\242\001\n\016Req" + "uestAddPeer\022\016\n\006gpg_id\030\001 \002(\t\0220\n\003cmd\030\002 \002(\016" + "2#.rsctrl.peers.RequestAddPeer.AddCmd\022\014\n" + "\004cert\030\003 \001(\t\"@\n\006AddCmd\022\010\n\004NOOP\020\000\022\007\n\003ADD\020\001" + "\022\n\n\006REMOVE\020\002\022\n\n\006IMPORT\020\003\022\013\n\007EXAMINE\020\004\"Z\n" + "\017ResponseAddPeer\022#\n\006status\030\001 \002(\0132\023.rsctr" + "l.core.Status\022\"\n\005peers\030\002 \003(\0132\023.rsctrl.co" + "re.Person\"\231\001\n\021RequestModifyPeer\0223\n\003cmd\030\001" + " \002(\0162&.rsctrl.peers.RequestModifyPeer.Mo" + "dCmd\022\"\n\005peers\030\002 \003(\0132\023.rsctrl.core.Person" + "\"+\n\006ModCmd\022\010\n\004NOOP\020\000\022\013\n\007ADDRESS\020\001\022\n\n\006DYN" + "DNS\020\002\"]\n\022ResponseModifyPeer\022#\n\006status\030\001 " + "\002(\0132\023.rsctrl.core.Status\022\"\n\005peers\030\002 \003(\0132" + "\023.rsctrl.core.Person*^\n\rRequestMsgIds\022\026\n" + "\022MsgId_RequestPeers\020\001\022\030\n\024MsgId_RequestAd" + "dPeer\020\002\022\033\n\027MsgId_RequestModifyPeer\020\003*e\n\016" + "ResponseMsgIds\022\032\n\026MsgId_ResponsePeerList" + "\020\001\022\031\n\025MsgId_ResponseAddPeer\020\002\022\034\n\030MsgId_R" + "esponseModifyPeer\020\003", 1139); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "peers.proto", &protobuf_RegisterTypes); + RequestPeers::default_instance_ = new RequestPeers(); + ResponsePeerList::default_instance_ = new ResponsePeerList(); + RequestAddPeer::default_instance_ = new RequestAddPeer(); + ResponseAddPeer::default_instance_ = new ResponseAddPeer(); + RequestModifyPeer::default_instance_ = new RequestModifyPeer(); + ResponseModifyPeer::default_instance_ = new ResponseModifyPeer(); + RequestPeers::default_instance_->InitAsDefaultInstance(); + ResponsePeerList::default_instance_->InitAsDefaultInstance(); + RequestAddPeer::default_instance_->InitAsDefaultInstance(); + ResponseAddPeer::default_instance_->InitAsDefaultInstance(); + RequestModifyPeer::default_instance_->InitAsDefaultInstance(); + ResponseModifyPeer::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_peers_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_peers_2eproto { + StaticDescriptorInitializer_peers_2eproto() { + protobuf_AddDesc_peers_2eproto(); + } +} static_descriptor_initializer_peers_2eproto_; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestMsgIds_descriptor_; +} +bool RequestMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseMsgIds_descriptor_; +} +bool ResponseMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestPeers_SetOption_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestPeers_SetOption_descriptor_; +} +bool RequestPeers_SetOption_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestPeers_SetOption RequestPeers::OWNID; +const RequestPeers_SetOption RequestPeers::LISTED; +const RequestPeers_SetOption RequestPeers::CONNECTED; +const RequestPeers_SetOption RequestPeers::FRIENDS; +const RequestPeers_SetOption RequestPeers::VALID; +const RequestPeers_SetOption RequestPeers::SIGNED; +const RequestPeers_SetOption RequestPeers::ALL; +const RequestPeers_SetOption RequestPeers::SetOption_MIN; +const RequestPeers_SetOption RequestPeers::SetOption_MAX; +const int RequestPeers::SetOption_ARRAYSIZE; +#endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* RequestPeers_InfoOption_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestPeers_InfoOption_descriptor_; +} +bool RequestPeers_InfoOption_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestPeers_InfoOption RequestPeers::NAMEONLY; +const RequestPeers_InfoOption RequestPeers::BASIC; +const RequestPeers_InfoOption RequestPeers::LOCATION; +const RequestPeers_InfoOption RequestPeers::ALLINFO; +const RequestPeers_InfoOption RequestPeers::InfoOption_MIN; +const RequestPeers_InfoOption RequestPeers::InfoOption_MAX; +const int RequestPeers::InfoOption_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestPeers::kSetFieldNumber; +const int RequestPeers::kInfoFieldNumber; +const int RequestPeers::kGpgIdsFieldNumber; +#endif // !_MSC_VER + +RequestPeers::RequestPeers() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestPeers::InitAsDefaultInstance() { +} + +RequestPeers::RequestPeers(const RequestPeers& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestPeers::SharedCtor() { + _cached_size_ = 0; + set_ = 1; + info_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestPeers::~RequestPeers() { + SharedDtor(); +} + +void RequestPeers::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestPeers::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestPeers::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestPeers_descriptor_; +} + +const RequestPeers& RequestPeers::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_peers_2eproto(); return *default_instance_; +} + +RequestPeers* RequestPeers::default_instance_ = NULL; + +RequestPeers* RequestPeers::New() const { + return new RequestPeers; +} + +void RequestPeers::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + set_ = 1; + info_ = 1; + } + gpg_ids_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestPeers::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.peers.RequestPeers.SetOption set = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::peers::RequestPeers_SetOption_IsValid(value)) { + set_set(static_cast< ::rsctrl::peers::RequestPeers_SetOption >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_info; + break; + } + + // required .rsctrl.peers.RequestPeers.InfoOption info = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_info: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::peers::RequestPeers_InfoOption_IsValid(value)) { + set_info(static_cast< ::rsctrl::peers::RequestPeers_InfoOption >(value)); + } else { + mutable_unknown_fields()->AddVarint(2, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_gpg_ids; + break; + } + + // repeated string gpg_ids = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_gpg_ids: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_gpg_ids())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_ids(0).data(), this->gpg_ids(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_gpg_ids; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestPeers::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.peers.RequestPeers.SetOption set = 1; + if (has_set()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->set(), output); + } + + // required .rsctrl.peers.RequestPeers.InfoOption info = 2; + if (has_info()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 2, this->info(), output); + } + + // repeated string gpg_ids = 3; + for (int i = 0; i < this->gpg_ids_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_ids(i).data(), this->gpg_ids(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->gpg_ids(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestPeers::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.peers.RequestPeers.SetOption set = 1; + if (has_set()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->set(), target); + } + + // required .rsctrl.peers.RequestPeers.InfoOption info = 2; + if (has_info()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 2, this->info(), target); + } + + // repeated string gpg_ids = 3; + for (int i = 0; i < this->gpg_ids_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_ids(i).data(), this->gpg_ids(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(3, this->gpg_ids(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestPeers::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.peers.RequestPeers.SetOption set = 1; + if (has_set()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->set()); + } + + // required .rsctrl.peers.RequestPeers.InfoOption info = 2; + if (has_info()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->info()); + } + + } + // repeated string gpg_ids = 3; + total_size += 1 * this->gpg_ids_size(); + for (int i = 0; i < this->gpg_ids_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->gpg_ids(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestPeers::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestPeers* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestPeers::MergeFrom(const RequestPeers& from) { + GOOGLE_CHECK_NE(&from, this); + gpg_ids_.MergeFrom(from.gpg_ids_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_set()) { + set_set(from.set()); + } + if (from.has_info()) { + set_info(from.info()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestPeers::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestPeers::CopyFrom(const RequestPeers& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestPeers::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void RequestPeers::Swap(RequestPeers* other) { + if (other != this) { + std::swap(set_, other->set_); + std::swap(info_, other->info_); + gpg_ids_.Swap(&other->gpg_ids_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestPeers::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestPeers_descriptor_; + metadata.reflection = RequestPeers_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponsePeerList::kStatusFieldNumber; +const int ResponsePeerList::kPeersFieldNumber; +#endif // !_MSC_VER + +ResponsePeerList::ResponsePeerList() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponsePeerList::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponsePeerList::ResponsePeerList(const ResponsePeerList& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponsePeerList::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponsePeerList::~ResponsePeerList() { + SharedDtor(); +} + +void ResponsePeerList::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponsePeerList::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponsePeerList::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponsePeerList_descriptor_; +} + +const ResponsePeerList& ResponsePeerList::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_peers_2eproto(); return *default_instance_; +} + +ResponsePeerList* ResponsePeerList::default_instance_ = NULL; + +ResponsePeerList* ResponsePeerList::New() const { + return new ResponsePeerList; +} + +void ResponsePeerList::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + peers_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponsePeerList::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + break; + } + + // repeated .rsctrl.core.Person peers = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_peers: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_peers())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponsePeerList::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->peers(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponsePeerList::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->peers(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponsePeerList::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated .rsctrl.core.Person peers = 2; + total_size += 1 * this->peers_size(); + for (int i = 0; i < this->peers_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->peers(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponsePeerList::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponsePeerList* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponsePeerList::MergeFrom(const ResponsePeerList& from) { + GOOGLE_CHECK_NE(&from, this); + peers_.MergeFrom(from.peers_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponsePeerList::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponsePeerList::CopyFrom(const ResponsePeerList& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponsePeerList::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + for (int i = 0; i < peers_size(); i++) { + if (!this->peers(i).IsInitialized()) return false; + } + return true; +} + +void ResponsePeerList::Swap(ResponsePeerList* other) { + if (other != this) { + std::swap(status_, other->status_); + peers_.Swap(&other->peers_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponsePeerList::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponsePeerList_descriptor_; + metadata.reflection = ResponsePeerList_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestAddPeer_AddCmd_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestAddPeer_AddCmd_descriptor_; +} +bool RequestAddPeer_AddCmd_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + case 3: + case 4: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestAddPeer_AddCmd RequestAddPeer::NOOP; +const RequestAddPeer_AddCmd RequestAddPeer::ADD; +const RequestAddPeer_AddCmd RequestAddPeer::REMOVE; +const RequestAddPeer_AddCmd RequestAddPeer::IMPORT; +const RequestAddPeer_AddCmd RequestAddPeer::EXAMINE; +const RequestAddPeer_AddCmd RequestAddPeer::AddCmd_MIN; +const RequestAddPeer_AddCmd RequestAddPeer::AddCmd_MAX; +const int RequestAddPeer::AddCmd_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestAddPeer::kGpgIdFieldNumber; +const int RequestAddPeer::kCmdFieldNumber; +const int RequestAddPeer::kCertFieldNumber; +#endif // !_MSC_VER + +RequestAddPeer::RequestAddPeer() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestAddPeer::InitAsDefaultInstance() { +} + +RequestAddPeer::RequestAddPeer(const RequestAddPeer& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestAddPeer::SharedCtor() { + _cached_size_ = 0; + gpg_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + cmd_ = 0; + cert_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestAddPeer::~RequestAddPeer() { + SharedDtor(); +} + +void RequestAddPeer::SharedDtor() { + if (gpg_id_ != &::google::protobuf::internal::kEmptyString) { + delete gpg_id_; + } + if (cert_ != &::google::protobuf::internal::kEmptyString) { + delete cert_; + } + if (this != default_instance_) { + } +} + +void RequestAddPeer::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestAddPeer::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestAddPeer_descriptor_; +} + +const RequestAddPeer& RequestAddPeer::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_peers_2eproto(); return *default_instance_; +} + +RequestAddPeer* RequestAddPeer::default_instance_ = NULL; + +RequestAddPeer* RequestAddPeer::New() const { + return new RequestAddPeer; +} + +void RequestAddPeer::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_gpg_id()) { + if (gpg_id_ != &::google::protobuf::internal::kEmptyString) { + gpg_id_->clear(); + } + } + cmd_ = 0; + if (has_cert()) { + if (cert_ != &::google::protobuf::internal::kEmptyString) { + cert_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestAddPeer::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string gpg_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_gpg_id())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_id().data(), this->gpg_id().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_cmd; + break; + } + + // required .rsctrl.peers.RequestAddPeer.AddCmd cmd = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_cmd: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::peers::RequestAddPeer_AddCmd_IsValid(value)) { + set_cmd(static_cast< ::rsctrl::peers::RequestAddPeer_AddCmd >(value)); + } else { + mutable_unknown_fields()->AddVarint(2, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_cert; + break; + } + + // optional string cert = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_cert: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_cert())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->cert().data(), this->cert().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestAddPeer::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string gpg_id = 1; + if (has_gpg_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_id().data(), this->gpg_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->gpg_id(), output); + } + + // required .rsctrl.peers.RequestAddPeer.AddCmd cmd = 2; + if (has_cmd()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 2, this->cmd(), output); + } + + // optional string cert = 3; + if (has_cert()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->cert().data(), this->cert().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->cert(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestAddPeer::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string gpg_id = 1; + if (has_gpg_id()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->gpg_id().data(), this->gpg_id().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->gpg_id(), target); + } + + // required .rsctrl.peers.RequestAddPeer.AddCmd cmd = 2; + if (has_cmd()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 2, this->cmd(), target); + } + + // optional string cert = 3; + if (has_cert()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->cert().data(), this->cert().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->cert(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestAddPeer::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string gpg_id = 1; + if (has_gpg_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->gpg_id()); + } + + // required .rsctrl.peers.RequestAddPeer.AddCmd cmd = 2; + if (has_cmd()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->cmd()); + } + + // optional string cert = 3; + if (has_cert()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->cert()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestAddPeer::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestAddPeer* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestAddPeer::MergeFrom(const RequestAddPeer& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_gpg_id()) { + set_gpg_id(from.gpg_id()); + } + if (from.has_cmd()) { + set_cmd(from.cmd()); + } + if (from.has_cert()) { + set_cert(from.cert()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestAddPeer::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestAddPeer::CopyFrom(const RequestAddPeer& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestAddPeer::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void RequestAddPeer::Swap(RequestAddPeer* other) { + if (other != this) { + std::swap(gpg_id_, other->gpg_id_); + std::swap(cmd_, other->cmd_); + std::swap(cert_, other->cert_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestAddPeer::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestAddPeer_descriptor_; + metadata.reflection = RequestAddPeer_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseAddPeer::kStatusFieldNumber; +const int ResponseAddPeer::kPeersFieldNumber; +#endif // !_MSC_VER + +ResponseAddPeer::ResponseAddPeer() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseAddPeer::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseAddPeer::ResponseAddPeer(const ResponseAddPeer& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseAddPeer::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseAddPeer::~ResponseAddPeer() { + SharedDtor(); +} + +void ResponseAddPeer::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseAddPeer::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseAddPeer::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseAddPeer_descriptor_; +} + +const ResponseAddPeer& ResponseAddPeer::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_peers_2eproto(); return *default_instance_; +} + +ResponseAddPeer* ResponseAddPeer::default_instance_ = NULL; + +ResponseAddPeer* ResponseAddPeer::New() const { + return new ResponseAddPeer; +} + +void ResponseAddPeer::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + peers_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseAddPeer::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + break; + } + + // repeated .rsctrl.core.Person peers = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_peers: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_peers())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseAddPeer::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->peers(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseAddPeer::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->peers(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseAddPeer::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated .rsctrl.core.Person peers = 2; + total_size += 1 * this->peers_size(); + for (int i = 0; i < this->peers_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->peers(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseAddPeer::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseAddPeer* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseAddPeer::MergeFrom(const ResponseAddPeer& from) { + GOOGLE_CHECK_NE(&from, this); + peers_.MergeFrom(from.peers_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseAddPeer::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseAddPeer::CopyFrom(const ResponseAddPeer& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseAddPeer::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + for (int i = 0; i < peers_size(); i++) { + if (!this->peers(i).IsInitialized()) return false; + } + return true; +} + +void ResponseAddPeer::Swap(ResponseAddPeer* other) { + if (other != this) { + std::swap(status_, other->status_); + peers_.Swap(&other->peers_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseAddPeer::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseAddPeer_descriptor_; + metadata.reflection = ResponseAddPeer_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestModifyPeer_ModCmd_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestModifyPeer_ModCmd_descriptor_; +} +bool RequestModifyPeer_ModCmd_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestModifyPeer_ModCmd RequestModifyPeer::NOOP; +const RequestModifyPeer_ModCmd RequestModifyPeer::ADDRESS; +const RequestModifyPeer_ModCmd RequestModifyPeer::DYNDNS; +const RequestModifyPeer_ModCmd RequestModifyPeer::ModCmd_MIN; +const RequestModifyPeer_ModCmd RequestModifyPeer::ModCmd_MAX; +const int RequestModifyPeer::ModCmd_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestModifyPeer::kCmdFieldNumber; +const int RequestModifyPeer::kPeersFieldNumber; +#endif // !_MSC_VER + +RequestModifyPeer::RequestModifyPeer() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestModifyPeer::InitAsDefaultInstance() { +} + +RequestModifyPeer::RequestModifyPeer(const RequestModifyPeer& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestModifyPeer::SharedCtor() { + _cached_size_ = 0; + cmd_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestModifyPeer::~RequestModifyPeer() { + SharedDtor(); +} + +void RequestModifyPeer::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestModifyPeer::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestModifyPeer::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestModifyPeer_descriptor_; +} + +const RequestModifyPeer& RequestModifyPeer::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_peers_2eproto(); return *default_instance_; +} + +RequestModifyPeer* RequestModifyPeer::default_instance_ = NULL; + +RequestModifyPeer* RequestModifyPeer::New() const { + return new RequestModifyPeer; +} + +void RequestModifyPeer::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + cmd_ = 0; + } + peers_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestModifyPeer::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.peers.RequestModifyPeer.ModCmd cmd = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::peers::RequestModifyPeer_ModCmd_IsValid(value)) { + set_cmd(static_cast< ::rsctrl::peers::RequestModifyPeer_ModCmd >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + break; + } + + // repeated .rsctrl.core.Person peers = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_peers: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_peers())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestModifyPeer::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.peers.RequestModifyPeer.ModCmd cmd = 1; + if (has_cmd()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->cmd(), output); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->peers(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestModifyPeer::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.peers.RequestModifyPeer.ModCmd cmd = 1; + if (has_cmd()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->cmd(), target); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->peers(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestModifyPeer::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.peers.RequestModifyPeer.ModCmd cmd = 1; + if (has_cmd()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->cmd()); + } + + } + // repeated .rsctrl.core.Person peers = 2; + total_size += 1 * this->peers_size(); + for (int i = 0; i < this->peers_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->peers(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestModifyPeer::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestModifyPeer* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestModifyPeer::MergeFrom(const RequestModifyPeer& from) { + GOOGLE_CHECK_NE(&from, this); + peers_.MergeFrom(from.peers_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_cmd()) { + set_cmd(from.cmd()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestModifyPeer::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestModifyPeer::CopyFrom(const RequestModifyPeer& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestModifyPeer::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + for (int i = 0; i < peers_size(); i++) { + if (!this->peers(i).IsInitialized()) return false; + } + return true; +} + +void RequestModifyPeer::Swap(RequestModifyPeer* other) { + if (other != this) { + std::swap(cmd_, other->cmd_); + peers_.Swap(&other->peers_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestModifyPeer::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestModifyPeer_descriptor_; + metadata.reflection = RequestModifyPeer_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseModifyPeer::kStatusFieldNumber; +const int ResponseModifyPeer::kPeersFieldNumber; +#endif // !_MSC_VER + +ResponseModifyPeer::ResponseModifyPeer() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseModifyPeer::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseModifyPeer::ResponseModifyPeer(const ResponseModifyPeer& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseModifyPeer::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseModifyPeer::~ResponseModifyPeer() { + SharedDtor(); +} + +void ResponseModifyPeer::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseModifyPeer::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseModifyPeer::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseModifyPeer_descriptor_; +} + +const ResponseModifyPeer& ResponseModifyPeer::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_peers_2eproto(); return *default_instance_; +} + +ResponseModifyPeer* ResponseModifyPeer::default_instance_ = NULL; + +ResponseModifyPeer* ResponseModifyPeer::New() const { + return new ResponseModifyPeer; +} + +void ResponseModifyPeer::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + peers_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseModifyPeer::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + break; + } + + // repeated .rsctrl.core.Person peers = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_peers: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_peers())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_peers; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseModifyPeer::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->peers(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseModifyPeer::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated .rsctrl.core.Person peers = 2; + for (int i = 0; i < this->peers_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->peers(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseModifyPeer::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated .rsctrl.core.Person peers = 2; + total_size += 1 * this->peers_size(); + for (int i = 0; i < this->peers_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->peers(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseModifyPeer::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseModifyPeer* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseModifyPeer::MergeFrom(const ResponseModifyPeer& from) { + GOOGLE_CHECK_NE(&from, this); + peers_.MergeFrom(from.peers_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseModifyPeer::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseModifyPeer::CopyFrom(const ResponseModifyPeer& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseModifyPeer::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + for (int i = 0; i < peers_size(); i++) { + if (!this->peers(i).IsInitialized()) return false; + } + return true; +} + +void ResponseModifyPeer::Swap(ResponseModifyPeer* other) { + if (other != this) { + std::swap(status_, other->status_); + peers_.Swap(&other->peers_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseModifyPeer::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseModifyPeer_descriptor_; + metadata.reflection = ResponseModifyPeer_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace peers +} // namespace rsctrl + +// @@protoc_insertion_point(global_scope) diff --git a/retroshare-nogui/src/rpc/proto/gencc/peers.pb.h b/retroshare-nogui/src/rpc/proto/gencc/peers.pb.h new file mode 100644 index 000000000..75a90eb12 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/peers.pb.h @@ -0,0 +1,1387 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: peers.proto + +#ifndef PROTOBUF_peers_2eproto__INCLUDED +#define PROTOBUF_peers_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include "core.pb.h" +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace peers { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_peers_2eproto(); +void protobuf_AssignDesc_peers_2eproto(); +void protobuf_ShutdownFile_peers_2eproto(); + +class RequestPeers; +class ResponsePeerList; +class RequestAddPeer; +class ResponseAddPeer; +class RequestModifyPeer; +class ResponseModifyPeer; + +enum RequestPeers_SetOption { + RequestPeers_SetOption_OWNID = 1, + RequestPeers_SetOption_LISTED = 2, + RequestPeers_SetOption_CONNECTED = 3, + RequestPeers_SetOption_FRIENDS = 4, + RequestPeers_SetOption_VALID = 5, + RequestPeers_SetOption_SIGNED = 6, + RequestPeers_SetOption_ALL = 7 +}; +bool RequestPeers_SetOption_IsValid(int value); +const RequestPeers_SetOption RequestPeers_SetOption_SetOption_MIN = RequestPeers_SetOption_OWNID; +const RequestPeers_SetOption RequestPeers_SetOption_SetOption_MAX = RequestPeers_SetOption_ALL; +const int RequestPeers_SetOption_SetOption_ARRAYSIZE = RequestPeers_SetOption_SetOption_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestPeers_SetOption_descriptor(); +inline const ::std::string& RequestPeers_SetOption_Name(RequestPeers_SetOption value) { + return ::google::protobuf::internal::NameOfEnum( + RequestPeers_SetOption_descriptor(), value); +} +inline bool RequestPeers_SetOption_Parse( + const ::std::string& name, RequestPeers_SetOption* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestPeers_SetOption_descriptor(), name, value); +} +enum RequestPeers_InfoOption { + RequestPeers_InfoOption_NAMEONLY = 1, + RequestPeers_InfoOption_BASIC = 2, + RequestPeers_InfoOption_LOCATION = 3, + RequestPeers_InfoOption_ALLINFO = 4 +}; +bool RequestPeers_InfoOption_IsValid(int value); +const RequestPeers_InfoOption RequestPeers_InfoOption_InfoOption_MIN = RequestPeers_InfoOption_NAMEONLY; +const RequestPeers_InfoOption RequestPeers_InfoOption_InfoOption_MAX = RequestPeers_InfoOption_ALLINFO; +const int RequestPeers_InfoOption_InfoOption_ARRAYSIZE = RequestPeers_InfoOption_InfoOption_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestPeers_InfoOption_descriptor(); +inline const ::std::string& RequestPeers_InfoOption_Name(RequestPeers_InfoOption value) { + return ::google::protobuf::internal::NameOfEnum( + RequestPeers_InfoOption_descriptor(), value); +} +inline bool RequestPeers_InfoOption_Parse( + const ::std::string& name, RequestPeers_InfoOption* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestPeers_InfoOption_descriptor(), name, value); +} +enum RequestAddPeer_AddCmd { + RequestAddPeer_AddCmd_NOOP = 0, + RequestAddPeer_AddCmd_ADD = 1, + RequestAddPeer_AddCmd_REMOVE = 2, + RequestAddPeer_AddCmd_IMPORT = 3, + RequestAddPeer_AddCmd_EXAMINE = 4 +}; +bool RequestAddPeer_AddCmd_IsValid(int value); +const RequestAddPeer_AddCmd RequestAddPeer_AddCmd_AddCmd_MIN = RequestAddPeer_AddCmd_NOOP; +const RequestAddPeer_AddCmd RequestAddPeer_AddCmd_AddCmd_MAX = RequestAddPeer_AddCmd_EXAMINE; +const int RequestAddPeer_AddCmd_AddCmd_ARRAYSIZE = RequestAddPeer_AddCmd_AddCmd_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestAddPeer_AddCmd_descriptor(); +inline const ::std::string& RequestAddPeer_AddCmd_Name(RequestAddPeer_AddCmd value) { + return ::google::protobuf::internal::NameOfEnum( + RequestAddPeer_AddCmd_descriptor(), value); +} +inline bool RequestAddPeer_AddCmd_Parse( + const ::std::string& name, RequestAddPeer_AddCmd* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestAddPeer_AddCmd_descriptor(), name, value); +} +enum RequestModifyPeer_ModCmd { + RequestModifyPeer_ModCmd_NOOP = 0, + RequestModifyPeer_ModCmd_ADDRESS = 1, + RequestModifyPeer_ModCmd_DYNDNS = 2 +}; +bool RequestModifyPeer_ModCmd_IsValid(int value); +const RequestModifyPeer_ModCmd RequestModifyPeer_ModCmd_ModCmd_MIN = RequestModifyPeer_ModCmd_NOOP; +const RequestModifyPeer_ModCmd RequestModifyPeer_ModCmd_ModCmd_MAX = RequestModifyPeer_ModCmd_DYNDNS; +const int RequestModifyPeer_ModCmd_ModCmd_ARRAYSIZE = RequestModifyPeer_ModCmd_ModCmd_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestModifyPeer_ModCmd_descriptor(); +inline const ::std::string& RequestModifyPeer_ModCmd_Name(RequestModifyPeer_ModCmd value) { + return ::google::protobuf::internal::NameOfEnum( + RequestModifyPeer_ModCmd_descriptor(), value); +} +inline bool RequestModifyPeer_ModCmd_Parse( + const ::std::string& name, RequestModifyPeer_ModCmd* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestModifyPeer_ModCmd_descriptor(), name, value); +} +enum RequestMsgIds { + MsgId_RequestPeers = 1, + MsgId_RequestAddPeer = 2, + MsgId_RequestModifyPeer = 3 +}; +bool RequestMsgIds_IsValid(int value); +const RequestMsgIds RequestMsgIds_MIN = MsgId_RequestPeers; +const RequestMsgIds RequestMsgIds_MAX = MsgId_RequestModifyPeer; +const int RequestMsgIds_ARRAYSIZE = RequestMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor(); +inline const ::std::string& RequestMsgIds_Name(RequestMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + RequestMsgIds_descriptor(), value); +} +inline bool RequestMsgIds_Parse( + const ::std::string& name, RequestMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestMsgIds_descriptor(), name, value); +} +enum ResponseMsgIds { + MsgId_ResponsePeerList = 1, + MsgId_ResponseAddPeer = 2, + MsgId_ResponseModifyPeer = 3 +}; +bool ResponseMsgIds_IsValid(int value); +const ResponseMsgIds ResponseMsgIds_MIN = MsgId_ResponsePeerList; +const ResponseMsgIds ResponseMsgIds_MAX = MsgId_ResponseModifyPeer; +const int ResponseMsgIds_ARRAYSIZE = ResponseMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor(); +inline const ::std::string& ResponseMsgIds_Name(ResponseMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + ResponseMsgIds_descriptor(), value); +} +inline bool ResponseMsgIds_Parse( + const ::std::string& name, ResponseMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ResponseMsgIds_descriptor(), name, value); +} +// =================================================================== + +class RequestPeers : public ::google::protobuf::Message { + public: + RequestPeers(); + virtual ~RequestPeers(); + + RequestPeers(const RequestPeers& from); + + inline RequestPeers& operator=(const RequestPeers& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestPeers& default_instance(); + + void Swap(RequestPeers* other); + + // implements Message ---------------------------------------------- + + RequestPeers* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestPeers& from); + void MergeFrom(const RequestPeers& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestPeers_SetOption SetOption; + static const SetOption OWNID = RequestPeers_SetOption_OWNID; + static const SetOption LISTED = RequestPeers_SetOption_LISTED; + static const SetOption CONNECTED = RequestPeers_SetOption_CONNECTED; + static const SetOption FRIENDS = RequestPeers_SetOption_FRIENDS; + static const SetOption VALID = RequestPeers_SetOption_VALID; + static const SetOption SIGNED = RequestPeers_SetOption_SIGNED; + static const SetOption ALL = RequestPeers_SetOption_ALL; + static inline bool SetOption_IsValid(int value) { + return RequestPeers_SetOption_IsValid(value); + } + static const SetOption SetOption_MIN = + RequestPeers_SetOption_SetOption_MIN; + static const SetOption SetOption_MAX = + RequestPeers_SetOption_SetOption_MAX; + static const int SetOption_ARRAYSIZE = + RequestPeers_SetOption_SetOption_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + SetOption_descriptor() { + return RequestPeers_SetOption_descriptor(); + } + static inline const ::std::string& SetOption_Name(SetOption value) { + return RequestPeers_SetOption_Name(value); + } + static inline bool SetOption_Parse(const ::std::string& name, + SetOption* value) { + return RequestPeers_SetOption_Parse(name, value); + } + + typedef RequestPeers_InfoOption InfoOption; + static const InfoOption NAMEONLY = RequestPeers_InfoOption_NAMEONLY; + static const InfoOption BASIC = RequestPeers_InfoOption_BASIC; + static const InfoOption LOCATION = RequestPeers_InfoOption_LOCATION; + static const InfoOption ALLINFO = RequestPeers_InfoOption_ALLINFO; + static inline bool InfoOption_IsValid(int value) { + return RequestPeers_InfoOption_IsValid(value); + } + static const InfoOption InfoOption_MIN = + RequestPeers_InfoOption_InfoOption_MIN; + static const InfoOption InfoOption_MAX = + RequestPeers_InfoOption_InfoOption_MAX; + static const int InfoOption_ARRAYSIZE = + RequestPeers_InfoOption_InfoOption_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + InfoOption_descriptor() { + return RequestPeers_InfoOption_descriptor(); + } + static inline const ::std::string& InfoOption_Name(InfoOption value) { + return RequestPeers_InfoOption_Name(value); + } + static inline bool InfoOption_Parse(const ::std::string& name, + InfoOption* value) { + return RequestPeers_InfoOption_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.peers.RequestPeers.SetOption set = 1; + inline bool has_set() const; + inline void clear_set(); + static const int kSetFieldNumber = 1; + inline ::rsctrl::peers::RequestPeers_SetOption set() const; + inline void set_set(::rsctrl::peers::RequestPeers_SetOption value); + + // required .rsctrl.peers.RequestPeers.InfoOption info = 2; + inline bool has_info() const; + inline void clear_info(); + static const int kInfoFieldNumber = 2; + inline ::rsctrl::peers::RequestPeers_InfoOption info() const; + inline void set_info(::rsctrl::peers::RequestPeers_InfoOption value); + + // repeated string gpg_ids = 3; + inline int gpg_ids_size() const; + inline void clear_gpg_ids(); + static const int kGpgIdsFieldNumber = 3; + inline const ::std::string& gpg_ids(int index) const; + inline ::std::string* mutable_gpg_ids(int index); + inline void set_gpg_ids(int index, const ::std::string& value); + inline void set_gpg_ids(int index, const char* value); + inline void set_gpg_ids(int index, const char* value, size_t size); + inline ::std::string* add_gpg_ids(); + inline void add_gpg_ids(const ::std::string& value); + inline void add_gpg_ids(const char* value); + inline void add_gpg_ids(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& gpg_ids() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_gpg_ids(); + + // @@protoc_insertion_point(class_scope:rsctrl.peers.RequestPeers) + private: + inline void set_has_set(); + inline void clear_has_set(); + inline void set_has_info(); + inline void clear_has_info(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + int set_; + int info_; + ::google::protobuf::RepeatedPtrField< ::std::string> gpg_ids_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_peers_2eproto(); + friend void protobuf_AssignDesc_peers_2eproto(); + friend void protobuf_ShutdownFile_peers_2eproto(); + + void InitAsDefaultInstance(); + static RequestPeers* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponsePeerList : public ::google::protobuf::Message { + public: + ResponsePeerList(); + virtual ~ResponsePeerList(); + + ResponsePeerList(const ResponsePeerList& from); + + inline ResponsePeerList& operator=(const ResponsePeerList& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponsePeerList& default_instance(); + + void Swap(ResponsePeerList* other); + + // implements Message ---------------------------------------------- + + ResponsePeerList* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponsePeerList& from); + void MergeFrom(const ResponsePeerList& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated .rsctrl.core.Person peers = 2; + inline int peers_size() const; + inline void clear_peers(); + static const int kPeersFieldNumber = 2; + inline const ::rsctrl::core::Person& peers(int index) const; + inline ::rsctrl::core::Person* mutable_peers(int index); + inline ::rsctrl::core::Person* add_peers(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& + peers() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* + mutable_peers(); + + // @@protoc_insertion_point(class_scope:rsctrl.peers.ResponsePeerList) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person > peers_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_peers_2eproto(); + friend void protobuf_AssignDesc_peers_2eproto(); + friend void protobuf_ShutdownFile_peers_2eproto(); + + void InitAsDefaultInstance(); + static ResponsePeerList* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestAddPeer : public ::google::protobuf::Message { + public: + RequestAddPeer(); + virtual ~RequestAddPeer(); + + RequestAddPeer(const RequestAddPeer& from); + + inline RequestAddPeer& operator=(const RequestAddPeer& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestAddPeer& default_instance(); + + void Swap(RequestAddPeer* other); + + // implements Message ---------------------------------------------- + + RequestAddPeer* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestAddPeer& from); + void MergeFrom(const RequestAddPeer& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestAddPeer_AddCmd AddCmd; + static const AddCmd NOOP = RequestAddPeer_AddCmd_NOOP; + static const AddCmd ADD = RequestAddPeer_AddCmd_ADD; + static const AddCmd REMOVE = RequestAddPeer_AddCmd_REMOVE; + static const AddCmd IMPORT = RequestAddPeer_AddCmd_IMPORT; + static const AddCmd EXAMINE = RequestAddPeer_AddCmd_EXAMINE; + static inline bool AddCmd_IsValid(int value) { + return RequestAddPeer_AddCmd_IsValid(value); + } + static const AddCmd AddCmd_MIN = + RequestAddPeer_AddCmd_AddCmd_MIN; + static const AddCmd AddCmd_MAX = + RequestAddPeer_AddCmd_AddCmd_MAX; + static const int AddCmd_ARRAYSIZE = + RequestAddPeer_AddCmd_AddCmd_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + AddCmd_descriptor() { + return RequestAddPeer_AddCmd_descriptor(); + } + static inline const ::std::string& AddCmd_Name(AddCmd value) { + return RequestAddPeer_AddCmd_Name(value); + } + static inline bool AddCmd_Parse(const ::std::string& name, + AddCmd* value) { + return RequestAddPeer_AddCmd_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required string gpg_id = 1; + inline bool has_gpg_id() const; + inline void clear_gpg_id(); + static const int kGpgIdFieldNumber = 1; + inline const ::std::string& gpg_id() const; + inline void set_gpg_id(const ::std::string& value); + inline void set_gpg_id(const char* value); + inline void set_gpg_id(const char* value, size_t size); + inline ::std::string* mutable_gpg_id(); + inline ::std::string* release_gpg_id(); + + // required .rsctrl.peers.RequestAddPeer.AddCmd cmd = 2; + inline bool has_cmd() const; + inline void clear_cmd(); + static const int kCmdFieldNumber = 2; + inline ::rsctrl::peers::RequestAddPeer_AddCmd cmd() const; + inline void set_cmd(::rsctrl::peers::RequestAddPeer_AddCmd value); + + // optional string cert = 3; + inline bool has_cert() const; + inline void clear_cert(); + static const int kCertFieldNumber = 3; + inline const ::std::string& cert() const; + inline void set_cert(const ::std::string& value); + inline void set_cert(const char* value); + inline void set_cert(const char* value, size_t size); + inline ::std::string* mutable_cert(); + inline ::std::string* release_cert(); + + // @@protoc_insertion_point(class_scope:rsctrl.peers.RequestAddPeer) + private: + inline void set_has_gpg_id(); + inline void clear_has_gpg_id(); + inline void set_has_cmd(); + inline void clear_has_cmd(); + inline void set_has_cert(); + inline void clear_has_cert(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* gpg_id_; + ::std::string* cert_; + int cmd_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_peers_2eproto(); + friend void protobuf_AssignDesc_peers_2eproto(); + friend void protobuf_ShutdownFile_peers_2eproto(); + + void InitAsDefaultInstance(); + static RequestAddPeer* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseAddPeer : public ::google::protobuf::Message { + public: + ResponseAddPeer(); + virtual ~ResponseAddPeer(); + + ResponseAddPeer(const ResponseAddPeer& from); + + inline ResponseAddPeer& operator=(const ResponseAddPeer& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseAddPeer& default_instance(); + + void Swap(ResponseAddPeer* other); + + // implements Message ---------------------------------------------- + + ResponseAddPeer* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseAddPeer& from); + void MergeFrom(const ResponseAddPeer& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated .rsctrl.core.Person peers = 2; + inline int peers_size() const; + inline void clear_peers(); + static const int kPeersFieldNumber = 2; + inline const ::rsctrl::core::Person& peers(int index) const; + inline ::rsctrl::core::Person* mutable_peers(int index); + inline ::rsctrl::core::Person* add_peers(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& + peers() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* + mutable_peers(); + + // @@protoc_insertion_point(class_scope:rsctrl.peers.ResponseAddPeer) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person > peers_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_peers_2eproto(); + friend void protobuf_AssignDesc_peers_2eproto(); + friend void protobuf_ShutdownFile_peers_2eproto(); + + void InitAsDefaultInstance(); + static ResponseAddPeer* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestModifyPeer : public ::google::protobuf::Message { + public: + RequestModifyPeer(); + virtual ~RequestModifyPeer(); + + RequestModifyPeer(const RequestModifyPeer& from); + + inline RequestModifyPeer& operator=(const RequestModifyPeer& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestModifyPeer& default_instance(); + + void Swap(RequestModifyPeer* other); + + // implements Message ---------------------------------------------- + + RequestModifyPeer* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestModifyPeer& from); + void MergeFrom(const RequestModifyPeer& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestModifyPeer_ModCmd ModCmd; + static const ModCmd NOOP = RequestModifyPeer_ModCmd_NOOP; + static const ModCmd ADDRESS = RequestModifyPeer_ModCmd_ADDRESS; + static const ModCmd DYNDNS = RequestModifyPeer_ModCmd_DYNDNS; + static inline bool ModCmd_IsValid(int value) { + return RequestModifyPeer_ModCmd_IsValid(value); + } + static const ModCmd ModCmd_MIN = + RequestModifyPeer_ModCmd_ModCmd_MIN; + static const ModCmd ModCmd_MAX = + RequestModifyPeer_ModCmd_ModCmd_MAX; + static const int ModCmd_ARRAYSIZE = + RequestModifyPeer_ModCmd_ModCmd_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + ModCmd_descriptor() { + return RequestModifyPeer_ModCmd_descriptor(); + } + static inline const ::std::string& ModCmd_Name(ModCmd value) { + return RequestModifyPeer_ModCmd_Name(value); + } + static inline bool ModCmd_Parse(const ::std::string& name, + ModCmd* value) { + return RequestModifyPeer_ModCmd_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.peers.RequestModifyPeer.ModCmd cmd = 1; + inline bool has_cmd() const; + inline void clear_cmd(); + static const int kCmdFieldNumber = 1; + inline ::rsctrl::peers::RequestModifyPeer_ModCmd cmd() const; + inline void set_cmd(::rsctrl::peers::RequestModifyPeer_ModCmd value); + + // repeated .rsctrl.core.Person peers = 2; + inline int peers_size() const; + inline void clear_peers(); + static const int kPeersFieldNumber = 2; + inline const ::rsctrl::core::Person& peers(int index) const; + inline ::rsctrl::core::Person* mutable_peers(int index); + inline ::rsctrl::core::Person* add_peers(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& + peers() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* + mutable_peers(); + + // @@protoc_insertion_point(class_scope:rsctrl.peers.RequestModifyPeer) + private: + inline void set_has_cmd(); + inline void clear_has_cmd(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person > peers_; + int cmd_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_peers_2eproto(); + friend void protobuf_AssignDesc_peers_2eproto(); + friend void protobuf_ShutdownFile_peers_2eproto(); + + void InitAsDefaultInstance(); + static RequestModifyPeer* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseModifyPeer : public ::google::protobuf::Message { + public: + ResponseModifyPeer(); + virtual ~ResponseModifyPeer(); + + ResponseModifyPeer(const ResponseModifyPeer& from); + + inline ResponseModifyPeer& operator=(const ResponseModifyPeer& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseModifyPeer& default_instance(); + + void Swap(ResponseModifyPeer* other); + + // implements Message ---------------------------------------------- + + ResponseModifyPeer* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseModifyPeer& from); + void MergeFrom(const ResponseModifyPeer& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated .rsctrl.core.Person peers = 2; + inline int peers_size() const; + inline void clear_peers(); + static const int kPeersFieldNumber = 2; + inline const ::rsctrl::core::Person& peers(int index) const; + inline ::rsctrl::core::Person* mutable_peers(int index); + inline ::rsctrl::core::Person* add_peers(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& + peers() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* + mutable_peers(); + + // @@protoc_insertion_point(class_scope:rsctrl.peers.ResponseModifyPeer) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person > peers_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_peers_2eproto(); + friend void protobuf_AssignDesc_peers_2eproto(); + friend void protobuf_ShutdownFile_peers_2eproto(); + + void InitAsDefaultInstance(); + static ResponseModifyPeer* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// RequestPeers + +// required .rsctrl.peers.RequestPeers.SetOption set = 1; +inline bool RequestPeers::has_set() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestPeers::set_has_set() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestPeers::clear_has_set() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestPeers::clear_set() { + set_ = 1; + clear_has_set(); +} +inline ::rsctrl::peers::RequestPeers_SetOption RequestPeers::set() const { + return static_cast< ::rsctrl::peers::RequestPeers_SetOption >(set_); +} +inline void RequestPeers::set_set(::rsctrl::peers::RequestPeers_SetOption value) { + GOOGLE_DCHECK(::rsctrl::peers::RequestPeers_SetOption_IsValid(value)); + set_has_set(); + set_ = value; +} + +// required .rsctrl.peers.RequestPeers.InfoOption info = 2; +inline bool RequestPeers::has_info() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RequestPeers::set_has_info() { + _has_bits_[0] |= 0x00000002u; +} +inline void RequestPeers::clear_has_info() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RequestPeers::clear_info() { + info_ = 1; + clear_has_info(); +} +inline ::rsctrl::peers::RequestPeers_InfoOption RequestPeers::info() const { + return static_cast< ::rsctrl::peers::RequestPeers_InfoOption >(info_); +} +inline void RequestPeers::set_info(::rsctrl::peers::RequestPeers_InfoOption value) { + GOOGLE_DCHECK(::rsctrl::peers::RequestPeers_InfoOption_IsValid(value)); + set_has_info(); + info_ = value; +} + +// repeated string gpg_ids = 3; +inline int RequestPeers::gpg_ids_size() const { + return gpg_ids_.size(); +} +inline void RequestPeers::clear_gpg_ids() { + gpg_ids_.Clear(); +} +inline const ::std::string& RequestPeers::gpg_ids(int index) const { + return gpg_ids_.Get(index); +} +inline ::std::string* RequestPeers::mutable_gpg_ids(int index) { + return gpg_ids_.Mutable(index); +} +inline void RequestPeers::set_gpg_ids(int index, const ::std::string& value) { + gpg_ids_.Mutable(index)->assign(value); +} +inline void RequestPeers::set_gpg_ids(int index, const char* value) { + gpg_ids_.Mutable(index)->assign(value); +} +inline void RequestPeers::set_gpg_ids(int index, const char* value, size_t size) { + gpg_ids_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* RequestPeers::add_gpg_ids() { + return gpg_ids_.Add(); +} +inline void RequestPeers::add_gpg_ids(const ::std::string& value) { + gpg_ids_.Add()->assign(value); +} +inline void RequestPeers::add_gpg_ids(const char* value) { + gpg_ids_.Add()->assign(value); +} +inline void RequestPeers::add_gpg_ids(const char* value, size_t size) { + gpg_ids_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +RequestPeers::gpg_ids() const { + return gpg_ids_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +RequestPeers::mutable_gpg_ids() { + return &gpg_ids_; +} + +// ------------------------------------------------------------------- + +// ResponsePeerList + +// required .rsctrl.core.Status status = 1; +inline bool ResponsePeerList::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponsePeerList::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponsePeerList::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponsePeerList::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponsePeerList::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponsePeerList::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponsePeerList::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated .rsctrl.core.Person peers = 2; +inline int ResponsePeerList::peers_size() const { + return peers_.size(); +} +inline void ResponsePeerList::clear_peers() { + peers_.Clear(); +} +inline const ::rsctrl::core::Person& ResponsePeerList::peers(int index) const { + return peers_.Get(index); +} +inline ::rsctrl::core::Person* ResponsePeerList::mutable_peers(int index) { + return peers_.Mutable(index); +} +inline ::rsctrl::core::Person* ResponsePeerList::add_peers() { + return peers_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& +ResponsePeerList::peers() const { + return peers_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* +ResponsePeerList::mutable_peers() { + return &peers_; +} + +// ------------------------------------------------------------------- + +// RequestAddPeer + +// required string gpg_id = 1; +inline bool RequestAddPeer::has_gpg_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestAddPeer::set_has_gpg_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestAddPeer::clear_has_gpg_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestAddPeer::clear_gpg_id() { + if (gpg_id_ != &::google::protobuf::internal::kEmptyString) { + gpg_id_->clear(); + } + clear_has_gpg_id(); +} +inline const ::std::string& RequestAddPeer::gpg_id() const { + return *gpg_id_; +} +inline void RequestAddPeer::set_gpg_id(const ::std::string& value) { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + gpg_id_->assign(value); +} +inline void RequestAddPeer::set_gpg_id(const char* value) { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + gpg_id_->assign(value); +} +inline void RequestAddPeer::set_gpg_id(const char* value, size_t size) { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + gpg_id_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RequestAddPeer::mutable_gpg_id() { + set_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + gpg_id_ = new ::std::string; + } + return gpg_id_; +} +inline ::std::string* RequestAddPeer::release_gpg_id() { + clear_has_gpg_id(); + if (gpg_id_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = gpg_id_; + gpg_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// required .rsctrl.peers.RequestAddPeer.AddCmd cmd = 2; +inline bool RequestAddPeer::has_cmd() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void RequestAddPeer::set_has_cmd() { + _has_bits_[0] |= 0x00000002u; +} +inline void RequestAddPeer::clear_has_cmd() { + _has_bits_[0] &= ~0x00000002u; +} +inline void RequestAddPeer::clear_cmd() { + cmd_ = 0; + clear_has_cmd(); +} +inline ::rsctrl::peers::RequestAddPeer_AddCmd RequestAddPeer::cmd() const { + return static_cast< ::rsctrl::peers::RequestAddPeer_AddCmd >(cmd_); +} +inline void RequestAddPeer::set_cmd(::rsctrl::peers::RequestAddPeer_AddCmd value) { + GOOGLE_DCHECK(::rsctrl::peers::RequestAddPeer_AddCmd_IsValid(value)); + set_has_cmd(); + cmd_ = value; +} + +// optional string cert = 3; +inline bool RequestAddPeer::has_cert() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void RequestAddPeer::set_has_cert() { + _has_bits_[0] |= 0x00000004u; +} +inline void RequestAddPeer::clear_has_cert() { + _has_bits_[0] &= ~0x00000004u; +} +inline void RequestAddPeer::clear_cert() { + if (cert_ != &::google::protobuf::internal::kEmptyString) { + cert_->clear(); + } + clear_has_cert(); +} +inline const ::std::string& RequestAddPeer::cert() const { + return *cert_; +} +inline void RequestAddPeer::set_cert(const ::std::string& value) { + set_has_cert(); + if (cert_ == &::google::protobuf::internal::kEmptyString) { + cert_ = new ::std::string; + } + cert_->assign(value); +} +inline void RequestAddPeer::set_cert(const char* value) { + set_has_cert(); + if (cert_ == &::google::protobuf::internal::kEmptyString) { + cert_ = new ::std::string; + } + cert_->assign(value); +} +inline void RequestAddPeer::set_cert(const char* value, size_t size) { + set_has_cert(); + if (cert_ == &::google::protobuf::internal::kEmptyString) { + cert_ = new ::std::string; + } + cert_->assign(reinterpret_cast(value), size); +} +inline ::std::string* RequestAddPeer::mutable_cert() { + set_has_cert(); + if (cert_ == &::google::protobuf::internal::kEmptyString) { + cert_ = new ::std::string; + } + return cert_; +} +inline ::std::string* RequestAddPeer::release_cert() { + clear_has_cert(); + if (cert_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = cert_; + cert_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// ResponseAddPeer + +// required .rsctrl.core.Status status = 1; +inline bool ResponseAddPeer::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseAddPeer::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseAddPeer::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseAddPeer::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseAddPeer::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseAddPeer::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseAddPeer::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated .rsctrl.core.Person peers = 2; +inline int ResponseAddPeer::peers_size() const { + return peers_.size(); +} +inline void ResponseAddPeer::clear_peers() { + peers_.Clear(); +} +inline const ::rsctrl::core::Person& ResponseAddPeer::peers(int index) const { + return peers_.Get(index); +} +inline ::rsctrl::core::Person* ResponseAddPeer::mutable_peers(int index) { + return peers_.Mutable(index); +} +inline ::rsctrl::core::Person* ResponseAddPeer::add_peers() { + return peers_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& +ResponseAddPeer::peers() const { + return peers_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* +ResponseAddPeer::mutable_peers() { + return &peers_; +} + +// ------------------------------------------------------------------- + +// RequestModifyPeer + +// required .rsctrl.peers.RequestModifyPeer.ModCmd cmd = 1; +inline bool RequestModifyPeer::has_cmd() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestModifyPeer::set_has_cmd() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestModifyPeer::clear_has_cmd() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestModifyPeer::clear_cmd() { + cmd_ = 0; + clear_has_cmd(); +} +inline ::rsctrl::peers::RequestModifyPeer_ModCmd RequestModifyPeer::cmd() const { + return static_cast< ::rsctrl::peers::RequestModifyPeer_ModCmd >(cmd_); +} +inline void RequestModifyPeer::set_cmd(::rsctrl::peers::RequestModifyPeer_ModCmd value) { + GOOGLE_DCHECK(::rsctrl::peers::RequestModifyPeer_ModCmd_IsValid(value)); + set_has_cmd(); + cmd_ = value; +} + +// repeated .rsctrl.core.Person peers = 2; +inline int RequestModifyPeer::peers_size() const { + return peers_.size(); +} +inline void RequestModifyPeer::clear_peers() { + peers_.Clear(); +} +inline const ::rsctrl::core::Person& RequestModifyPeer::peers(int index) const { + return peers_.Get(index); +} +inline ::rsctrl::core::Person* RequestModifyPeer::mutable_peers(int index) { + return peers_.Mutable(index); +} +inline ::rsctrl::core::Person* RequestModifyPeer::add_peers() { + return peers_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& +RequestModifyPeer::peers() const { + return peers_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* +RequestModifyPeer::mutable_peers() { + return &peers_; +} + +// ------------------------------------------------------------------- + +// ResponseModifyPeer + +// required .rsctrl.core.Status status = 1; +inline bool ResponseModifyPeer::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseModifyPeer::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseModifyPeer::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseModifyPeer::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseModifyPeer::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseModifyPeer::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseModifyPeer::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated .rsctrl.core.Person peers = 2; +inline int ResponseModifyPeer::peers_size() const { + return peers_.size(); +} +inline void ResponseModifyPeer::clear_peers() { + peers_.Clear(); +} +inline const ::rsctrl::core::Person& ResponseModifyPeer::peers(int index) const { + return peers_.Get(index); +} +inline ::rsctrl::core::Person* ResponseModifyPeer::mutable_peers(int index) { + return peers_.Mutable(index); +} +inline ::rsctrl::core::Person* ResponseModifyPeer::add_peers() { + return peers_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >& +ResponseModifyPeer::peers() const { + return peers_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::core::Person >* +ResponseModifyPeer::mutable_peers() { + return &peers_; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace peers +} // namespace rsctrl + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::peers::RequestPeers_SetOption>() { + return ::rsctrl::peers::RequestPeers_SetOption_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::peers::RequestPeers_InfoOption>() { + return ::rsctrl::peers::RequestPeers_InfoOption_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::peers::RequestAddPeer_AddCmd>() { + return ::rsctrl::peers::RequestAddPeer_AddCmd_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::peers::RequestModifyPeer_ModCmd>() { + return ::rsctrl::peers::RequestModifyPeer_ModCmd_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::peers::RequestMsgIds>() { + return rsctrl::peers::RequestMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::peers::ResponseMsgIds>() { + return rsctrl::peers::ResponseMsgIds_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_peers_2eproto__INCLUDED diff --git a/retroshare-nogui/src/rpc/proto/gencc/search.pb.cc b/retroshare-nogui/src/rpc/proto/gencc/search.pb.cc new file mode 100644 index 000000000..7f41f346d --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/search.pb.cc @@ -0,0 +1,2437 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "search.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace search { + +namespace { + +const ::google::protobuf::Descriptor* SearchHit_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SearchHit_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* SearchHit_LocFlag_descriptor_ = NULL; +const ::google::protobuf::Descriptor* SearchSet_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SearchSet_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestBasicSearch_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestBasicSearch_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestAdvSearch_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestAdvSearch_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseSearchIds_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseSearchIds_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestCloseSearch_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestCloseSearch_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestListSearches_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestListSearches_reflection_ = NULL; +const ::google::protobuf::Descriptor* RequestSearchResults_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestSearchResults_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseSearchResults_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseSearchResults_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_search_2eproto() { + protobuf_AddDesc_search_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "search.proto"); + GOOGLE_CHECK(file != NULL); + SearchHit_descriptor_ = file->message_type(0); + static const int SearchHit_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchHit, file_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchHit, loc_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchHit, no_hits_), + }; + SearchHit_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SearchHit_descriptor_, + SearchHit::default_instance_, + SearchHit_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchHit, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchHit, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SearchHit)); + SearchHit_LocFlag_descriptor_ = SearchHit_descriptor_->enum_type(0); + SearchSet_descriptor_ = file->message_type(1); + static const int SearchSet_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchSet, search_id_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchSet, hits_), + }; + SearchSet_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SearchSet_descriptor_, + SearchSet::default_instance_, + SearchSet_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchSet, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SearchSet, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SearchSet)); + RequestBasicSearch_descriptor_ = file->message_type(2); + static const int RequestBasicSearch_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestBasicSearch, terms_), + }; + RequestBasicSearch_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestBasicSearch_descriptor_, + RequestBasicSearch::default_instance_, + RequestBasicSearch_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestBasicSearch, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestBasicSearch, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestBasicSearch)); + RequestAdvSearch_descriptor_ = file->message_type(3); + static const int RequestAdvSearch_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAdvSearch, terms_), + }; + RequestAdvSearch_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestAdvSearch_descriptor_, + RequestAdvSearch::default_instance_, + RequestAdvSearch_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAdvSearch, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestAdvSearch, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestAdvSearch)); + ResponseSearchIds_descriptor_ = file->message_type(4); + static const int ResponseSearchIds_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchIds, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchIds, search_id_), + }; + ResponseSearchIds_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseSearchIds_descriptor_, + ResponseSearchIds::default_instance_, + ResponseSearchIds_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchIds, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchIds, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseSearchIds)); + RequestCloseSearch_descriptor_ = file->message_type(5); + static const int RequestCloseSearch_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCloseSearch, search_id_), + }; + RequestCloseSearch_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestCloseSearch_descriptor_, + RequestCloseSearch::default_instance_, + RequestCloseSearch_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCloseSearch, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestCloseSearch, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestCloseSearch)); + RequestListSearches_descriptor_ = file->message_type(6); + static const int RequestListSearches_offsets_[1] = { + }; + RequestListSearches_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestListSearches_descriptor_, + RequestListSearches::default_instance_, + RequestListSearches_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestListSearches, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestListSearches, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestListSearches)); + RequestSearchResults_descriptor_ = file->message_type(7); + static const int RequestSearchResults_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSearchResults, search_ids_), + }; + RequestSearchResults_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestSearchResults_descriptor_, + RequestSearchResults::default_instance_, + RequestSearchResults_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSearchResults, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSearchResults, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestSearchResults)); + ResponseSearchResults_descriptor_ = file->message_type(8); + static const int ResponseSearchResults_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchResults, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchResults, searches_), + }; + ResponseSearchResults_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseSearchResults_descriptor_, + ResponseSearchResults::default_instance_, + ResponseSearchResults_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchResults, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSearchResults, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseSearchResults)); + RequestMsgIds_descriptor_ = file->enum_type(0); + ResponseMsgIds_descriptor_ = file->enum_type(1); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_search_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SearchHit_descriptor_, &SearchHit::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SearchSet_descriptor_, &SearchSet::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestBasicSearch_descriptor_, &RequestBasicSearch::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestAdvSearch_descriptor_, &RequestAdvSearch::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseSearchIds_descriptor_, &ResponseSearchIds::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestCloseSearch_descriptor_, &RequestCloseSearch::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestListSearches_descriptor_, &RequestListSearches::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestSearchResults_descriptor_, &RequestSearchResults::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseSearchResults_descriptor_, &ResponseSearchResults::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_search_2eproto() { + delete SearchHit::default_instance_; + delete SearchHit_reflection_; + delete SearchSet::default_instance_; + delete SearchSet_reflection_; + delete RequestBasicSearch::default_instance_; + delete RequestBasicSearch_reflection_; + delete RequestAdvSearch::default_instance_; + delete RequestAdvSearch_reflection_; + delete ResponseSearchIds::default_instance_; + delete ResponseSearchIds_reflection_; + delete RequestCloseSearch::default_instance_; + delete RequestCloseSearch_reflection_; + delete RequestListSearches::default_instance_; + delete RequestListSearches_reflection_; + delete RequestSearchResults::default_instance_; + delete RequestSearchResults_reflection_; + delete ResponseSearchResults::default_instance_; + delete ResponseSearchResults_reflection_; +} + +void protobuf_AddDesc_search_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::rsctrl::core::protobuf_AddDesc_core_2eproto(); + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\014search.proto\022\rrsctrl.search\032\ncore.prot" + "o\"y\n\tSearchHit\022\037\n\004file\030\001 \002(\0132\021.rsctrl.co" + "re.File\022\013\n\003loc\030\002 \002(\r\022\017\n\007no_hits\030\003 \002(\r\"-\n" + "\007LocFlag\022\t\n\005LOCAL\020\001\022\n\n\006FRIEND\020\002\022\013\n\007NETWO" + "RK\020\004\"F\n\tSearchSet\022\021\n\tsearch_id\030\001 \002(\r\022&\n\004" + "hits\030\002 \003(\0132\030.rsctrl.search.SearchHit\"#\n\022" + "RequestBasicSearch\022\r\n\005terms\030\001 \003(\t\"!\n\020Req" + "uestAdvSearch\022\r\n\005terms\030\001 \003(\t\"K\n\021Response" + "SearchIds\022#\n\006status\030\001 \002(\0132\023.rsctrl.core." + "Status\022\021\n\tsearch_id\030\002 \003(\r\"\'\n\022RequestClos" + "eSearch\022\021\n\tsearch_id\030\001 \002(\r\"\025\n\023RequestLis" + "tSearches\"*\n\024RequestSearchResults\022\022\n\nsea" + "rch_ids\030\002 \003(\r\"h\n\025ResponseSearchResults\022#" + "\n\006status\030\001 \002(\0132\023.rsctrl.core.Status\022*\n\010s" + "earches\030\002 \003(\0132\030.rsctrl.search.SearchSet*" + "\212\001\n\rRequestMsgIds\022\034\n\030MsgId_RequestBasicS" + "earch\020\001\022\034\n\030MsgId_RequestCloseSearch\020\003\022\035\n" + "\031MsgId_RequestListSearches\020\004\022\036\n\032MsgId_Re" + "questSearchResults\020\005*N\n\016ResponseMsgIds\022\033" + "\n\027MsgId_ResponseSearchIds\020\001\022\037\n\033MsgId_Res" + "ponseSearchResults\020\005", 820); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "search.proto", &protobuf_RegisterTypes); + SearchHit::default_instance_ = new SearchHit(); + SearchSet::default_instance_ = new SearchSet(); + RequestBasicSearch::default_instance_ = new RequestBasicSearch(); + RequestAdvSearch::default_instance_ = new RequestAdvSearch(); + ResponseSearchIds::default_instance_ = new ResponseSearchIds(); + RequestCloseSearch::default_instance_ = new RequestCloseSearch(); + RequestListSearches::default_instance_ = new RequestListSearches(); + RequestSearchResults::default_instance_ = new RequestSearchResults(); + ResponseSearchResults::default_instance_ = new ResponseSearchResults(); + SearchHit::default_instance_->InitAsDefaultInstance(); + SearchSet::default_instance_->InitAsDefaultInstance(); + RequestBasicSearch::default_instance_->InitAsDefaultInstance(); + RequestAdvSearch::default_instance_->InitAsDefaultInstance(); + ResponseSearchIds::default_instance_->InitAsDefaultInstance(); + RequestCloseSearch::default_instance_->InitAsDefaultInstance(); + RequestListSearches::default_instance_->InitAsDefaultInstance(); + RequestSearchResults::default_instance_->InitAsDefaultInstance(); + ResponseSearchResults::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_search_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_search_2eproto { + StaticDescriptorInitializer_search_2eproto() { + protobuf_AddDesc_search_2eproto(); + } +} static_descriptor_initializer_search_2eproto_; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestMsgIds_descriptor_; +} +bool RequestMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 3: + case 4: + case 5: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseMsgIds_descriptor_; +} +bool ResponseMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 5: + return true; + default: + return false; + } +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* SearchHit_LocFlag_descriptor() { + protobuf_AssignDescriptorsOnce(); + return SearchHit_LocFlag_descriptor_; +} +bool SearchHit_LocFlag_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 4: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const SearchHit_LocFlag SearchHit::LOCAL; +const SearchHit_LocFlag SearchHit::FRIEND; +const SearchHit_LocFlag SearchHit::NETWORK; +const SearchHit_LocFlag SearchHit::LocFlag_MIN; +const SearchHit_LocFlag SearchHit::LocFlag_MAX; +const int SearchHit::LocFlag_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int SearchHit::kFileFieldNumber; +const int SearchHit::kLocFieldNumber; +const int SearchHit::kNoHitsFieldNumber; +#endif // !_MSC_VER + +SearchHit::SearchHit() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SearchHit::InitAsDefaultInstance() { + file_ = const_cast< ::rsctrl::core::File*>(&::rsctrl::core::File::default_instance()); +} + +SearchHit::SearchHit(const SearchHit& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SearchHit::SharedCtor() { + _cached_size_ = 0; + file_ = NULL; + loc_ = 0u; + no_hits_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SearchHit::~SearchHit() { + SharedDtor(); +} + +void SearchHit::SharedDtor() { + if (this != default_instance_) { + delete file_; + } +} + +void SearchHit::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SearchHit::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SearchHit_descriptor_; +} + +const SearchHit& SearchHit::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +SearchHit* SearchHit::default_instance_ = NULL; + +SearchHit* SearchHit::New() const { + return new SearchHit; +} + +void SearchHit::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_file()) { + if (file_ != NULL) file_->::rsctrl::core::File::Clear(); + } + loc_ = 0u; + no_hits_ = 0u; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SearchHit::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.File file = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_file())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_loc; + break; + } + + // required uint32 loc = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_loc: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &loc_))); + set_has_loc(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_no_hits; + break; + } + + // required uint32 no_hits = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_no_hits: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &no_hits_))); + set_has_no_hits(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SearchHit::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.File file = 1; + if (has_file()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->file(), output); + } + + // required uint32 loc = 2; + if (has_loc()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->loc(), output); + } + + // required uint32 no_hits = 3; + if (has_no_hits()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->no_hits(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SearchHit::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.File file = 1; + if (has_file()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->file(), target); + } + + // required uint32 loc = 2; + if (has_loc()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->loc(), target); + } + + // required uint32 no_hits = 3; + if (has_no_hits()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->no_hits(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SearchHit::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.File file = 1; + if (has_file()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->file()); + } + + // required uint32 loc = 2; + if (has_loc()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->loc()); + } + + // required uint32 no_hits = 3; + if (has_no_hits()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->no_hits()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SearchHit::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SearchHit* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SearchHit::MergeFrom(const SearchHit& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_file()) { + mutable_file()->::rsctrl::core::File::MergeFrom(from.file()); + } + if (from.has_loc()) { + set_loc(from.loc()); + } + if (from.has_no_hits()) { + set_no_hits(from.no_hits()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SearchHit::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SearchHit::CopyFrom(const SearchHit& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SearchHit::IsInitialized() const { + if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; + + if (has_file()) { + if (!this->file().IsInitialized()) return false; + } + return true; +} + +void SearchHit::Swap(SearchHit* other) { + if (other != this) { + std::swap(file_, other->file_); + std::swap(loc_, other->loc_); + std::swap(no_hits_, other->no_hits_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SearchHit::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SearchHit_descriptor_; + metadata.reflection = SearchHit_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int SearchSet::kSearchIdFieldNumber; +const int SearchSet::kHitsFieldNumber; +#endif // !_MSC_VER + +SearchSet::SearchSet() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SearchSet::InitAsDefaultInstance() { +} + +SearchSet::SearchSet(const SearchSet& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SearchSet::SharedCtor() { + _cached_size_ = 0; + search_id_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SearchSet::~SearchSet() { + SharedDtor(); +} + +void SearchSet::SharedDtor() { + if (this != default_instance_) { + } +} + +void SearchSet::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SearchSet::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SearchSet_descriptor_; +} + +const SearchSet& SearchSet::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +SearchSet* SearchSet::default_instance_ = NULL; + +SearchSet* SearchSet::New() const { + return new SearchSet; +} + +void SearchSet::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + search_id_ = 0u; + } + hits_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SearchSet::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required uint32 search_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &search_id_))); + set_has_search_id(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_hits; + break; + } + + // repeated .rsctrl.search.SearchHit hits = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_hits: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_hits())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_hits; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SearchSet::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required uint32 search_id = 1; + if (has_search_id()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->search_id(), output); + } + + // repeated .rsctrl.search.SearchHit hits = 2; + for (int i = 0; i < this->hits_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->hits(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SearchSet::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required uint32 search_id = 1; + if (has_search_id()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->search_id(), target); + } + + // repeated .rsctrl.search.SearchHit hits = 2; + for (int i = 0; i < this->hits_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->hits(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SearchSet::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required uint32 search_id = 1; + if (has_search_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->search_id()); + } + + } + // repeated .rsctrl.search.SearchHit hits = 2; + total_size += 1 * this->hits_size(); + for (int i = 0; i < this->hits_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->hits(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SearchSet::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SearchSet* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SearchSet::MergeFrom(const SearchSet& from) { + GOOGLE_CHECK_NE(&from, this); + hits_.MergeFrom(from.hits_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_search_id()) { + set_search_id(from.search_id()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SearchSet::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SearchSet::CopyFrom(const SearchSet& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SearchSet::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + for (int i = 0; i < hits_size(); i++) { + if (!this->hits(i).IsInitialized()) return false; + } + return true; +} + +void SearchSet::Swap(SearchSet* other) { + if (other != this) { + std::swap(search_id_, other->search_id_); + hits_.Swap(&other->hits_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SearchSet::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SearchSet_descriptor_; + metadata.reflection = SearchSet_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestBasicSearch::kTermsFieldNumber; +#endif // !_MSC_VER + +RequestBasicSearch::RequestBasicSearch() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestBasicSearch::InitAsDefaultInstance() { +} + +RequestBasicSearch::RequestBasicSearch(const RequestBasicSearch& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestBasicSearch::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestBasicSearch::~RequestBasicSearch() { + SharedDtor(); +} + +void RequestBasicSearch::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestBasicSearch::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestBasicSearch::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestBasicSearch_descriptor_; +} + +const RequestBasicSearch& RequestBasicSearch::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +RequestBasicSearch* RequestBasicSearch::default_instance_ = NULL; + +RequestBasicSearch* RequestBasicSearch::New() const { + return new RequestBasicSearch; +} + +void RequestBasicSearch::Clear() { + terms_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestBasicSearch::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated string terms = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_terms: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_terms())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->terms(0).data(), this->terms(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_terms; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestBasicSearch::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated string terms = 1; + for (int i = 0; i < this->terms_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->terms(i).data(), this->terms(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->terms(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestBasicSearch::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated string terms = 1; + for (int i = 0; i < this->terms_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->terms(i).data(), this->terms(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(1, this->terms(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestBasicSearch::ByteSize() const { + int total_size = 0; + + // repeated string terms = 1; + total_size += 1 * this->terms_size(); + for (int i = 0; i < this->terms_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->terms(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestBasicSearch::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestBasicSearch* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestBasicSearch::MergeFrom(const RequestBasicSearch& from) { + GOOGLE_CHECK_NE(&from, this); + terms_.MergeFrom(from.terms_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestBasicSearch::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestBasicSearch::CopyFrom(const RequestBasicSearch& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestBasicSearch::IsInitialized() const { + + return true; +} + +void RequestBasicSearch::Swap(RequestBasicSearch* other) { + if (other != this) { + terms_.Swap(&other->terms_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestBasicSearch::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestBasicSearch_descriptor_; + metadata.reflection = RequestBasicSearch_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestAdvSearch::kTermsFieldNumber; +#endif // !_MSC_VER + +RequestAdvSearch::RequestAdvSearch() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestAdvSearch::InitAsDefaultInstance() { +} + +RequestAdvSearch::RequestAdvSearch(const RequestAdvSearch& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestAdvSearch::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestAdvSearch::~RequestAdvSearch() { + SharedDtor(); +} + +void RequestAdvSearch::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestAdvSearch::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestAdvSearch::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestAdvSearch_descriptor_; +} + +const RequestAdvSearch& RequestAdvSearch::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +RequestAdvSearch* RequestAdvSearch::default_instance_ = NULL; + +RequestAdvSearch* RequestAdvSearch::New() const { + return new RequestAdvSearch; +} + +void RequestAdvSearch::Clear() { + terms_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestAdvSearch::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated string terms = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_terms: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_terms())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->terms(0).data(), this->terms(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_terms; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestAdvSearch::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated string terms = 1; + for (int i = 0; i < this->terms_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->terms(i).data(), this->terms(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->terms(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestAdvSearch::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated string terms = 1; + for (int i = 0; i < this->terms_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->terms(i).data(), this->terms(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(1, this->terms(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestAdvSearch::ByteSize() const { + int total_size = 0; + + // repeated string terms = 1; + total_size += 1 * this->terms_size(); + for (int i = 0; i < this->terms_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->terms(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestAdvSearch::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestAdvSearch* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestAdvSearch::MergeFrom(const RequestAdvSearch& from) { + GOOGLE_CHECK_NE(&from, this); + terms_.MergeFrom(from.terms_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestAdvSearch::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestAdvSearch::CopyFrom(const RequestAdvSearch& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestAdvSearch::IsInitialized() const { + + return true; +} + +void RequestAdvSearch::Swap(RequestAdvSearch* other) { + if (other != this) { + terms_.Swap(&other->terms_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestAdvSearch::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestAdvSearch_descriptor_; + metadata.reflection = RequestAdvSearch_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseSearchIds::kStatusFieldNumber; +const int ResponseSearchIds::kSearchIdFieldNumber; +#endif // !_MSC_VER + +ResponseSearchIds::ResponseSearchIds() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseSearchIds::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseSearchIds::ResponseSearchIds(const ResponseSearchIds& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseSearchIds::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseSearchIds::~ResponseSearchIds() { + SharedDtor(); +} + +void ResponseSearchIds::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseSearchIds::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseSearchIds::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSearchIds_descriptor_; +} + +const ResponseSearchIds& ResponseSearchIds::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +ResponseSearchIds* ResponseSearchIds::default_instance_ = NULL; + +ResponseSearchIds* ResponseSearchIds::New() const { + return new ResponseSearchIds; +} + +void ResponseSearchIds::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + search_id_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseSearchIds::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_search_id; + break; + } + + // repeated uint32 search_id = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_search_id: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + 1, 16, input, this->mutable_search_id()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, this->mutable_search_id()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_search_id; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseSearchIds::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated uint32 search_id = 2; + for (int i = 0; i < this->search_id_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32( + 2, this->search_id(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseSearchIds::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated uint32 search_id = 2; + for (int i = 0; i < this->search_id_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteUInt32ToArray(2, this->search_id(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseSearchIds::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated uint32 search_id = 2; + { + int data_size = 0; + for (int i = 0; i < this->search_id_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + UInt32Size(this->search_id(i)); + } + total_size += 1 * this->search_id_size() + data_size; + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseSearchIds::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseSearchIds* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseSearchIds::MergeFrom(const ResponseSearchIds& from) { + GOOGLE_CHECK_NE(&from, this); + search_id_.MergeFrom(from.search_id_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseSearchIds::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseSearchIds::CopyFrom(const ResponseSearchIds& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseSearchIds::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + return true; +} + +void ResponseSearchIds::Swap(ResponseSearchIds* other) { + if (other != this) { + std::swap(status_, other->status_); + search_id_.Swap(&other->search_id_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseSearchIds::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseSearchIds_descriptor_; + metadata.reflection = ResponseSearchIds_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestCloseSearch::kSearchIdFieldNumber; +#endif // !_MSC_VER + +RequestCloseSearch::RequestCloseSearch() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestCloseSearch::InitAsDefaultInstance() { +} + +RequestCloseSearch::RequestCloseSearch(const RequestCloseSearch& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestCloseSearch::SharedCtor() { + _cached_size_ = 0; + search_id_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestCloseSearch::~RequestCloseSearch() { + SharedDtor(); +} + +void RequestCloseSearch::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestCloseSearch::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestCloseSearch::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestCloseSearch_descriptor_; +} + +const RequestCloseSearch& RequestCloseSearch::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +RequestCloseSearch* RequestCloseSearch::default_instance_ = NULL; + +RequestCloseSearch* RequestCloseSearch::New() const { + return new RequestCloseSearch; +} + +void RequestCloseSearch::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + search_id_ = 0u; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestCloseSearch::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required uint32 search_id = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &search_id_))); + set_has_search_id(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestCloseSearch::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required uint32 search_id = 1; + if (has_search_id()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->search_id(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestCloseSearch::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required uint32 search_id = 1; + if (has_search_id()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->search_id(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestCloseSearch::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required uint32 search_id = 1; + if (has_search_id()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->search_id()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestCloseSearch::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestCloseSearch* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestCloseSearch::MergeFrom(const RequestCloseSearch& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_search_id()) { + set_search_id(from.search_id()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestCloseSearch::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestCloseSearch::CopyFrom(const RequestCloseSearch& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestCloseSearch::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void RequestCloseSearch::Swap(RequestCloseSearch* other) { + if (other != this) { + std::swap(search_id_, other->search_id_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestCloseSearch::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestCloseSearch_descriptor_; + metadata.reflection = RequestCloseSearch_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +#endif // !_MSC_VER + +RequestListSearches::RequestListSearches() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestListSearches::InitAsDefaultInstance() { +} + +RequestListSearches::RequestListSearches(const RequestListSearches& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestListSearches::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestListSearches::~RequestListSearches() { + SharedDtor(); +} + +void RequestListSearches::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestListSearches::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestListSearches::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestListSearches_descriptor_; +} + +const RequestListSearches& RequestListSearches::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +RequestListSearches* RequestListSearches::default_instance_ = NULL; + +RequestListSearches* RequestListSearches::New() const { + return new RequestListSearches; +} + +void RequestListSearches::Clear() { + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestListSearches::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + } + return true; +#undef DO_ +} + +void RequestListSearches::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestListSearches::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestListSearches::ByteSize() const { + int total_size = 0; + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestListSearches::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestListSearches* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestListSearches::MergeFrom(const RequestListSearches& from) { + GOOGLE_CHECK_NE(&from, this); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestListSearches::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestListSearches::CopyFrom(const RequestListSearches& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestListSearches::IsInitialized() const { + + return true; +} + +void RequestListSearches::Swap(RequestListSearches* other) { + if (other != this) { + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestListSearches::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestListSearches_descriptor_; + metadata.reflection = RequestListSearches_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int RequestSearchResults::kSearchIdsFieldNumber; +#endif // !_MSC_VER + +RequestSearchResults::RequestSearchResults() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestSearchResults::InitAsDefaultInstance() { +} + +RequestSearchResults::RequestSearchResults(const RequestSearchResults& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestSearchResults::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestSearchResults::~RequestSearchResults() { + SharedDtor(); +} + +void RequestSearchResults::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestSearchResults::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestSearchResults::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestSearchResults_descriptor_; +} + +const RequestSearchResults& RequestSearchResults::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +RequestSearchResults* RequestSearchResults::default_instance_ = NULL; + +RequestSearchResults* RequestSearchResults::New() const { + return new RequestSearchResults; +} + +void RequestSearchResults::Clear() { + search_ids_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestSearchResults::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated uint32 search_ids = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_search_ids: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + 1, 16, input, this->mutable_search_ids()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, this->mutable_search_ids()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_search_ids; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestSearchResults::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated uint32 search_ids = 2; + for (int i = 0; i < this->search_ids_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32( + 2, this->search_ids(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestSearchResults::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated uint32 search_ids = 2; + for (int i = 0; i < this->search_ids_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteUInt32ToArray(2, this->search_ids(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestSearchResults::ByteSize() const { + int total_size = 0; + + // repeated uint32 search_ids = 2; + { + int data_size = 0; + for (int i = 0; i < this->search_ids_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + UInt32Size(this->search_ids(i)); + } + total_size += 1 * this->search_ids_size() + data_size; + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestSearchResults::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestSearchResults* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestSearchResults::MergeFrom(const RequestSearchResults& from) { + GOOGLE_CHECK_NE(&from, this); + search_ids_.MergeFrom(from.search_ids_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestSearchResults::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestSearchResults::CopyFrom(const RequestSearchResults& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestSearchResults::IsInitialized() const { + + return true; +} + +void RequestSearchResults::Swap(RequestSearchResults* other) { + if (other != this) { + search_ids_.Swap(&other->search_ids_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestSearchResults::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestSearchResults_descriptor_; + metadata.reflection = RequestSearchResults_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseSearchResults::kStatusFieldNumber; +const int ResponseSearchResults::kSearchesFieldNumber; +#endif // !_MSC_VER + +ResponseSearchResults::ResponseSearchResults() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseSearchResults::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseSearchResults::ResponseSearchResults(const ResponseSearchResults& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseSearchResults::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseSearchResults::~ResponseSearchResults() { + SharedDtor(); +} + +void ResponseSearchResults::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseSearchResults::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseSearchResults::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSearchResults_descriptor_; +} + +const ResponseSearchResults& ResponseSearchResults::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_search_2eproto(); return *default_instance_; +} + +ResponseSearchResults* ResponseSearchResults::default_instance_ = NULL; + +ResponseSearchResults* ResponseSearchResults::New() const { + return new ResponseSearchResults; +} + +void ResponseSearchResults::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + searches_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseSearchResults::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_searches; + break; + } + + // repeated .rsctrl.search.SearchSet searches = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_searches: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_searches())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_searches; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseSearchResults::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // repeated .rsctrl.search.SearchSet searches = 2; + for (int i = 0; i < this->searches_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->searches(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseSearchResults::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // repeated .rsctrl.search.SearchSet searches = 2; + for (int i = 0; i < this->searches_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->searches(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseSearchResults::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + // repeated .rsctrl.search.SearchSet searches = 2; + total_size += 1 * this->searches_size(); + for (int i = 0; i < this->searches_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->searches(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseSearchResults::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseSearchResults* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseSearchResults::MergeFrom(const ResponseSearchResults& from) { + GOOGLE_CHECK_NE(&from, this); + searches_.MergeFrom(from.searches_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseSearchResults::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseSearchResults::CopyFrom(const ResponseSearchResults& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseSearchResults::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + for (int i = 0; i < searches_size(); i++) { + if (!this->searches(i).IsInitialized()) return false; + } + return true; +} + +void ResponseSearchResults::Swap(ResponseSearchResults* other) { + if (other != this) { + std::swap(status_, other->status_); + searches_.Swap(&other->searches_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseSearchResults::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseSearchResults_descriptor_; + metadata.reflection = ResponseSearchResults_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace search +} // namespace rsctrl + +// @@protoc_insertion_point(global_scope) diff --git a/retroshare-nogui/src/rpc/proto/gencc/search.pb.h b/retroshare-nogui/src/rpc/proto/gencc/search.pb.h new file mode 100644 index 000000000..d006025cb --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/search.pb.h @@ -0,0 +1,1370 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: search.proto + +#ifndef PROTOBUF_search_2eproto__INCLUDED +#define PROTOBUF_search_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include "core.pb.h" +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace search { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_search_2eproto(); +void protobuf_AssignDesc_search_2eproto(); +void protobuf_ShutdownFile_search_2eproto(); + +class SearchHit; +class SearchSet; +class RequestBasicSearch; +class RequestAdvSearch; +class ResponseSearchIds; +class RequestCloseSearch; +class RequestListSearches; +class RequestSearchResults; +class ResponseSearchResults; + +enum SearchHit_LocFlag { + SearchHit_LocFlag_LOCAL = 1, + SearchHit_LocFlag_FRIEND = 2, + SearchHit_LocFlag_NETWORK = 4 +}; +bool SearchHit_LocFlag_IsValid(int value); +const SearchHit_LocFlag SearchHit_LocFlag_LocFlag_MIN = SearchHit_LocFlag_LOCAL; +const SearchHit_LocFlag SearchHit_LocFlag_LocFlag_MAX = SearchHit_LocFlag_NETWORK; +const int SearchHit_LocFlag_LocFlag_ARRAYSIZE = SearchHit_LocFlag_LocFlag_MAX + 1; + +const ::google::protobuf::EnumDescriptor* SearchHit_LocFlag_descriptor(); +inline const ::std::string& SearchHit_LocFlag_Name(SearchHit_LocFlag value) { + return ::google::protobuf::internal::NameOfEnum( + SearchHit_LocFlag_descriptor(), value); +} +inline bool SearchHit_LocFlag_Parse( + const ::std::string& name, SearchHit_LocFlag* value) { + return ::google::protobuf::internal::ParseNamedEnum( + SearchHit_LocFlag_descriptor(), name, value); +} +enum RequestMsgIds { + MsgId_RequestBasicSearch = 1, + MsgId_RequestCloseSearch = 3, + MsgId_RequestListSearches = 4, + MsgId_RequestSearchResults = 5 +}; +bool RequestMsgIds_IsValid(int value); +const RequestMsgIds RequestMsgIds_MIN = MsgId_RequestBasicSearch; +const RequestMsgIds RequestMsgIds_MAX = MsgId_RequestSearchResults; +const int RequestMsgIds_ARRAYSIZE = RequestMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor(); +inline const ::std::string& RequestMsgIds_Name(RequestMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + RequestMsgIds_descriptor(), value); +} +inline bool RequestMsgIds_Parse( + const ::std::string& name, RequestMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestMsgIds_descriptor(), name, value); +} +enum ResponseMsgIds { + MsgId_ResponseSearchIds = 1, + MsgId_ResponseSearchResults = 5 +}; +bool ResponseMsgIds_IsValid(int value); +const ResponseMsgIds ResponseMsgIds_MIN = MsgId_ResponseSearchIds; +const ResponseMsgIds ResponseMsgIds_MAX = MsgId_ResponseSearchResults; +const int ResponseMsgIds_ARRAYSIZE = ResponseMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor(); +inline const ::std::string& ResponseMsgIds_Name(ResponseMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + ResponseMsgIds_descriptor(), value); +} +inline bool ResponseMsgIds_Parse( + const ::std::string& name, ResponseMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ResponseMsgIds_descriptor(), name, value); +} +// =================================================================== + +class SearchHit : public ::google::protobuf::Message { + public: + SearchHit(); + virtual ~SearchHit(); + + SearchHit(const SearchHit& from); + + inline SearchHit& operator=(const SearchHit& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const SearchHit& default_instance(); + + void Swap(SearchHit* other); + + // implements Message ---------------------------------------------- + + SearchHit* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SearchHit& from); + void MergeFrom(const SearchHit& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef SearchHit_LocFlag LocFlag; + static const LocFlag LOCAL = SearchHit_LocFlag_LOCAL; + static const LocFlag FRIEND = SearchHit_LocFlag_FRIEND; + static const LocFlag NETWORK = SearchHit_LocFlag_NETWORK; + static inline bool LocFlag_IsValid(int value) { + return SearchHit_LocFlag_IsValid(value); + } + static const LocFlag LocFlag_MIN = + SearchHit_LocFlag_LocFlag_MIN; + static const LocFlag LocFlag_MAX = + SearchHit_LocFlag_LocFlag_MAX; + static const int LocFlag_ARRAYSIZE = + SearchHit_LocFlag_LocFlag_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + LocFlag_descriptor() { + return SearchHit_LocFlag_descriptor(); + } + static inline const ::std::string& LocFlag_Name(LocFlag value) { + return SearchHit_LocFlag_Name(value); + } + static inline bool LocFlag_Parse(const ::std::string& name, + LocFlag* value) { + return SearchHit_LocFlag_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.File file = 1; + inline bool has_file() const; + inline void clear_file(); + static const int kFileFieldNumber = 1; + inline const ::rsctrl::core::File& file() const; + inline ::rsctrl::core::File* mutable_file(); + inline ::rsctrl::core::File* release_file(); + + // required uint32 loc = 2; + inline bool has_loc() const; + inline void clear_loc(); + static const int kLocFieldNumber = 2; + inline ::google::protobuf::uint32 loc() const; + inline void set_loc(::google::protobuf::uint32 value); + + // required uint32 no_hits = 3; + inline bool has_no_hits() const; + inline void clear_no_hits(); + static const int kNoHitsFieldNumber = 3; + inline ::google::protobuf::uint32 no_hits() const; + inline void set_no_hits(::google::protobuf::uint32 value); + + // @@protoc_insertion_point(class_scope:rsctrl.search.SearchHit) + private: + inline void set_has_file(); + inline void clear_has_file(); + inline void set_has_loc(); + inline void clear_has_loc(); + inline void set_has_no_hits(); + inline void clear_has_no_hits(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::File* file_; + ::google::protobuf::uint32 loc_; + ::google::protobuf::uint32 no_hits_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static SearchHit* default_instance_; +}; +// ------------------------------------------------------------------- + +class SearchSet : public ::google::protobuf::Message { + public: + SearchSet(); + virtual ~SearchSet(); + + SearchSet(const SearchSet& from); + + inline SearchSet& operator=(const SearchSet& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const SearchSet& default_instance(); + + void Swap(SearchSet* other); + + // implements Message ---------------------------------------------- + + SearchSet* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SearchSet& from); + void MergeFrom(const SearchSet& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required uint32 search_id = 1; + inline bool has_search_id() const; + inline void clear_search_id(); + static const int kSearchIdFieldNumber = 1; + inline ::google::protobuf::uint32 search_id() const; + inline void set_search_id(::google::protobuf::uint32 value); + + // repeated .rsctrl.search.SearchHit hits = 2; + inline int hits_size() const; + inline void clear_hits(); + static const int kHitsFieldNumber = 2; + inline const ::rsctrl::search::SearchHit& hits(int index) const; + inline ::rsctrl::search::SearchHit* mutable_hits(int index); + inline ::rsctrl::search::SearchHit* add_hits(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchHit >& + hits() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchHit >* + mutable_hits(); + + // @@protoc_insertion_point(class_scope:rsctrl.search.SearchSet) + private: + inline void set_has_search_id(); + inline void clear_has_search_id(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchHit > hits_; + ::google::protobuf::uint32 search_id_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static SearchSet* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestBasicSearch : public ::google::protobuf::Message { + public: + RequestBasicSearch(); + virtual ~RequestBasicSearch(); + + RequestBasicSearch(const RequestBasicSearch& from); + + inline RequestBasicSearch& operator=(const RequestBasicSearch& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestBasicSearch& default_instance(); + + void Swap(RequestBasicSearch* other); + + // implements Message ---------------------------------------------- + + RequestBasicSearch* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestBasicSearch& from); + void MergeFrom(const RequestBasicSearch& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated string terms = 1; + inline int terms_size() const; + inline void clear_terms(); + static const int kTermsFieldNumber = 1; + inline const ::std::string& terms(int index) const; + inline ::std::string* mutable_terms(int index); + inline void set_terms(int index, const ::std::string& value); + inline void set_terms(int index, const char* value); + inline void set_terms(int index, const char* value, size_t size); + inline ::std::string* add_terms(); + inline void add_terms(const ::std::string& value); + inline void add_terms(const char* value); + inline void add_terms(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& terms() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_terms(); + + // @@protoc_insertion_point(class_scope:rsctrl.search.RequestBasicSearch) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::std::string> terms_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static RequestBasicSearch* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestAdvSearch : public ::google::protobuf::Message { + public: + RequestAdvSearch(); + virtual ~RequestAdvSearch(); + + RequestAdvSearch(const RequestAdvSearch& from); + + inline RequestAdvSearch& operator=(const RequestAdvSearch& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestAdvSearch& default_instance(); + + void Swap(RequestAdvSearch* other); + + // implements Message ---------------------------------------------- + + RequestAdvSearch* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestAdvSearch& from); + void MergeFrom(const RequestAdvSearch& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated string terms = 1; + inline int terms_size() const; + inline void clear_terms(); + static const int kTermsFieldNumber = 1; + inline const ::std::string& terms(int index) const; + inline ::std::string* mutable_terms(int index); + inline void set_terms(int index, const ::std::string& value); + inline void set_terms(int index, const char* value); + inline void set_terms(int index, const char* value, size_t size); + inline ::std::string* add_terms(); + inline void add_terms(const ::std::string& value); + inline void add_terms(const char* value); + inline void add_terms(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& terms() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_terms(); + + // @@protoc_insertion_point(class_scope:rsctrl.search.RequestAdvSearch) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::std::string> terms_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static RequestAdvSearch* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseSearchIds : public ::google::protobuf::Message { + public: + ResponseSearchIds(); + virtual ~ResponseSearchIds(); + + ResponseSearchIds(const ResponseSearchIds& from); + + inline ResponseSearchIds& operator=(const ResponseSearchIds& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseSearchIds& default_instance(); + + void Swap(ResponseSearchIds* other); + + // implements Message ---------------------------------------------- + + ResponseSearchIds* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseSearchIds& from); + void MergeFrom(const ResponseSearchIds& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated uint32 search_id = 2; + inline int search_id_size() const; + inline void clear_search_id(); + static const int kSearchIdFieldNumber = 2; + inline ::google::protobuf::uint32 search_id(int index) const; + inline void set_search_id(int index, ::google::protobuf::uint32 value); + inline void add_search_id(::google::protobuf::uint32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + search_id() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + mutable_search_id(); + + // @@protoc_insertion_point(class_scope:rsctrl.search.ResponseSearchIds) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > search_id_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static ResponseSearchIds* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestCloseSearch : public ::google::protobuf::Message { + public: + RequestCloseSearch(); + virtual ~RequestCloseSearch(); + + RequestCloseSearch(const RequestCloseSearch& from); + + inline RequestCloseSearch& operator=(const RequestCloseSearch& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestCloseSearch& default_instance(); + + void Swap(RequestCloseSearch* other); + + // implements Message ---------------------------------------------- + + RequestCloseSearch* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestCloseSearch& from); + void MergeFrom(const RequestCloseSearch& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required uint32 search_id = 1; + inline bool has_search_id() const; + inline void clear_search_id(); + static const int kSearchIdFieldNumber = 1; + inline ::google::protobuf::uint32 search_id() const; + inline void set_search_id(::google::protobuf::uint32 value); + + // @@protoc_insertion_point(class_scope:rsctrl.search.RequestCloseSearch) + private: + inline void set_has_search_id(); + inline void clear_has_search_id(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::uint32 search_id_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static RequestCloseSearch* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestListSearches : public ::google::protobuf::Message { + public: + RequestListSearches(); + virtual ~RequestListSearches(); + + RequestListSearches(const RequestListSearches& from); + + inline RequestListSearches& operator=(const RequestListSearches& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestListSearches& default_instance(); + + void Swap(RequestListSearches* other); + + // implements Message ---------------------------------------------- + + RequestListSearches* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestListSearches& from); + void MergeFrom(const RequestListSearches& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // @@protoc_insertion_point(class_scope:rsctrl.search.RequestListSearches) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[1]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static RequestListSearches* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestSearchResults : public ::google::protobuf::Message { + public: + RequestSearchResults(); + virtual ~RequestSearchResults(); + + RequestSearchResults(const RequestSearchResults& from); + + inline RequestSearchResults& operator=(const RequestSearchResults& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestSearchResults& default_instance(); + + void Swap(RequestSearchResults* other); + + // implements Message ---------------------------------------------- + + RequestSearchResults* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestSearchResults& from); + void MergeFrom(const RequestSearchResults& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated uint32 search_ids = 2; + inline int search_ids_size() const; + inline void clear_search_ids(); + static const int kSearchIdsFieldNumber = 2; + inline ::google::protobuf::uint32 search_ids(int index) const; + inline void set_search_ids(int index, ::google::protobuf::uint32 value); + inline void add_search_ids(::google::protobuf::uint32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + search_ids() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + mutable_search_ids(); + + // @@protoc_insertion_point(class_scope:rsctrl.search.RequestSearchResults) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > search_ids_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static RequestSearchResults* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseSearchResults : public ::google::protobuf::Message { + public: + ResponseSearchResults(); + virtual ~ResponseSearchResults(); + + ResponseSearchResults(const ResponseSearchResults& from); + + inline ResponseSearchResults& operator=(const ResponseSearchResults& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseSearchResults& default_instance(); + + void Swap(ResponseSearchResults* other); + + // implements Message ---------------------------------------------- + + ResponseSearchResults* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseSearchResults& from); + void MergeFrom(const ResponseSearchResults& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // repeated .rsctrl.search.SearchSet searches = 2; + inline int searches_size() const; + inline void clear_searches(); + static const int kSearchesFieldNumber = 2; + inline const ::rsctrl::search::SearchSet& searches(int index) const; + inline ::rsctrl::search::SearchSet* mutable_searches(int index); + inline ::rsctrl::search::SearchSet* add_searches(); + inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchSet >& + searches() const; + inline ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchSet >* + mutable_searches(); + + // @@protoc_insertion_point(class_scope:rsctrl.search.ResponseSearchResults) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchSet > searches_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void protobuf_AddDesc_search_2eproto(); + friend void protobuf_AssignDesc_search_2eproto(); + friend void protobuf_ShutdownFile_search_2eproto(); + + void InitAsDefaultInstance(); + static ResponseSearchResults* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// SearchHit + +// required .rsctrl.core.File file = 1; +inline bool SearchHit::has_file() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void SearchHit::set_has_file() { + _has_bits_[0] |= 0x00000001u; +} +inline void SearchHit::clear_has_file() { + _has_bits_[0] &= ~0x00000001u; +} +inline void SearchHit::clear_file() { + if (file_ != NULL) file_->::rsctrl::core::File::Clear(); + clear_has_file(); +} +inline const ::rsctrl::core::File& SearchHit::file() const { + return file_ != NULL ? *file_ : *default_instance_->file_; +} +inline ::rsctrl::core::File* SearchHit::mutable_file() { + set_has_file(); + if (file_ == NULL) file_ = new ::rsctrl::core::File; + return file_; +} +inline ::rsctrl::core::File* SearchHit::release_file() { + clear_has_file(); + ::rsctrl::core::File* temp = file_; + file_ = NULL; + return temp; +} + +// required uint32 loc = 2; +inline bool SearchHit::has_loc() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void SearchHit::set_has_loc() { + _has_bits_[0] |= 0x00000002u; +} +inline void SearchHit::clear_has_loc() { + _has_bits_[0] &= ~0x00000002u; +} +inline void SearchHit::clear_loc() { + loc_ = 0u; + clear_has_loc(); +} +inline ::google::protobuf::uint32 SearchHit::loc() const { + return loc_; +} +inline void SearchHit::set_loc(::google::protobuf::uint32 value) { + set_has_loc(); + loc_ = value; +} + +// required uint32 no_hits = 3; +inline bool SearchHit::has_no_hits() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void SearchHit::set_has_no_hits() { + _has_bits_[0] |= 0x00000004u; +} +inline void SearchHit::clear_has_no_hits() { + _has_bits_[0] &= ~0x00000004u; +} +inline void SearchHit::clear_no_hits() { + no_hits_ = 0u; + clear_has_no_hits(); +} +inline ::google::protobuf::uint32 SearchHit::no_hits() const { + return no_hits_; +} +inline void SearchHit::set_no_hits(::google::protobuf::uint32 value) { + set_has_no_hits(); + no_hits_ = value; +} + +// ------------------------------------------------------------------- + +// SearchSet + +// required uint32 search_id = 1; +inline bool SearchSet::has_search_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void SearchSet::set_has_search_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void SearchSet::clear_has_search_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void SearchSet::clear_search_id() { + search_id_ = 0u; + clear_has_search_id(); +} +inline ::google::protobuf::uint32 SearchSet::search_id() const { + return search_id_; +} +inline void SearchSet::set_search_id(::google::protobuf::uint32 value) { + set_has_search_id(); + search_id_ = value; +} + +// repeated .rsctrl.search.SearchHit hits = 2; +inline int SearchSet::hits_size() const { + return hits_.size(); +} +inline void SearchSet::clear_hits() { + hits_.Clear(); +} +inline const ::rsctrl::search::SearchHit& SearchSet::hits(int index) const { + return hits_.Get(index); +} +inline ::rsctrl::search::SearchHit* SearchSet::mutable_hits(int index) { + return hits_.Mutable(index); +} +inline ::rsctrl::search::SearchHit* SearchSet::add_hits() { + return hits_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchHit >& +SearchSet::hits() const { + return hits_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchHit >* +SearchSet::mutable_hits() { + return &hits_; +} + +// ------------------------------------------------------------------- + +// RequestBasicSearch + +// repeated string terms = 1; +inline int RequestBasicSearch::terms_size() const { + return terms_.size(); +} +inline void RequestBasicSearch::clear_terms() { + terms_.Clear(); +} +inline const ::std::string& RequestBasicSearch::terms(int index) const { + return terms_.Get(index); +} +inline ::std::string* RequestBasicSearch::mutable_terms(int index) { + return terms_.Mutable(index); +} +inline void RequestBasicSearch::set_terms(int index, const ::std::string& value) { + terms_.Mutable(index)->assign(value); +} +inline void RequestBasicSearch::set_terms(int index, const char* value) { + terms_.Mutable(index)->assign(value); +} +inline void RequestBasicSearch::set_terms(int index, const char* value, size_t size) { + terms_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* RequestBasicSearch::add_terms() { + return terms_.Add(); +} +inline void RequestBasicSearch::add_terms(const ::std::string& value) { + terms_.Add()->assign(value); +} +inline void RequestBasicSearch::add_terms(const char* value) { + terms_.Add()->assign(value); +} +inline void RequestBasicSearch::add_terms(const char* value, size_t size) { + terms_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +RequestBasicSearch::terms() const { + return terms_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +RequestBasicSearch::mutable_terms() { + return &terms_; +} + +// ------------------------------------------------------------------- + +// RequestAdvSearch + +// repeated string terms = 1; +inline int RequestAdvSearch::terms_size() const { + return terms_.size(); +} +inline void RequestAdvSearch::clear_terms() { + terms_.Clear(); +} +inline const ::std::string& RequestAdvSearch::terms(int index) const { + return terms_.Get(index); +} +inline ::std::string* RequestAdvSearch::mutable_terms(int index) { + return terms_.Mutable(index); +} +inline void RequestAdvSearch::set_terms(int index, const ::std::string& value) { + terms_.Mutable(index)->assign(value); +} +inline void RequestAdvSearch::set_terms(int index, const char* value) { + terms_.Mutable(index)->assign(value); +} +inline void RequestAdvSearch::set_terms(int index, const char* value, size_t size) { + terms_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* RequestAdvSearch::add_terms() { + return terms_.Add(); +} +inline void RequestAdvSearch::add_terms(const ::std::string& value) { + terms_.Add()->assign(value); +} +inline void RequestAdvSearch::add_terms(const char* value) { + terms_.Add()->assign(value); +} +inline void RequestAdvSearch::add_terms(const char* value, size_t size) { + terms_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +RequestAdvSearch::terms() const { + return terms_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +RequestAdvSearch::mutable_terms() { + return &terms_; +} + +// ------------------------------------------------------------------- + +// ResponseSearchIds + +// required .rsctrl.core.Status status = 1; +inline bool ResponseSearchIds::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseSearchIds::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseSearchIds::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseSearchIds::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseSearchIds::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseSearchIds::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseSearchIds::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated uint32 search_id = 2; +inline int ResponseSearchIds::search_id_size() const { + return search_id_.size(); +} +inline void ResponseSearchIds::clear_search_id() { + search_id_.Clear(); +} +inline ::google::protobuf::uint32 ResponseSearchIds::search_id(int index) const { + return search_id_.Get(index); +} +inline void ResponseSearchIds::set_search_id(int index, ::google::protobuf::uint32 value) { + search_id_.Set(index, value); +} +inline void ResponseSearchIds::add_search_id(::google::protobuf::uint32 value) { + search_id_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +ResponseSearchIds::search_id() const { + return search_id_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +ResponseSearchIds::mutable_search_id() { + return &search_id_; +} + +// ------------------------------------------------------------------- + +// RequestCloseSearch + +// required uint32 search_id = 1; +inline bool RequestCloseSearch::has_search_id() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestCloseSearch::set_has_search_id() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestCloseSearch::clear_has_search_id() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestCloseSearch::clear_search_id() { + search_id_ = 0u; + clear_has_search_id(); +} +inline ::google::protobuf::uint32 RequestCloseSearch::search_id() const { + return search_id_; +} +inline void RequestCloseSearch::set_search_id(::google::protobuf::uint32 value) { + set_has_search_id(); + search_id_ = value; +} + +// ------------------------------------------------------------------- + +// RequestListSearches + +// ------------------------------------------------------------------- + +// RequestSearchResults + +// repeated uint32 search_ids = 2; +inline int RequestSearchResults::search_ids_size() const { + return search_ids_.size(); +} +inline void RequestSearchResults::clear_search_ids() { + search_ids_.Clear(); +} +inline ::google::protobuf::uint32 RequestSearchResults::search_ids(int index) const { + return search_ids_.Get(index); +} +inline void RequestSearchResults::set_search_ids(int index, ::google::protobuf::uint32 value) { + search_ids_.Set(index, value); +} +inline void RequestSearchResults::add_search_ids(::google::protobuf::uint32 value) { + search_ids_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +RequestSearchResults::search_ids() const { + return search_ids_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +RequestSearchResults::mutable_search_ids() { + return &search_ids_; +} + +// ------------------------------------------------------------------- + +// ResponseSearchResults + +// required .rsctrl.core.Status status = 1; +inline bool ResponseSearchResults::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseSearchResults::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseSearchResults::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseSearchResults::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseSearchResults::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseSearchResults::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseSearchResults::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// repeated .rsctrl.search.SearchSet searches = 2; +inline int ResponseSearchResults::searches_size() const { + return searches_.size(); +} +inline void ResponseSearchResults::clear_searches() { + searches_.Clear(); +} +inline const ::rsctrl::search::SearchSet& ResponseSearchResults::searches(int index) const { + return searches_.Get(index); +} +inline ::rsctrl::search::SearchSet* ResponseSearchResults::mutable_searches(int index) { + return searches_.Mutable(index); +} +inline ::rsctrl::search::SearchSet* ResponseSearchResults::add_searches() { + return searches_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchSet >& +ResponseSearchResults::searches() const { + return searches_; +} +inline ::google::protobuf::RepeatedPtrField< ::rsctrl::search::SearchSet >* +ResponseSearchResults::mutable_searches() { + return &searches_; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace search +} // namespace rsctrl + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::search::SearchHit_LocFlag>() { + return ::rsctrl::search::SearchHit_LocFlag_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::search::RequestMsgIds>() { + return rsctrl::search::RequestMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::search::ResponseMsgIds>() { + return rsctrl::search::ResponseMsgIds_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_search_2eproto__INCLUDED diff --git a/retroshare-nogui/src/rpc/proto/gencc/system.pb.cc b/retroshare-nogui/src/rpc/proto/gencc/system.pb.cc new file mode 100644 index 000000000..915d6affd --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/system.pb.cc @@ -0,0 +1,1262 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "system.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace system { + +namespace { + +const ::google::protobuf::Descriptor* RequestSystemStatus_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestSystemStatus_reflection_ = NULL; +const ::google::protobuf::Descriptor* ResponseSystemStatus_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseSystemStatus_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* ResponseSystemStatus_NetCode_descriptor_ = NULL; +const ::google::protobuf::Descriptor* RequestSystemQuit_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + RequestSystemQuit_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestSystemQuit_QuitCode_descriptor_ = NULL; +const ::google::protobuf::Descriptor* ResponseSystemQuit_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ResponseSystemQuit_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_system_2eproto() { + protobuf_AddDesc_system_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "system.proto"); + GOOGLE_CHECK(file != NULL); + RequestSystemStatus_descriptor_ = file->message_type(0); + static const int RequestSystemStatus_offsets_[1] = { + }; + RequestSystemStatus_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestSystemStatus_descriptor_, + RequestSystemStatus::default_instance_, + RequestSystemStatus_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSystemStatus, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSystemStatus, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestSystemStatus)); + ResponseSystemStatus_descriptor_ = file->message_type(1); + static const int ResponseSystemStatus_offsets_[5] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, no_peers_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, no_connected_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, net_status_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, bw_total_), + }; + ResponseSystemStatus_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseSystemStatus_descriptor_, + ResponseSystemStatus::default_instance_, + ResponseSystemStatus_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemStatus, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseSystemStatus)); + ResponseSystemStatus_NetCode_descriptor_ = ResponseSystemStatus_descriptor_->enum_type(0); + RequestSystemQuit_descriptor_ = file->message_type(2); + static const int RequestSystemQuit_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSystemQuit, quit_code_), + }; + RequestSystemQuit_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + RequestSystemQuit_descriptor_, + RequestSystemQuit::default_instance_, + RequestSystemQuit_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSystemQuit, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RequestSystemQuit, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(RequestSystemQuit)); + RequestSystemQuit_QuitCode_descriptor_ = RequestSystemQuit_descriptor_->enum_type(0); + ResponseSystemQuit_descriptor_ = file->message_type(3); + static const int ResponseSystemQuit_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemQuit, status_), + }; + ResponseSystemQuit_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ResponseSystemQuit_descriptor_, + ResponseSystemQuit::default_instance_, + ResponseSystemQuit_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemQuit, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ResponseSystemQuit, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ResponseSystemQuit)); + RequestMsgIds_descriptor_ = file->enum_type(0); + ResponseMsgIds_descriptor_ = file->enum_type(1); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_system_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestSystemStatus_descriptor_, &RequestSystemStatus::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseSystemStatus_descriptor_, &ResponseSystemStatus::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + RequestSystemQuit_descriptor_, &RequestSystemQuit::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ResponseSystemQuit_descriptor_, &ResponseSystemQuit::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_system_2eproto() { + delete RequestSystemStatus::default_instance_; + delete RequestSystemStatus_reflection_; + delete ResponseSystemStatus::default_instance_; + delete ResponseSystemStatus_reflection_; + delete RequestSystemQuit::default_instance_; + delete RequestSystemQuit_reflection_; + delete ResponseSystemQuit::default_instance_; + delete ResponseSystemQuit_reflection_; +} + +void protobuf_AddDesc_system_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::rsctrl::core::protobuf_AddDesc_core_2eproto(); + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\014system.proto\022\rrsctrl.system\032\ncore.prot" + "o\"\025\n\023RequestSystemStatus\"\366\002\n\024ResponseSys" + "temStatus\022#\n\006status\030\001 \002(\0132\023.rsctrl.core." + "Status\022\020\n\010no_peers\030\002 \002(\r\022\024\n\014no_connected" + "\030\003 \002(\r\022\?\n\nnet_status\030\004 \002(\0162+.rsctrl.syst" + "em.ResponseSystemStatus.NetCode\022(\n\010bw_to" + "tal\030\005 \002(\0132\026.rsctrl.core.Bandwidth\"\245\001\n\007Ne" + "tCode\022\017\n\013BAD_UNKNOWN\020\000\022\017\n\013BAD_OFFLINE\020\001\022" + "\016\n\nBAD_NATSYM\020\002\022\021\n\rBAD_NODHT_NAT\020\003\022\023\n\017WA" + "RNING_RESTART\020\004\022\022\n\016WARNING_NATTED\020\005\022\021\n\rW" + "ARNING_NODHT\020\006\022\010\n\004GOOD\020\007\022\017\n\013ADV_FORWARD\020" + "\010\"\201\001\n\021RequestSystemQuit\022<\n\tquit_code\030\001 \002" + "(\0162).rsctrl.system.RequestSystemQuit.Qui" + "tCode\".\n\010QuitCode\022\021\n\rCLOSE_CHANNEL\020\001\022\017\n\013" + "SHUTDOWN_RS\020\002\"9\n\022ResponseSystemQuit\022#\n\006s" + "tatus\030\001 \002(\0132\023.rsctrl.core.Status*K\n\rRequ" + "estMsgIds\022\035\n\031MsgId_RequestSystemStatus\020\001" + "\022\033\n\027MsgId_RequestSystemQuit\020\002*N\n\016Respons" + "eMsgIds\022\036\n\032MsgId_ResponseSystemStatus\020\001\022" + "\034\n\030MsgId_ResponseSystemQuit\020\002", 789); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "system.proto", &protobuf_RegisterTypes); + RequestSystemStatus::default_instance_ = new RequestSystemStatus(); + ResponseSystemStatus::default_instance_ = new ResponseSystemStatus(); + RequestSystemQuit::default_instance_ = new RequestSystemQuit(); + ResponseSystemQuit::default_instance_ = new ResponseSystemQuit(); + RequestSystemStatus::default_instance_->InitAsDefaultInstance(); + ResponseSystemStatus::default_instance_->InitAsDefaultInstance(); + RequestSystemQuit::default_instance_->InitAsDefaultInstance(); + ResponseSystemQuit::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_system_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_system_2eproto { + StaticDescriptorInitializer_system_2eproto() { + protobuf_AddDesc_system_2eproto(); + } +} static_descriptor_initializer_system_2eproto_; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestMsgIds_descriptor_; +} +bool RequestMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseMsgIds_descriptor_; +} +bool ResponseMsgIds_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + + +// =================================================================== + +#ifndef _MSC_VER +#endif // !_MSC_VER + +RequestSystemStatus::RequestSystemStatus() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestSystemStatus::InitAsDefaultInstance() { +} + +RequestSystemStatus::RequestSystemStatus(const RequestSystemStatus& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestSystemStatus::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestSystemStatus::~RequestSystemStatus() { + SharedDtor(); +} + +void RequestSystemStatus::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestSystemStatus::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestSystemStatus::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestSystemStatus_descriptor_; +} + +const RequestSystemStatus& RequestSystemStatus::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_system_2eproto(); return *default_instance_; +} + +RequestSystemStatus* RequestSystemStatus::default_instance_ = NULL; + +RequestSystemStatus* RequestSystemStatus::New() const { + return new RequestSystemStatus; +} + +void RequestSystemStatus::Clear() { + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestSystemStatus::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + } + return true; +#undef DO_ +} + +void RequestSystemStatus::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestSystemStatus::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestSystemStatus::ByteSize() const { + int total_size = 0; + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestSystemStatus::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestSystemStatus* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestSystemStatus::MergeFrom(const RequestSystemStatus& from) { + GOOGLE_CHECK_NE(&from, this); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestSystemStatus::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestSystemStatus::CopyFrom(const RequestSystemStatus& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestSystemStatus::IsInitialized() const { + + return true; +} + +void RequestSystemStatus::Swap(RequestSystemStatus* other) { + if (other != this) { + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestSystemStatus::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestSystemStatus_descriptor_; + metadata.reflection = RequestSystemStatus_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* ResponseSystemStatus_NetCode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSystemStatus_NetCode_descriptor_; +} +bool ResponseSystemStatus_NetCode_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const ResponseSystemStatus_NetCode ResponseSystemStatus::BAD_UNKNOWN; +const ResponseSystemStatus_NetCode ResponseSystemStatus::BAD_OFFLINE; +const ResponseSystemStatus_NetCode ResponseSystemStatus::BAD_NATSYM; +const ResponseSystemStatus_NetCode ResponseSystemStatus::BAD_NODHT_NAT; +const ResponseSystemStatus_NetCode ResponseSystemStatus::WARNING_RESTART; +const ResponseSystemStatus_NetCode ResponseSystemStatus::WARNING_NATTED; +const ResponseSystemStatus_NetCode ResponseSystemStatus::WARNING_NODHT; +const ResponseSystemStatus_NetCode ResponseSystemStatus::GOOD; +const ResponseSystemStatus_NetCode ResponseSystemStatus::ADV_FORWARD; +const ResponseSystemStatus_NetCode ResponseSystemStatus::NetCode_MIN; +const ResponseSystemStatus_NetCode ResponseSystemStatus::NetCode_MAX; +const int ResponseSystemStatus::NetCode_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int ResponseSystemStatus::kStatusFieldNumber; +const int ResponseSystemStatus::kNoPeersFieldNumber; +const int ResponseSystemStatus::kNoConnectedFieldNumber; +const int ResponseSystemStatus::kNetStatusFieldNumber; +const int ResponseSystemStatus::kBwTotalFieldNumber; +#endif // !_MSC_VER + +ResponseSystemStatus::ResponseSystemStatus() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseSystemStatus::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); + bw_total_ = const_cast< ::rsctrl::core::Bandwidth*>(&::rsctrl::core::Bandwidth::default_instance()); +} + +ResponseSystemStatus::ResponseSystemStatus(const ResponseSystemStatus& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseSystemStatus::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + no_peers_ = 0u; + no_connected_ = 0u; + net_status_ = 0; + bw_total_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseSystemStatus::~ResponseSystemStatus() { + SharedDtor(); +} + +void ResponseSystemStatus::SharedDtor() { + if (this != default_instance_) { + delete status_; + delete bw_total_; + } +} + +void ResponseSystemStatus::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseSystemStatus::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSystemStatus_descriptor_; +} + +const ResponseSystemStatus& ResponseSystemStatus::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_system_2eproto(); return *default_instance_; +} + +ResponseSystemStatus* ResponseSystemStatus::default_instance_ = NULL; + +ResponseSystemStatus* ResponseSystemStatus::New() const { + return new ResponseSystemStatus; +} + +void ResponseSystemStatus::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + no_peers_ = 0u; + no_connected_ = 0u; + net_status_ = 0; + if (has_bw_total()) { + if (bw_total_ != NULL) bw_total_->::rsctrl::core::Bandwidth::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseSystemStatus::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_no_peers; + break; + } + + // required uint32 no_peers = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_no_peers: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &no_peers_))); + set_has_no_peers(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_no_connected; + break; + } + + // required uint32 no_connected = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_no_connected: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &no_connected_))); + set_has_no_connected(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_net_status; + break; + } + + // required .rsctrl.system.ResponseSystemStatus.NetCode net_status = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_net_status: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::system::ResponseSystemStatus_NetCode_IsValid(value)) { + set_net_status(static_cast< ::rsctrl::system::ResponseSystemStatus_NetCode >(value)); + } else { + mutable_unknown_fields()->AddVarint(4, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(42)) goto parse_bw_total; + break; + } + + // required .rsctrl.core.Bandwidth bw_total = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_bw_total: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_bw_total())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseSystemStatus::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + // required uint32 no_peers = 2; + if (has_no_peers()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->no_peers(), output); + } + + // required uint32 no_connected = 3; + if (has_no_connected()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->no_connected(), output); + } + + // required .rsctrl.system.ResponseSystemStatus.NetCode net_status = 4; + if (has_net_status()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 4, this->net_status(), output); + } + + // required .rsctrl.core.Bandwidth bw_total = 5; + if (has_bw_total()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 5, this->bw_total(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseSystemStatus::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + // required uint32 no_peers = 2; + if (has_no_peers()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->no_peers(), target); + } + + // required uint32 no_connected = 3; + if (has_no_connected()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->no_connected(), target); + } + + // required .rsctrl.system.ResponseSystemStatus.NetCode net_status = 4; + if (has_net_status()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 4, this->net_status(), target); + } + + // required .rsctrl.core.Bandwidth bw_total = 5; + if (has_bw_total()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 5, this->bw_total(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseSystemStatus::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + // required uint32 no_peers = 2; + if (has_no_peers()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->no_peers()); + } + + // required uint32 no_connected = 3; + if (has_no_connected()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->no_connected()); + } + + // required .rsctrl.system.ResponseSystemStatus.NetCode net_status = 4; + if (has_net_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->net_status()); + } + + // required .rsctrl.core.Bandwidth bw_total = 5; + if (has_bw_total()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->bw_total()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseSystemStatus::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseSystemStatus* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseSystemStatus::MergeFrom(const ResponseSystemStatus& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + if (from.has_no_peers()) { + set_no_peers(from.no_peers()); + } + if (from.has_no_connected()) { + set_no_connected(from.no_connected()); + } + if (from.has_net_status()) { + set_net_status(from.net_status()); + } + if (from.has_bw_total()) { + mutable_bw_total()->::rsctrl::core::Bandwidth::MergeFrom(from.bw_total()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseSystemStatus::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseSystemStatus::CopyFrom(const ResponseSystemStatus& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseSystemStatus::IsInitialized() const { + if ((_has_bits_[0] & 0x0000001f) != 0x0000001f) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + if (has_bw_total()) { + if (!this->bw_total().IsInitialized()) return false; + } + return true; +} + +void ResponseSystemStatus::Swap(ResponseSystemStatus* other) { + if (other != this) { + std::swap(status_, other->status_); + std::swap(no_peers_, other->no_peers_); + std::swap(no_connected_, other->no_connected_); + std::swap(net_status_, other->net_status_); + std::swap(bw_total_, other->bw_total_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseSystemStatus::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseSystemStatus_descriptor_; + metadata.reflection = ResponseSystemStatus_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* RequestSystemQuit_QuitCode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestSystemQuit_QuitCode_descriptor_; +} +bool RequestSystemQuit_QuitCode_IsValid(int value) { + switch(value) { + case 1: + case 2: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const RequestSystemQuit_QuitCode RequestSystemQuit::CLOSE_CHANNEL; +const RequestSystemQuit_QuitCode RequestSystemQuit::SHUTDOWN_RS; +const RequestSystemQuit_QuitCode RequestSystemQuit::QuitCode_MIN; +const RequestSystemQuit_QuitCode RequestSystemQuit::QuitCode_MAX; +const int RequestSystemQuit::QuitCode_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int RequestSystemQuit::kQuitCodeFieldNumber; +#endif // !_MSC_VER + +RequestSystemQuit::RequestSystemQuit() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void RequestSystemQuit::InitAsDefaultInstance() { +} + +RequestSystemQuit::RequestSystemQuit(const RequestSystemQuit& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void RequestSystemQuit::SharedCtor() { + _cached_size_ = 0; + quit_code_ = 1; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +RequestSystemQuit::~RequestSystemQuit() { + SharedDtor(); +} + +void RequestSystemQuit::SharedDtor() { + if (this != default_instance_) { + } +} + +void RequestSystemQuit::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* RequestSystemQuit::descriptor() { + protobuf_AssignDescriptorsOnce(); + return RequestSystemQuit_descriptor_; +} + +const RequestSystemQuit& RequestSystemQuit::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_system_2eproto(); return *default_instance_; +} + +RequestSystemQuit* RequestSystemQuit::default_instance_ = NULL; + +RequestSystemQuit* RequestSystemQuit::New() const { + return new RequestSystemQuit; +} + +void RequestSystemQuit::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + quit_code_ = 1; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool RequestSystemQuit::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.system.RequestSystemQuit.QuitCode quit_code = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::rsctrl::system::RequestSystemQuit_QuitCode_IsValid(value)) { + set_quit_code(static_cast< ::rsctrl::system::RequestSystemQuit_QuitCode >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void RequestSystemQuit::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.system.RequestSystemQuit.QuitCode quit_code = 1; + if (has_quit_code()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->quit_code(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* RequestSystemQuit::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.system.RequestSystemQuit.QuitCode quit_code = 1; + if (has_quit_code()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->quit_code(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int RequestSystemQuit::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.system.RequestSystemQuit.QuitCode quit_code = 1; + if (has_quit_code()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->quit_code()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void RequestSystemQuit::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const RequestSystemQuit* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void RequestSystemQuit::MergeFrom(const RequestSystemQuit& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_quit_code()) { + set_quit_code(from.quit_code()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void RequestSystemQuit::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RequestSystemQuit::CopyFrom(const RequestSystemQuit& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RequestSystemQuit::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + return true; +} + +void RequestSystemQuit::Swap(RequestSystemQuit* other) { + if (other != this) { + std::swap(quit_code_, other->quit_code_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata RequestSystemQuit::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = RequestSystemQuit_descriptor_; + metadata.reflection = RequestSystemQuit_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ResponseSystemQuit::kStatusFieldNumber; +#endif // !_MSC_VER + +ResponseSystemQuit::ResponseSystemQuit() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ResponseSystemQuit::InitAsDefaultInstance() { + status_ = const_cast< ::rsctrl::core::Status*>(&::rsctrl::core::Status::default_instance()); +} + +ResponseSystemQuit::ResponseSystemQuit(const ResponseSystemQuit& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ResponseSystemQuit::SharedCtor() { + _cached_size_ = 0; + status_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ResponseSystemQuit::~ResponseSystemQuit() { + SharedDtor(); +} + +void ResponseSystemQuit::SharedDtor() { + if (this != default_instance_) { + delete status_; + } +} + +void ResponseSystemQuit::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ResponseSystemQuit::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ResponseSystemQuit_descriptor_; +} + +const ResponseSystemQuit& ResponseSystemQuit::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_system_2eproto(); return *default_instance_; +} + +ResponseSystemQuit* ResponseSystemQuit::default_instance_ = NULL; + +ResponseSystemQuit* ResponseSystemQuit::New() const { + return new ResponseSystemQuit; +} + +void ResponseSystemQuit::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_status()) { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ResponseSystemQuit::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required .rsctrl.core.Status status = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_status())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ResponseSystemQuit::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->status(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ResponseSystemQuit::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->status(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ResponseSystemQuit::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required .rsctrl.core.Status status = 1; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->status()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ResponseSystemQuit::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ResponseSystemQuit* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ResponseSystemQuit::MergeFrom(const ResponseSystemQuit& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_status()) { + mutable_status()->::rsctrl::core::Status::MergeFrom(from.status()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ResponseSystemQuit::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ResponseSystemQuit::CopyFrom(const ResponseSystemQuit& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ResponseSystemQuit::IsInitialized() const { + if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; + + if (has_status()) { + if (!this->status().IsInitialized()) return false; + } + return true; +} + +void ResponseSystemQuit::Swap(ResponseSystemQuit* other) { + if (other != this) { + std::swap(status_, other->status_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ResponseSystemQuit::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ResponseSystemQuit_descriptor_; + metadata.reflection = ResponseSystemQuit_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace system +} // namespace rsctrl + +// @@protoc_insertion_point(global_scope) diff --git a/retroshare-nogui/src/rpc/proto/gencc/system.pb.h b/retroshare-nogui/src/rpc/proto/gencc/system.pb.h new file mode 100644 index 000000000..92ff1cb6a --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/gencc/system.pb.h @@ -0,0 +1,770 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: system.proto + +#ifndef PROTOBUF_system_2eproto__INCLUDED +#define PROTOBUF_system_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2004000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include "core.pb.h" +// @@protoc_insertion_point(includes) + +namespace rsctrl { +namespace system { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_system_2eproto(); +void protobuf_AssignDesc_system_2eproto(); +void protobuf_ShutdownFile_system_2eproto(); + +class RequestSystemStatus; +class ResponseSystemStatus; +class RequestSystemQuit; +class ResponseSystemQuit; + +enum ResponseSystemStatus_NetCode { + ResponseSystemStatus_NetCode_BAD_UNKNOWN = 0, + ResponseSystemStatus_NetCode_BAD_OFFLINE = 1, + ResponseSystemStatus_NetCode_BAD_NATSYM = 2, + ResponseSystemStatus_NetCode_BAD_NODHT_NAT = 3, + ResponseSystemStatus_NetCode_WARNING_RESTART = 4, + ResponseSystemStatus_NetCode_WARNING_NATTED = 5, + ResponseSystemStatus_NetCode_WARNING_NODHT = 6, + ResponseSystemStatus_NetCode_GOOD = 7, + ResponseSystemStatus_NetCode_ADV_FORWARD = 8 +}; +bool ResponseSystemStatus_NetCode_IsValid(int value); +const ResponseSystemStatus_NetCode ResponseSystemStatus_NetCode_NetCode_MIN = ResponseSystemStatus_NetCode_BAD_UNKNOWN; +const ResponseSystemStatus_NetCode ResponseSystemStatus_NetCode_NetCode_MAX = ResponseSystemStatus_NetCode_ADV_FORWARD; +const int ResponseSystemStatus_NetCode_NetCode_ARRAYSIZE = ResponseSystemStatus_NetCode_NetCode_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ResponseSystemStatus_NetCode_descriptor(); +inline const ::std::string& ResponseSystemStatus_NetCode_Name(ResponseSystemStatus_NetCode value) { + return ::google::protobuf::internal::NameOfEnum( + ResponseSystemStatus_NetCode_descriptor(), value); +} +inline bool ResponseSystemStatus_NetCode_Parse( + const ::std::string& name, ResponseSystemStatus_NetCode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ResponseSystemStatus_NetCode_descriptor(), name, value); +} +enum RequestSystemQuit_QuitCode { + RequestSystemQuit_QuitCode_CLOSE_CHANNEL = 1, + RequestSystemQuit_QuitCode_SHUTDOWN_RS = 2 +}; +bool RequestSystemQuit_QuitCode_IsValid(int value); +const RequestSystemQuit_QuitCode RequestSystemQuit_QuitCode_QuitCode_MIN = RequestSystemQuit_QuitCode_CLOSE_CHANNEL; +const RequestSystemQuit_QuitCode RequestSystemQuit_QuitCode_QuitCode_MAX = RequestSystemQuit_QuitCode_SHUTDOWN_RS; +const int RequestSystemQuit_QuitCode_QuitCode_ARRAYSIZE = RequestSystemQuit_QuitCode_QuitCode_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestSystemQuit_QuitCode_descriptor(); +inline const ::std::string& RequestSystemQuit_QuitCode_Name(RequestSystemQuit_QuitCode value) { + return ::google::protobuf::internal::NameOfEnum( + RequestSystemQuit_QuitCode_descriptor(), value); +} +inline bool RequestSystemQuit_QuitCode_Parse( + const ::std::string& name, RequestSystemQuit_QuitCode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestSystemQuit_QuitCode_descriptor(), name, value); +} +enum RequestMsgIds { + MsgId_RequestSystemStatus = 1, + MsgId_RequestSystemQuit = 2 +}; +bool RequestMsgIds_IsValid(int value); +const RequestMsgIds RequestMsgIds_MIN = MsgId_RequestSystemStatus; +const RequestMsgIds RequestMsgIds_MAX = MsgId_RequestSystemQuit; +const int RequestMsgIds_ARRAYSIZE = RequestMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* RequestMsgIds_descriptor(); +inline const ::std::string& RequestMsgIds_Name(RequestMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + RequestMsgIds_descriptor(), value); +} +inline bool RequestMsgIds_Parse( + const ::std::string& name, RequestMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + RequestMsgIds_descriptor(), name, value); +} +enum ResponseMsgIds { + MsgId_ResponseSystemStatus = 1, + MsgId_ResponseSystemQuit = 2 +}; +bool ResponseMsgIds_IsValid(int value); +const ResponseMsgIds ResponseMsgIds_MIN = MsgId_ResponseSystemStatus; +const ResponseMsgIds ResponseMsgIds_MAX = MsgId_ResponseSystemQuit; +const int ResponseMsgIds_ARRAYSIZE = ResponseMsgIds_MAX + 1; + +const ::google::protobuf::EnumDescriptor* ResponseMsgIds_descriptor(); +inline const ::std::string& ResponseMsgIds_Name(ResponseMsgIds value) { + return ::google::protobuf::internal::NameOfEnum( + ResponseMsgIds_descriptor(), value); +} +inline bool ResponseMsgIds_Parse( + const ::std::string& name, ResponseMsgIds* value) { + return ::google::protobuf::internal::ParseNamedEnum( + ResponseMsgIds_descriptor(), name, value); +} +// =================================================================== + +class RequestSystemStatus : public ::google::protobuf::Message { + public: + RequestSystemStatus(); + virtual ~RequestSystemStatus(); + + RequestSystemStatus(const RequestSystemStatus& from); + + inline RequestSystemStatus& operator=(const RequestSystemStatus& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestSystemStatus& default_instance(); + + void Swap(RequestSystemStatus* other); + + // implements Message ---------------------------------------------- + + RequestSystemStatus* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestSystemStatus& from); + void MergeFrom(const RequestSystemStatus& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // @@protoc_insertion_point(class_scope:rsctrl.system.RequestSystemStatus) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[1]; + + friend void protobuf_AddDesc_system_2eproto(); + friend void protobuf_AssignDesc_system_2eproto(); + friend void protobuf_ShutdownFile_system_2eproto(); + + void InitAsDefaultInstance(); + static RequestSystemStatus* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseSystemStatus : public ::google::protobuf::Message { + public: + ResponseSystemStatus(); + virtual ~ResponseSystemStatus(); + + ResponseSystemStatus(const ResponseSystemStatus& from); + + inline ResponseSystemStatus& operator=(const ResponseSystemStatus& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseSystemStatus& default_instance(); + + void Swap(ResponseSystemStatus* other); + + // implements Message ---------------------------------------------- + + ResponseSystemStatus* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseSystemStatus& from); + void MergeFrom(const ResponseSystemStatus& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef ResponseSystemStatus_NetCode NetCode; + static const NetCode BAD_UNKNOWN = ResponseSystemStatus_NetCode_BAD_UNKNOWN; + static const NetCode BAD_OFFLINE = ResponseSystemStatus_NetCode_BAD_OFFLINE; + static const NetCode BAD_NATSYM = ResponseSystemStatus_NetCode_BAD_NATSYM; + static const NetCode BAD_NODHT_NAT = ResponseSystemStatus_NetCode_BAD_NODHT_NAT; + static const NetCode WARNING_RESTART = ResponseSystemStatus_NetCode_WARNING_RESTART; + static const NetCode WARNING_NATTED = ResponseSystemStatus_NetCode_WARNING_NATTED; + static const NetCode WARNING_NODHT = ResponseSystemStatus_NetCode_WARNING_NODHT; + static const NetCode GOOD = ResponseSystemStatus_NetCode_GOOD; + static const NetCode ADV_FORWARD = ResponseSystemStatus_NetCode_ADV_FORWARD; + static inline bool NetCode_IsValid(int value) { + return ResponseSystemStatus_NetCode_IsValid(value); + } + static const NetCode NetCode_MIN = + ResponseSystemStatus_NetCode_NetCode_MIN; + static const NetCode NetCode_MAX = + ResponseSystemStatus_NetCode_NetCode_MAX; + static const int NetCode_ARRAYSIZE = + ResponseSystemStatus_NetCode_NetCode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + NetCode_descriptor() { + return ResponseSystemStatus_NetCode_descriptor(); + } + static inline const ::std::string& NetCode_Name(NetCode value) { + return ResponseSystemStatus_NetCode_Name(value); + } + static inline bool NetCode_Parse(const ::std::string& name, + NetCode* value) { + return ResponseSystemStatus_NetCode_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // required uint32 no_peers = 2; + inline bool has_no_peers() const; + inline void clear_no_peers(); + static const int kNoPeersFieldNumber = 2; + inline ::google::protobuf::uint32 no_peers() const; + inline void set_no_peers(::google::protobuf::uint32 value); + + // required uint32 no_connected = 3; + inline bool has_no_connected() const; + inline void clear_no_connected(); + static const int kNoConnectedFieldNumber = 3; + inline ::google::protobuf::uint32 no_connected() const; + inline void set_no_connected(::google::protobuf::uint32 value); + + // required .rsctrl.system.ResponseSystemStatus.NetCode net_status = 4; + inline bool has_net_status() const; + inline void clear_net_status(); + static const int kNetStatusFieldNumber = 4; + inline ::rsctrl::system::ResponseSystemStatus_NetCode net_status() const; + inline void set_net_status(::rsctrl::system::ResponseSystemStatus_NetCode value); + + // required .rsctrl.core.Bandwidth bw_total = 5; + inline bool has_bw_total() const; + inline void clear_bw_total(); + static const int kBwTotalFieldNumber = 5; + inline const ::rsctrl::core::Bandwidth& bw_total() const; + inline ::rsctrl::core::Bandwidth* mutable_bw_total(); + inline ::rsctrl::core::Bandwidth* release_bw_total(); + + // @@protoc_insertion_point(class_scope:rsctrl.system.ResponseSystemStatus) + private: + inline void set_has_status(); + inline void clear_has_status(); + inline void set_has_no_peers(); + inline void clear_has_no_peers(); + inline void set_has_no_connected(); + inline void clear_has_no_connected(); + inline void set_has_net_status(); + inline void clear_has_net_status(); + inline void set_has_bw_total(); + inline void clear_has_bw_total(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + ::google::protobuf::uint32 no_peers_; + ::google::protobuf::uint32 no_connected_; + ::rsctrl::core::Bandwidth* bw_total_; + int net_status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; + + friend void protobuf_AddDesc_system_2eproto(); + friend void protobuf_AssignDesc_system_2eproto(); + friend void protobuf_ShutdownFile_system_2eproto(); + + void InitAsDefaultInstance(); + static ResponseSystemStatus* default_instance_; +}; +// ------------------------------------------------------------------- + +class RequestSystemQuit : public ::google::protobuf::Message { + public: + RequestSystemQuit(); + virtual ~RequestSystemQuit(); + + RequestSystemQuit(const RequestSystemQuit& from); + + inline RequestSystemQuit& operator=(const RequestSystemQuit& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const RequestSystemQuit& default_instance(); + + void Swap(RequestSystemQuit* other); + + // implements Message ---------------------------------------------- + + RequestSystemQuit* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const RequestSystemQuit& from); + void MergeFrom(const RequestSystemQuit& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef RequestSystemQuit_QuitCode QuitCode; + static const QuitCode CLOSE_CHANNEL = RequestSystemQuit_QuitCode_CLOSE_CHANNEL; + static const QuitCode SHUTDOWN_RS = RequestSystemQuit_QuitCode_SHUTDOWN_RS; + static inline bool QuitCode_IsValid(int value) { + return RequestSystemQuit_QuitCode_IsValid(value); + } + static const QuitCode QuitCode_MIN = + RequestSystemQuit_QuitCode_QuitCode_MIN; + static const QuitCode QuitCode_MAX = + RequestSystemQuit_QuitCode_QuitCode_MAX; + static const int QuitCode_ARRAYSIZE = + RequestSystemQuit_QuitCode_QuitCode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + QuitCode_descriptor() { + return RequestSystemQuit_QuitCode_descriptor(); + } + static inline const ::std::string& QuitCode_Name(QuitCode value) { + return RequestSystemQuit_QuitCode_Name(value); + } + static inline bool QuitCode_Parse(const ::std::string& name, + QuitCode* value) { + return RequestSystemQuit_QuitCode_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // required .rsctrl.system.RequestSystemQuit.QuitCode quit_code = 1; + inline bool has_quit_code() const; + inline void clear_quit_code(); + static const int kQuitCodeFieldNumber = 1; + inline ::rsctrl::system::RequestSystemQuit_QuitCode quit_code() const; + inline void set_quit_code(::rsctrl::system::RequestSystemQuit_QuitCode value); + + // @@protoc_insertion_point(class_scope:rsctrl.system.RequestSystemQuit) + private: + inline void set_has_quit_code(); + inline void clear_has_quit_code(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + int quit_code_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_system_2eproto(); + friend void protobuf_AssignDesc_system_2eproto(); + friend void protobuf_ShutdownFile_system_2eproto(); + + void InitAsDefaultInstance(); + static RequestSystemQuit* default_instance_; +}; +// ------------------------------------------------------------------- + +class ResponseSystemQuit : public ::google::protobuf::Message { + public: + ResponseSystemQuit(); + virtual ~ResponseSystemQuit(); + + ResponseSystemQuit(const ResponseSystemQuit& from); + + inline ResponseSystemQuit& operator=(const ResponseSystemQuit& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ResponseSystemQuit& default_instance(); + + void Swap(ResponseSystemQuit* other); + + // implements Message ---------------------------------------------- + + ResponseSystemQuit* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ResponseSystemQuit& from); + void MergeFrom(const ResponseSystemQuit& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required .rsctrl.core.Status status = 1; + inline bool has_status() const; + inline void clear_status(); + static const int kStatusFieldNumber = 1; + inline const ::rsctrl::core::Status& status() const; + inline ::rsctrl::core::Status* mutable_status(); + inline ::rsctrl::core::Status* release_status(); + + // @@protoc_insertion_point(class_scope:rsctrl.system.ResponseSystemQuit) + private: + inline void set_has_status(); + inline void clear_has_status(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::rsctrl::core::Status* status_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void protobuf_AddDesc_system_2eproto(); + friend void protobuf_AssignDesc_system_2eproto(); + friend void protobuf_ShutdownFile_system_2eproto(); + + void InitAsDefaultInstance(); + static ResponseSystemQuit* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// RequestSystemStatus + +// ------------------------------------------------------------------- + +// ResponseSystemStatus + +// required .rsctrl.core.Status status = 1; +inline bool ResponseSystemStatus::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseSystemStatus::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseSystemStatus::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseSystemStatus::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseSystemStatus::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseSystemStatus::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseSystemStatus::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + +// required uint32 no_peers = 2; +inline bool ResponseSystemStatus::has_no_peers() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void ResponseSystemStatus::set_has_no_peers() { + _has_bits_[0] |= 0x00000002u; +} +inline void ResponseSystemStatus::clear_has_no_peers() { + _has_bits_[0] &= ~0x00000002u; +} +inline void ResponseSystemStatus::clear_no_peers() { + no_peers_ = 0u; + clear_has_no_peers(); +} +inline ::google::protobuf::uint32 ResponseSystemStatus::no_peers() const { + return no_peers_; +} +inline void ResponseSystemStatus::set_no_peers(::google::protobuf::uint32 value) { + set_has_no_peers(); + no_peers_ = value; +} + +// required uint32 no_connected = 3; +inline bool ResponseSystemStatus::has_no_connected() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ResponseSystemStatus::set_has_no_connected() { + _has_bits_[0] |= 0x00000004u; +} +inline void ResponseSystemStatus::clear_has_no_connected() { + _has_bits_[0] &= ~0x00000004u; +} +inline void ResponseSystemStatus::clear_no_connected() { + no_connected_ = 0u; + clear_has_no_connected(); +} +inline ::google::protobuf::uint32 ResponseSystemStatus::no_connected() const { + return no_connected_; +} +inline void ResponseSystemStatus::set_no_connected(::google::protobuf::uint32 value) { + set_has_no_connected(); + no_connected_ = value; +} + +// required .rsctrl.system.ResponseSystemStatus.NetCode net_status = 4; +inline bool ResponseSystemStatus::has_net_status() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void ResponseSystemStatus::set_has_net_status() { + _has_bits_[0] |= 0x00000008u; +} +inline void ResponseSystemStatus::clear_has_net_status() { + _has_bits_[0] &= ~0x00000008u; +} +inline void ResponseSystemStatus::clear_net_status() { + net_status_ = 0; + clear_has_net_status(); +} +inline ::rsctrl::system::ResponseSystemStatus_NetCode ResponseSystemStatus::net_status() const { + return static_cast< ::rsctrl::system::ResponseSystemStatus_NetCode >(net_status_); +} +inline void ResponseSystemStatus::set_net_status(::rsctrl::system::ResponseSystemStatus_NetCode value) { + GOOGLE_DCHECK(::rsctrl::system::ResponseSystemStatus_NetCode_IsValid(value)); + set_has_net_status(); + net_status_ = value; +} + +// required .rsctrl.core.Bandwidth bw_total = 5; +inline bool ResponseSystemStatus::has_bw_total() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void ResponseSystemStatus::set_has_bw_total() { + _has_bits_[0] |= 0x00000010u; +} +inline void ResponseSystemStatus::clear_has_bw_total() { + _has_bits_[0] &= ~0x00000010u; +} +inline void ResponseSystemStatus::clear_bw_total() { + if (bw_total_ != NULL) bw_total_->::rsctrl::core::Bandwidth::Clear(); + clear_has_bw_total(); +} +inline const ::rsctrl::core::Bandwidth& ResponseSystemStatus::bw_total() const { + return bw_total_ != NULL ? *bw_total_ : *default_instance_->bw_total_; +} +inline ::rsctrl::core::Bandwidth* ResponseSystemStatus::mutable_bw_total() { + set_has_bw_total(); + if (bw_total_ == NULL) bw_total_ = new ::rsctrl::core::Bandwidth; + return bw_total_; +} +inline ::rsctrl::core::Bandwidth* ResponseSystemStatus::release_bw_total() { + clear_has_bw_total(); + ::rsctrl::core::Bandwidth* temp = bw_total_; + bw_total_ = NULL; + return temp; +} + +// ------------------------------------------------------------------- + +// RequestSystemQuit + +// required .rsctrl.system.RequestSystemQuit.QuitCode quit_code = 1; +inline bool RequestSystemQuit::has_quit_code() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void RequestSystemQuit::set_has_quit_code() { + _has_bits_[0] |= 0x00000001u; +} +inline void RequestSystemQuit::clear_has_quit_code() { + _has_bits_[0] &= ~0x00000001u; +} +inline void RequestSystemQuit::clear_quit_code() { + quit_code_ = 1; + clear_has_quit_code(); +} +inline ::rsctrl::system::RequestSystemQuit_QuitCode RequestSystemQuit::quit_code() const { + return static_cast< ::rsctrl::system::RequestSystemQuit_QuitCode >(quit_code_); +} +inline void RequestSystemQuit::set_quit_code(::rsctrl::system::RequestSystemQuit_QuitCode value) { + GOOGLE_DCHECK(::rsctrl::system::RequestSystemQuit_QuitCode_IsValid(value)); + set_has_quit_code(); + quit_code_ = value; +} + +// ------------------------------------------------------------------- + +// ResponseSystemQuit + +// required .rsctrl.core.Status status = 1; +inline bool ResponseSystemQuit::has_status() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ResponseSystemQuit::set_has_status() { + _has_bits_[0] |= 0x00000001u; +} +inline void ResponseSystemQuit::clear_has_status() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ResponseSystemQuit::clear_status() { + if (status_ != NULL) status_->::rsctrl::core::Status::Clear(); + clear_has_status(); +} +inline const ::rsctrl::core::Status& ResponseSystemQuit::status() const { + return status_ != NULL ? *status_ : *default_instance_->status_; +} +inline ::rsctrl::core::Status* ResponseSystemQuit::mutable_status() { + set_has_status(); + if (status_ == NULL) status_ = new ::rsctrl::core::Status; + return status_; +} +inline ::rsctrl::core::Status* ResponseSystemQuit::release_status() { + clear_has_status(); + ::rsctrl::core::Status* temp = status_; + status_ = NULL; + return temp; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace system +} // namespace rsctrl + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::system::ResponseSystemStatus_NetCode>() { + return ::rsctrl::system::ResponseSystemStatus_NetCode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::rsctrl::system::RequestSystemQuit_QuitCode>() { + return ::rsctrl::system::RequestSystemQuit_QuitCode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::system::RequestMsgIds>() { + return rsctrl::system::RequestMsgIds_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< rsctrl::system::ResponseMsgIds>() { + return rsctrl::system::ResponseMsgIds_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_system_2eproto__INCLUDED diff --git a/retroshare-nogui/src/rpc/proto/rpcprotochat.cc b/retroshare-nogui/src/rpc/proto/rpcprotochat.cc new file mode 100644 index 000000000..7fba114ba --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotochat.cc @@ -0,0 +1,1286 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/proto/rpcprotochat.h" +#include "rpc/proto/gencc/chat.pb.h" + +#include +#include + +#include "util/rsstring.h" + +#include + +#include +#include + +#include + + +// Helper Functions -> maybe move to libretroshare/utils ?? +bool convertUTF8toWString(const std::string &msg_utf8, std::wstring &msg_wstr); +bool convertWStringToUTF8(const std::wstring &msg_wstr, std::string &msg_utf8); + +bool convertStringToLobbyId(const std::string &chat_id, ChatLobbyId &lobby_id); +bool convertLobbyIdToString(const ChatLobbyId &lobby_id, std::string &chat_id); + +bool fillLobbyInfoFromChatLobbyInfo(const ChatLobbyInfo &cfi, rsctrl::chat::ChatLobbyInfo *lobby); +bool fillLobbyInfoFromPublicChatLobbyRecord(const PublicChatLobbyRecord &pclr, rsctrl::chat::ChatLobbyInfo *lobby); +bool fillLobbyInfoFromChatLobbyInvite(const ChatLobbyInvite &cli, rsctrl::chat::ChatLobbyInfo *lobby); + +bool createQueuedEventSendMsg(const ChatInfo &chatinfo, rsctrl::chat::ChatType ctype, + std::string chat_id, const RpcEventRegister &ereg, RpcQueuedMsg &qmsg); + + +RpcProtoChat::RpcProtoChat(uint32_t serviceId) + :RpcQueueService(serviceId) +{ + return; +} + +//RpcProtoChat::msgsAccepted(std::list &msgIds); /* not used at the moment */ + +int RpcProtoChat::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + /* check the msgId */ + uint8_t topbyte = getRpcMsgIdExtension(msg_id); + uint16_t service = getRpcMsgIdService(msg_id); + uint8_t submsg = getRpcMsgIdSubMsg(msg_id); + bool isResponse = isRpcMsgIdResponse(msg_id); + + + std::cerr << "RpcProtoChat::processMsg() topbyte: " << (int32_t) topbyte; + std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg; + std::cerr << std::endl; + + if (isResponse) + { + std::cerr << "RpcProtoChat::processMsg() isResponse() - not processing"; + std::cerr << std::endl; + return 0; + } + + if (topbyte != (uint8_t) rsctrl::core::CORE) + { + std::cerr << "RpcProtoChat::processMsg() Extension Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (service != (uint16_t) rsctrl::core::CHAT) + { + std::cerr << "RpcProtoChat::processMsg() Service Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (!rsctrl::chat::RequestMsgIds_IsValid(submsg)) + { + std::cerr << "RpcProtoChat::processMsg() SubMsg Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + switch(submsg) + { + case rsctrl::chat::MsgId_RequestChatLobbies: + processReqChatLobbies(chan_id, msg_id, req_id, msg); + break; + case rsctrl::chat::MsgId_RequestCreateLobby: + processReqCreateLobby(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::chat::MsgId_RequestJoinOrLeaveLobby: + processReqJoinOrLeaveLobby(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::chat::MsgId_RequestSetLobbyNickname: + processReqSetLobbyNickname(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::chat::MsgId_RequestRegisterEvents: + processReqRegisterEvents(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::chat::MsgId_RequestSendMessage: + processReqSendMessage(chan_id, msg_id, req_id, msg); + break; + + + default: + std::cerr << "RpcProtoChat::processMsg() ERROR should never get here"; + std::cerr << std::endl; + return 0; + } + + /* must have matched id to get here */ + return 1; +} + + +// Registrations. +//#define REGISTRATION_EVENT_CHAT 1 + +int RpcProtoChat::processReqChatLobbies(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoChat::processReqChatLobbies()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::chat::RequestChatLobbies req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoChat::processReqChatLobbies() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::chat::ResponseChatLobbies resp; + bool success = true; + std::string errorMsg; + + // set these flags from request. + bool fetch_chatlobbylist = true; + bool fetch_invites = true; + bool fetch_publiclobbies = true; + + switch(req.lobby_set()) + { + case rsctrl::chat::RequestChatLobbies::LOBBYSET_ALL: + std::cerr << "RpcProtoChat::processReqChatLobbies() LOBBYSET_ALL"; + std::cerr << std::endl; + fetch_chatlobbylist = true; + fetch_invites = true; + fetch_publiclobbies = true; + break; + case rsctrl::chat::RequestChatLobbies::LOBBYSET_JOINED: + std::cerr << "RpcProtoChat::processReqChatLobbies() LOBBYSET_JOINED"; + std::cerr << std::endl; + fetch_chatlobbylist = true; + fetch_invites = false; + fetch_publiclobbies = false; + break; + case rsctrl::chat::RequestChatLobbies::LOBBYSET_INVITED: + std::cerr << "RpcProtoChat::processReqChatLobbies() LOBBYSET_INVITED"; + std::cerr << std::endl; + fetch_chatlobbylist = false; + fetch_invites = true; + fetch_publiclobbies = false; + break; + case rsctrl::chat::RequestChatLobbies::LOBBYSET_PUBLIC: + std::cerr << "RpcProtoChat::processReqChatLobbies() LOBBYSET_PUBLIC"; + std::cerr << std::endl; + fetch_chatlobbylist = false; + fetch_invites = false; + fetch_publiclobbies = true; + break; + default: + std::cerr << "RpcProtoChat::processReqChatLobbies() LOBBYSET ERROR"; + std::cerr << std::endl; + success = false; + errorMsg = "Invalid Lobby Set"; + } + + + std::set done_lobbies; // list of ones we've added already (to avoid duplicates). + + if (fetch_chatlobbylist) + { + std::cerr << "RpcProtoChat::processReqChatLobbies() Fetching chatlobbylist"; + std::cerr << std::endl; + + std::list cl_info; + std::list::iterator it; + + rsMsgs->getChatLobbyList(cl_info); + + for(it = cl_info.begin(); it != cl_info.end(); it++) + { + rsctrl::chat::ChatLobbyInfo *lobby = resp.add_lobbies(); + fillLobbyInfoFromChatLobbyInfo(*it, lobby); + + done_lobbies.insert(it->lobby_id); + + std::cerr << "\t Added Lobby: " << it->lobby_id; + std::cerr << std::endl; + } + } + + /* This is before Public Lobbies - as knowing you have been invited is + * more important, than the full info that might be gleaned from lobby. + * In the future, we might try to merge the info. + */ + if (fetch_invites) + { + std::cerr << "RpcProtoChat::processReqChatLobbies() Fetching invites"; + std::cerr << std::endl; + + std::list invites; + std::list::iterator it; + rsMsgs->getPendingChatLobbyInvites(invites); + + for(it = invites.begin(); it != invites.end(); it++) + { + if (done_lobbies.find(it->lobby_id) == done_lobbies.end()) + { + rsctrl::chat::ChatLobbyInfo *lobby = resp.add_lobbies(); + fillLobbyInfoFromChatLobbyInvite(*it, lobby); + + done_lobbies.insert(it->lobby_id); + + std::cerr << "\t Added Lobby: " << it->lobby_id; + std::cerr << std::endl; + } + else + { + std::cerr << "\t Skipping Already Added Lobby: " << it->lobby_id; + std::cerr << std::endl; + } + } + } + + if (fetch_publiclobbies) + { + std::cerr << "RpcProtoChat::processReqChatLobbies() Fetching public lobbies"; + std::cerr << std::endl; + + std::vector public_lobbies; + std::vector::iterator it; + + rsMsgs->getListOfNearbyChatLobbies(public_lobbies); + + for(it = public_lobbies.begin(); it != public_lobbies.end(); it++) + { + if (done_lobbies.find(it->lobby_id) == done_lobbies.end()) + { + rsctrl::chat::ChatLobbyInfo *lobby = resp.add_lobbies(); + fillLobbyInfoFromPublicChatLobbyRecord(*it, lobby); + + done_lobbies.insert(it->lobby_id); + + std::cerr << "\t Added Lobby: " << it->lobby_id; + std::cerr << std::endl; + } + else + { + std::cerr << "\t Skipping Already Added Lobby: " << it->lobby_id; + std::cerr << std::endl; + } + } + } + + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::processReqChatLobbies() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_ResponseChatLobbies, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +int RpcProtoChat::processReqCreateLobby(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoChat::processReqCreateLobby()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::chat::RequestCreateLobby req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoChat::processReqCreateLobby() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::chat::ResponseChatLobbies resp; + bool success = true; + std::string errorMsg; + + /* convert msg parameters into local ones */ + + std::string lobby_name = req.lobby_name(); + std::string lobby_topic = req.lobby_topic(); + std::list invited_friends; + uint32_t lobby_privacy_type; + + switch(req.privacy_level()) + { + case rsctrl::chat::PRIVACY_PRIVATE: + std::cerr << "\tCreating Private Lobby"; + std::cerr << std::endl; + lobby_privacy_type = RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE; + break; + case rsctrl::chat::PRIVACY_PUBLIC: + std::cerr << "\tCreating Public Lobby"; + std::cerr << std::endl; + lobby_privacy_type = RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC; + break; + default: + std::cerr << "ERROR invalid Privacy Level"; + std::cerr << std::endl; + + success = false; + errorMsg = "Invalid Privacy Level"; + } + + int no_invites = req.invited_friends_size(); + for(int i = 0; i < no_invites; i++) + { + std::string peer = req.invited_friends(i); + /* check that they are a valid friend */ + if (!rsPeers->isFriend(peer)) // checks SSL ID. + { + std::cerr << "ERROR invalid SSL Friend ID: " << peer; + std::cerr << std::endl; + + success = false; + errorMsg = "Invalid SSL Friend ID"; + break; + } + + std::cerr << "Adding Valid Friend to Invites: " << peer; + std::cerr << std::endl; + + invited_friends.push_back(peer); + } + + ChatLobbyId created_lobby_id = 0; + if (success) + { + created_lobby_id = rsMsgs->createChatLobby(lobby_name,lobby_topic, + invited_friends,lobby_privacy_type); + + std::cerr << "Created Lobby Id: " << created_lobby_id; + std::cerr << std::endl; + + std::list cl_info; + std::list::iterator it; + + rsMsgs->getChatLobbyList(cl_info); + + bool found_entry = false; + for(it = cl_info.begin(); it != cl_info.end(); it++) + { + if (it->lobby_id == created_lobby_id) + { + std::cerr << "Found Created Lobby Id: " << created_lobby_id; + std::cerr << std::endl; + + rsctrl::chat::ChatLobbyInfo *lobby = resp.add_lobbies(); + fillLobbyInfoFromChatLobbyInfo(*it, lobby); + found_entry = true; + break; + } + } + + if (!found_entry) + { + std::cerr << "FAILED TO FIND Created Lobby Id: " << created_lobby_id; + std::cerr << std::endl; + + success = false; + errorMsg = "Chat Lobby Creation appears to have failed"; + } + } + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::processReqCreateLobbies() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_ResponseChatLobbies, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +int RpcProtoChat::processReqJoinOrLeaveLobby(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoChat::processReqJoinOrLeaveLobby()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::chat::RequestJoinOrLeaveLobby req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoChat::processReqJoinOrLeaveLobby() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::chat::ResponseChatLobbies resp; + bool success = false; + std::string errorMsg; + + /* convert msg parameters into local ones */ + ChatLobbyId lobby_id = 0; + convertStringToLobbyId(req.lobby_id(), lobby_id); + + std::cerr << "Requested Lobby is: " << lobby_id; + std::cerr << std::endl; + + /* now must work out if its an invite or an existing lobby */ + /* look for a pending invitation */ + bool isPendingInvite = false; + { + std::list invites; + std::list::iterator it; + rsMsgs->getPendingChatLobbyInvites(invites); + + for(it = invites.begin(); it != invites.end(); it++) + { + if (it->lobby_id == lobby_id) + { + std::cerr << "It is a Pending Invite" << lobby_id; + std::cerr << std::endl; + + isPendingInvite = true; + break; + } + } + } + + switch(req.action()) + { + case rsctrl::chat::RequestJoinOrLeaveLobby::JOIN_OR_ACCEPT: + { + std::cerr << "Request to JOIN_OR_ACCEPT"; + std::cerr << std::endl; + + if (isPendingInvite) + { + if (!rsMsgs->acceptLobbyInvite(lobby_id)) + { + std::cerr << "ERROR acceptLobbyInvite FAILED"; + std::cerr << std::endl; + + success = false; + errorMsg = "AcceptLobbyInvite returned False"; + } + } + else + { + if (!rsMsgs->joinPublicChatLobby(lobby_id)) + { + std::cerr << "ERROR joinPublicChatLobby FAILED"; + std::cerr << std::endl; + + success = false; + errorMsg = "joinPublicChatLobby returned False"; + } + } + + break; + } + case rsctrl::chat::RequestJoinOrLeaveLobby::LEAVE_OR_DENY: + { + std::cerr << "Request to LEAVE_OR_DENY (No fail codes!)"; + std::cerr << std::endl; + + if (isPendingInvite) + { + // return void - so can't check. + rsMsgs->denyLobbyInvite(lobby_id); + } + else + { + // return void - so can't check. + rsMsgs->unsubscribeChatLobby(lobby_id); + } + + break; + } + default: + success = false; + errorMsg = "Unknown Action"; + } + + + if (success && (req.action() == rsctrl::chat::RequestJoinOrLeaveLobby::JOIN_OR_ACCEPT)) + { + std::list cl_info; + std::list::iterator it; + + rsMsgs->getChatLobbyList(cl_info); + + bool found_entry = false; + for(it = cl_info.begin(); it != cl_info.end(); it++) + { + if (it->lobby_id == lobby_id) + { + rsctrl::chat::ChatLobbyInfo *lobby = resp.add_lobbies(); + fillLobbyInfoFromChatLobbyInfo(*it, lobby); + found_entry = true; + break; + } + } + + if (!found_entry) + { + success = false; + errorMsg = "Chat Lobby JOIN/ACCEPT appears to have failed"; + } + } + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::processReqCreateLobbies() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_ResponseChatLobbies, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +int RpcProtoChat::processReqSetLobbyNickname(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoChat::processReqSetLobbyNickname()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::chat::RequestSetLobbyNickname req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoChat::processReqSetLobbyNickname() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::chat::ResponseSetLobbyNickname resp; + bool success = true; + std::string errorMsg; + + /* convert msg parameters into local ones */ + std::string nickname = req.nickname(); + + std::cerr << "choosen nickname is: " << nickname; + std::cerr << std::endl; + + int no_lobbyids = req.lobby_ids_size(); + for(int i = 0; i < no_lobbyids; i++) + { + std::string idstr = req.lobby_ids(i); + ChatLobbyId id = 0; + convertStringToLobbyId(idstr, id); + + std::cerr << "setting nickname for lobby: " << id; + std::cerr << std::endl; + + if (!rsMsgs->setNickNameForChatLobby(id, nickname)) + { + std::cerr << "ERROR setting nickname for lobby: " << id; + std::cerr << std::endl; + + success = false; + errorMsg = "Failed to Set one of the nicknames"; + break; + } + + } + + if (no_lobbyids == 0) + { + std::cerr << "setting default nickname"; + std::cerr << std::endl; + + /* just do default instead */ + rsMsgs->setDefaultNickNameForChatLobby(nickname); + } + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::processReqCreateLobbies() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_ResponseSetLobbyNickname, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; + +} + + + +int RpcProtoChat::processReqRegisterEvents(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoChat::processReqRegisterEvents()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::chat::RequestRegisterEvents req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoChat::processReqRegisterEvents() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::chat::ResponseRegisterEvents resp; + bool success = true; + bool doregister = false; + std::string errorMsg; + + switch(req.action()) + { + case rsctrl::chat::RequestRegisterEvents::REGISTER: + doregister = true; + break; + case rsctrl::chat::RequestRegisterEvents::DEREGISTER: + doregister = false; + break; + default: + std::cerr << "ERROR action is invalid"; + std::cerr << std::endl; + + success = false; + errorMsg = "RegisterEvent.Action is invalid"; + break; + } + + if (success) + { + if (doregister) + { + std::cerr << "Registering for Chat Events"; + std::cerr << std::endl; + + registerForEvents(chan_id, req_id, REGISTRATION_EVENT_CHAT); + } + else + { + std::cerr << "Deregistering for Chat Events"; + std::cerr << std::endl; + + deregisterForEvents(chan_id, req_id, REGISTRATION_EVENT_CHAT); + } + printEventRegister(std::cerr); + } + + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::processReqCreateLobbies() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_ResponseRegisterEvents, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +int RpcProtoChat::processReqSendMessage(uint32_t chan_id, uint32_t /*msg_id*/, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoChat::processReqSendMessage()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::chat::RequestSendMessage req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoChat::processReqSendMessage() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::chat::ResponseSendMessage resp; + bool success = true; + std::string errorMsg; + + // Send the message. + bool priv_or_lobby = true; + std::string chat_id; + std::wstring chat_msg; + convertUTF8toWString(req.msg().msg(), chat_msg); + + std::cerr << "Chat Message is: " << req.msg().msg(); + std::cerr << std::endl; + + /* switch depending on type */ + switch(req.msg().id().chat_type()) + { + case rsctrl::chat::TYPE_PRIVATE: + // easy one. + chat_id = req.msg().id().chat_id(); + priv_or_lobby = true; + + std::cerr << "Sending Private Chat"; + std::cerr << std::endl; + + + break; + case rsctrl::chat::TYPE_LOBBY: + { + std::cerr << "Sending Lobby Chat"; + std::cerr << std::endl; + + /* convert string->ChatLobbyId */ + ChatLobbyId lobby_id; + if (!convertStringToLobbyId(req.msg().id().chat_id(), lobby_id)) + { + std::cerr << "ERROR Failed conversion of Lobby Id"; + std::cerr << std::endl; + + success = false; + errorMsg = "Failed Conversion of Lobby Id"; + } + /* convert lobby id to virtual peer id */ + else if (!rsMsgs->getVirtualPeerId(lobby_id, chat_id)) + { + std::cerr << "ERROR Invalid Lobby Id"; + std::cerr << std::endl; + + success = false; + errorMsg = "Invalid Lobby Id"; + } + priv_or_lobby = true; + break; + } + case rsctrl::chat::TYPE_GROUP: + + std::cerr << "Sending Group Chat"; + std::cerr << std::endl; + + priv_or_lobby = false; + break; + default: + + std::cerr << "ERROR Chat Type invalid"; + std::cerr << std::endl; + + success = false; + errorMsg = "Invalid Chat Type"; + break; + } + + if (success) + { + if (priv_or_lobby) + { + rsMsgs->sendPrivateChat(chat_id, chat_msg); + } + else + { + rsMsgs->sendPublicChat(chat_msg); + } + } + + /* DONE - Generate Reply */ + + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::processReqSendMessage() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_ResponseSendMessage, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + // EVENTS. +int RpcProtoChat::locked_checkForEvents(uint32_t event, const std::list ®istered, std::list &events) +{ + /* Wow - here already! */ + std::cerr << "locked_checkForEvents()"; + std::cerr << std::endl; + + /* only one event type for now */ + if (event != REGISTRATION_EVENT_CHAT) + { + std::cerr << "ERROR Invalid Chat Event Type"; + std::cerr << std::endl; + + /* error */ + return 0; + } + + /* possible events */ + /* TODO lobby invites. how do we make sure these are only sent once? */ + + // Likewise with Chat Queues -> We'll have to track which items have been sent + // to which Chan Ids.... a bit painful. + + /* public chat queues */ + if (rsMsgs->getPublicChatQueueCount() > 0) + { + std::cerr << "Fetching Public Chat Queue"; + std::cerr << std::endl; + + std::list chats; + rsMsgs->getPublicChatQueue(chats); + std::list::iterator it; + for(it = chats.begin(); it != chats.end(); it++) + { + std::cerr << "Public Chat from : " << it->rsid; + std::cerr << " name: " << it->peer_nickname; + std::cerr << std::endl; + { + std::string msg_utf8; + librs::util::ConvertUtf16ToUtf8(it->msg, msg_utf8); + std::cerr << " Msg: " << msg_utf8; + std::cerr << std::endl; + } + + /* must send to all registered clients */ + std::list::const_iterator rit; + for(rit = registered.begin(); rit != registered.end(); rit++) + { + RpcQueuedMsg qmsg; + rsctrl::chat::ChatType ctype = rsctrl::chat::TYPE_GROUP; + std::string chat_id = ""; // No ID for group. + + if (createQueuedEventSendMsg(*it, ctype, chat_id, *rit, qmsg)) + { + std::cerr << "Created MsgEvent"; + std::cerr << std::endl; + + events.push_back(qmsg); + } + else + { + std::cerr << "ERROR Creating MsgEvent"; + std::cerr << std::endl; + } + } + } + } + + + /* private chat queues */ + bool incoming = true; // ignore outgoing for now. (client can request that some other way) + if (rsMsgs->getPrivateChatQueueCount(incoming) > 0) + { + std::cerr << "Fetching Private Chat Queues"; + std::cerr << std::endl; + + std::list priv_chat_ids; + std::list::iterator cit; + rsMsgs->getPrivateChatQueueIds(incoming, priv_chat_ids); + for(cit = priv_chat_ids.begin(); cit != priv_chat_ids.end(); cit++) + { + std::list chats; + rsMsgs->getPrivateChatQueue(incoming, *cit, chats); + rsMsgs->clearPrivateChatQueue(incoming, *cit); + + // Default to Private. + rsctrl::chat::ChatType ctype = rsctrl::chat::TYPE_PRIVATE; + std::string chat_id = *cit; + + + // Check if its actually a LobbyId. + ChatLobbyId lobby_id; + if (rsMsgs->isLobbyId(*cit, lobby_id)) + { + ctype = rsctrl::chat::TYPE_LOBBY; + chat_id.clear(); + convertLobbyIdToString(lobby_id, chat_id); + + std::cerr << "Lobby Chat Queue: " << chat_id; + std::cerr << std::endl; + } + else + { + std::cerr << "Private Chat Queue: " << *cit; + std::cerr << std::endl; + } + + std::list::iterator it; + for(it = chats.begin(); it != chats.end(); it++) + { + std::cerr << "Private Chat from : " << it->rsid; + std::cerr << " name: " << it->peer_nickname; + std::cerr << std::endl; + { + std::string msg_utf8; + librs::util::ConvertUtf16ToUtf8(it->msg, msg_utf8); + std::cerr << " Msg: " << msg_utf8; + std::cerr << std::endl; + } + /* must send to all registered clients */ + std::list::const_iterator rit; + for(rit = registered.begin(); rit != registered.end(); rit++) + { + RpcQueuedMsg qmsg; + if (createQueuedEventSendMsg(*it, ctype, chat_id, *rit, qmsg)) + { + std::cerr << "Created MsgEvent"; + std::cerr << std::endl; + + events.push_back(qmsg); + } + else + { + std::cerr << "ERROR Creating MsgEvent"; + std::cerr << std::endl; + } + } + } + } + } + + return 1; +} + + +/***** HELPER FUNCTIONS *****/ + + + +bool fillLobbyInfoFromChatLobbyInfo(const ChatLobbyInfo &cli, rsctrl::chat::ChatLobbyInfo *lobby) +{ + /* convert info into response */ + std::string chat_id; + convertLobbyIdToString(cli.lobby_id, chat_id); + lobby->set_lobby_id(chat_id); + lobby->set_lobby_name(cli.lobby_name); + lobby->set_lobby_topic(cli.lobby_topic); + + /* see if there's a specific nickname for here */ + std::string nick; + if (!rsMsgs->getNickNameForChatLobby(cli.lobby_id,nick)) + { + rsMsgs->getDefaultNickNameForChatLobby(nick); + } + + lobby->set_lobby_nickname(nick); + + // Could be Private or Public. + if (cli.lobby_privacy_level & RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE) + { + lobby->set_privacy_level(rsctrl::chat::PRIVACY_PRIVATE); + } + else + { + lobby->set_privacy_level(rsctrl::chat::PRIVACY_PUBLIC); + } + lobby->set_lobby_state(rsctrl::chat::ChatLobbyInfo::LOBBYSTATE_JOINED); + + lobby->set_no_peers(cli.nick_names.size()); + + lobby->set_last_report_time(0); + lobby->set_last_activity(cli.last_activity); + + std::set::const_iterator pit; + for(pit = cli.participating_friends.begin(); pit != cli.participating_friends.begin(); pit++) + { + lobby->add_participating_friends(*pit); + } + + std::map::const_iterator mit; + for(mit = cli.nick_names.begin(); mit != cli.nick_names.begin(); mit++) + { + lobby->add_nicknames(mit->first); + } + return true; +} + + +bool fillLobbyInfoFromPublicChatLobbyRecord(const PublicChatLobbyRecord &pclr, rsctrl::chat::ChatLobbyInfo *lobby) +{ + /* convert info into response */ + std::string chat_id; + convertLobbyIdToString(pclr.lobby_id, chat_id); + lobby->set_lobby_id(chat_id); + lobby->set_lobby_name(pclr.lobby_name); + lobby->set_lobby_topic(pclr.lobby_topic); + + /* see if there's a specific nickname for here */ + std::string nick; + if (!rsMsgs->getNickNameForChatLobby(pclr.lobby_id,nick)) + { + rsMsgs->getDefaultNickNameForChatLobby(nick); + } + + lobby->set_lobby_nickname(nick); + + lobby->set_privacy_level(rsctrl::chat::PRIVACY_PUBLIC); + lobby->set_lobby_state(rsctrl::chat::ChatLobbyInfo::LOBBYSTATE_PUBLIC); + + lobby->set_no_peers(pclr.total_number_of_peers); + + lobby->set_last_report_time(pclr.last_report_time); + lobby->set_last_activity(0); // Unknown. + + std::set::const_iterator it; + for(it = pclr.participating_friends.begin(); it != pclr.participating_friends.begin(); it++) + { + lobby->add_participating_friends(*it); + } + + //lobby->add_nicknames(); // Unknown. + return true; +} + + +bool fillLobbyInfoFromChatLobbyInvite(const ChatLobbyInvite &cli, rsctrl::chat::ChatLobbyInfo *lobby) +{ + /* convert info into response */ + std::string chat_id; + convertLobbyIdToString(cli.lobby_id, chat_id); + lobby->set_lobby_id(chat_id); + lobby->set_lobby_name(cli.lobby_name); + lobby->set_lobby_topic(cli.lobby_topic); + + /* see if there's a specific nickname for here */ + std::string nick; + if (!rsMsgs->getNickNameForChatLobby(cli.lobby_id,nick)) + { + rsMsgs->getDefaultNickNameForChatLobby(nick); + } + + lobby->set_lobby_nickname(nick); + + // Can be invited to both Public and Private. + if (cli.lobby_privacy_level & RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE) + { + lobby->set_privacy_level(rsctrl::chat::PRIVACY_PRIVATE); + } + else + { + lobby->set_privacy_level(rsctrl::chat::PRIVACY_PUBLIC); + } + lobby->set_lobby_state(rsctrl::chat::ChatLobbyInfo::LOBBYSTATE_INVITED); + + lobby->set_no_peers(0); // Unknown. + + lobby->set_last_report_time(0); // Unknown + lobby->set_last_activity(0); // Unknown + + // Unknown, but we can fill in the inviting party here (the only one we know). + lobby->add_participating_friends(cli.peer_id); + //lobby->add_nicknames(); // Unknown. + return true; +} + + +bool createQueuedEventSendMsg(const ChatInfo &chatinfo, rsctrl::chat::ChatType ctype, + std::string chat_id, const RpcEventRegister &ereg, RpcQueuedMsg &qmsg) +{ + + rsctrl::chat::EventChatMessage event; + rsctrl::chat::ChatMessage *msg = event.mutable_msg(); + rsctrl::chat::ChatId *id = msg->mutable_id(); + + id->set_chat_type(ctype); + id->set_chat_id(chat_id); + + msg->set_peer_nickname(chatinfo.peer_nickname); + msg->set_chat_flags(chatinfo.chatflags); + msg->set_send_time(chatinfo.sendTime); + msg->set_recv_time(chatinfo.recvTime); + + std::string msg_utf8; + if (!convertWStringToUTF8(chatinfo.msg, msg_utf8)) + { + std::cerr << "RpcProtoChat::createQueuedEventSendMsg() ERROR Converting Msg"; + std::cerr << std::endl; + return false; + } + + msg->set_msg(msg_utf8); + + /* DONE - Generate Reply */ + std::string outmsg; + if (!event.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoChat::createQueuedEventSendMsg() ERROR SerialiseToString()"; + std::cerr << std::endl; + return false; + } + + // Correctly Name Message. + qmsg.mMsgId = constructMsgId(rsctrl::core::CORE, rsctrl::core::CHAT, + rsctrl::chat::MsgId_EventChatMessage, true); + + qmsg.mChanId = ereg.mChanId; + qmsg.mReqId = ereg.mReqId; + qmsg.mMsg = outmsg; + + return true; +} + +bool convertUTF8toWString(const std::string &msg_utf8, std::wstring &msg_wstr) +{ + return librs::util::ConvertUtf8ToUtf16(msg_utf8, msg_wstr); +} + +bool convertWStringToUTF8(const std::wstring &msg_wstr, std::string &msg_utf8) +{ + return librs::util::ConvertUtf16ToUtf8(msg_wstr, msg_utf8); +} + + +/* dependent on ChatLobbyId definition as uint64_t */ +bool convertStringToLobbyId(const std::string &chat_id, ChatLobbyId &lobby_id) +{ + if (1 != sscanf(chat_id.c_str(), UINT64FMT, &lobby_id)) + { + return false; + } + return true; +} + +bool convertLobbyIdToString(const ChatLobbyId &lobby_id, std::string &chat_id) +{ + rs_sprintf(chat_id, UINT64FMT, lobby_id); + return true; +} + + diff --git a/retroshare-nogui/src/rpc/proto/rpcprotochat.h b/retroshare-nogui/src/rpc/proto/rpcprotochat.h new file mode 100644 index 000000000..d42ab37de --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotochat.h @@ -0,0 +1,53 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_PROTO_CHAT_H +#define RS_RPC_PROTO_CHAT_H + +#include "rpc/rpcserver.h" + +// Registrations. +#define REGISTRATION_EVENT_CHAT 1 + +class RpcProtoChat: public RpcQueueService +{ +public: + RpcProtoChat(uint32_t serviceId); + virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg); + +protected: + + int processReqChatLobbies(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqCreateLobby(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqJoinOrLeaveLobby(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqSetLobbyNickname(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqRegisterEvents(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqSendMessage(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + + // EVENTS. + virtual int locked_checkForEvents(uint32_t event, const std::list ®istered, std::list &events); +}; + + +#endif /* RS_PROTO_CHAT_H */ diff --git a/retroshare-nogui/src/rpc/proto/rpcprotofiles.cc b/retroshare-nogui/src/rpc/proto/rpcprotofiles.cc new file mode 100644 index 000000000..60488fc37 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotofiles.cc @@ -0,0 +1,344 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/proto/rpcprotofiles.h" +#include "rpc/proto/gencc/files.pb.h" + +#include + +#include "util/rsstring.h" + +#include + +#include +#include + +#include + + +RpcProtoFiles::RpcProtoFiles(uint32_t serviceId) + :RpcQueueService(serviceId) +{ + return; +} + +int RpcProtoFiles::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + /* check the msgId */ + uint8_t topbyte = getRpcMsgIdExtension(msg_id); + uint16_t service = getRpcMsgIdService(msg_id); + uint8_t submsg = getRpcMsgIdSubMsg(msg_id); + bool isResponse = isRpcMsgIdResponse(msg_id); + + + std::cerr << "RpcProtoFiles::processMsg() topbyte: " << (int32_t) topbyte; + std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg; + std::cerr << std::endl; + + if (isResponse) + { + std::cerr << "RpcProtoFiles::processMsg() isResponse() - not processing"; + std::cerr << std::endl; + return 0; + } + + if (topbyte != (uint8_t) rsctrl::core::CORE) + { + std::cerr << "RpcProtoFiles::processMsg() Extension Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (service != (uint16_t) rsctrl::core::FILES) + { + std::cerr << "RpcProtoFiles::processMsg() Service Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (!rsctrl::files::RequestMsgIds_IsValid(submsg)) + { + std::cerr << "RpcProtoFiles::processMsg() SubMsg Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + switch(submsg) + { + case rsctrl::files::MsgId_RequestTransferList: + processReqTransferList(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::files::MsgId_RequestControlDownload: + processReqControlDownload(chan_id, msg_id, req_id, msg); + break; + + default: + std::cerr << "RpcProtoFiles::processMsg() ERROR should never get here"; + std::cerr << std::endl; + return 0; + } + + /* must have matched id to get here */ + return 1; +} + + + +int RpcProtoFiles::processReqTransferList(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoFiles::processReqTransferList()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::files::RequestTransferList req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoFiles::processReqTransferList() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::files::ResponseTransferList resp; + bool success = true; + std::string errorMsg; + + std::list file_list; + int hints = 0; + + /* convert msg parameters into local ones */ + switch(req.direction()) + { + case rsctrl::files::DIRECTION_UPLOAD: + { + rsFiles->FileUploads(file_list); + hints = RS_FILE_HINTS_UPLOAD; + break; + } + case rsctrl::files::DIRECTION_DOWNLOAD: + { + rsFiles->FileDownloads(file_list); + hints = RS_FILE_HINTS_DOWNLOAD; + break; + } + default: + std::cerr << "RpcProtoFiles::processReqTransferList() ERROR Unknown Dir"; + std::cerr << std::endl; + success = false; + errorMsg = "Unknown Direction"; + break; + } + + std::list::iterator lit; + for(lit = file_list.begin(); lit != file_list.end(); lit++) + { + rsctrl::files::FileTransfer *transfer = resp.add_transfers(); + transfer->set_direction(req.direction()); + + FileInfo info; + if (!rsFiles->FileDetails(*lit, hints, info)) + { + /* error */ + continue; + } + + /* copy file details */ + rsctrl::core::File *filedetails = transfer->mutable_file(); + filedetails->set_hash(info.hash); + filedetails->set_size(info.size); + filedetails->set_name(info.fname); + + transfer->set_fraction( (float) info.transfered / info.size ); + transfer->set_rate_kbs( info.tfRate ); + } + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoFiles::processReqTransferList() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::FILES, + rsctrl::files::MsgId_ResponseTransferList, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + +int RpcProtoFiles::processReqControlDownload(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoFiles::processReqControlDownload()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::files::RequestControlDownload req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoFiles::processReqControlDownload() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::files::ResponseControlDownload resp; + bool success = true; + std::string errorMsg; + + std::string filehash = req.file().hash(); + switch(req.action()) + { + case rsctrl::files::RequestControlDownload::ACTION_START: + { + std::list srcIds; + + std::string filename = req.file().name(); + uint64_t filesize = req.file().size(); + + // We Set NETWORK_WIDE flag here -> as files will be found via search. + // If this changes, we might be adjust flag (or pass it in!) + if (!rsFiles -> FileRequest(filename, filehash, filesize, + "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) + { + success = false; + errorMsg = "FileRequest ERROR"; + } + break; + } + case rsctrl::files::RequestControlDownload::ACTION_CONTINUE: + { + if (!rsFiles->changeQueuePosition(filehash,QUEUE_TOP)) + { + success = false; + errorMsg = "File QueuePosition(Top) ERROR"; + } + break; + } + case rsctrl::files::RequestControlDownload::ACTION_WAIT: + { + if (!rsFiles->changeQueuePosition(filehash,QUEUE_BOTTOM)) + { + success = false; + errorMsg = "File QueuePosition(Bottom) ERROR"; + + } + break; + } + case rsctrl::files::RequestControlDownload::ACTION_PAUSE: + { + if (!rsFiles->FileControl(filehash,RS_FILE_CTRL_PAUSE)) + { + success = false; + errorMsg = "FileControl(Pause) ERROR"; + + } + break; + } + case rsctrl::files::RequestControlDownload::ACTION_RESTART: + { + if (!rsFiles->FileControl(filehash,RS_FILE_CTRL_START)) + { + success = false; + errorMsg = "FileControl(Start) ERROR"; + + } + break; + } + case rsctrl::files::RequestControlDownload::ACTION_CHECK: + { + if (!rsFiles->FileControl(filehash,RS_FILE_CTRL_FORCE_CHECK)) + { + success = false; + errorMsg = "FileControl(Check) ERROR"; + + } + break; + } + case rsctrl::files::RequestControlDownload::ACTION_CANCEL: + { + if (!rsFiles->FileCancel(filehash)) + { + success = false; + errorMsg = "FileCancel ERROR"; + } + break; + } + default: + success = false; + errorMsg = "Invalid Action"; + break; + } + + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoFiles::processReqControlDownload() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::FILES, + rsctrl::files::MsgId_ResponseControlDownload, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + +/***** HELPER FUNCTIONS *****/ + diff --git a/retroshare-nogui/src/rpc/proto/rpcprotofiles.h b/retroshare-nogui/src/rpc/proto/rpcprotofiles.h new file mode 100644 index 000000000..89f8d17f9 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotofiles.h @@ -0,0 +1,44 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_PROTO_FILES_H +#define RS_RPC_PROTO_FILES_H + +#include "rpc/rpcserver.h" + +class RpcProtoFiles: public RpcQueueService +{ +public: + RpcProtoFiles(uint32_t serviceId); + + virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg); + +protected: + + int processReqTransferList(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqControlDownload(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + +}; + +#endif /* RS_PROTO_FILES_H */ diff --git a/retroshare-nogui/src/rpc/proto/rpcprotopeers.cc b/retroshare-nogui/src/rpc/proto/rpcprotopeers.cc new file mode 100644 index 000000000..aefe0312d --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotopeers.cc @@ -0,0 +1,429 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/proto/rpcprotopeers.h" +#include "rpc/proto/gencc/peers.pb.h" + +#include +#include + +#include +#include + +RpcProtoPeers::RpcProtoPeers(uint32_t serviceId) + :RpcQueueService(serviceId) +{ + return; +} + +//RpcProtoPeers::msgsAccepted(std::list &msgIds); /* not used at the moment */ + +int RpcProtoPeers::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + /* check the msgId */ + uint8_t topbyte = getRpcMsgIdExtension(msg_id); + uint16_t service = getRpcMsgIdService(msg_id); + uint8_t submsg = getRpcMsgIdSubMsg(msg_id); + bool isResponse = isRpcMsgIdResponse(msg_id); + + + std::cerr << "RpcProtoPeers::processMsg() topbyte: " << (int32_t) topbyte; + std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg; + std::cerr << std::endl; + + if (isResponse) + { + std::cerr << "RpcProtoPeers::processMsg() isResponse() - not processing"; + std::cerr << std::endl; + return 0; + } + + + if (topbyte != (uint8_t) rsctrl::core::CORE) + { + std::cerr << "RpcProtoPeers::processMsg() Extension Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (service != (uint16_t) rsctrl::core::PEERS) + { + std::cerr << "RpcProtoPeers::processMsg() Service Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (!rsctrl::peers::RequestMsgIds_IsValid(submsg)) + { + std::cerr << "RpcProtoPeers::processMsg() SubMsg Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + switch(submsg) + { + case rsctrl::peers::MsgId_RequestPeers: + processRequestPeers(chan_id, msg_id, req_id, msg); + break; + case rsctrl::peers::MsgId_RequestAddPeer: + processAddPeer(chan_id, msg_id, req_id, msg); + break; + case rsctrl::peers::MsgId_RequestModifyPeer: + processModifyPeer(chan_id, msg_id, req_id, msg); + break; + default: + std::cerr << "RpcProtoPeers::processMsg() ERROR should never get here"; + std::cerr << std::endl; + return 0; + } + + /* must have matched id to get here */ + return 1; +} + + +int RpcProtoPeers::processAddPeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoPeers::processAddPeer() NOT FINISHED"; + std::cerr << std::endl; + + // response. + rsctrl::peers::ResponseAddPeer resp; + bool success = false; + + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::NO_IMPL_YET); + } + + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoPeers::processAddPeer() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS, + rsctrl::peers::MsgId_ResponseAddPeer, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + +int RpcProtoPeers::processModifyPeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoPeers::processModifyPeer() NOT FINISHED"; + std::cerr << std::endl; + + + // response. + rsctrl::peers::ResponseModifyPeer resp; + bool success = false; + + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::NO_IMPL_YET); + } + + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoPeers::processModifyPeer() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS, + rsctrl::peers::MsgId_ResponseModifyPeer, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +int RpcProtoPeers::processRequestPeers(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoPeers::processRequestPeers()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::peers::RequestPeers reqp; + if (!reqp.ParseFromString(msg)) + { + std::cerr << "RpcProtoPeers::processRequestPeers() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // Get the list of gpg_id to generate data for. + std::list ids; + bool onlyConnected = false; + bool success = true; + switch(reqp.set()) + { + case rsctrl::peers::RequestPeers::OWNID: + { + std::cerr << "RpcProtoPeers::processRequestPeers() OWNID"; + std::cerr << std::endl; + std::string own_id = rsPeers->getGPGOwnId(); + ids.push_back(own_id); + break; + } + case rsctrl::peers::RequestPeers::LISTED: + { + std::cerr << "RpcProtoPeers::processRequestPeers() LISTED"; + std::cerr << std::endl; + /* extract ids from request (TODO) */ + std::string own_id = rsPeers->getGPGOwnId(); + ids.push_back(own_id); + break; + + } + case rsctrl::peers::RequestPeers::ALL: + std::cerr << "RpcProtoPeers::processRequestPeers() ALL"; + std::cerr << std::endl; + rsPeers->getGPGAllList(ids); + break; + case rsctrl::peers::RequestPeers::CONNECTED: + { + std::cerr << "RpcProtoPeers::processRequestPeers() CONNECTED"; + std::cerr << std::endl; + /* this ones a bit hard too */ + onlyConnected = true; + std::list ssl_ids; + std::list::const_iterator sit; + rsPeers->getOnlineList(ssl_ids); + for(sit = ssl_ids.begin(); sit != ssl_ids.end(); sit++) + { + std::string gpg_id = rsPeers->getGPGId(*sit); + if (gpg_id.size() > 0) + { + if (std::find(ids.begin(), ids.end(),gpg_id) == ids.end()) + { + ids.push_back(gpg_id); + } + } + } + break; + } + case rsctrl::peers::RequestPeers::FRIENDS: + std::cerr << "RpcProtoPeers::processRequestPeers() FRIENDS"; + std::cerr << std::endl; + rsPeers->getGPGAcceptedList(ids); + break; + case rsctrl::peers::RequestPeers::SIGNED: + std::cerr << "RpcProtoPeers::processRequestPeers() SIGNED"; + std::cerr << std::endl; + rsPeers->getGPGSignedList(ids); + break; + case rsctrl::peers::RequestPeers::VALID: + std::cerr << "RpcProtoPeers::processRequestPeers() VALID"; + std::cerr << std::endl; + rsPeers->getGPGSignedList(ids); + break; + } + + + // work out what data we need to request. + bool getLocations = false; + switch(reqp.info()) + { + default: + case rsctrl::peers::RequestPeers::NAMEONLY: + case rsctrl::peers::RequestPeers::BASIC: + break; + case rsctrl::peers::RequestPeers::LOCATION: + case rsctrl::peers::RequestPeers::ALLINFO: + getLocations = true; + break; + } + + // response. + rsctrl::peers::ResponsePeerList respp; + + /* now iterate through the peers and fill in the response. */ + std::list::const_iterator git; + for(git = ids.begin(); git != ids.end(); git++) + { + + RsPeerDetails details; + if (!rsPeers->getGPGDetails(*git, details)) + { + continue; /* uhm.. */ + } + + rsctrl::core::Person *person = respp.add_peers(); + + /* fill in key gpg details */ + person->set_gpg_id(*git); + person->set_name(details.name); + + std::cerr << "RpcProtoPeers::processRequestPeers() Adding GPGID: "; + std::cerr << *git << " name: " << details.name; + std::cerr << std::endl; + + if (details.state & RS_PEER_STATE_FRIEND) + { + person->set_relation(rsctrl::core::Person::FRIEND); + } + else + { + std::list common_friends; + rsDisc->getDiscGPGFriends(*git, common_friends); + int size = common_friends.size(); + if (size) + { + if (size > 2) + { + person->set_relation(rsctrl::core::Person::FRIEND_OF_MANY_FRIENDS); + } + else + { + person->set_relation(rsctrl::core::Person::FRIEND_OF_FRIENDS); + } + } + else + { + person->set_relation(rsctrl::core::Person::UNKNOWN); + } + } + + if (getLocations) + { + std::list ssl_ids; + std::list::const_iterator sit; + + if (!rsPeers->getAssociatedSSLIds(*git, ssl_ids)) + { + continue; /* end of this peer */ + } + + for(sit = ssl_ids.begin(); sit != ssl_ids.end(); sit++) + { + RsPeerDetails ssldetails; + if (!rsPeers->getPeerDetails(*sit, ssldetails)) + { + continue; /* uhm.. */ + } + if ((onlyConnected) && + (!(ssldetails.state & RS_PEER_STATE_CONNECTED))) + { + continue; + } + + rsctrl::core::Location *loc = person->add_locations(); + + std::cerr << "RpcProtoPeers::processRequestPeers() \t Adding Location: "; + std::cerr << *sit << " loc: " << ssldetails.location; + std::cerr << std::endl; + + /* fill in ssl details */ + loc->set_ssl_id(*sit); + loc->set_location(ssldetails.location); + + /* set addresses */ + rsctrl::core::IpAddr *laddr = loc->mutable_localaddr(); + laddr->set_addr(ssldetails.localAddr); + laddr->set_port(ssldetails.localPort); + + rsctrl::core::IpAddr *eaddr = loc->mutable_extaddr(); + eaddr->set_addr(ssldetails.extAddr); + eaddr->set_port(ssldetails.extPort); + + /* translate status */ + uint32_t loc_state = 0; + //dont think this state should be here. + //if (ssldetails.state & RS_PEER_STATE_FRIEND) + if (ssldetails.state & RS_PEER_STATE_ONLINE) + { + loc_state |= (uint32_t) rsctrl::core::Location::ONLINE; + } + if (ssldetails.state & RS_PEER_STATE_CONNECTED) + { + loc_state |= (uint32_t) rsctrl::core::Location::CONNECTED; + } + if (ssldetails.state & RS_PEER_STATE_UNREACHABLE) + { + loc_state |= (uint32_t) rsctrl::core::Location::UNREACHABLE; + } + + loc->set_state(loc_state); + } + } + } + + if (success) + { + rsctrl::core::Status *status = respp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = respp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg("Unknown ERROR"); + } + + + std::string outmsg; + if (!respp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoPeers::processRequestPeers() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::PEERS, + rsctrl::peers::MsgId_ResponsePeerList, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + diff --git a/retroshare-nogui/src/rpc/proto/rpcprotopeers.h b/retroshare-nogui/src/rpc/proto/rpcprotopeers.h new file mode 100644 index 000000000..92e91d88a --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotopeers.h @@ -0,0 +1,43 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_PROTO_PEERS_H +#define RS_RPC_PROTO_PEERS_H + +#include "rpc/rpcserver.h" + +class RpcProtoPeers: public RpcQueueService +{ +public: + RpcProtoPeers(uint32_t serviceId); +// virtual msgsAccepted(std::list &msgIds); /* not used at the moment */ + virtual int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + + virtual int processRequestPeers(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + virtual int processAddPeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + virtual int processModifyPeer(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); +}; + + +#endif /* RS_PROTO_PEERS_H */ diff --git a/retroshare-nogui/src/rpc/proto/rpcprotosearch.cc b/retroshare-nogui/src/rpc/proto/rpcprotosearch.cc new file mode 100644 index 000000000..31f97cd72 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotosearch.cc @@ -0,0 +1,593 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/proto/rpcprotosearch.h" +#include "rpc/proto/gencc/search.pb.h" + +#include "notifytxt.h" + +#include +#include + +#include "util/rsstring.h" + +#include + +#include +#include + +#include + + +RpcProtoSearch::RpcProtoSearch(uint32_t serviceId, NotifyTxt *notify) + :RpcQueueService(serviceId), mNotify(notify), searchMtx("RpcProtoSearch") +{ + return; +} + +void RpcProtoSearch::reset(uint32_t chan_id) +{ + RpcQueueService::reset(chan_id); + + /* must clear all searches */ + clear_searches(chan_id); +} + + +int RpcProtoSearch::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + /* check the msgId */ + uint8_t topbyte = getRpcMsgIdExtension(msg_id); + uint16_t service = getRpcMsgIdService(msg_id); + uint8_t submsg = getRpcMsgIdSubMsg(msg_id); + bool isResponse = isRpcMsgIdResponse(msg_id); + + + std::cerr << "RpcProtoSearch::processMsg() topbyte: " << (int32_t) topbyte; + std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg; + std::cerr << std::endl; + + if (isResponse) + { + std::cerr << "RpcProtoSearch::processMsg() isResponse() - not processing"; + std::cerr << std::endl; + return 0; + } + + if (topbyte != (uint8_t) rsctrl::core::CORE) + { + std::cerr << "RpcProtoSearch::processMsg() Extension Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (service != (uint16_t) rsctrl::core::SEARCH) + { + std::cerr << "RpcProtoSearch::processMsg() Service Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (!rsctrl::search::RequestMsgIds_IsValid(submsg)) + { + std::cerr << "RpcProtoSearch::processMsg() SubMsg Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + switch(submsg) + { + case rsctrl::search::MsgId_RequestBasicSearch: + processReqBasicSearch(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::search::MsgId_RequestCloseSearch: + processReqCloseSearch(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::search::MsgId_RequestListSearches: + processReqListSearches(chan_id, msg_id, req_id, msg); + break; + + case rsctrl::search::MsgId_RequestSearchResults: + processReqSearchResults(chan_id, msg_id, req_id, msg); + break; + + default: + std::cerr << "RpcProtoSearch::processMsg() ERROR should never get here"; + std::cerr << std::endl; + return 0; + } + + /* must have matched id to get here */ + return 1; +} + + + +int RpcProtoSearch::processReqBasicSearch(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoSearch::processReqBasicSearch()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::search::RequestBasicSearch req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoSearch::processReqBasicSearch() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::search::ResponseSearchIds resp; + bool success = true; + std::string errorMsg; + + /* convert msg parameters into local ones */ + std::list terms; + + int no_terms = req.terms_size(); + for(int i = 0; i < no_terms; i++) + { + std::string term = req.terms(i); + /* check for valid term? */ + if (term.size() > 0) + { + terms.push_back(term); + } + } + + NameExpression nameexp(ContainsAllStrings, terms, true); + LinearizedExpression lexpr; + nameexp.linearize(lexpr); + + uint32_t searchId = (uint32_t) rsTurtle->turtleSearch(lexpr); + mNotify->collectSearchResults(searchId); + + /* add into search array */ + add_search(chan_id, searchId); + + /* add to answer */ + resp.add_search_id(searchId); + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoSearch::processReqBasicSearch() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH, + rsctrl::search::MsgId_ResponseSearchIds, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + +int RpcProtoSearch::processReqCloseSearch(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoSearch::processReqCloseSearch()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::search::RequestCloseSearch req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoSearch::processReqCloseSearch() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::search::ResponseSearchIds resp; + bool success = true; + std::string errorMsg; + + /* convert msg parameters into local ones */ + uint32_t searchId = req.search_id(); + + + /* remove into search array */ + if (!remove_search(chan_id, searchId)) + { + success = false; + errorMsg = "Unknown SearchId in List"; + } + + /* clear search results + * we cannot cancel a turtle search + * so we tell notify to ignore further results + */ + + if (success) + { + if (!mNotify->clearSearchId(searchId)) + { + success = false; + errorMsg = "Unknown SearchId in Notify"; + } + } + + /* add to answer */ + if (success) + { + resp.add_search_id(searchId); + } + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoSearch::processReqCloseSearch() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH, + rsctrl::search::MsgId_ResponseSearchIds, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + +int RpcProtoSearch::processReqListSearches(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoSearch::processReqListSearches()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::search::RequestListSearches req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoSearch::processReqListSearches() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::search::ResponseSearchIds resp; + bool success = true; + std::string errorMsg; + + /* convert msg parameters into local ones */ + // Nothing to do. + + std::list reg_search_ids; + std::list::iterator it; + if (!get_search_list(chan_id, reg_search_ids)) + { + /* warning */ + success = false; + errorMsg = "No Searches Active"; + } + + /* iterate through search array */ + for(it = reg_search_ids.begin(); it != reg_search_ids.end(); it++) + { + /* add to answer */ + resp.add_search_id(*it); + } + + /* DONE - Generate Reply */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoSearch::processReqListSearches() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH, + rsctrl::search::MsgId_ResponseSearchIds, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + +int RpcProtoSearch::processReqSearchResults(uint32_t chan_id, uint32_t /* msg_id */, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoSearch::processReqSearchResults()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::search::RequestSearchResults req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoSearch::processReqSearchResults() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // response. + rsctrl::search::ResponseSearchResults resp; + bool success = true; + std::string errorMsg; + + /* convert msg parameters into local ones */ + std::list reg_search_ids; + std::list requested_search_ids; + if (!get_search_list(chan_id, reg_search_ids)) + { + /* warning */ + } + + int no_searches = req.search_ids_size(); + if (no_searches) + { + /* painful check that they are our searches */ + for(int i = 0; i < no_searches; i++) + { + uint32_t search_id = req.search_ids(i); + + /* check that its in reg_search_ids */ + if (reg_search_ids.end() != std::find(reg_search_ids.begin(), reg_search_ids.end(), search_id)) + { + /* error */ + continue; + } + requested_search_ids.push_back(search_id); + } + } + else + { + /* all current searches */ + requested_search_ids = reg_search_ids; + } + + + std::list::iterator rit; + for(rit = requested_search_ids.begin(); + rit != requested_search_ids.end(); rit++) + { + rsctrl::search::SearchSet *set = resp.add_searches(); + /* add to answer */ + set->set_search_id(*rit); + /* no search details at the moment */ + + /* add into search array */ + std::list::iterator it; + std::list searchResults; + mNotify->getSearchResults(*rit, searchResults); + + /* convert into useful list */ + for(it = searchResults.begin(); it != searchResults.end(); it++) + { + /* add to answer */ + rsctrl::search::SearchHit *hit = set->add_hits(); + rsctrl::core::File *file = hit->mutable_file(); + + file->set_hash(it->hash); + file->set_name(it->name); + file->set_size(it->size); + + // Uhm not provided for now. default to NETWORK + hit->set_loc(rsctrl::search::SearchHit::NETWORK); + hit->set_no_hits(1); // No aggregation yet. + } + } + + /* DONE - Generate Reply */ + /* different to others - partial success possible */ + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg(errorMsg); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoSearch::processReqSearchResults() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SEARCH, + rsctrl::search::MsgId_ResponseSearchResults, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +/***** HELPER FUNCTIONS *****/ + + // These private functions use Mutex below and manipulate mActiveSearches. +int RpcProtoSearch::get_search_list(uint32_t chan_id, std::list &search_ids) +{ + std::cerr << "RpcProtoSearch::get_search_list(" << chan_id << ")"; + std::cerr << std::endl; + + RsStackMutex stack(searchMtx); /******* LOCKED *********/ + + std::map >::iterator mit; + + mit = mActiveSearches.find(chan_id); + if (mit == mActiveSearches.end()) + { + return 0; + } + + search_ids = mit->second; + + return 1; +} + +int RpcProtoSearch::add_search(uint32_t chan_id, uint32_t search_id) +{ + std::cerr << "RpcProtoSearch::add_search(" << chan_id << ", " << search_id << ")"; + std::cerr << std::endl; + + RsStackMutex stack(searchMtx); /******* LOCKED *********/ + + std::map >::iterator mit; + + mit = mActiveSearches.find(chan_id); + if (mit == mActiveSearches.end()) + { + std::list emptyList; + mActiveSearches[chan_id] = emptyList; + + mit = mActiveSearches.find(chan_id); + } + + /* sanity check */ + if (mit->second.end() != std::find(mit->second.begin(), mit->second.end(), search_id)) + { + std::cerr << "RpcProtoSearch::add_search() ERROR search_id already exists"; + std::cerr << std::endl; + return 0; + } + + mit->second.push_back(search_id); + return 1; +} + +int RpcProtoSearch::remove_search(uint32_t chan_id, uint32_t search_id) +{ + std::cerr << "RpcProtoSearch::remove_search(" << chan_id << ", " << search_id << ")"; + std::cerr << std::endl; + + RsStackMutex stack(searchMtx); /******* LOCKED *********/ + + std::map >::iterator mit; + + mit = mActiveSearches.find(chan_id); + if (mit == mActiveSearches.end()) + { + std::cerr << "RpcProtoSearch::remove_search() ERROR search set doesn't exist"; + std::cerr << std::endl; + return 0; + } + + bool removed = false; + std::list::iterator lit; + for(lit = mit->second.begin(); lit != mit->second.end();) + { + if (*lit == search_id) + { + lit = mit->second.erase(lit); + if (removed) + { + std::cerr << "RpcProtoSearch::remove_search() ERROR removed multiple"; + std::cerr << std::endl; + } + removed = true; + } + else + { + lit++; + } + } + + if (removed) + return 1; + + std::cerr << "RpcProtoSearch::remove_search() ERROR search_id not found"; + std::cerr << std::endl; + + return 0; +} + +int RpcProtoSearch::clear_searches(uint32_t chan_id) +{ + std::cerr << "RpcProtoSearch::clear_searches(" << chan_id << ")"; + std::cerr << std::endl; + + RsStackMutex stack(searchMtx); /******* LOCKED *********/ + + std::map >::iterator mit; + + mit = mActiveSearches.find(chan_id); + if (mit == mActiveSearches.end()) + { + std::cerr << "RpcProtoSearch::clear_searches() WARNING search set not found"; + std::cerr << std::endl; + return 0; + } + + mActiveSearches.erase(mit); + return 1; +} + diff --git a/retroshare-nogui/src/rpc/proto/rpcprotosearch.h b/retroshare-nogui/src/rpc/proto/rpcprotosearch.h new file mode 100644 index 000000000..3ad77ce75 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotosearch.h @@ -0,0 +1,64 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_PROTO_SEARCH_H +#define RS_RPC_PROTO_SEARCH_H + +#include "rpc/rpcserver.h" + +class NotifyTxt; + +class RpcProtoSearch: public RpcQueueService +{ +public: + RpcProtoSearch(uint32_t serviceId, NotifyTxt *notify); + virtual void reset(uint32_t chan_id); + + virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg); + +protected: + + int processReqBasicSearch(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqCloseSearch(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqListSearches(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + int processReqSearchResults(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + + +private: + // These private functions use Mutex below and manipulate mActiveSearches. + int get_search_list(uint32_t chan_id, std::list &search_ids); + int add_search(uint32_t chan_id, uint32_t search_id); + int remove_search(uint32_t chan_id, uint32_t search_id); + int clear_searches(uint32_t chan_id); + + NotifyTxt *mNotify; + + RsMutex searchMtx; + + /* must store list of active searches per channel */ + std::map > mActiveSearches; + +}; + +#endif /* RS_PROTO_SEARCH_H */ diff --git a/retroshare-nogui/src/rpc/proto/rpcprotosystem.cc b/retroshare-nogui/src/rpc/proto/rpcprotosystem.cc new file mode 100644 index 000000000..7a0e1e52a --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotosystem.cc @@ -0,0 +1,286 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/proto/rpcprotosystem.h" +#include "rpc/proto/gencc/system.pb.h" + +#include +#include +#include + +#include +#include + +RpcProtoSystem::RpcProtoSystem(uint32_t serviceId) + :RpcQueueService(serviceId) +{ + return; +} + +//RpcProtoSystem::msgsAccepted(std::list &msgIds); /* not used at the moment */ + +int RpcProtoSystem::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + /* check the msgId */ + uint8_t topbyte = getRpcMsgIdExtension(msg_id); + uint16_t service = getRpcMsgIdService(msg_id); + uint8_t submsg = getRpcMsgIdSubMsg(msg_id); + bool isResponse = isRpcMsgIdResponse(msg_id); + + + std::cerr << "RpcProtoSystem::processMsg() topbyte: " << (int32_t) topbyte; + std::cerr << " service: " << (int32_t) service << " submsg: " << (int32_t) submsg; + std::cerr << std::endl; + + if (isResponse) + { + std::cerr << "RpcProtoSystem::processMsg() isResponse() - not processing"; + std::cerr << std::endl; + return 0; + } + + + if (topbyte != (uint8_t) rsctrl::core::CORE) + { + std::cerr << "RpcProtoSystem::processMsg() Extension Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (service != (uint16_t) rsctrl::core::SYSTEM) + { + std::cerr << "RpcProtoSystem::processMsg() Service Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + if (!rsctrl::system::RequestMsgIds_IsValid(submsg)) + { + std::cerr << "RpcProtoSystem::processMsg() SubMsg Mismatch - not processing"; + std::cerr << std::endl; + return 0; + } + + switch(submsg) + { + case rsctrl::system::MsgId_RequestSystemStatus: + processSystemStatus(chan_id, msg_id, req_id, msg); + break; +#if 0 + case rsctrl::system::MsgId_RequestSystemQuit: + processSystemQuit(chan_id, msg_id, req_id, msg); + break; +#endif + default: + std::cerr << "RpcProtoSystem::processMsg() ERROR should never get here"; + std::cerr << std::endl; + return 0; + } + + /* must have matched id to get here */ + return 1; +} + + +int RpcProtoSystem::processSystemStatus(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoSystem::processSystemStatus()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::system::RequestSystemStatus req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoSystem::processSystemStatus() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // NO Options... so go straight to answer. + // response. + rsctrl::system::ResponseSystemStatus resp; + bool success = true; + + unsigned int nTotal = 0; + unsigned int nConnected = 0; + rsPeers->getPeerCount(&nTotal, &nConnected, false); + + float downKb = 0; + float upKb = 0; + rsicontrol -> ConfigGetDataRates(downKb, upKb); + + // set the data. + resp.set_no_peers(nTotal); + resp.set_no_connected(nConnected); + + rsctrl::core::Bandwidth *bw = resp.mutable_bw_total(); + bw->set_up(upKb); + bw->set_down(downKb); + bw->set_name("Total Connection Bandwidth"); + + uint32_t netState = rsConfig->getNetState(); + std::string natState("Unknown"); + rsctrl::system::ResponseSystemStatus_NetCode protoCode; + + switch(netState) + { + default: + case RSNET_NETSTATE_BAD_UNKNOWN: + protoCode = rsctrl::system::ResponseSystemStatus::BAD_UNKNOWN; + break; + + case RSNET_NETSTATE_BAD_OFFLINE: + protoCode = rsctrl::system::ResponseSystemStatus::BAD_OFFLINE; + break; + + case RSNET_NETSTATE_BAD_NATSYM: + protoCode = rsctrl::system::ResponseSystemStatus::BAD_NATSYM; + break; + + case RSNET_NETSTATE_BAD_NODHT_NAT: + protoCode = rsctrl::system::ResponseSystemStatus::BAD_NODHT_NAT; + break; + + case RSNET_NETSTATE_WARNING_RESTART: + protoCode = rsctrl::system::ResponseSystemStatus::WARNING_RESTART; + break; + + case RSNET_NETSTATE_WARNING_NATTED: + protoCode = rsctrl::system::ResponseSystemStatus::WARNING_NATTED; + break; + + case RSNET_NETSTATE_WARNING_NODHT: + protoCode = rsctrl::system::ResponseSystemStatus::WARNING_NODHT; + break; + + case RSNET_NETSTATE_GOOD: + protoCode = rsctrl::system::ResponseSystemStatus::GOOD; + break; + + case RSNET_NETSTATE_ADV_FORWARD: + protoCode = rsctrl::system::ResponseSystemStatus::ADV_FORWARD; + break; + } + + resp.set_net_status(protoCode); + + + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg("Unknown ERROR"); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoSystem::processSystemStatus() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SYSTEM, + rsctrl::system::MsgId_ResponseSystemStatus, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + + +int RpcProtoSystem::processSystemQuit(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcProtoSystem::processSystemQuit()"; + std::cerr << std::endl; + + // parse msg. + rsctrl::system::RequestSystemQuit req; + if (!req.ParseFromString(msg)) + { + std::cerr << "RpcProtoSystem::processSystemQuit() ERROR ParseFromString()"; + std::cerr << std::endl; + return 0; + } + + // NO Options... so go straight to answer. + // response. + rsctrl::system::ResponseSystemQuit resp; + bool success = true; + + switch(req.quit_code()) + { + default: + case rsctrl::system::RequestSystemQuit::CLOSE_CHANNEL: + { + RpcServer *server = getRpcServer(); + server->error(chan_id, "CLOSE_CHANNEL"); + + break; + } + case rsctrl::system::RequestSystemQuit::SHUTDOWN_RS: + { + rsicontrol->rsGlobalShutDown(); + break; + } + } + + if (success) + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::SUCCESS); + } + else + { + rsctrl::core::Status *status = resp.mutable_status(); + status->set_code(rsctrl::core::Status::FAILED); + status->set_msg("Unknown ERROR"); + } + + std::string outmsg; + if (!resp.SerializeToString(&outmsg)) + { + std::cerr << "RpcProtoSystem::processSystemQuit() ERROR SerialiseToString()"; + std::cerr << std::endl; + return 0; + } + + // Correctly Name Message. + uint32_t out_msg_id = constructMsgId(rsctrl::core::CORE, rsctrl::core::SYSTEM, + rsctrl::system::MsgId_ResponseSystemQuit, true); + + // queue it. + queueResponse(chan_id, out_msg_id, req_id, outmsg); + + return 1; +} + + diff --git a/retroshare-nogui/src/rpc/proto/rpcprotosystem.h b/retroshare-nogui/src/rpc/proto/rpcprotosystem.h new file mode 100644 index 000000000..f1490fed5 --- /dev/null +++ b/retroshare-nogui/src/rpc/proto/rpcprotosystem.h @@ -0,0 +1,42 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_PROTO_SYSTEM_H +#define RS_RPC_PROTO_SYSTEM_H + +#include "rpc/rpcserver.h" + +class RpcProtoSystem: public RpcQueueService +{ +public: + RpcProtoSystem(uint32_t serviceId); +// virtual msgsAccepted(std::list &msgIds); /* not used at the moment */ + virtual int processMsg(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg); + + virtual int processSystemStatus(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + virtual int processSystemQuit(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); +}; + + +#endif /* RS_PROTO_SYSTEM_H */ diff --git a/retroshare-nogui/src/rpc/rpc.cc b/retroshare-nogui/src/rpc/rpc.cc new file mode 100644 index 000000000..a1aa1683b --- /dev/null +++ b/retroshare-nogui/src/rpc/rpc.cc @@ -0,0 +1,307 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/rpc.h" +#include "rpc/rpcserver.h" + +// This one is inside libretroshare (BAD)!!! +#include "serialiser/rsbaseserial.h" + +#include + +const uint32_t kMsgHeaderSize = 16; +const uint32_t kMsgMagicCode = 0x137f0001; // Arbitary + 0x0001 + +RpcMediator::RpcMediator(RpcComms *c) + :mComms(c), mServer(NULL) +{ + return; +} + +void RpcMediator::reset(uint32_t chan_id) +{ + mServer->reset(chan_id); +} + +int RpcMediator::error(uint32_t chan_id, std::string msg) +{ + return mComms->error(chan_id, msg); +} + + +int RpcMediator::tick() +{ + bool worked = false; + if (recv()) + { + worked = true; + } + + if (mServer->checkPending()) + { + worked = true; + } + + if (mServer->checkEvents()) + { + worked = true; + } + + if (worked) + return 1; + else + return 0; + return 0; +} + + +int RpcMediator::recv() +{ + int recvd = 0; + + std::list chan_ids; + std::list::iterator it; + mComms->active_channels(chan_ids); + for(it = chan_ids.begin(); it != chan_ids.end(); it++) + { + while(recv_msg(*it)) + { + recvd = 1; + } + } + return recvd; +} + + +int RpcMediator::recv_msg(uint32_t chan_id) +{ + /* nothing in here needs a Mutex... */ + + if (!mComms->recv_ready(chan_id)) + { + return 0; + } + + std::cerr << "RpcMediator::recv_msg() Data Ready"; + std::cerr << std::endl; + + /* read in data */ + uint8_t buffer[kMsgHeaderSize]; + uint32_t bufsize = kMsgHeaderSize; + uint32_t msg_id; + uint32_t req_id; + uint32_t msg_size; + std::string msg_body; + + std::cerr << "RpcMediator::recv_msg() get Header: " << bufsize; + std::cerr << " bytes" << std::endl; + + int read = mComms->recv_blocking(chan_id, buffer, bufsize); + if (read != bufsize) + { + /* error */ + std::cerr << "RpcMediator::recv_msg() Error Reading Header: " << bufsize; + std::cerr << " bytes" << std::endl; + + mComms->error(chan_id, "Failed to Recv Header"); + return 0; + } + + if (!MsgPacker::deserialiseHeader(msg_id, req_id, msg_size, buffer, bufsize)) + { + /* error */ + std::cerr << "RpcMediator::recv_msg() Error Deserialising Header"; + std::cerr << std::endl; + + mComms->error(chan_id, "Failed to Deserialise Header"); + return 0; + } + + std::cerr << "RpcMediator::recv_msg() ChanId: " << chan_id; + std::cerr << " MsgId: " << msg_id; + std::cerr << " ReqId: " << req_id; + std::cerr << std::endl; + + std::cerr << "RpcMediator::recv_msg() get Body: " << msg_size; + std::cerr << " bytes" << std::endl; + + /* grab real size */ + read = mComms->recv_blocking(chan_id, msg_body, msg_size); + if (read != msg_size) + { + /* error */ + std::cerr << "RpcMediator::recv_msg() Error Reading Body: " << bufsize; + std::cerr << " bytes" << std::endl; + + mComms->error(chan_id, "Failed to Recv MsgBody"); + return 0; + } + mServer->processMsg(chan_id, msg_id, req_id, msg_body); + + return 1; +} + + +int RpcMediator::send(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) + +{ + std::cerr << "RpcMediator::send(" << msg_id << "," << req_id << ", len("; + std::cerr << msg.size() << ")) on chan_id: " << chan_id; + std::cerr << std::endl; + + uint8_t buffer[kMsgHeaderSize]; + uint32_t bufsize = kMsgHeaderSize; + uint32_t msg_size = msg.size(); + + bool okay = MsgPacker::serialiseHeader(msg_id, req_id, msg_size, buffer, bufsize); + if (!okay) + { + std::cerr << "RpcMediator::send() SerialiseHeader Failed"; + std::cerr << std::endl; + /* error */ + return 0; + } + + if (!mComms->send(chan_id, buffer, bufsize)) + { + std::cerr << "RpcMediator::send() Send Header Failed"; + std::cerr << std::endl; + /* error */ + mComms->error(chan_id, "Failed to Send Header"); + return 0; + } + + /* now send the body */ + if (!mComms->send(chan_id, msg)) + { + std::cerr << "RpcMediator::send() Send Body Failed"; + std::cerr << std::endl; + /* error */ + mComms->error(chan_id, "Failed to Send Msg"); + return 0; + } + return 1; +} + + + + +/* Msg Packing */ +int MsgPacker::headersize() +{ + return kMsgHeaderSize; +} + +#if 0 +int MsgPacker::msgsize(Message *msg) +{ + /* */ + return 0; +} + +int MsgPacker::pktsize(Message *msg) +{ + /* */ + return headersize() + msgsize(); +} +#endif + +bool MsgPacker::serialiseHeader(uint32_t msg_id, uint32_t req_id, uint32_t msg_size, uint8_t *buffer, uint32_t bufsize) +{ + /* check size */ + if (bufsize < kMsgHeaderSize) + { + return false; + } + + /* pack the data (using libretroshare serialiser for now */ + void *data = buffer; + uint32_t offset = 0; + uint32_t size = bufsize; + + bool ok = true; + + /* 4 x uint32_t for header */ + ok &= setRawUInt32(data, size, &offset, kMsgMagicCode); + ok &= setRawUInt32(data, size, &offset, msg_id); + ok &= setRawUInt32(data, size, &offset, req_id); + ok &= setRawUInt32(data, size, &offset, msg_size); + + return ok; +} + + +bool MsgPacker::deserialiseHeader(uint32_t &msg_id, uint32_t &req_id, uint32_t &msg_size, uint8_t *buffer, uint32_t bufsize) +{ + /* check size */ + if (bufsize < kMsgHeaderSize) + { + return false; + } + + /* pack the data (using libretroshare serialiser for now */ + void *data = buffer; + uint32_t offset = 0; + uint32_t size = bufsize; + uint32_t magic_code; + + bool ok = true; + + /* 4 x uint32_t for header */ + ok &= getRawUInt32(data, size, &offset, &magic_code); + if (!ok) + { + std::cerr << "Failed to deserialise uint32_t(0)"; + std::cerr << std::endl; + } + ok &= getRawUInt32(data, size, &offset, &msg_id); + if (!ok) + { + std::cerr << "Failed to deserialise uint32_t(1)"; + std::cerr << std::endl; + } + ok &= getRawUInt32(data, size, &offset, &req_id); + if (!ok) + { + std::cerr << "Failed to deserialise uint32_t(2)"; + std::cerr << std::endl; + } + ok &= getRawUInt32(data, size, &offset, &msg_size); + if (!ok) + { + std::cerr << "Failed to deserialise uint32_t(3)"; + std::cerr << std::endl; + } + + ok &= (magic_code == kMsgMagicCode); + if (!ok) + { + std::cerr << "Failed to Match MagicCode"; + std::cerr << std::endl; + } + + return ok; +} + + + diff --git a/retroshare-nogui/src/rpc/rpc.h b/retroshare-nogui/src/rpc/rpc.h new file mode 100644 index 000000000..bdc2e8a18 --- /dev/null +++ b/retroshare-nogui/src/rpc/rpc.h @@ -0,0 +1,72 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RPC_MEDIATOR_H +#define RPC_MEDIATOR_H + +/* + * Interface between RpcServer and RpcComms. + */ + +#include +#include + +#include "rpcsystem.h" + +class RpcServer; + +class RpcMediator: public RpcSystem +{ +public: + + RpcMediator(RpcComms *c); + void setRpcServer(RpcServer *s) { mServer = s; } /* Must only be called during setup */ + + // Overloaded from RpcSystem. +virtual void reset(uint32_t chan_id); +virtual int tick(); + + int recv(); + int recv_msg(uint32_t chan_id); + int send(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + + int error(uint32_t chan_id, std::string msg); // pass an error up to comms level. +private: + RpcComms *mComms; + RpcServer *mServer; + +}; + + +/* Msg Packing */ +class MsgPacker +{ +public: + static int headersize(); + static bool serialiseHeader(uint32_t msg_id, uint32_t req_id, uint32_t msg_size, uint8_t *buffer, uint32_t bufsize); + static bool deserialiseHeader(uint32_t &msg_id, uint32_t &req_id, uint32_t &msg_size, uint8_t *buffer, uint32_t bufsize); +}; + + + +#endif /* RPC_MEDIATOR_H */ diff --git a/retroshare-nogui/src/rpc/rpcecho.cc b/retroshare-nogui/src/rpc/rpcecho.cc new file mode 100644 index 000000000..b11220bb8 --- /dev/null +++ b/retroshare-nogui/src/rpc/rpcecho.cc @@ -0,0 +1,40 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/rpcecho.h" + +RpcEcho::RpcEcho(uint32_t serviceId) +:RpcQueueService(serviceId) +{ + return; +} + +int RpcEcho::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + /* */ + queueResponse(chan_id, msg_id, req_id, msg); + return 1; +} + + + diff --git a/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.h b/retroshare-nogui/src/rpc/rpcecho.h similarity index 62% rename from retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.h rename to retroshare-nogui/src/rpc/rpcecho.h index dd3ea03df..b34446310 100644 --- a/retroshare-gui/src/gui/PhotoShare/PhotoDetailsDialog.h +++ b/retroshare-nogui/src/rpc/rpcecho.h @@ -1,5 +1,5 @@ /* - * Retroshare Photo Plugin. + * RetroShare External Interface. * * Copyright 2012-2012 by Robert Fernie. * @@ -21,39 +21,18 @@ * */ -#ifndef MRK_PHOTO_DETAILS_DIALOG_H -#define MRK_PHOTO_DETAILS_DIALOG_H -#include "ui_PhotoDetailsDialog.h" +#ifndef RS_RPC_ECHO_H +#define RS_RPC_ECHO_H -class PhotoItem; +#include "rpc/rpcserver.h" -class PhotoDetailsDialog : public QWidget +class RpcEcho: public RpcQueueService { - Q_OBJECT - public: - PhotoDetailsDialog(QWidget *parent = 0); - -void setPhotoItem(PhotoItem *item); - -signals: - void editingDone(); - -private: -void saveDetails(); -void refreshDetails(); - -private slots: -void updateDetails(); -void blankDetails(); - -private: - PhotoItem *mPhotoItem; - - Ui::PhotoDetailsDialog ui; - + RpcEcho(uint32_t serviceId); + virtual int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); }; -#endif +#endif /* RS_RPC_ECHO_H */ diff --git a/retroshare-nogui/src/rpc/rpcserver.cc b/retroshare-nogui/src/rpc/rpcserver.cc new file mode 100644 index 000000000..a879e08df --- /dev/null +++ b/retroshare-nogui/src/rpc/rpcserver.cc @@ -0,0 +1,538 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/rpcserver.h" + +#include "rpc/rpc.h" + +#include + + + +bool operator<(const RpcUniqueId &a, const RpcUniqueId &b) +{ + if (a.mChanId == b.mChanId) + return (a.mReqId < b.mReqId); + return (a.mChanId < b.mChanId); +} + + +RpcServer::RpcServer(RpcMediator *med) + :mMediator(med), mRpcMtx("RpcMtx") +{ + +} + +void RpcServer::reset(uint32_t chan_id) +{ + std::cerr << "RpcServer::reset(" << chan_id << ")" << std::endl; + { + RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/ + + std::list::iterator it; + for(it = mAllServices.begin(); it != mAllServices.end(); it++) + { + /* in mutex, but should be okay */ + (*it)->reset(chan_id); + } + + // clear existing queue. + mRpcQueue.clear(); + } + + return; +} + +int RpcServer::error(uint32_t chan_id, std::string msg) +{ + return mMediator->error(chan_id, msg); +} + +int RpcServer::addService(RpcService *service) +{ + RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/ + + service->setRpcServer(this); + mAllServices.push_back(service); + + return 1; +} + + +int RpcServer::processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + std::cerr << "RpcServer::processMsg(" << msg_id << "," << req_id; + std::cerr << ", len(" << msg.size() << ")) from channel: " << chan_id; + std::cerr << std::endl; + + { + RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/ + + std::list::iterator it; + for(it = mAllServices.begin(); it != mAllServices.end(); it++) + { + int rt = (*it)->processMsg(chan_id, msg_id, req_id, msg); + if (!rt) + continue; + + /* remember request */ + queueRequest_locked(chan_id, msg_id, req_id, (*it)); + return 1; + } + } + + std::cerr << "RpcServer::processMsg() No service to accepted it - discard"; + std::cerr << std::endl; + return 0; +} + +int RpcServer::queueRequest_locked(uint32_t chan_id, uint32_t /* msgId */, uint32_t req_id, RpcService *service) +{ + std::cerr << "RpcServer::queueRequest_locked() req_id: " << req_id; + std::cerr << std::endl; + + RpcQueuedObj obj; + obj.mChanId = chan_id; + obj.mReqId = req_id; + obj.mService = service; + + mRpcQueue.push_back(obj); + + return 1; +} + + +bool RpcServer::checkPending() +{ + std::list msgsToSend; + bool someRemaining = false; + bool someToSend = false; + + { + RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/ + + std::list::iterator it; + for(it = mRpcQueue.begin(); it != mRpcQueue.end();) + { + uint32_t out_chan_id = it->mChanId; + uint32_t out_msg_id = 0; + uint32_t out_req_id = it->mReqId; + std::string out_msg; + if (it->mService->getResponse(out_chan_id, out_msg_id, out_req_id, out_msg)) + { + std::cerr << "RpcServer::checkPending() Response: ("; + std::cerr << out_msg_id << "," << out_req_id; + std::cerr << ", len(" << out_msg.size() << "))"; + std::cerr << " for chan_id: " << out_chan_id; + std::cerr << std::endl; + + /* store and send after queue is processed */ + RpcQueuedMsg msg; + msg.mChanId = out_chan_id; + msg.mMsgId = out_msg_id; + msg.mReqId = out_req_id; + msg.mMsg = out_msg; + + msgsToSend.push_back(msg); + + it = mRpcQueue.erase(it); + someToSend = true; + } + else + { + it++; + someRemaining = true; + } + } + } + + if (someToSend) + { + sendQueuedMsgs(msgsToSend); + } + + return someRemaining; +} + + +bool RpcServer::checkEvents() +{ + std::list msgsToSend; + bool someToSend = false; + + { + RsStackMutex stack(mRpcMtx); /********** LOCKED MUTEX ***************/ + + std::list::iterator it; + for(it = mAllServices.begin(); it != mAllServices.end(); it++) + { + if ((*it)->getEvents(msgsToSend)) + someToSend = true; + } + } + + if (someToSend) + { + sendQueuedMsgs(msgsToSend); + } + return someToSend; +} + +bool RpcServer::sendQueuedMsgs(std::list &msgs) +{ + /* No need for lock, as mOut is the only accessed item - and that has own protection */ + + std::cerr << "RpcServer::sendQueuedMsg() " << msgs.size() << " to send"; + std::cerr << std::endl; + + std::list::iterator it; + for (it = msgs.begin(); it != msgs.end(); it++) + { + mMediator->send(it->mChanId, it->mMsgId, it->mReqId, it->mMsg); + } + return true; +} + + + + + + + +RpcQueueService::RpcQueueService(uint32_t serviceId) +:RpcService(serviceId), mQueueMtx("RpcQueueService") +{ + return; +} + + +void RpcQueueService::reset(uint32_t chan_id) +{ + clearEventsForChannel(chan_id); + + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::list toRemove; + + // iterate through and remove only chan_id items. + std::map::iterator mit; + for(mit = mResponses.begin(); mit != mResponses.end(); mit++) + { + if (mit->second.mChanId == chan_id) + toRemove.push_back(mit->first); + } + + /* remove items */ + std::list::iterator rit; + for(rit = toRemove.begin(); rit != toRemove.end(); rit++) + { + mit = mResponses.find(*rit); + mResponses.erase(mit); + } + + + return; +} + +int RpcQueueService::getResponse(uint32_t &chan_id, uint32_t &msg_id, uint32_t &req_id, std::string &msg) +{ + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::map::iterator it; + + RpcUniqueId uid(chan_id, req_id); + it = mResponses.find(uid); + if (it == mResponses.end()) + { + return 0; + } + + // chan_id & req_id are already set. + msg_id = it->second.mMsgId; + msg = it->second.mMsg; + + mResponses.erase(it); + + return 1; +} + +int RpcQueueService::queueResponse(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) +{ + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + RpcQueuedMsg qmsg; + qmsg.mChanId = chan_id; + qmsg.mMsgId = msg_id; + qmsg.mReqId = req_id; + qmsg.mMsg = msg; + + RpcUniqueId uid(chan_id, req_id); + mResponses[uid] = qmsg; + + return 1; +} + + + + +/********* Events & Registration ******/ + + +int RpcQueueService::getEvents(std::list &events) +{ + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::map >::iterator it; + for(it = mEventRegister.begin(); it != mEventRegister.end(); it++) + { + locked_checkForEvents(it->first, it->second, events); + } + + if (events.empty()) + { + return 0; + } + return 1; +} + +int RpcQueueService::locked_checkForEvents(uint32_t event, const std::list ®istered, std::list & /* events */) +{ + std::cerr << "RpcQueueService::locked_checkForEvents() NOT IMPLEMENTED"; + std::cerr << std::endl; + std::cerr << "\tRegistered for Event Type: " << event; + std::cerr << std::endl; + + std::list::const_iterator it; + for(it = registered.begin(); it != registered.end(); it++) + { + std::cerr << "\t\t Channel ID: " << it->mChanId; + std::cerr << " Request ID: " << it->mReqId; + std::cerr << std::endl; + } + + return 1; +} + +int RpcQueueService::registerForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id) +{ + std::cerr << "RpcQueueService::registerForEvents(ChanId: " << chan_id; + std::cerr << ", ReqId: " << req_id; + std::cerr << ", EventId: " << event_id; + std::cerr << ")"; + std::cerr << std::endl; + + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::map >::iterator mit; + mit = mEventRegister.find(event_id); + if (mit == mEventRegister.end()) + { + std::list emptyList; + mEventRegister[event_id] = emptyList; + + mit = mEventRegister.find(event_id); + } + + RpcEventRegister reg; + reg.mChanId = chan_id; + reg.mReqId = req_id; + reg.mEventId = event_id; + + mit->second.push_back(reg); + + return 1; +} + +int RpcQueueService::deregisterForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id) +{ + std::cerr << "RpcQueueService::deregisterForEvents(ChanId: " << chan_id; + std::cerr << ", ReqId: " << req_id; + std::cerr << ", EventId: " << event_id; + std::cerr << ")"; + std::cerr << std::endl; + + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::map >::iterator mit; + mit = mEventRegister.find(event_id); + if (mit == mEventRegister.end()) + { + std::cerr << "RpcQueueService::deregisterForEvents() "; + std::cerr << "ERROR no EventId: " << event_id; + std::cerr << std::endl; + + return 0; + } + + bool removed = false; + std::list::iterator lit; + for(lit = mit->second.begin(); lit != mit->second.end();) + { + /* remove all matches */ + if ((lit->mReqId == req_id) && (lit->mChanId == chan_id)) + { + lit = mit->second.erase(lit); + if (removed == true) + { + std::cerr << "RpcQueueService::deregisterForEvents() "; + std::cerr << "WARNING REMOVING MULTIPLE MATCHES"; + std::cerr << std::endl; + } + removed = true; + } + else + { + lit++; + } + } + + if (mit->second.empty()) + { + std::cerr << "RpcQueueService::deregisterForEvents() "; + std::cerr << " Last Registrant for Event, removing List from Map"; + std::cerr << std::endl; + + mEventRegister.erase(mit); + } + + return 1; +} + + +int RpcQueueService::clearEventsForChannel(uint32_t chan_id) +{ + std::cerr << "RpcQueueService::clearEventsForChannel(" << chan_id; + std::cerr << ")"; + std::cerr << std::endl; + + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::list toMapRemove; + + std::map >::iterator mit; + for(mit = mEventRegister.begin(); mit != mEventRegister.end(); mit++) + { + std::list::iterator lit; + for(lit = mit->second.begin(); lit != mit->second.end();) + { + /* remove all matches */ + if (lit->mChanId == chan_id) + { + std::cerr << "RpcQueueService::clearEventsForChannel() "; + std::cerr << " Removing ReqId: " << lit->mReqId; + std::cerr << " for EventId: " << lit->mEventId; + std::cerr << std::endl; + + lit = mit->second.erase(lit); + } + else + { + lit++; + } + } + if (mit->second.empty()) + { + toMapRemove.push_back(mit->first); + } + } + + /* remove any empty lists now */ + std::list::iterator rit; + for(rit = toMapRemove.begin(); rit != toMapRemove.end(); rit++) + { + mit = mEventRegister.find(*rit); + mEventRegister.erase(mit); + } + + return 1; +} + + +int RpcQueueService::printEventRegister(std::ostream &out) +{ + out << "RpcQueueService::printEventRegister()"; + out << std::endl; + + RsStackMutex stack(mQueueMtx); /********** LOCKED MUTEX ***************/ + + std::list toMapRemove; + + std::map >::iterator mit; + for(mit = mEventRegister.begin(); mit != mEventRegister.end(); mit++) + { + out << "Event: " << mit->first; + out << std::endl; + + std::list::iterator lit; + for(lit = mit->second.begin(); lit != mit->second.end(); lit++) + { + out << "\tRegistrant: ReqId: " << lit->mReqId; + out << "\t ChanId: " << lit->mChanId; + out << std::endl; + } + } + return 1; +} + + + + +// Lower 8 bits. +uint8_t getRpcMsgIdSubMsg(uint32_t msg_id) +{ + return msg_id & 0xFF; +} + +// Middle 16 bits. +uint16_t getRpcMsgIdService(uint32_t msg_id) +{ + return (msg_id >> 8) & 0xFFFF; +} + +// Top 8 bits. +uint8_t getRpcMsgIdExtension(uint32_t msg_id) +{ + return (msg_id >> 24) & 0xFE; // Bottom Bit is for Request / Response +} + +bool isRpcMsgIdResponse(uint32_t msg_id) +{ + return (msg_id >> 24) & 0x01; +} + + +uint32_t constructMsgId(uint8_t ext, uint16_t service, uint8_t submsg, bool is_response) +{ + if (is_response) + ext |= 0x01; // Set Bottom Bit. + else + ext &= 0xFE; // Clear Bottom Bit. + + uint32_t msg_id = (ext << 24) + (service << 8) + (submsg); + return msg_id; +} + + + + + diff --git a/retroshare-nogui/src/rpc/rpcserver.h b/retroshare-nogui/src/rpc/rpcserver.h new file mode 100644 index 000000000..341086234 --- /dev/null +++ b/retroshare-nogui/src/rpc/rpcserver.h @@ -0,0 +1,164 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_SERVER_H +#define RS_RPC_SERVER_H + +#include +#include +#include +#include + +#include "util/rsthreads.h" + +// Dividing up MsgIds into components: + +uint8_t getRpcMsgIdSubMsg(uint32_t msg_id); +uint16_t getRpcMsgIdService(uint32_t msg_id); // Middle 16 bits. +uint8_t getRpcMsgIdExtension(uint32_t msg_id); // Top 7 of 8 bits. Bottom Bit is for Request / Response +bool isRpcMsgIdResponse(uint32_t msg_id); + +uint32_t constructMsgId(uint8_t ext, uint16_t service, uint8_t submsg, bool is_response); + +/*** This can be overloaded for plugins + * Also allows a natural seperation of the full interface into sections. + */ + +// The Combination of ChanId & ReqId must be unique for each RPC call. +// This is used as an map index, so failure to make it unique, will lead to lost entries. +class RpcUniqueId +{ + public: + RpcUniqueId():mChanId(0), mReqId(0) {return;} + RpcUniqueId(uint32_t chan_id, uint32_t req_id):mChanId(chan_id), mReqId(req_id) {return;} + uint32_t mChanId; + uint32_t mReqId; +}; + +bool operator<(const RpcUniqueId &a, const RpcUniqueId &b); + +class RpcQueuedMsg +{ +public: + uint32_t mChanId; + uint32_t mMsgId; + uint32_t mReqId; + std::string mMsg; +}; + +class RpcServer; + +class RpcService +{ +public: + RpcService(uint32_t /* serviceId */ ):mRpcServer(NULL) { return; } + virtual void reset(uint32_t /* chan_id */) { return; } + virtual int msgsAccepted(std::list & /* msgIds */) { return 0; } /* not used at the moment */ + virtual int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg) = 0; /* returns 0 - not handled, > 0, accepted */ + virtual int getResponse(uint32_t &chan_id, uint32_t &msgId, uint32_t &req_id, std::string &msg) = 0; /* 0 - not ready, > 0 heres the response */ + + virtual int getEvents(std::list & /* events */) { return 0; } /* 0 = none, optional feature */ + + void setRpcServer(RpcServer *server) {mRpcServer = server; } + RpcServer *getRpcServer() { return mRpcServer; } +private: + RpcServer *mRpcServer; +}; + + +class RpcEventRegister +{ + public: + uint32_t mChanId; + uint32_t mReqId; + uint32_t mEventId; // THIS IS A LOCAL PARAMETER, Service Specific +}; + +/* Implements a Queue for quick implementation of Instant Response Services */ +class RpcQueueService: public RpcService +{ +public: + RpcQueueService(uint32_t serviceId); +virtual void reset(uint32_t chan_id); +virtual int getResponse(uint32_t &chan_id, uint32_t &msg_id, uint32_t &req_id, std::string &msg); +virtual int getEvents(std::list &events); + +protected: + int queueResponse(uint32_t chan_id, uint32_t msgId, uint32_t req_id, const std::string &msg); + +virtual int locked_checkForEvents(uint32_t event, const std::list ®istered, std::list &events); // Overload for functionality. + + int registerForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id); + int deregisterForEvents(uint32_t chan_id, uint32_t req_id, uint32_t event_id); + + int clearEventsForChannel(uint32_t chan_id); + int printEventRegister(std::ostream &out); + +private: + RsMutex mQueueMtx; + + std::map mResponses; + std::map > mEventRegister; +}; + + +/* For Tracking responses */ +class RpcQueuedObj +{ +public: + uint32_t mChanId; + uint32_t mReqId; + RpcService *mService; +}; + + +class RpcMediator; + +class RpcServer +{ + +public: + RpcServer(RpcMediator *med); + int addService(RpcService *service); + int processMsg(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, const std::string &msg); + bool checkPending(); + bool checkEvents(); + + void reset(uint32_t chan_id); + int error(uint32_t chan_id, std::string msg); // pass an error to mediator. + +private: + bool sendQueuedMsgs(std::list &msgs); + int queueRequest_locked(uint32_t chan_id, uint32_t msg_id, uint32_t req_id, RpcService *service); + + RpcMediator *mMediator; + + RsMutex mRpcMtx; + + std::list mRpcQueue; + std::list mAllServices; +}; + + +#endif /* RS_RPC_SERVER_H */ diff --git a/retroshare-nogui/src/rpc/rpcsetup.cc b/retroshare-nogui/src/rpc/rpcsetup.cc new file mode 100644 index 000000000..015d72142 --- /dev/null +++ b/retroshare-nogui/src/rpc/rpcsetup.cc @@ -0,0 +1,64 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rpc/rpcsetup.h" +#include "rpc/rpcserver.h" + +#include "rpc/proto/rpcprotopeers.h" +#include "rpc/proto/rpcprotosystem.h" +#include "rpc/proto/rpcprotochat.h" +#include "rpc/proto/rpcprotosearch.h" +#include "rpc/proto/rpcprotofiles.h" + +#include "rpc/rpcecho.h" + +RpcMediator *CreateRpcSystem(RpcComms *comms, NotifyTxt *notify) +{ + RpcMediator *med = new RpcMediator(comms); + RpcServer *server = new RpcServer(med); + + /* add services */ + RpcProtoPeers *peers = new RpcProtoPeers(1); + server->addService(peers); + + RpcProtoSystem *system = new RpcProtoSystem(1); + server->addService(system); + + RpcProtoChat *chat = new RpcProtoChat(1); + server->addService(chat); + + RpcProtoSearch *search = new RpcProtoSearch(1, notify); + server->addService(search); + + RpcProtoFiles *files = new RpcProtoFiles(1); + server->addService(files); + + /* Finally an Echo Service - which will echo back any unprocesses commands. */ + RpcEcho *echo = new RpcEcho(1); + server->addService(echo); + + med->setRpcServer(server); + + return med; +} + diff --git a/retroshare-nogui/src/rpc/rpcsetup.h b/retroshare-nogui/src/rpc/rpcsetup.h new file mode 100644 index 000000000..b95193f87 --- /dev/null +++ b/retroshare-nogui/src/rpc/rpcsetup.h @@ -0,0 +1,36 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RPC_SETUP_H +#define RPC_SETUP_H + + +#include "rpc/rpc.h" + +class NotifyTxt; + +RpcMediator *CreateRpcSystem(RpcComms *comms, NotifyTxt *notify); + +#endif + diff --git a/retroshare-nogui/src/rpcsystem.h b/retroshare-nogui/src/rpcsystem.h new file mode 100644 index 000000000..dd1ccfc43 --- /dev/null +++ b/retroshare-nogui/src/rpcsystem.h @@ -0,0 +1,64 @@ +/* + * RetroShare External Interface. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RS_RPC_SYSTEM_H +#define RS_RPC_SYSTEM_H + +#include +#include +#include + +class RpcComms +{ +public: + virtual int isOkay() = 0; + virtual int error(uint32_t chan_id, std::string msg) = 0; + + virtual int active_channels(std::list &chan_ids) = 0; + + virtual int recv_ready(uint32_t chan_id) = 0; + virtual int recv(uint32_t chan_id, uint8_t *buffer, int bytes) = 0; + virtual int recv(uint32_t chan_id, std::string &buffer, int bytes) = 0; + + // these make it easier... + virtual int recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes) = 0; + virtual int recv_blocking(uint32_t chan_id, std::string &buffer, int bytes) = 0; + + virtual int send(uint32_t chan_id, uint8_t *buffer, int bytes) = 0; + virtual int send(uint32_t chan_id, const std::string &buffer) = 0; + + virtual int setSleepPeriods(float /* busy */, float /* idle */) { return 0; } +}; + + +class RpcSystem +{ +public: + /* this must be regularly ticked to update the display */ + virtual void reset(uint32_t chan_id) = 0; + virtual int tick() = 0; +}; + + +#endif // RS_RPC_SERVER_H diff --git a/retroshare-nogui/src/ssh/rssshd.cc b/retroshare-nogui/src/ssh/rssshd.cc new file mode 100644 index 000000000..895cc318b --- /dev/null +++ b/retroshare-nogui/src/ssh/rssshd.cc @@ -0,0 +1,915 @@ +/* This is a sample implementation of a libssh based SSH server */ +/* +Copyright 2003-2009 Aris Adamantiadis + +This file is part of the SSH Library + +You are free to copy this file, modify it in any way, consider it being public +domain. This does not apply to the rest of the library though, but it is +allowed to cut-and-paste working code from this file to any license of +program. +The goal is to show the API in action. It's not a reference on how terminal +clients must be made or how a client should react. +*/ + +/***** + * Heavily Modified by Robert Fernie 2012... for retroshare project! + * + */ + + +#include + +#include "ssh/rssshd.h" + +#include + +#define RSSSHD_STATE_NULL 0 +#define RSSSHD_STATE_INIT_OK 1 +#define RSSSHD_STATE_CONNECTED 2 +#define RSSSHD_STATE_ERROR 3 + +RsSshd *rsSshd = NULL; // External Reference Variable. + +// NB: This must be called EARLY before all the threads are launched. +RsSshd *RsSshd::InitRsSshd(const std::string &portStr, const std::string &rsakeyfile) +{ +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + ssh_threads_set_callbacks(ssh_threads_get_pthread()); +#endif + ssh_init(); + + rsSshd = new RsSshd(portStr); + if (rsSshd->init(rsakeyfile)) + { + return rsSshd; + } + + rsSshd = NULL; + return rsSshd; +} + + +RsSshd::RsSshd(std::string portStr) +:mSshMtx("sshMtx"), mPortStr(portStr), mChannel(0) +{ + + mState = RSSSHD_STATE_NULL; + mBindState = 0; + mRpcSystem = NULL; + + mSession = NULL; + + setSleepPeriods(0.01, 0.1); + return; +} + + + +int RsSshd::init(const std::string &pathrsakey) +{ + + mBind=ssh_bind_new(); + + //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); + //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); + + //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); + ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, mPortStr.c_str()); + //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, arg); + //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_HOSTKEY, arg); + ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, pathrsakey.c_str()); + //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); + + mState = RSSSHD_STATE_INIT_OK; + mBindState = 0; + + return 1; +} + + +void RsSshd::run() +{ + /* main loop */ + + /* listen */ + bool sshOk = true; + while(sshOk) + { + std::cerr << "RsSshd::run() starting sshd cycle"; + std::cerr << std::endl; + + if (listenConnect()) + { + std::cerr << "RsSshd::run() success connect => setup mSession"; + std::cerr << std::endl; + + if (setupSession()) + { + std::cerr << "RsSshd::run() setup mSession => interactive"; + std::cerr << std::endl; + + mState = RSSSHD_STATE_CONNECTED; + interactive(); + } + else + { + std::cerr << "RsSshd::run() setup mSession failed"; + std::cerr << std::endl; + } + } + cleanupSession(); +#ifndef WINDOWS_SYS + sleep(5); // have a break; +#else + Sleep(5000); // have a break; +#endif + } +} + + +int RsSshd::listenConnect() +{ + std::cerr << "RsSshd::listenConnect()"; + std::cerr << std::endl; + + if (!mBindState) + { + if(ssh_bind_listen(mBind)<0) + { + printf("Error listening to socket: %s\n",ssh_get_error(mBind)); + return 0; + } + mBindState = 1; + } + else + { + std::cerr << "RsSshd::listenConnect() Already Bound..."; + std::cerr << std::endl; + } + + mSession=ssh_new(); + int r=ssh_bind_accept(mBind,mSession); + if(r==SSH_ERROR) + { + printf("error accepting a connection : %s\n",ssh_get_error(mBind)); + return 0; + } + +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + if (ssh_handle_key_exchange(mSession)) +#else + if (ssh_accept(mSession)) +#endif + { + printf("ssh_handle_key_exchange: %s\n", ssh_get_error(mSession)); + return 0; + } + return 1; +} + + +int RsSshd::setupSession() +{ + std::cerr << "RsSshd::listenConnect()"; + std::cerr << std::endl; + + if (authUser()) + { + std::cerr << "RsSshd::listenConnect() authUser SUCCESS"; + std::cerr << std::endl; + + if (setupChannel()) + { + std::cerr << "RsSshd::listenConnect() setupChannel SUCCESS"; + std::cerr << std::endl; + + if (setupShell()) + { + std::cerr << "RsSshd::listenConnect() setupShell SUCCESS"; + std::cerr << std::endl; + + return 1; + } + } + } + std::cerr << "RsSshd::listenConnect() Failed"; + std::cerr << std::endl; + + return 0; +} + + +int RsSshd::interactive() +{ + std::cerr << "RsSshd::interactive()"; + std::cerr << std::endl; + + doRpcSystem(); + //doEcho(); + return 1; +} + + + +int RsSshd::authUser() +{ + std::cerr << "RsSshd::authUser()"; + std::cerr << std::endl; + + + ssh_message message; + int auth = 0; + + do { + message=ssh_message_get(mSession); + if(!message) + break; + switch(ssh_message_type(message)){ + case SSH_REQUEST_AUTH: + switch(ssh_message_subtype(message)){ + case SSH_AUTH_METHOD_PASSWORD: + printf("User %s wants to auth with pass %s\n", + ssh_message_auth_user(message), + ssh_message_auth_password(message)); + if(auth_password(ssh_message_auth_user(message), + ssh_message_auth_password(message))){ + auth=1; + ssh_message_auth_reply_success(message,0); + break; + } + // not authenticated, send default message + case SSH_AUTH_METHOD_NONE: + default: + ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD); + ssh_message_reply_default(message); + break; + } + break; + default: + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (!auth); + + if(!auth){ + printf("auth error: %s\n",ssh_get_error(mSession)); + ssh_disconnect(mSession); + return 0; + } + + std::cerr << "RsSshd::authuser() Success"; + std::cerr << std::endl; + + return 1; +} + + +int RsSshd::setupChannel() +{ + std::cerr << "RsSshd::setupChannel()"; + std::cerr << std::endl; + + ssh_message message; + + + do { + message=ssh_message_get(mSession); + if(message){ + switch(ssh_message_type(message)){ + case SSH_REQUEST_CHANNEL_OPEN: + if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){ + mChannel=ssh_message_channel_request_open_reply_accept(message); + break; + } + default: + ssh_message_reply_default(message); + } + ssh_message_free(message); + } + } while(message && !mChannel); + if(!mChannel){ + printf("error : %s\n",ssh_get_error(mSession)); + ssh_finalize(); + return 0; + } + + return 1; +} + + +int RsSshd::setupShell() +{ + std::cerr << "RsSshd::setupShell()"; + std::cerr << std::endl; + + int shell = 0; + ssh_message message; + + do { + message=ssh_message_get(mSession); + if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL && + ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){ + shell = 1; + ssh_message_channel_request_reply_success(message); + break; + } + if(!shell){ + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (message && !shell); + + if(!shell){ + printf("error : %s\n",ssh_get_error(mSession)); + return 0; + } + + return 1; +} + +// CLEANUP +int RsSshd::cleanupSession() +{ + std::cerr << "RsSshd::cleanupSession()"; + std::cerr << std::endl; + + ssh_disconnect(mSession); + ssh_free(mSession); + return 1; +} + + +int RsSshd::cleanupAll() +{ + std::cerr << "RsSshd::cleanupAll()"; + std::cerr << std::endl; + + cleanupSession(); + if (mBindState) + { + ssh_bind_free(mBind); + mBindState = 0; + } + ssh_finalize(); + return 1; +} + + + +// Various Operating Modes. +int RsSshd::doEcho() +{ + std::cerr << "RsSshd::doEcho()"; + std::cerr << std::endl; + int i = 0; + char buf[2048]; + + do{ +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + i=ssh_channel_read(mChannel,buf, 2048, 0); +#else + i=channel_read(mChannel,buf, 2048, 0); +#endif + if(i>0) { +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + ssh_channel_write(mChannel, buf, i); + ssh_channel_write(mChannel, buf, i); +#else + channel_write(mChannel, buf, i); + channel_write(mChannel, buf, i); +#endif + if (write(1,buf,i) < 0) { + printf("error writing to buffer\n"); + return 0; + } + } + } while (i>0); + + std::cerr << "RsSshd::doEcho() Finished"; + std::cerr << std::endl; + + return 1; +} + + +int RsSshd::setRpcSystem(RpcSystem *s) +{ + mRpcSystem = s; + return 1; +} + + +#if 0 + +int RsSshd::doTermServer() +{ + std::cerr << "RsSshd::doTermServer()"; + std::cerr << std::endl; + + if (!mTermServer) + { + std::cerr << "RsSshd::doTermServer() ERROR Not Set"; + std::cerr << std::endl; + return 0; + } + + mTermServer->reset(); // clear everything for new user. + + bool okay = true; + while(okay) + { + char buf; +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + int size = ssh_channel_read_nonblocking(mChannel, &buf, 1, 0); +#else + int size = channel_read_nonblocking(mChannel, &buf, 1, 0); +#endif + bool haveInput = (size > 0); + std::string output; + + int rt = mTermServer->tick(haveInput, buf, output); + + if (output.size() > 0) + { +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + ssh_channel_write(mChannel, output.c_str(), output.size()); +#else + channel_write(mChannel, output.c_str(), output.size()); +#endif + } + + if (!haveInput) + { + /* have a little sleep */ + sleep(1); //0000000); // 1/10th sec. + //usleep(10000000); // 1/10th sec. + } + else + { + usleep(10000); // 1/100th sec. + } + + if (rt < 0) + { + okay = false; // exit. + } + } + + std::cerr << "RsSshd::doTermServer() Finished"; + std::cerr << std::endl; + + return 1; +} + +#endif + + +int RsSshd::doRpcSystem() +{ + std::cerr << "RsSshd::doRpcSystem()"; + std::cerr << std::endl; + + if (!mRpcSystem) + { + std::cerr << "RsSshd::doRpcSystem() ERROR Not Set"; + std::cerr << std::endl; + return 0; + } + + uint32_t dummy_chan_id = 1; + mRpcSystem->reset(dummy_chan_id); // clear everything for new user. + + bool okay = true; + while(okay) + { + int rt = mRpcSystem->tick(); + if (rt) + { + // Working - so small sleep, + usleep(mBusyUSleep); + } + else + { + // No work cycle, longer break. + usleep(mIdleUSleep); + } + + if (rt < 0) + { + okay = false; // exit. + } + + if (!isOkay()) + { + okay = false; + } + } + + mRpcSystem->reset(dummy_chan_id); // cleanup old channel items. + + std::cerr << "RsSshd::doRpcSystem() Finished"; + std::cerr << std::endl; + + return 1; +} + +// RpcComms Interface.... +int RsSshd::isOkay() +{ + return (mState == RSSSHD_STATE_CONNECTED); +} + + std::list::iterator it; +int RsSshd::active_channels(std::list &chan_ids) +{ + if (isOkay()) + { + chan_ids.push_back(1); // dummy for now. + } + + return 1; +} + +int RsSshd::error(uint32_t chan_id, std::string msg) +{ + std::cerr << "RsSshd::error(" << msg << ")"; + std::cerr << std::endl; + + mState = RSSSHD_STATE_ERROR; + return 1; +} + + +int RsSshd::recv_ready(uint32_t chan_id) +{ + int bytes = ssh_channel_poll(mChannel, 0); + return bytes; +} + + +int RsSshd::recv(uint32_t chan_id, uint8_t *buffer, int bytes) +{ +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + int size = ssh_channel_read_nonblocking(mChannel, buffer, bytes, 0); +#else + int size = channel_read_nonblocking(mChannel, buffer, bytes, 0); +#endif + return size; +} + + +int RsSshd::recv(uint32_t chan_id, std::string &buffer, int bytes) +{ + char input[bytes]; +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + int size = ssh_channel_read_nonblocking(mChannel, input, bytes, 0); +#else + int size = channel_read_nonblocking(mChannel, input, bytes, 0); +#endif + for(int i = 0; i < size; i++) + { + buffer += input[i]; + } + return size; +} + + +int RsSshd::recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes) +{ +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + int size = ssh_channel_read(mChannel, buffer, bytes, 0); +#else + int size = channel_read(mChannel, buffer, bytes, 0); +#endif + return size; +} + + +int RsSshd::recv_blocking(uint32_t chan_id, std::string &buffer, int bytes) +{ + char input[bytes]; +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + int size = ssh_channel_read(mChannel, input, bytes, 0); +#else + int size = channel_read(mChannel, input, bytes, 0); +#endif + for(int i = 0; i < size; i++) + { + buffer += input[i]; + } + return size; +} + +int RsSshd::send(uint32_t chan_id, uint8_t *buffer, int bytes) +{ +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + ssh_channel_write(mChannel, buffer, bytes); +#else + channel_write(mChannel, buffer, bytes); +#endif + return 1; +} + +int RsSshd::send(uint32_t chan_id, const std::string &buffer) +{ +#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,5,0) + ssh_channel_write(mChannel, buffer.c_str(), buffer.size()); +#else + channel_write(mChannel, buffer.c_str(), buffer.size()); +#endif + return 1; +} + +int RsSshd::setSleepPeriods(float busy, float idle) +{ + mBusyUSleep = busy * 1000000; + mIdleUSleep = idle * 1000000; + return 1; +} + + + +/***********************************************************************************/ + /* PASSWORDS */ +/***********************************************************************************/ + +int RsSshd::auth_password(const char *name, const char *pwd) +{ +#ifdef ALLOW_CLEARPWDS + if (auth_password_basic(name, pwd)) + return 1; +#endif // ALLOW_CLEARPWDS + + if (auth_password_hashed(name, pwd)) + return 1; + return 0; +} + +#define RSSSHD_MIN_PASSWORD 4 +#define RSSSHD_MIN_USERNAME 3 + +#ifdef ALLOW_CLEARPWDS +int RsSshd::adduser(std::string username, std::string password) +{ + if (password.length() < RSSSHD_MIN_PASSWORD) + { + std::cerr << "RsSshd::adduser() Password Too Short"; + return 0; + } + + if (username.length() < RSSSHD_MIN_USERNAME) + { + std::cerr << "RsSshd::adduser() Password Too Short"; + return 0; + } + + std::map::iterator it; + it = mPasswords.find(username); + if (it != mPasswords.end()) + { + std::cerr << "RsSshd::adduser() Warning username already exists"; + } + + mPasswords[username] = password; + + return 1; +} + + +int RsSshd::auth_password_basic(char *name, char *pwd) +{ + std::string username(name); + std::string password(pwd); + + std::map::iterator it; + it = mPasswords.find(username); + if (it == mPasswords.end()) + { + std::cerr << "RsSshd::auth_password() Unknown username"; + return 0; + } + + if (it->second == password) + { + std::cerr << "RsSshd::auth_password() logged in " << username; + return 1; + } + + std::cerr << "RsSshd::auth_password() Invalid pwd for " << username; + return 0; +} +#endif // ALLOW_CLEARPWDS + +//#define RSSSHD_HASH_PWD_LENGTH 40 + +int RsSshd::adduserpwdhash(std::string username, std::string hash) +{ +#if 0 + if (hash.length() != RSSSHD_HASH_PWD_LENGTH) + { + std::cerr << "RsSshd::adduserpwdhash() Hash Wrong Length"; + return 0; + } +#endif + + if (username.length() < RSSSHD_MIN_USERNAME) + { + std::cerr << "RsSshd::adduserpwdhash() Username Too Short"; + return 0; + } + + std::map::iterator it; + it = mPwdHashs.find(username); + if (it != mPwdHashs.end()) + { + std::cerr << "RsSshd::adduser() Warning username already exists"; + } + + mPwdHashs[username] = hash; + + return 1; +} + + +int RsSshd::auth_password_hashed(const char *name, const char *pwd) +{ + std::string username(name); + std::string password(pwd); + + std::map::iterator it; + it = mPwdHashs.find(username); + if (it == mPwdHashs.end()) + { + std::cerr << "RsSshd::auth_password_hashed() Unknown username"; + return 0; + } + + if (CheckPasswordHash(it->second, password)) + { + std::cerr << "RsSshd::auth_password_hashed() logged in " << username; + return 1; + } + + std::cerr << "RsSshd::auth_password_hashed() Invalid pwd for " << username; + return 0; +} + +#include "util/radix64.h" +#include "util/rsrandom.h" +#include + +#define RSSSHD_PWD_SALT_LEN 16 +#define RSSSHD_PWD_MIN_LEN 8 + + +#if 0 +int printHex(const char *data, int len) +{ + for(int i = 0; i < len; i++) + { + fprintf(stderr, "%02x", (uint8_t) data[i]); + } + return 1; +} +#endif + + + +int GenerateSalt(std::string &saltBin) +{ + /* get from random */ + for(int i = 0; i < RSSSHD_PWD_SALT_LEN / 4; i++) + { + uint32_t rnd = RSRandom::random_u32(); + saltBin += ((char *) &rnd)[0]; + saltBin += ((char *) &rnd)[1]; + saltBin += ((char *) &rnd)[2]; + saltBin += ((char *) &rnd)[3]; + } + +#if 0 + std::cerr << "HexSalt: "; + printHex(saltBin.c_str(), saltBin.size()); + std::cerr << std::endl; +#endif + + return 1; +} + +int GeneratePasswordHash(std::string saltBin, std::string password, std::string &pwdHashRadix64) +{ +#if 0 + std::cerr << "GeneratePasswordHash()"; + std::cerr << std::endl; + + std::cerr << "HexSalt: "; + printHex(saltBin.c_str(), saltBin.size()); + std::cerr << std::endl; +#endif + + if (saltBin.size() != RSSSHD_PWD_SALT_LEN) + { + return 0; + } + + if (password.size() < RSSSHD_PWD_MIN_LEN) + { + return 0; + } + + EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + EVP_DigestInit(ctx, EVP_sha256()); + + EVP_DigestUpdate(ctx, saltBin.c_str(), saltBin.size()); + EVP_DigestUpdate(ctx, password.c_str(), password.size()); + + + unsigned char hash[1024]; + unsigned int s = 1024 - RSSSHD_PWD_SALT_LEN; + + for(int i = 0; i < RSSSHD_PWD_SALT_LEN; i++) + { + hash[i] = saltBin[i]; + } + + EVP_DigestFinal(ctx, &(hash[RSSSHD_PWD_SALT_LEN]), &s); + + Radix64::encode((char *)hash, s + RSSSHD_PWD_SALT_LEN, pwdHashRadix64); + +#if 0 + std::cerr << "Salt Length: " << RSSSHD_PWD_SALT_LEN; + std::cerr << std::endl; + std::cerr << "Hash Length: " << s; + std::cerr << std::endl; + std::cerr << "Total Length: " << s + RSSSHD_PWD_SALT_LEN; + std::cerr << std::endl; + + + std::cerr << "Encoded Length: " << pwdHashRadix64.size(); + std::cerr << std::endl; + + std::cerr << "GeneratePasswordHash() Output: " << pwdHashRadix64; + std::cerr << std::endl; +#endif + + return 1; +} + + +int CheckPasswordHash(std::string pwdHashRadix64, std::string password) +{ + char output[1024]; + char *buf = NULL; + size_t len = 1024; + Radix64::decode(pwdHashRadix64, buf, len); + for(unsigned int i = 0; (i < len) && (i < 1024); i++) + { + output[i] = buf[i]; + } + delete []buf; + +#if 0 + std::cerr << "CheckPasswordHash() Input: " << pwdHashRadix64; + std::cerr << std::endl; + std::cerr << "Decode Length: " << len; + std::cerr << std::endl; + std::cerr << "HexDecoded: "; + printHex(output, len); + std::cerr << std::endl; +#endif + + /* first N bytes are SALT */ + EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + EVP_DigestInit(ctx, EVP_sha256()); + + EVP_DigestUpdate(ctx, output, RSSSHD_PWD_SALT_LEN); + EVP_DigestUpdate(ctx, password.c_str(), password.size()); + +#if 0 + std::cerr << "HexSalt: "; + printHex(output, RSSSHD_PWD_SALT_LEN); + std::cerr << std::endl; +#endif + + unsigned char hash[128]; + unsigned int s = 128; + EVP_DigestFinal(ctx, hash, &s); + + /* Final Comparison */ + if (s != len - RSSSHD_PWD_SALT_LEN) + { + std::cerr << "Length Mismatch"; + return 0; + } + + if (0 == strncmp(&(output[RSSSHD_PWD_SALT_LEN]), (char *) hash, s)) + { + return 1; + } + + return 0; +} + + + diff --git a/retroshare-nogui/src/ssh/rssshd.h b/retroshare-nogui/src/ssh/rssshd.h new file mode 100644 index 000000000..4033907c3 --- /dev/null +++ b/retroshare-nogui/src/ssh/rssshd.h @@ -0,0 +1,157 @@ +/* This is a sample implementation of a libssh based SSH server */ +/* +Copyright 2003-2009 Aris Adamantiadis + +This file is part of the SSH Library + +You are free to copy this file, modify it in any way, consider it being public +domain. This does not apply to the rest of the library though, but it is +allowed to cut-and-paste working code from this file to any license of +program. +The goal is to show the API in action. It's not a reference on how terminal +clients must be made or how a client should react. +*/ + +/***** + * Heavily Modified by Robert Fernie 2012... for retroshare project! + * + */ + + +#ifndef RS_SSHD_INTERFACE_H +#define RS_SSHD_INTERFACE_H + +#include +#include + +#include +#include +#include + +// From inside libretroshare.a +#include "util/rsthreads.h" + +#include +#include + +#include "rpcsystem.h" + +#ifndef KEYS_FOLDER +#ifdef _WIN32 +#define KEYS_FOLDER +#else +#define KEYS_FOLDER "/etc/ssh/" +#endif +#endif + + + +/****** + * + * Minimal Options to start with + * + */ + + + +//#define ALLOW_CLEARPWDS 1 + +class RsSshd; +extern RsSshd *rsSshd; + + + // TODO: NB: THIS FN DOES NOT USE A "SLOW" HASH FUNCTION. + // THE FIRST HALF OF THE HASH STRING IS THE SALT +int CheckPasswordHash(std::string pwdHashRadix64, std::string password); +int GeneratePasswordHash(std::string saltBin, std::string password, std::string &pwdHashRadix64); +int GenerateSalt(std::string &saltBin); + +class RsSshd: public RsThread, public RpcComms +{ +public: + +// NB: This must be called EARLY before all the threads are launched. +static RsSshd *InitRsSshd(const std::string &portstr, const std::string &rsakeyfile); + + + // Interface. +int setRpcSystem(RpcSystem *s); +int adduserpwdhash(std::string username, std::string hash); + + // RsThreads Interface. + virtual void run(); /* called once the thread is started */ + + // RsComms Interface. + virtual int isOkay(); + virtual int error(uint32_t chan_id, std::string msg); + + virtual int active_channels(std::list &chan_ids); + virtual int recv_ready(uint32_t chan_id); + + virtual int recv(uint32_t chan_id, uint8_t *buffer, int bytes); + virtual int recv(uint32_t chan_id, std::string &buffer, int bytes); + virtual int recv_blocking(uint32_t chan_id, uint8_t *buffer, int bytes); + virtual int recv_blocking(uint32_t chan_id, std::string &buffer, int bytes); + + virtual int send(uint32_t chan_id, uint8_t *buffer, int bytes); + virtual int send(uint32_t chan_id, const std::string &buffer); + + virtual int setSleepPeriods(float busy, float idle); + +private: + RsSshd(std::string portStr); /* private constructor => so can only create with */ + +int init(const std::string &pathrsakey); + + // High level operations. +int listenConnect(); +int setupSession(); +int interactive(); + + // Lower Level Operations. +int authUser(); +int setupChannel(); +int setupShell(); +int doEcho(); + + // Terminal Handling! +//int doTermServer(); +int doRpcSystem(); + +int cleanupSession(); +int cleanupAll(); + + /* Password Checking */ +int auth_password(const char *name, const char *pwd); +int auth_password_hashed(const char *name, const char *pwd); +#ifdef ALLOW_CLEARPWDS +int auth_password_basic(char *name, char *pwd); +#endif // ALLOW_CLEARPWDS + + // DATA. + + RsMutex mSshMtx; + + uint32_t mBusyUSleep; + uint32_t mIdleUSleep; + + uint32_t mState; + uint32_t mBindState; + + std::string mPortStr; + ssh_session mSession; + ssh_bind mBind; + ssh_channel mChannel; + + RpcSystem *mRpcSystem; + +#ifdef ALLOW_CLEARPWDS + std::map mPasswords; +#endif // ALLOW_CLEARPWDS + std::map mPwdHashs; + +}; + + +#endif + diff --git a/rsctrl/src/Makefile b/rsctrl/src/Makefile new file mode 100644 index 000000000..b6305a374 --- /dev/null +++ b/rsctrl/src/Makefile @@ -0,0 +1,33 @@ + +EXEC = protoc +#PROTO = core.proto peers.proto system.proto chat.proto search.proto files.proto gxs.proto msgs.proto +PROTO = core.proto peers.proto system.proto chat.proto search.proto files.proto + +PROTOPATH = ./definition +#CDESTPATH = ./gencc +CDESTPATH = ../../retroshare-nogui/src/rpc/proto/gencc +PYDESTPATH = ./genpy +#PYDESTPATH = ../../../../github/pyrs/pyrs/proto + +CLIST = $(PROTO:%.proto=%.cc) +CCODE = $(patsubst %.proto,$(CDESTPATH)/%.pb.cc, $(PROTO)) +HCODE = $(patsubst %.proto,$(CDESTPATH)/%.pb.h, $(PROTO)) +PYCODE = $(patsubst %.proto,$(PYDESTPATH)/%_pb2.py, $(PROTO)) + + +all: allc + +allc: $(CCODE) + echo $(CCODE) + +python_proto: $(PYCODE) + echo $(PYCODE) + +$(CDESTPATH)/%.pb.cc : $(PROTOPATH)/%.proto + $(EXEC) --proto_path=$(PROTOPATH) --cpp_out=$(CDESTPATH) $< + +$(PYDESTPATH)/%_pb2.py : $(PROTOPATH)/%.proto + $(EXEC) --proto_path=$(PROTOPATH) --python_out=$(PYDESTPATH) $< + +clean: + -/bin/rm $(CCODE) $(HCODE) $(PYCODE) diff --git a/rsctrl/src/NOTES.txt b/rsctrl/src/NOTES.txt new file mode 100644 index 000000000..a06f35ce2 --- /dev/null +++ b/rsctrl/src/NOTES.txt @@ -0,0 +1,60 @@ + +This document proposes the finer details of how to communicate with RS, +using SSH and protobuf classes. +========================================================================== + +Message Format +==================== + +Protobuf serialisation does not identify Message Types or Message Size. +So we need to have an encapsulation header system + +These headers describe the actual message via a MsgId and MsgSize. +Care must be taken to ensure these IDS are correct, as this is NOT enforced +by protobuf, and will lead to incorrect deserialisation! + +In Each .proto there is a list of MsgIds as an ENUM. + +The protocol message format is as follows: + [HEADER: 16 bytes: 4 x Network Order uint32_t][ VARIABLE LENGTH BODY ] + + [ MAGIC_CODE ] [ MSG_ID ] [ REQ_ID ] [ BODY_SIZE ] [ ..... BODY ..... ] + MagicCode = 0x137f0001. will be incremented for new versions of the protocol. + MsgID = Corresponds to the format of the Body. + ReqID = Generated by Requester, Returned in Response, + make sure its unique. (undefined behaviour for duplicates) + BodySize = Byte Length of Body. + + The Body will consist of a protobuf encoded message. + + +Usage +================= + * Create SSH connection to retroshare-nogui. + * Create Request Message(s), and send over SSH channel - You can send as meny requests as you want. + * They will processed, and responses sent back (potentially in an arbitary order). + +MsgIDs +================= +In Each .proto there is a list of MsgIds as an ENUM. + +0x00 XX XX xx => Reserved for libretroshare Requests. (XX - area, xxxx specific msg) +0x01 XX XX xx => Reserved for libretroshare Responses + +eg. 0x00 (fa bc) [01] -> Request, 0x01 (fa bc) [01/02/03] -> responses + +0x10 YY YY yy => Extensions for project YY (16k), with sub commands yy (256) +0x11 YY YY yy + +... if we run out of YY's will use 0x20 etc. + + +Extensions +================= + +These are welcome and encouraged. +We just need to make sure that MsgIDs don't clash. + + + + diff --git a/rsctrl/src/definition/chat.proto b/rsctrl/src/definition/chat.proto new file mode 100644 index 000000000..12706e3ed --- /dev/null +++ b/rsctrl/src/definition/chat.proto @@ -0,0 +1,243 @@ +package rsctrl.chat; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// Private, Group and Chat Lobby RPC. +// +// OTHER COMMANDS TO ADD? +// Status Strings. +// Invite Friends to Private Lobbies. +// Chat History. +// ??? +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestChatLobbies = 1; + MsgId_RequestCreateLobby = 2; + MsgId_RequestJoinOrLeaveLobby = 3; + MsgId_RequestSetLobbyNickname = 4; + MsgId_RequestRegisterEvents = 5; + MsgId_RequestSendMessage = 6; +} + +enum ResponseMsgIds { + // STANDARD RESPONSES. + MsgId_ResponseChatLobbies = 1; + MsgId_ResponseSetLobbyNickname = 4; + MsgId_ResponseRegisterEvents = 5; + MsgId_ResponseSendMessage = 6; + + // EVENTS + MsgId_EventLobbyInvite = 101; + MsgId_EventChatMessage = 102; +} + +/////////////////////////////////////////////////////////////// +// BUILDING BLOCKS. + +// This is a combination of ChatLobbyInfo & PublicChatLobbyRecord. +// Which seem very similar?? + +enum LobbyPrivacyLevel { + PRIVACY_PRIVATE = 1; + PRIVACY_PUBLIC = 2; +} + +enum ChatType { + TYPE_PRIVATE = 1; + TYPE_LOBBY = 2; + TYPE_GROUP = 3; +} + +message ChatLobbyInfo { + required string lobby_id = 1; + required string lobby_topic = 2; + required string lobby_name = 3; + + required string lobby_nickname = 4; // empty for none set. + + enum LobbyState { + LOBBYSTATE_JOINED = 1; + LOBBYSTATE_INVITED = 2; + LOBBYSTATE_PUBLIC = 3; + } + + required LobbyPrivacyLevel privacy_level = 5; + required LobbyState lobby_state = 6; + + required uint32 no_peers = 7; + required uint32 last_report_time = 8; + required uint32 last_activity = 9; + + repeated string participating_friends = 10; // SSL_IDS? + repeated string nicknames = 11; +} + + +message ChatId { + + required ChatType chat_type = 1; + required string chat_id = 2; + +} + +message ChatMessage { + + required ChatId id = 1; + required string msg = 2; + + optional string peer_nickname = 3; + optional uint32 chat_flags = 4; + + optional uint32 send_time = 5; + optional uint32 recv_time = 6; + +} + + +// RESPONSE: ResponseChatLobbies +// This is a generic Response - used often. +// lobbies, will contain a list of affected / requested Lobbies. +message ResponseChatLobbies { + + required rsctrl.core.Status status = 1; + repeated ChatLobbyInfo lobbies = 2; +} + + + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestChatLobbies +message RequestChatLobbies { + + enum LobbySet { + LOBBYSET_ALL = 1; + LOBBYSET_JOINED = 2; + LOBBYSET_INVITED = 3; + LOBBYSET_PUBLIC = 4; + } + + required LobbySet lobby_set = 1; + +} + +// RESPONSE: ResponseChatLobbies + +/////////////////////////////////////////////////////////////// + + +// REQUEST: RequestCreateLobby +message RequestCreateLobby { + + required string lobby_name = 1; + required string lobby_topic = 2; + + required LobbyPrivacyLevel privacy_level = 4; + + repeated string invited_friends = 3; // SSL_IDS +} + +// RESPONSE: ResponseChatLobbies + +/////////////////////////////////////////////////////////////// + +// Accept / Deny Invite, Join / Leave Lobby (these can be combined?) + +// REQUEST: RequestJoinOrLeaveLobby +message RequestJoinOrLeaveLobby { + + enum LobbyAction { + JOIN_OR_ACCEPT = 1; + LEAVE_OR_DENY = 2; + } + + required string lobby_id = 1; + required LobbyAction action = 2; +} + +// RESPONSE: ResponseChatLobbies + +/////////////////////////////////////////////////////////////// + +// Set Nickname. +// Get is done via requesting ChatLobby Info. +// Empty lobby_ids => default Nickname. + +// REQUEST: RequestSetLobbyNickname +message RequestSetLobbyNickname { + required string nickname = 1; + repeated string lobby_ids = 2; +} + +// RESPONSE: ResponseSetLobbyNickname +// Didnt think the whole Lobby status was necessary. +message ResponseSetLobbyNickname { + required rsctrl.core.Status status = 1; +} + + +/////////////////////////////////////////////////////////////// + +// Request Chat Events. +// This is done by registering for events. + +// REQUEST: RequestRegisterEvents +message RequestRegisterEvents { + + enum RegisterAction { + REGISTER = 1; + DEREGISTER = 2; + } + + required RegisterAction action = 1; +} + +// RESPONSE: ResponseRegisterEvents +message ResponseRegisterEvents { + required rsctrl.core.Status status = 1; +} + +// RESPONSE: EventLobbyInvite +message EventLobbyInvite { + required ChatLobbyInfo lobby = 1; +} + +// RESPONSE: EventChatMessage +message EventChatMessage { + required ChatMessage msg = 1; +} + +/////////////////////////////////////////////////////////////// +// Send Message. + +// REQUEST: RequestSendMessage +message RequestSendMessage { + required ChatMessage msg = 1; +} + +// RESPONSE: ResponseSendMessage +message ResponseSendMessage { + required rsctrl.core.Status status = 1; +} + +/////////////////////////////////////////////////////////////// +//// Chat History. +//// THIS IS NOT IMPLEMENTED YET, DONT USE. +// +//// REQUEST: RequestChatHistory +//message RequestChatHistory { +// required ChatId id = 1; /* lobby or chat, group id */ +// required bool incoming = 2; +//} +// +//// RESPONSE: ResponseChatHistory +//message ResponseChatHistory { +// required rsctrl.core.Status status = 1; +// repeated ChatMessage msg = 2; +//} +// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + diff --git a/rsctrl/src/definition/core.proto b/rsctrl/src/definition/core.proto new file mode 100644 index 000000000..69443af5d --- /dev/null +++ b/rsctrl/src/definition/core.proto @@ -0,0 +1,151 @@ +package rsctrl.core; + +/////////////////////////////////////////////////////////////// +// These are basic Messages, which are used as building blocks +// throughout the rest of the interface. +// They should not be sent RAW, but should be wrapped in another msg. +/////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////// +// Expected PackageIds. + +enum ExtensionId { CORE = 0; } + +enum PackageId { + PEERS = 1; + SYSTEM = 2; + CHAT = 3; + SEARCH = 4; + FILES = 5; + // BELOW HERE IS STILL BEING DESIGNED. + //MSGS = 5; + //TRANSFER = 6; + + // THEORETICAL ONES. + GXS = 1000; +} + + +/////////////////////////////////////////////////////////////// +// Basic Status Response, should be in all responses + +message Status { + enum StatusCode { + FAILED = 0; + NO_IMPL_YET = 1; + INVALID_QUERY = 2; + PARTIAL_SUCCESS = 3; + SUCCESS = 4; + READMSG = 5; + } + + required StatusCode code = 1; + optional string msg = 2; +} + +/////////////////////////////////////////////////////////////// + +message IpAddr { + required string addr = 1 [default = ""]; + required uint32 port = 2 [default = 0]; // must be 16 bit, 0 for unknown. +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +// Peer structures, mainly rsctrl.peers related. + +message Location { + + enum StateFlags { // ORd together... + ONLINE = 1; + CONNECTED = 2; + UNREACHABLE = 4; + } + + required string ssl_id = 1; + required string location = 2; + + required IpAddr localaddr = 3; + required IpAddr extaddr = 4; + + required uint32 state = 5; // Not an ENUM as ORd together. +} + +message Person { + + enum Relationship { + FRIEND = 1; + FRIEND_OF_MANY_FRIENDS = 2; // 3+ at the moment. + FRIEND_OF_FRIENDS = 3; // 1 or 2. + UNKNOWN = 4; + } + + required string gpg_id = 1; + required string name = 2; + required Relationship relation = 3; + + repeated Location locations = 4; +} + +/////////////////////////////////////////////////////////////// +// File structures, mainly rsctrl.files related. + +message File { + required string name = 1; + required string hash = 2; + required uint64 size = 3; + + // THINK WE DONT WANT THESE HERE... + // BETTER TO KEEP File simple. + //optional string path = 4; + //optional string avail = 5; +} + +message Dir { + required string name = 1; + required string path = 2; + + repeated Dir subdirs = 3; + repeated File files = 4; +} + + +/////////////////////////////////////////////////////////////// +// System Status + +message SystemStatus { + enum NetCode { + BAD_UNKNOWN = 0; + BAD_OFFLINE = 1; + BAD_NATSYM = 2; + BAD_NODHT_NAT = 3; + WARNING_RESTART = 4; + WARNING_NATTED = 5; + WARNING_NODHT = 6; + GOOD = 7; + ADV_FORWARD = 8; + } + + required NetCode net_status = 1; + optional string msg = 2; +} + + +/////////////////////////////////////////////////////////////// +// Bandwidth Measurements. + +message Bandwidth { + required float up = 1; // kB/s + required float down = 2; // kB/s + optional string name = 3; // e.g. DHT, UDP, TCP, Stun, or Total. +} + +message BandwidthSet { + repeated Bandwidth bandwidths = 1; +} + + + +/////////////////////////////////////////////////////////////// + + diff --git a/rsctrl/src/definition/files.proto b/rsctrl/src/definition/files.proto new file mode 100644 index 000000000..5546c2efc --- /dev/null +++ b/rsctrl/src/definition/files.proto @@ -0,0 +1,117 @@ +package rsctrl.files; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// List Transfers. +// Control Transfers. +// +// TODO: +// Share Directories. +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestTransferList = 1; + MsgId_RequestControlDownload = 2; +} + +enum ResponseMsgIds { + MsgId_ResponseTransferList = 1; + MsgId_ResponseControlDownload = 2; +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + +// Building Blocks + +enum Direction { + DIRECTION_UPLOAD = 1; + DIRECTION_DOWNLOAD = 2; +} + +message FileTransfer { + + required rsctrl.core.File file = 1; + required Direction direction = 2; + required float fraction = 3; + required float rate_kBs = 4; +} + +/////////////////////////////////////////////////////////////// +// Transfer List. + +// REQUEST: RequestTransferList +message RequestTransferList { + required Direction direction = 1; +} + +// RESPONSE: ResponseTransferList +message ResponseTransferList { + + required rsctrl.core.Status status = 1; + repeated FileTransfer transfers = 2; + +} + +/////////////////////////////////////////////////////////////// +// Download. + +// REQUEST: RequestControlDownload +// START requires name, hash & size. +// other actions only require file hash. +message RequestControlDownload { + + enum Action { + ACTION_START = 1; // start download. + ACTION_CONTINUE = 2; // move to top of queue. + ACTION_WAIT = 3; // send to bottom of queue. + ACTION_PAUSE = 4; // hold indefinitely. + ACTION_RESTART = 5; // end pause, restart download. + ACTION_CHECK = 6; // force check. + ACTION_CANCEL = 7; // remove permenantly. + } + + required rsctrl.core.File file = 1; + required Action action = 2; + +} + +// RESPONSE: ResponseControlDownload +message ResponseControlDownload { + required rsctrl.core.Status status = 1; +} + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +// SHARED FILES +// THIS STUFF IS NOT FINISHED YET! +// +//// REQUEST: RequestListShares +//message RequestListShares { +// +// required uint32 depth = 1; // HOW Many Directories to drill down. +// repeated string ShareLocation = 2; +//} +// +//message ShareLocation { +// required string ssl_id = 1; +// required string path = 2; +//} +// +// +// +//// REQUEST: RequestChangeShares +// +//// REQUEST: RequestLiCloseSearch +//// REQUEST: RequestCloseSearch +// + + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + diff --git a/rsctrl/src/definition/gxs.proto b/rsctrl/src/definition/gxs.proto new file mode 100644 index 000000000..57bcd5a0f --- /dev/null +++ b/rsctrl/src/definition/gxs.proto @@ -0,0 +1,287 @@ +package rsctrl.gxs; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// Base Messages for GXS Interface. +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestPeers = 1; + MsgId_RequestAddPeer = 2; + MsgId_RequestModifyPeer = 3; +} + +enum ResponseMsgIds { + MsgId_ResponsePeerList = 1; + MsgId_ResponseAddPeer = 2; + MsgId_ResponseModifyPeer = 3; +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + +// BASE DATA TYPES + +message Service { + // + required uint32 service_id = 1; + optional string service_name = 2; +} + +message GroupMeta { + + // FLAGS as ENUMs. + enum GroupFlags { + GF_FLAG1 = 1; + GF_FLAG2 = 2; + GF_FLAG3 = 4; + GF_FLAG4 = 8; + } + + enum SignFlags { + SF_FLAG1 = 1; + SF_FLAG2 = 2; + } + + enum SubscribeFlags { + SUBF_FLAG1 = 1; + SUBF_FLAG2 = 2; + } + + enum StatusFlags { + STATF_FLAG1 = 1; + STATF_FLAG2 = 2; + } + + // THIS IS FIXED: From NETWORK. + required string group_id = 1; + required string group_name = 2; + required uint32 group_flags = 3; + required uint32 sign_flags = 4; + + required uint32 publish_ts = 5; + optional string author_id = 6; + + // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. + + required uint32 subscribe_flags = 7; + required uint32 group_status = 8; + + optional string service_string = 9; + + optional uint32 pop = 10; // USED? + optional uint32 msg_count = 11; // ??? + optional int32 last_post = 12; // ??? +} + + +message GroupGenericData { + required GroupMeta meta = 1; + required string encoded_data = 2; +} + + +message MsgMeta { + + // FLAGS as ENUMs. + enum GroupFlags { + GF_FLAG1 = 1; + GF_FLAG2 = 2; + GF_FLAG3 = 4; + GF_FLAG4 = 8; + } + + enum SignFlags { + SF_FLAG1 = 1; + SF_FLAG2 = 2; + } + + enum SubscribeFlags { + SUBF_FLAG1 = 1; + SUBF_FLAG2 = 2; + } + + enum StatusFlags { + STATF_FLAG1 = 1; + STATF_FLAG2 = 2; + } + + // THIS IS FIXED: From NETWORK. + required string group_id = 1; + required string msg_id = 2; + + required string thread_id = 3; + required uint32 parent_id = 4; + required uint32 origmsg_id = 5; + + optional string author_id = 6; + + required uint32 publish_ts = 7; + required uint32 msg_name = 8; + + required uint32 msg_flags = 9; + + // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. + + required uint32 msg_status = 10; + required uint32 child_ts = 11; + optional string service_string = 12; +} + +message MsgGenericData { + required MsgMeta meta = 1; + required string encoded_data = 2; +} + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + +message Filter { + required uint32 options = 1; + + optional uint32 status_filter = 2; + optional uint32 status_mask = 3; + + optional uint32 req_type = 4; + + optional uint32 subscribe_filter = 5; + + optional int32 before = 6; + optional int32 after = 7; +} + +message MsgSet { + required string group_id = 1; + repeated string msg_id = 2; +} + +message GroupMsgSet { + repeated MsgSet groups = 1; +} + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestGroupInfo +message RequestGroupInfo { + + required Service service = 1; + + required uint32 ans_type = 2; + required Filter options = 3; + repeated string group_ids = 4; +} + + +// RESPONSE: ResponseGroupList +message ResponseGroupList { + + required rsctrl.core.Status status = 1; + + required Service service = 2; + repeated string group_ids = 3; +} + + +// RESPONSE: ResponseGroupMeta +message ResponseGroupMeta { + + required rsctrl.core.Status status = 1; + + required Service service = 2; + repeated GroupMeta meta = 3; +} + + +// RESPONSE: ResponseGroupData +message ResponseGroupData { + + required rsctrl.core.Status status = 1; + + required Service service = 2; + repeated GroupGenericData data = 3; +} + + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestMsgInfo +message RequestMsgInfo { + + required Service service = 1; + + required uint32 ans_type = 2; + required Filter options = 3; + repeated GroupMsgSet msgs = 4; +} + +// REQUEST: RequestMsgRelatedInfo +message RequestMsgRelatedInfo { + + required Service service = 1; + + required uint32 ans_type = 2; + required Filter options = 3; + repeated GroupMsgSet msgs = 4; +} + +// RESPONSE: ResponseMsgList +message ResponseMsgList { + + required rsctrl.core.Status status = 1; + + required Service service = 2; + repeated GroupMsgSet msgs = 3; +} + +// RESPONSE: ResponseMsgMeta +message ResponseMsgMeta { + + required rsctrl.core.Status status = 1; + + required Service service = 2; + repeated MsgMeta meta = 3; +} + +// RESPONSE: ResponseMsgData +message ResponseMsgData { + + required rsctrl.core.Status status = 1; + + required Service service = 2; + repeated MsgGenericData data = 3; +} + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + + +// REQUEST: RequestCreateGroup +message RequestCreateGroup { + + required Service service = 1; + repeated GroupGenericData data = 2; +} + + +// RESPONSE: ResponseMsgMeta +// As defined above. + + +// REQUEST: RequestCreateMsg +message RequestCreateMsg { + + required Service service = 1; + repeated MsgGenericData data = 2; +} + +// RESPONSE: ResponseMsgMeta +// As defined above. + + + + diff --git a/rsctrl/src/definition/msgs.proto b/rsctrl/src/definition/msgs.proto new file mode 100644 index 000000000..e011dfb33 --- /dev/null +++ b/rsctrl/src/definition/msgs.proto @@ -0,0 +1,108 @@ +package rsctrl.msgs; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// Access, and Control your Friends / Peers and related Settings. +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestPeers = 1; + MsgId_RequestAddPeer = 2; + MsgId_RequestModifyPeer = 3; +} + +enum ResponseMsgIds { + MsgId_ResponsePeerList = 1; + MsgId_ResponseAddPeer = 2; + MsgId_ResponseModifyPeer = 3; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestPeers +message RequestPeers { + + // About Who? + enum SetOption { + OWNID = 1; + LISTED = 2; + ONLINE = 3; + FRIENDS = 4; + VALID = 5; + SIGNED = 6; + ALL = 7; + } + + // What do you want? + enum InfoOption { + NAMEONLY = 1; + BASIC = 2; + LOCATION = 3; + ALLINFO = 4; + } + + required SetOption set = 1; + required InfoOption info = 2; + repeated string gpg_ids = 3; +} + + +// RESPONSE: ResponsePeerList +message ResponsePeerList { + required rsctrl.core.Status status = 1; + repeated rsctrl.core.Person peers = 2; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestAddPeer +message RequestAddPeer { + + enum AddCmd { + NOOP = 0; // No op. + ADD = 1; // Add existing from gpg_id. + REMOVE = 2; // Remove existing from gpg_id. + IMPORT = 3; // Import from cert, with gpg_id. + EXAMINE = 4; // Examine cert, but no action. + } + + required string gpg_id = 1; + required AddCmd cmd = 2; + optional string cert = 3; +} + +// RESPONSE: ResponseAddPeer +message ResponseAddPeer { + required rsctrl.core.Status status = 1; + repeated rsctrl.core.Person peers = 2; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestModifyPeer +message RequestModifyPeer { + + enum ModCmd { + NOOP = 0; + ADDRESS = 1; + DYNDNS = 2; + //SOMETHING_ELSE = 0x0000010; + //SOMETHING_ELSE = 0x0000020; + //SOMETHING_ELSE = 0x0000040; + //SOMETHING_ELSE = 0x0000080; + } + + required ModCmd cmd = 1; + //required int64 cmd = 1; // Could we OR the Cmds together? + repeated rsctrl.core.Person peers = 2; +} + +// RESPONSE: ResponseModifyPeer +message ResponseModifyPeer { + required rsctrl.core.Status status = 1; + repeated rsctrl.core.Person peers = 2; +} + +/////////////////////////////////////////////////////////////// + diff --git a/rsctrl/src/definition/peers.proto b/rsctrl/src/definition/peers.proto new file mode 100644 index 000000000..8e27ae8f8 --- /dev/null +++ b/rsctrl/src/definition/peers.proto @@ -0,0 +1,108 @@ +package rsctrl.peers; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// Access, and Control your Friends / Peers and related Settings. +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestPeers = 1; + MsgId_RequestAddPeer = 2; + MsgId_RequestModifyPeer = 3; +} + +enum ResponseMsgIds { + MsgId_ResponsePeerList = 1; + MsgId_ResponseAddPeer = 2; + MsgId_ResponseModifyPeer = 3; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestPeers +message RequestPeers { + + // About Who? + enum SetOption { + OWNID = 1; + LISTED = 2; + CONNECTED = 3; + FRIENDS = 4; + VALID = 5; + SIGNED = 6; + ALL = 7; + } + + // What do you want? + enum InfoOption { + NAMEONLY = 1; + BASIC = 2; + LOCATION = 3; + ALLINFO = 4; + } + + required SetOption set = 1; + required InfoOption info = 2; + repeated string gpg_ids = 3; +} + + +// RESPONSE: ResponsePeerList +message ResponsePeerList { + required rsctrl.core.Status status = 1; + repeated rsctrl.core.Person peers = 2; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestAddPeer +message RequestAddPeer { + + enum AddCmd { + NOOP = 0; // No op. + ADD = 1; // Add existing from gpg_id. + REMOVE = 2; // Remove existing from gpg_id. + IMPORT = 3; // Import from cert, with gpg_id. + EXAMINE = 4; // Examine cert, but no action. + } + + required string gpg_id = 1; + required AddCmd cmd = 2; + optional string cert = 3; +} + +// RESPONSE: ResponseAddPeer +message ResponseAddPeer { + required rsctrl.core.Status status = 1; + repeated rsctrl.core.Person peers = 2; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestModifyPeer +message RequestModifyPeer { + + enum ModCmd { + NOOP = 0; + ADDRESS = 1; + DYNDNS = 2; + //SOMETHING_ELSE = 0x0000010; + //SOMETHING_ELSE = 0x0000020; + //SOMETHING_ELSE = 0x0000040; + //SOMETHING_ELSE = 0x0000080; + } + + required ModCmd cmd = 1; + //required int64 cmd = 1; // Could we OR the Cmds together? + repeated rsctrl.core.Person peers = 2; +} + +// RESPONSE: ResponseModifyPeer +message ResponseModifyPeer { + required rsctrl.core.Status status = 1; + repeated rsctrl.core.Person peers = 2; +} + +/////////////////////////////////////////////////////////////// + diff --git a/rsctrl/src/definition/search.proto b/rsctrl/src/definition/search.proto new file mode 100644 index 000000000..6aecdb49f --- /dev/null +++ b/rsctrl/src/definition/search.proto @@ -0,0 +1,120 @@ +package rsctrl.search; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// Searches +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestBasicSearch = 1; + //MsgId_RequestAdvSearch = 2; // NOT IMPLEMENTED YET. + MsgId_RequestCloseSearch = 3; + MsgId_RequestListSearches = 4; + MsgId_RequestSearchResults = 5; +} + +enum ResponseMsgIds { + MsgId_ResponseSearchIds = 1; + MsgId_ResponseSearchResults = 5; +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +// Building Block +message SearchHit { + + enum LocFlag { + LOCAL = 1; // We Have it. + FRIEND = 2; // Browsable + NETWORK = 4; // Network. + } + + required rsctrl.core.File file = 1; + required uint32 loc = 2; // OR of LocFlag so uint field + required uint32 no_hits = 3; // NOT USED YET. + +} + +message SearchSet { + + required uint32 search_id = 1; + repeated SearchHit hits = 2; + +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +// SEARCH (start). + +// REQUEST: RequestBasicSearch +message RequestBasicSearch { + + repeated string terms = 1; +} + +// REQUEST: RequestAdvSearch +message RequestAdvSearch { + + repeated string terms = 1; +} + + +// RESPONSE: ResponseSearchIds +message ResponseSearchIds { + + required rsctrl.core.Status status = 1; + repeated uint32 search_id = 2; +} + + +/////////////////////////////////////////////////////////////// +// SEARCH (cancel) + +// REQUEST: RequestCloseSearch +message RequestCloseSearch { + + required uint32 search_id = 1; +} + + +// RESPONSE: ResponseSearchIds +// As before. + +/////////////////////////////////////////////////////////////// +// SEARCH (list) + +// REQUEST: RequestListSearches +message RequestListSearches { + // Nothing here. +} + +// RESPONSE: ResponseSearchIds +// As before. + +/////////////////////////////////////////////////////////////// +// SEARCH (list) + + +// REQUEST: RequestSearchResults +// Empty search_ids => all results. +message RequestSearchResults { + + repeated uint32 search_ids = 2; + +} + +// RESPONSE: ResponseSearchResults +message ResponseSearchResults { + + required rsctrl.core.Status status = 1; + repeated SearchSet searches = 2; +} + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + diff --git a/rsctrl/src/definition/system.proto b/rsctrl/src/definition/system.proto new file mode 100644 index 000000000..e24e42b29 --- /dev/null +++ b/rsctrl/src/definition/system.proto @@ -0,0 +1,79 @@ +package rsctrl.system; + +import "core.proto"; + +/////////////////////////////////////////////////////////////// +// Configuration and Stats. +/////////////////////////////////////////////////////////////// + +enum RequestMsgIds { + MsgId_RequestSystemStatus = 1; + MsgId_RequestSystemQuit = 2; +} + +enum ResponseMsgIds { + MsgId_ResponseSystemStatus = 1; + MsgId_ResponseSystemQuit = 2; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestSystemStatus +message RequestSystemStatus { + // Nothing here? +} + +// RESPONSE: ResponseSystemStatus +message ResponseSystemStatus { + + enum NetCode { + BAD_UNKNOWN = 0; + BAD_OFFLINE = 1; + BAD_NATSYM = 2; + BAD_NODHT_NAT = 3; + WARNING_RESTART = 4; + WARNING_NATTED = 5; + WARNING_NODHT = 6; + GOOD = 7; + ADV_FORWARD = 8; + } + + // Status of response. + required rsctrl.core.Status status = 1; + + // Peers. + required uint32 no_peers = 2; + required uint32 no_connected = 3; + + // Basic Network Information. + required NetCode net_status = 4; + + required rsctrl.core.Bandwidth bw_total = 5; +} + +/////////////////////////////////////////////////////////////// + +// REQUEST: RequestSystemQuit +message RequestSystemQuit { + + enum QuitCode { + CLOSE_CHANNEL = 1; + SHUTDOWN_RS = 2; // NOT RECOMMENDED (but some people might like it) + } + + required QuitCode quit_code = 1; +} + +// RESPONSE: ResponseSystemQuit +// Effect potentially immediate (with loss of connection) - only expect a response error. +// Shutdown takes longer - so you should get a response. +message ResponseSystemQuit { + + // Status of response. + required rsctrl.core.Status status = 1; +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + diff --git a/supportlibs/pegmarkdown/GLibFacade.c b/supportlibs/pegmarkdown/GLibFacade.c new file mode 100644 index 000000000..f60c1443b --- /dev/null +++ b/supportlibs/pegmarkdown/GLibFacade.c @@ -0,0 +1,208 @@ +/* + * GLibFacade.c + * MultiMarkdown + * + * Created by Daniel Jalkut on 7/26/11. + * Modified by Fletcher T. Penney on 9/15/11. + * Modified by Dan Lowe on 1/3/12. + * Copyright 2011 __MyCompanyName__. All rights reserved. + */ + +#include "GLibFacade.h" + +#include +#include +#include +#include + +/* + * The following section came from: + * + * http://lists-archives.org/mingw-users/12649-asprintf-missing-vsnprintf- + * behaving-differently-and-_vsncprintf-undefined.html + * + * and + * + * http://groups.google.com/group/jansson-users/browse_thread/thread/ + * 76a88d63d9519978/041a7d0570de2d48?lnk=raot + */ + +/* Solaris and Windows do not provide vasprintf() or asprintf(). */ +#if defined(__WIN32) || (defined(__SVR4) && defined(__sun)) +int vasprintf( char **sptr, char *fmt, va_list argv ) +{ + int wanted = vsnprintf( *sptr = NULL, 0, fmt, argv ); + if( (wanted > 0) && ((*sptr = malloc( 1 + wanted )) != NULL) ) + return vsprintf( *sptr, fmt, argv ); + + return wanted; +} + +int asprintf( char **sptr, char *fmt, ... ) +{ + int retval; + va_list argv; + va_start( argv, fmt ); + retval = vasprintf( sptr, fmt, argv ); + va_end( argv ); + return retval; +} +#endif + + +/* GString */ + +#define kStringBufferStartingSize 1024 +#define kStringBufferGrowthMultiplier 2 + +GString* g_string_new(char *startingString) +{ + GString* newString = malloc(sizeof(GString)); + + if (startingString == NULL) startingString = ""; + + size_t startingBufferSize = kStringBufferStartingSize; + size_t startingStringSize = strlen(startingString); + while (startingBufferSize < (startingStringSize + 1)) + { + startingBufferSize *= kStringBufferGrowthMultiplier; + } + + newString->str = malloc(startingBufferSize); + newString->currentStringBufferSize = startingBufferSize; + strncpy(newString->str, startingString, startingStringSize); + newString->str[startingStringSize] = '\0'; + newString->currentStringLength = startingStringSize; + + return newString; +} + +char* g_string_free(GString* ripString, bool freeCharacterData) +{ + char* returnedString = ripString->str; + if (freeCharacterData) + { + if (ripString->str != NULL) + { + free(ripString->str); + } + returnedString = NULL; + } + + free(ripString); + + return returnedString; +} + +static void ensureStringBufferCanHold(GString* baseString, size_t newStringSize) +{ + size_t newBufferSizeNeeded = newStringSize + 1; + if (newBufferSizeNeeded > baseString->currentStringBufferSize) + { + size_t newBufferSize = baseString->currentStringBufferSize; + + while (newBufferSizeNeeded > newBufferSize) + { + newBufferSize *= kStringBufferGrowthMultiplier; + } + + baseString->str = realloc(baseString->str, newBufferSize); + baseString->currentStringBufferSize = newBufferSize; + } +} + +void g_string_append(GString* baseString, char* appendedString) +{ + if ((appendedString != NULL) && (strlen(appendedString) > 0)) + { + size_t appendedStringLength = strlen(appendedString); + size_t newStringLength = baseString->currentStringLength + appendedStringLength; + ensureStringBufferCanHold(baseString, newStringLength); + + /* We already know where the current string ends, so pass that as the starting address for strncat */ + strncat(baseString->str + baseString->currentStringLength, appendedString, appendedStringLength); + baseString->currentStringLength = newStringLength; + } +} + +void g_string_append_c(GString* baseString, char appendedCharacter) +{ + size_t newSizeNeeded = baseString->currentStringLength + 1; + ensureStringBufferCanHold(baseString, newSizeNeeded); + + baseString->str[baseString->currentStringLength] = appendedCharacter; + baseString->currentStringLength++; + baseString->str[baseString->currentStringLength] = '\0'; +} + +void g_string_append_printf(GString* baseString, char* format, ...) +{ + va_list args; + va_start(args, format); + + char* formattedString = NULL; + vasprintf(&formattedString, format, args); + if (formattedString != NULL) + { + g_string_append(baseString, formattedString); + free(formattedString); + } +} + +void g_string_prepend(GString* baseString, char* prependedString) +{ + if ((prependedString != NULL) && (strlen(prependedString) > 0)) + { + size_t prependedStringLength = strlen(prependedString); + size_t newStringLength = baseString->currentStringLength + prependedStringLength; + ensureStringBufferCanHold(baseString, newStringLength); + + memmove(baseString->str + prependedStringLength, baseString->str, baseString->currentStringLength); + strncpy(baseString->str, prependedString, prependedStringLength); + baseString->currentStringLength = newStringLength; + baseString->str[baseString->currentStringLength] = '\0'; + } +} + +/* GSList */ + +void g_slist_free(GSList* ripList) +{ + GSList* thisListItem = ripList; + while (thisListItem != NULL) + { + GSList* nextItem = thisListItem->next; + + /* I guess we don't release the data? Non-retained memory management is hard... let's figure it out later. */ + free(thisListItem); + + thisListItem = nextItem; + } +} + +/* Currently only used for markdown_output.c endnotes printing */ +GSList* g_slist_reverse(GSList* theList) +{ + GSList* lastNodeSeen = NULL; + + /* Iterate the list items, tacking them on to our new reversed List as we find them */ + GSList* listWalker = theList; + while (listWalker != NULL) + { + GSList* nextNode = listWalker->next; + listWalker->next = lastNodeSeen; + lastNodeSeen = listWalker; + listWalker = nextNode; + } + + return lastNodeSeen; +} + +GSList* g_slist_prepend(GSList* targetElement, void* newElementData) +{ + GSList* newElement = malloc(sizeof(GSList)); + newElement->data = newElementData; + newElement->next = targetElement; + return newElement; +} + diff --git a/supportlibs/pegmarkdown/GLibFacade.h b/supportlibs/pegmarkdown/GLibFacade.h new file mode 100644 index 000000000..30651ac54 --- /dev/null +++ b/supportlibs/pegmarkdown/GLibFacade.h @@ -0,0 +1,67 @@ +/* + * GLibFacade.h + * MultiMarkdown + * + * Created by Daniel Jalkut on 7/26/11. + * Copyright 2011 __MyCompanyName__. All rights reserved. + */ + +#ifndef __MARKDOWN_GLIB_FACADE__ +#define __MARKDOWN_GLIB_FACADE__ + +/* peg_markdown uses the link symbol for its own purposes */ +#define link MARKDOWN_LINK_IGNORED +#include +#undef link + +#include +#include + +typedef int gboolean; +typedef char gchar; + +/* This style of bool is used in shared source code */ +#define FALSE false +#define TRUE true + +/* WE implement minimal mirror implementations of GLib's GString and GSList + * sufficient to cover the functionality required by MultiMarkdown. + * + * NOTE: THese are 100% clean, from-scratch implementations using only the + * GLib function prototype as guide for behavior. + */ + +typedef struct +{ + /* Current UTF8 byte stream this string represents */ + char* str; + + /* Where in the str buffer will we add new characters */ + /* or append new strings? */ + int currentStringBufferSize; + int currentStringLength; +} GString; + +GString* g_string_new(char *startingString); +char* g_string_free(GString* ripString, bool freeCharacterData); + +void g_string_append_c(GString* baseString, char appendedCharacter); +void g_string_append(GString* baseString, char *appendedString); + +void g_string_prepend(GString* baseString, char* prependedString); + +void g_string_append_printf(GString* baseString, char* format, ...); + +/* Just implement a very simple singly linked list. */ + +typedef struct _GSList +{ + void* data; + struct _GSList* next; +} GSList; + +void g_slist_free(GSList* ripList); +GSList* g_slist_prepend(GSList* targetElement, void* newElementData); +GSList* g_slist_reverse(GSList* theList); + +#endif diff --git a/supportlibs/pegmarkdown/LICENSE b/supportlibs/pegmarkdown/LICENSE new file mode 100644 index 000000000..878252980 --- /dev/null +++ b/supportlibs/pegmarkdown/LICENSE @@ -0,0 +1,88 @@ +markdown in c, implemented using PEG grammar +Copyright (c) 2008-2011 John MacFarlane +ODF output code (c) 2011 Fletcher T. Penney + +peg-markdown is released under both the GPL and MIT licenses. +You may pick the license that best fits your needs. + +The GPL + +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 +(at your option) 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. + +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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +The MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +peg-0.1.4 (included for convenience - http://piumarta.com/software/peg/) + +Copyright (c) 2007 by Ian Piumarta +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the 'Software'), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, provided that the above copyright notice(s) and this +permission notice appear in all copies of the Software. Acknowledgement +of the use of this Software in supporting documentation would be +appreciated but is not required. + +THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK. + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +my_getopt (included for convenience - http://www.geocities.com/bsittler/) + +Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/supportlibs/pegmarkdown/Makefile.orig b/supportlibs/pegmarkdown/Makefile.orig new file mode 100644 index 000000000..1e8c7a003 --- /dev/null +++ b/supportlibs/pegmarkdown/Makefile.orig @@ -0,0 +1,42 @@ +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +ifneq (,$(findstring MINGW,$(uname_S))) + X = .exe +endif + +export X + +PROGRAM=markdown$(X) +CFLAGS ?= -Wall -O3 -ansi -D_GNU_SOURCE # -flto for newer GCC versions +OBJS=markdown_parser.o markdown_output.o markdown_lib.o utility_functions.o parsing_functions.o odf.o +PEGDIR=peg-0.1.9 +LEG=$(PEGDIR)/leg$(X) +PKG_CONFIG = pkg-config + +ALL : $(PROGRAM) + +$(LEG): $(PEGDIR) + CC=gcc make -C $(PEGDIR) + +%.o : %.c markdown_peg.h + $(CC) -c `$(PKG_CONFIG) --cflags glib-2.0` $(CFLAGS) -o $@ $< + +$(PROGRAM) : markdown.c $(OBJS) + $(CC) `$(PKG_CONFIG) --cflags glib-2.0` $(CFLAGS) -o $@ $< $(OBJS) `$(PKG_CONFIG) --libs glib-2.0` + +markdown_parser.c : markdown_parser.leg $(LEG) markdown_peg.h parsing_functions.c utility_functions.c + $(LEG) -o $@ $< + +.PHONY: clean test + +clean: + rm -f markdown_parser.c $(PROGRAM) $(OBJS) + +distclean: clean + make -C $(PEGDIR) clean +\ +test: $(PROGRAM) + cd MarkdownTest_1.0.3; \ + ./MarkdownTest.pl --script=../$(PROGRAM) --tidy + +leak-check: $(PROGRAM) + valgrind --leak-check=full ./markdown README diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/MarkdownTest.pl b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/MarkdownTest.pl new file mode 100755 index 000000000..55553d09c --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/MarkdownTest.pl @@ -0,0 +1,176 @@ +#!/usr/bin/perl + +# +# MarkdownTester -- Run tests for Markdown implementations +# +# Copyright (c) 2004-2005 John Gruber +# +# + +use strict; +use warnings; +use Getopt::Long; +use Benchmark; + +our $VERSION = '1.0.2'; +# Sat 24 Dec 2005 + +my $time_start = new Benchmark; +my $test_dir = "Tests"; +my $script = "./Markdown.pl"; +my $use_tidy = 0; +my ($flag_version); + +GetOptions ( + "script=s" => \$script, + "testdir=s" => \$test_dir, + "tidy" => \$use_tidy, + "version" => \$flag_version, + ); + +if($flag_version) { + my $progname = $0; + $progname =~ s{.*/}{}; + die "$progname version $VERSION\n"; +} + +unless (-d $test_dir) { die "'$test_dir' is not a directory.\n"; } +unless (-f $script) { die "$script does not exist.\n"; } +unless (-x $script) { die "$script is not executable.\n"; } + +my $tests_passed = 0; +my $tests_failed = 0; + +TEST: +foreach my $testfile (glob "$test_dir/*.text") { + my $testname = $testfile; + $testname =~ s{.*/(.+)\.text$}{$1}i; + print "$testname ... "; + + # Look for a corresponding .html file for each .text file: + my $resultfile = $testfile; + $resultfile =~ s{\.text$}{\.html}i; + unless (-f $resultfile) { + print "'$resultfile' does not exist.\n\n"; + next TEST; + } + + # open(TEST, $testfile) || die("Can't open testfile: $!"); + open(RESULT, $resultfile) || die("Can't open resultfile: $!"); + undef $/; + # my $t_input = ; + my $t_result = ; + + my $t_output = `'$script' '$testfile'`; + + # Normalize the output and expected result strings: + $t_result =~ s/\s+\z//; # trim trailing whitespace + $t_output =~ s/\s+\z//; # trim trailing whitespace + if ($use_tidy) { + # Escape the strings, pass them through to CLI tidy tool for tag-level equivalency + $t_result =~ s{'}{'\\''}g; # escape ' chars for shell + $t_output =~ s{'}{'\\''}g; + $t_result = `echo '$t_result' | tidy --show-body-only 1 --quiet 1 --show-warnings 0`; + $t_output = `echo '$t_output' | tidy --show-body-only 1 --quiet 1 --show-warnings 0`; + } + + if ($t_output eq $t_result) { + print "OK\n"; + $tests_passed++; + } + else { + print "FAILED\n\n"; +# This part added by JM to print diffs + open(OUT, '>tmp1') or die $!; + print OUT $t_output or die $!; + open(RES, '>tmp2') or die $!; + print RES $t_result or die $!; + print `diff tmp1 tmp2`; + close RES; + close OUT; + print "\n"; + `rm tmp?`; +# End of added part + $tests_failed++; + } +} + +print "\n\n"; +print "$tests_passed passed; $tests_failed failed.\n"; + +my $time_end = new Benchmark; +my $time_diff = timediff($time_end, $time_start); +print "Benchmark: ", timestr($time_diff), "\n"; + + +__END__ + +=pod + +=head1 NAME + +B + + +=head1 SYNOPSIS + +B [ B<--options> ] [ I ... ] + + +=head1 DESCRIPTION + + +=head1 OPTIONS + +Use "--" to end switch parsing. For example, to open a file named "-z", use: + + MarkdownTest.pl -- -z + +=over 4 + +=item B<--script> + +Specify the path to the Markdown script to test. Defaults to +"./Markdown.pl". Example: + + ./MarkdownTest.pl --script ./PHP-Markdown/php-markdown + +=item B<--testdir> + +Specify the path to a directory containing test data. Defaults to "Tests". + +=item B<--tidy> + +Flag to turn on using the command line 'tidy' tool to normalize HTML +output before comparing script output to the expected test result. +Assumes that the 'tidy' command is available in your PATH. Defaults to +off. + +=back + + + +=head1 BUGS + + + +=head1 VERSION HISTORY + +1.0 Mon 13 Dec 2004-2005 + +1.0.1 Mon 19 Sep 2005 + + + Better handling of case when foo.text exists, but foo.html doesn't. + It now prints a message and moves on, rather than dying. + + +=head1 COPYRIGHT AND LICENSE + +Copyright (c) 2004-2005 John Gruber + +All rights reserved. + +This is free software; you may redistribute it and/or modify it under +the same terms as Perl itself. + +=cut diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html new file mode 100644 index 000000000..9606860b6 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html @@ -0,0 +1,17 @@ +

AT&T has an ampersand in their name.

+ +

AT&T is another way to write it.

+ +

This & that.

+ +

4 < 5.

+ +

6 > 5.

+ +

Here's a link with an ampersand in the URL.

+ +

Here's a link with an amersand in the link text: AT&T.

+ +

Here's an inline link.

+ +

Here's an inline link.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text new file mode 100644 index 000000000..0e9527f93 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text @@ -0,0 +1,21 @@ +AT&T has an ampersand in their name. + +AT&T is another way to write it. + +This & that. + +4 < 5. + +6 > 5. + +Here's a [link] [1] with an ampersand in the URL. + +Here's a link with an amersand in the link text: [AT&T] [2]. + +Here's an inline [link](/script?foo=1&bar=2). + +Here's an inline [link](). + + +[1]: http://example.com/?foo=1&bar=2 +[2]: http://att.com/ "AT&T" \ No newline at end of file diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Auto links.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Auto links.html new file mode 100644 index 000000000..f8df9852c --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Auto links.html @@ -0,0 +1,18 @@ +

Link: http://example.com/.

+ +

With an ampersand: http://example.com/?foo=1&bar=2

+ + + +
+

Blockquoted: http://example.com/

+
+ +

Auto-links should not occur here: <http://example.com/>

+ +
or here: <http://example.com/>
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Auto links.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Auto links.text new file mode 100644 index 000000000..abbc48869 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Auto links.text @@ -0,0 +1,13 @@ +Link: . + +With an ampersand: + +* In a list? +* +* It should. + +> Blockquoted: + +Auto-links should not occur here: `` + + or here: \ No newline at end of file diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Backslash escapes.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Backslash escapes.html new file mode 100644 index 000000000..29870dac5 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Backslash escapes.html @@ -0,0 +1,118 @@ +

These should all get escaped:

+ +

Backslash: \

+ +

Backtick: `

+ +

Asterisk: *

+ +

Underscore: _

+ +

Left brace: {

+ +

Right brace: }

+ +

Left bracket: [

+ +

Right bracket: ]

+ +

Left paren: (

+ +

Right paren: )

+ +

Greater-than: >

+ +

Hash: #

+ +

Period: .

+ +

Bang: !

+ +

Plus: +

+ +

Minus: -

+ +

These should not, because they occur within a code block:

+ +
Backslash: \\
+
+Backtick: \`
+
+Asterisk: \*
+
+Underscore: \_
+
+Left brace: \{
+
+Right brace: \}
+
+Left bracket: \[
+
+Right bracket: \]
+
+Left paren: \(
+
+Right paren: \)
+
+Greater-than: \>
+
+Hash: \#
+
+Period: \.
+
+Bang: \!
+
+Plus: \+
+
+Minus: \-
+
+ +

Nor should these, which occur in code spans:

+ +

Backslash: \\

+ +

Backtick: \`

+ +

Asterisk: \*

+ +

Underscore: \_

+ +

Left brace: \{

+ +

Right brace: \}

+ +

Left bracket: \[

+ +

Right bracket: \]

+ +

Left paren: \(

+ +

Right paren: \)

+ +

Greater-than: \>

+ +

Hash: \#

+ +

Period: \.

+ +

Bang: \!

+ +

Plus: \+

+ +

Minus: \-

+ + +

These should get escaped, even though they're matching pairs for +other Markdown constructs:

+ +

*asterisks*

+ +

_underscores_

+ +

`backticks`

+ +

This is a code span with a literal backslash-backtick sequence: \`

+ +

This is a tag with unescaped backticks bar.

+ +

This is a tag with backslashes bar.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Backslash escapes.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Backslash escapes.text new file mode 100644 index 000000000..5b014cb33 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Backslash escapes.text @@ -0,0 +1,120 @@ +These should all get escaped: + +Backslash: \\ + +Backtick: \` + +Asterisk: \* + +Underscore: \_ + +Left brace: \{ + +Right brace: \} + +Left bracket: \[ + +Right bracket: \] + +Left paren: \( + +Right paren: \) + +Greater-than: \> + +Hash: \# + +Period: \. + +Bang: \! + +Plus: \+ + +Minus: \- + + + +These should not, because they occur within a code block: + + Backslash: \\ + + Backtick: \` + + Asterisk: \* + + Underscore: \_ + + Left brace: \{ + + Right brace: \} + + Left bracket: \[ + + Right bracket: \] + + Left paren: \( + + Right paren: \) + + Greater-than: \> + + Hash: \# + + Period: \. + + Bang: \! + + Plus: \+ + + Minus: \- + + +Nor should these, which occur in code spans: + +Backslash: `\\` + +Backtick: `` \` `` + +Asterisk: `\*` + +Underscore: `\_` + +Left brace: `\{` + +Right brace: `\}` + +Left bracket: `\[` + +Right bracket: `\]` + +Left paren: `\(` + +Right paren: `\)` + +Greater-than: `\>` + +Hash: `\#` + +Period: `\.` + +Bang: `\!` + +Plus: `\+` + +Minus: `\-` + + +These should get escaped, even though they're matching pairs for +other Markdown constructs: + +\*asterisks\* + +\_underscores\_ + +\`backticks\` + +This is a code span with a literal backslash-backtick sequence: `` \` `` + +This is a tag with unescaped backticks bar. + +This is a tag with backslashes bar. diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html new file mode 100644 index 000000000..990202a1b --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html @@ -0,0 +1,15 @@ +
+

Example:

+ +
sub status {
+    print "working";
+}
+
+ +

Or:

+ +
sub status {
+    return "working";
+}
+
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text new file mode 100644 index 000000000..c31d17104 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text @@ -0,0 +1,11 @@ +> Example: +> +> sub status { +> print "working"; +> } +> +> Or: +> +> sub status { +> return "working"; +> } diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Blocks.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Blocks.html new file mode 100644 index 000000000..32703f5cb --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Blocks.html @@ -0,0 +1,18 @@ +
code block on the first line
+
+ +

Regular text.

+ +
code block indented by spaces
+
+ +

Regular text.

+ +
the lines in this block  
+all contain trailing spaces  
+
+ +

Regular Text.

+ +
code block on the last line
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Blocks.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Blocks.text new file mode 100644 index 000000000..b54b09285 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Blocks.text @@ -0,0 +1,14 @@ + code block on the first line + +Regular text. + + code block indented by spaces + +Regular text. + + the lines in this block + all contain trailing spaces + +Regular Text. + + code block on the last line \ No newline at end of file diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Spans.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Spans.html new file mode 100644 index 000000000..4b8afbb70 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Spans.html @@ -0,0 +1,6 @@ +

<test a=" content of attribute ">

+ +

Fix for backticks within HTML tag: like this

+ +

Here's how you put `backticks` in a code span.

+ diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Spans.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Spans.text new file mode 100644 index 000000000..750a1973d --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Code Spans.text @@ -0,0 +1,6 @@ +`` + +Fix for backticks within HTML tag: like this + +Here's how you put `` `backticks` `` in a code span. + diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html new file mode 100644 index 000000000..e21ac79a2 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html @@ -0,0 +1,8 @@ +

In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked like a +list item.

+ +

Here's one with a bullet. +* criminey.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text new file mode 100644 index 000000000..f8a5b27bf --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text @@ -0,0 +1,8 @@ +In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked like a +list item. + +Here's one with a bullet. +* criminey. diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Horizontal rules.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Horizontal rules.html new file mode 100644 index 000000000..2dc2ab656 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Horizontal rules.html @@ -0,0 +1,71 @@ +

Dashes:

+ +
+ +
+ +
+ +
+ +
---
+
+ +
+ +
+ +
+ +
+ +
- - -
+
+ +

Asterisks:

+ +
+ +
+ +
+ +
+ +
***
+
+ +
+ +
+ +
+ +
+ +
* * *
+
+ +

Underscores:

+ +
+ +
+ +
+ +
+ +
___
+
+ +
+ +
+ +
+ +
+ +
_ _ _
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Horizontal rules.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Horizontal rules.text new file mode 100644 index 000000000..1594bda27 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Horizontal rules.text @@ -0,0 +1,67 @@ +Dashes: + +--- + + --- + + --- + + --- + + --- + +- - - + + - - - + + - - - + + - - - + + - - - + + +Asterisks: + +*** + + *** + + *** + + *** + + *** + +* * * + + * * * + + * * * + + * * * + + * * * + + +Underscores: + +___ + + ___ + + ___ + + ___ + + ___ + +_ _ _ + + _ _ _ + + _ _ _ + + _ _ _ + + _ _ _ diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html new file mode 100644 index 000000000..3af9cafb1 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html @@ -0,0 +1,15 @@ +

Simple block on one line:

+ +
foo
+ +

And nested without indentation:

+ +
+
+
+foo +
+
+
+
bar
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text new file mode 100644 index 000000000..86b7206d2 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text @@ -0,0 +1,15 @@ +Simple block on one line: + +
foo
+ +And nested without indentation: + +
+
+
+foo +
+
+
+
bar
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html new file mode 100644 index 000000000..6bf78f8fc --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html @@ -0,0 +1,72 @@ +

Here's a simple block:

+ +
+ foo +
+ +

This should be a code block, though:

+ +
<div>
+    foo
+</div>
+
+ +

As should this:

+ +
<div>foo</div>
+
+ +

Now, nested:

+ +
+
+
+ foo +
+
+
+ +

This should just be an HTML comment:

+ + + +

Multiline:

+ + + +

Code block:

+ +
<!-- Comment -->
+
+ +

Just plain comment, with trailing spaces on the line:

+ + + +

Code:

+ +
<hr />
+
+ +

Hr's:

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text new file mode 100644 index 000000000..14aa2dc27 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text @@ -0,0 +1,69 @@ +Here's a simple block: + +
+ foo +
+ +This should be a code block, though: + +
+ foo +
+ +As should this: + +
foo
+ +Now, nested: + +
+
+
+ foo +
+
+
+ +This should just be an HTML comment: + + + +Multiline: + + + +Code block: + + + +Just plain comment, with trailing spaces on the line: + + + +Code: + +
+ +Hr's: + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML comments.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML comments.html new file mode 100644 index 000000000..3f167a161 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML comments.html @@ -0,0 +1,13 @@ +

Paragraph one.

+ + + + + +

Paragraph two.

+ + + +

The end.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML comments.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML comments.text new file mode 100644 index 000000000..41d830d03 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Inline HTML comments.text @@ -0,0 +1,13 @@ +Paragraph one. + + + + + +Paragraph two. + + + +The end. diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, inline style.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, inline style.html new file mode 100644 index 000000000..f36607ddd --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, inline style.html @@ -0,0 +1,11 @@ +

Just a URL.

+ +

URL and title.

+ +

URL and title.

+ +

URL and title.

+ +

URL and title.

+ +

Empty.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, inline style.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, inline style.text new file mode 100644 index 000000000..09017a90c --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, inline style.text @@ -0,0 +1,12 @@ +Just a [URL](/url/). + +[URL and title](/url/ "title"). + +[URL and title](/url/ "title preceded by two spaces"). + +[URL and title](/url/ "title preceded by a tab"). + +[URL and title](/url/ "title has spaces afterward" ). + + +[Empty](). diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, reference style.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, reference style.html new file mode 100644 index 000000000..8e70c32f4 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, reference style.html @@ -0,0 +1,52 @@ +

Foo bar.

+ +

Foo bar.

+ +

Foo bar.

+ +

With embedded [brackets].

+ +

Indented once.

+ +

Indented twice.

+ +

Indented thrice.

+ +

Indented [four][] times.

+ +
[four]: /url
+
+ +
+ +

this should work

+ +

So should this.

+ +

And this.

+ +

And this.

+ +

And this.

+ +

But not [that] [].

+ +

Nor [that][].

+ +

Nor [that].

+ +

[Something in brackets like this should work]

+ +

[Same with this.]

+ +

In this case, this points to something else.

+ +

Backslashing should suppress [this] and [this].

+ +
+ +

Here's one where the link +breaks across lines.

+ +

Here's another where the link +breaks across lines, but with a line-ending space.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, reference style.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, reference style.text new file mode 100644 index 000000000..341ec88e3 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, reference style.text @@ -0,0 +1,71 @@ +Foo [bar] [1]. + +Foo [bar][1]. + +Foo [bar] +[1]. + +[1]: /url/ "Title" + + +With [embedded [brackets]] [b]. + + +Indented [once][]. + +Indented [twice][]. + +Indented [thrice][]. + +Indented [four][] times. + + [once]: /url + + [twice]: /url + + [thrice]: /url + + [four]: /url + + +[b]: /url/ + +* * * + +[this] [this] should work + +So should [this][this]. + +And [this] []. + +And [this][]. + +And [this]. + +But not [that] []. + +Nor [that][]. + +Nor [that]. + +[Something in brackets like [this][] should work] + +[Same with [this].] + +In this case, [this](/somethingelse/) points to something else. + +Backslashing should suppress \[this] and [this\]. + +[this]: foo + + +* * * + +Here's one where the [link +breaks] across lines. + +Here's another where the [link +breaks] across lines, but with a line-ending space. + + +[link breaks]: /url/ diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, shortcut references.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, shortcut references.html new file mode 100644 index 000000000..bf81e939f --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, shortcut references.html @@ -0,0 +1,9 @@ +

This is the simple case.

+ +

This one has a line +break.

+ +

This one has a line +break with a line-ending space.

+ +

this and the other

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, shortcut references.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, shortcut references.text new file mode 100644 index 000000000..8c44c98fe --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Links, shortcut references.text @@ -0,0 +1,20 @@ +This is the [simple case]. + +[simple case]: /simple + + + +This one has a [line +break]. + +This one has a [line +break] with a line-ending space. + +[line break]: /foo + + +[this] [that] and the [other] + +[this]: /this +[that]: /that +[other]: /other diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html new file mode 100644 index 000000000..611c1ac61 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html @@ -0,0 +1,3 @@ +

Foo bar.

+ +

Foo bar.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text new file mode 100644 index 000000000..29d0e4235 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text @@ -0,0 +1,7 @@ +Foo [bar][]. + +Foo [bar](/url/ "Title with "quotes" inside"). + + + [bar]: /url/ "Title with "quotes" inside" + diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html new file mode 100644 index 000000000..d5bdbb29a --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html @@ -0,0 +1,314 @@ +

Markdown: Basics

+ + + +

Getting the Gist of Markdown's Formatting Syntax

+ +

This page offers a brief overview of what it's like to use Markdown. +The syntax page provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown.

+ +

It's also helpful to simply try Markdown out; the Dingus is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML.

+ +

Note: This document is itself written using Markdown; you +can see the source for it by adding '.text' to the URL.

+ +

Paragraphs, Headers, Blockquotes

+ +

A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks like a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs.

+ +

Markdown offers two styles of headers: Setext and atx. +Setext-style headers for <h1> and <h2> are created by +"underlining" with equal signs (=) and hyphens (-), respectively. +To create an atx-style header, you put 1-6 hash marks (#) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level.

+ +

Blockquotes are indicated using email-style '>' angle brackets.

+ +

Markdown:

+ +
A First Level Header
+====================
+
+A Second Level Header
+---------------------
+
+Now is the time for all good men to come to
+the aid of their country. This is just a
+regular paragraph.
+
+The quick brown fox jumped over the lazy
+dog's back.
+
+### Header 3
+
+> This is a blockquote.
+> 
+> This is the second paragraph in the blockquote.
+>
+> ## This is an H2 in a blockquote
+
+ +

Output:

+ +
<h1>A First Level Header</h1>
+
+<h2>A Second Level Header</h2>
+
+<p>Now is the time for all good men to come to
+the aid of their country. This is just a
+regular paragraph.</p>
+
+<p>The quick brown fox jumped over the lazy
+dog's back.</p>
+
+<h3>Header 3</h3>
+
+<blockquote>
+    <p>This is a blockquote.</p>
+
+    <p>This is the second paragraph in the blockquote.</p>
+
+    <h2>This is an H2 in a blockquote</h2>
+</blockquote>
+
+ +

Phrase Emphasis

+ +

Markdown uses asterisks and underscores to indicate spans of emphasis.

+ +

Markdown:

+ +
Some of these words *are emphasized*.
+Some of these words _are emphasized also_.
+
+Use two asterisks for **strong emphasis**.
+Or, if you prefer, __use two underscores instead__.
+
+ +

Output:

+ +
<p>Some of these words <em>are emphasized</em>.
+Some of these words <em>are emphasized also</em>.</p>
+
+<p>Use two asterisks for <strong>strong emphasis</strong>.
+Or, if you prefer, <strong>use two underscores instead</strong>.</p>
+
+ +

Lists

+ +

Unordered (bulleted) lists use asterisks, pluses, and hyphens (*, ++, and -) as list markers. These three markers are +interchangable; this:

+ +
*   Candy.
+*   Gum.
+*   Booze.
+
+ +

this:

+ +
+   Candy.
++   Gum.
++   Booze.
+
+ +

and this:

+ +
-   Candy.
+-   Gum.
+-   Booze.
+
+ +

all produce the same output:

+ +
<ul>
+<li>Candy.</li>
+<li>Gum.</li>
+<li>Booze.</li>
+</ul>
+
+ +

Ordered (numbered) lists use regular numbers, followed by periods, as +list markers:

+ +
1.  Red
+2.  Green
+3.  Blue
+
+ +

Output:

+ +
<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
+
+ +

If you put blank lines between items, you'll get <p> tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab:

+ +
*   A list item.
+
+    With multiple paragraphs.
+
+*   Another item in the list.
+
+ +

Output:

+ +
<ul>
+<li><p>A list item.</p>
+<p>With multiple paragraphs.</p></li>
+<li><p>Another item in the list.</p></li>
+</ul>
+
+ +

Links

+ +

Markdown supports two styles for creating links: inline and +reference. With both styles, you use square brackets to delimit the +text you want to turn into a link.

+ +

Inline-style links use parentheses immediately after the link text. +For example:

+ +
This is an [example link](http://example.com/).
+
+ +

Output:

+ +
<p>This is an <a href="http://example.com/">
+example link</a>.</p>
+
+ +

Optionally, you may include a title attribute in the parentheses:

+ +
This is an [example link](http://example.com/ "With a Title").
+
+ +

Output:

+ +
<p>This is an <a href="http://example.com/" title="With a Title">
+example link</a>.</p>
+
+ +

Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document:

+ +
I get 10 times more traffic from [Google][1] than from
+[Yahoo][2] or [MSN][3].
+
+[1]: http://google.com/        "Google"
+[2]: http://search.yahoo.com/  "Yahoo Search"
+[3]: http://search.msn.com/    "MSN Search"
+
+ +

Output:

+ +
<p>I get 10 times more traffic from <a href="http://google.com/"
+title="Google">Google</a> than from <a href="http://search.yahoo.com/"
+title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
+title="MSN Search">MSN</a>.</p>
+
+ +

The title attribute is optional. Link names may contain letters, +numbers and spaces, but are not case sensitive:

+ +
I start my morning with a cup of coffee and
+[The New York Times][NY Times].
+
+[ny times]: http://www.nytimes.com/
+
+ +

Output:

+ +
<p>I start my morning with a cup of coffee and
+<a href="http://www.nytimes.com/">The New York Times</a>.</p>
+
+ +

Images

+ +

Image syntax is very much like link syntax.

+ +

Inline (titles are optional):

+ +
![alt text](/path/to/img.jpg "Title")
+
+ +

Reference-style:

+ +
![alt text][id]
+
+[id]: /path/to/img.jpg "Title"
+
+ +

Both of the above examples produce the same output:

+ +
<img src="/path/to/img.jpg" alt="alt text" title="Title" />
+
+ +

Code

+ +

In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (&) and angle brackets (< or +>) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code:

+ +
I strongly recommend against using any `<blink>` tags.
+
+I wish SmartyPants used named entities like `&mdash;`
+instead of decimal-encoded entites like `&#8212;`.
+
+ +

Output:

+ +
<p>I strongly recommend against using any
+<code>&lt;blink&gt;</code> tags.</p>
+
+<p>I wish SmartyPants used named entities like
+<code>&amp;mdash;</code> instead of decimal-encoded
+entites like <code>&amp;#8212;</code>.</p>
+
+ +

To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just like with code spans, &, <, +and > characters will be escaped automatically.

+ +

Markdown:

+ +
If you want your page to validate under XHTML 1.0 Strict,
+you've got to put paragraph tags in your blockquotes:
+
+    <blockquote>
+        <p>For example.</p>
+    </blockquote>
+
+ +

Output:

+ +
<p>If you want your page to validate under XHTML 1.0 Strict,
+you've got to put paragraph tags in your blockquotes:</p>
+
+<pre><code>&lt;blockquote&gt;
+    &lt;p&gt;For example.&lt;/p&gt;
+&lt;/blockquote&gt;
+</code></pre>
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text new file mode 100644 index 000000000..486055ca7 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text @@ -0,0 +1,306 @@ +Markdown: Basics +================ + + + + +Getting the Gist of Markdown's Formatting Syntax +------------------------------------------------ + +This page offers a brief overview of what it's like to use Markdown. +The [syntax page] [s] provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown. + +It's also helpful to simply try Markdown out; the [Dingus] [d] is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML. + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL] [src]. + + [s]: /projects/markdown/syntax "Markdown Syntax" + [d]: /projects/markdown/dingus "Markdown Dingus" + [src]: /projects/markdown/basics.text + + +## Paragraphs, Headers, Blockquotes ## + +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks like a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +Markdown offers two styles of headers: *Setext* and *atx*. +Setext-style headers for `

` and `

` are created by +"underlining" with equal signs (`=`) and hyphens (`-`), respectively. +To create an atx-style header, you put 1-6 hash marks (`#`) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level. + +Blockquotes are indicated using email-style '`>`' angle brackets. + +Markdown: + + A First Level Header + ==================== + + A Second Level Header + --------------------- + + Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph. + + The quick brown fox jumped over the lazy + dog's back. + + ### Header 3 + + > This is a blockquote. + > + > This is the second paragraph in the blockquote. + > + > ## This is an H2 in a blockquote + + +Output: + +

A First Level Header

+ +

A Second Level Header

+ +

Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph.

+ +

The quick brown fox jumped over the lazy + dog's back.

+ +

Header 3

+ +
+

This is a blockquote.

+ +

This is the second paragraph in the blockquote.

+ +

This is an H2 in a blockquote

+
+ + + +### Phrase Emphasis ### + +Markdown uses asterisks and underscores to indicate spans of emphasis. + +Markdown: + + Some of these words *are emphasized*. + Some of these words _are emphasized also_. + + Use two asterisks for **strong emphasis**. + Or, if you prefer, __use two underscores instead__. + +Output: + +

Some of these words are emphasized. + Some of these words are emphasized also.

+ +

Use two asterisks for strong emphasis. + Or, if you prefer, use two underscores instead.

+ + + +## Lists ## + +Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, +`+`, and `-`) as list markers. These three markers are +interchangable; this: + + * Candy. + * Gum. + * Booze. + +this: + + + Candy. + + Gum. + + Booze. + +and this: + + - Candy. + - Gum. + - Booze. + +all produce the same output: + +
    +
  • Candy.
  • +
  • Gum.
  • +
  • Booze.
  • +
+ +Ordered (numbered) lists use regular numbers, followed by periods, as +list markers: + + 1. Red + 2. Green + 3. Blue + +Output: + +
    +
  1. Red
  2. +
  3. Green
  4. +
  5. Blue
  6. +
+ +If you put blank lines between items, you'll get `

` tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab: + + * A list item. + + With multiple paragraphs. + + * Another item in the list. + +Output: + +

    +
  • A list item.

    +

    With multiple paragraphs.

  • +
  • Another item in the list.

  • +
+ + + +### Links ### + +Markdown supports two styles for creating links: *inline* and +*reference*. With both styles, you use square brackets to delimit the +text you want to turn into a link. + +Inline-style links use parentheses immediately after the link text. +For example: + + This is an [example link](http://example.com/). + +Output: + +

This is an + example link.

+ +Optionally, you may include a title attribute in the parentheses: + + This is an [example link](http://example.com/ "With a Title"). + +Output: + +

This is an + example link.

+ +Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document: + + I get 10 times more traffic from [Google][1] than from + [Yahoo][2] or [MSN][3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Output: + +

I get 10 times more traffic from Google than from Yahoo or MSN.

+ +The title attribute is optional. Link names may contain letters, +numbers and spaces, but are *not* case sensitive: + + I start my morning with a cup of coffee and + [The New York Times][NY Times]. + + [ny times]: http://www.nytimes.com/ + +Output: + +

I start my morning with a cup of coffee and + The New York Times.

+ + +### Images ### + +Image syntax is very much like link syntax. + +Inline (titles are optional): + + ![alt text](/path/to/img.jpg "Title") + +Reference-style: + + ![alt text][id] + + [id]: /path/to/img.jpg "Title" + +Both of the above examples produce the same output: + + alt text + + + +### Code ### + +In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (`&`) and angle brackets (`<` or +`>`) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code: + + I strongly recommend against using any `` tags. + + I wish SmartyPants used named entities like `—` + instead of decimal-encoded entites like `—`. + +Output: + +

I strongly recommend against using any + <blink> tags.

+ +

I wish SmartyPants used named entities like + &mdash; instead of decimal-encoded + entites like &#8212;.

+ + +To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`, +and `>` characters will be escaped automatically. + +Markdown: + + If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes: + +
+

For example.

+
+ +Output: + +

If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes:

+ +
<blockquote>
+        <p>For example.</p>
+    </blockquote>
+    
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html new file mode 100644 index 000000000..5c01306cc --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html @@ -0,0 +1,942 @@ +

Markdown: Syntax

+ + + + + +

Note: This document is itself written using Markdown; you +can see the source for it by adding '.text' to the URL.

+ +
+ +

Overview

+ +

Philosophy

+ +

Markdown is intended to be as easy-to-read and easy-to-write as is feasible.

+ +

Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +like it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including Setext, atx, Textile, reStructuredText, +Grutatext, and EtText -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email.

+ +

To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look like what they mean. E.g., asterisks around a word actually +look like *emphasis*. Markdown lists look like, well, lists. Even +blockquotes look like quoted passages of text, assuming you've ever +used email.

+ +

Inline HTML

+ +

Markdown's syntax is intended for one purpose: to be used as a +format for writing for the web.

+ +

Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is not to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a publishing format; Markdown is a writing +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text.

+ +

For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags.

+ +

The only restrictions are that block-level HTML elements -- e.g. <div>, +<table>, <pre>, <p>, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) <p> tags around HTML block-level tags.

+ +

For example, to add an HTML table to a Markdown article:

+ +
This is a regular paragraph.
+
+<table>
+    <tr>
+        <td>Foo</td>
+    </tr>
+</table>
+
+This is another regular paragraph.
+
+ +

Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style *emphasis* inside an +HTML block.

+ +

Span-level HTML tags -- e.g. <span>, <cite>, or <del> -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML <a> or <img> tags instead of Markdown's +link or image syntax, go right ahead.

+ +

Unlike block-level HTML tags, Markdown syntax is processed within +span-level tags.

+ +

Automatic Escaping for Special Characters

+ +

In HTML, there are two characters that demand special treatment: < +and &. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. &lt;, and +&amp;.

+ +

Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write 'AT&amp;T'. You even need to +escape ampersands within URLs. Thus, if you want to link to:

+ +
http://images.google.com/images?num=30&q=larry+bird
+
+ +

you need to encode the URL as:

+ +
http://images.google.com/images?num=30&amp;q=larry+bird
+
+ +

in your anchor tag href attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites.

+ +

Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into &amp;.

+ +

So, if you want to include a copyright symbol in your article, you can write:

+ +
&copy;
+
+ +

and Markdown will leave it alone. But if you write:

+ +
AT&T
+
+ +

Markdown will translate it to:

+ +
AT&amp;T
+
+ +

Similarly, because Markdown supports inline HTML, if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write:

+ +
4 < 5
+
+ +

Markdown will translate it to:

+ +
4 &lt; 5
+
+ +

However, inside Markdown code spans and blocks, angle brackets and +ampersands are always encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single < +and & in your example code needs to be escaped.)

+ +
+ +

Block Elements

+ +

Paragraphs and Line Breaks

+ +

A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks like a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs.

+ +

The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a <br /> tag.

+ +

When you do want to insert a <br /> break tag using Markdown, you +end a line with two or more spaces, then type return.

+ +

Yes, this takes a tad more effort to create a <br />, but a simplistic +"every line break is a <br />" rule wouldn't work for Markdown. +Markdown's email-style blockquoting and multi-paragraph list items +work best -- and look better -- when you format them with hard breaks.

+ + + +

Markdown supports two styles of headers, Setext and atx.

+ +

Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example:

+ +
This is an H1
+=============
+
+This is an H2
+-------------
+
+ +

Any number of underlining ='s or -'s will work.

+ +

Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example:

+ +
# This is an H1
+
+## This is an H2
+
+###### This is an H6
+
+ +

Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) :

+ +
# This is an H1 #
+
+## This is an H2 ##
+
+### This is an H3 ######
+
+ +

Blockquotes

+ +

Markdown uses email-style > characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a > before every line:

+ +
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+> 
+> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+> id sem consectetuer libero luctus adipiscing.
+
+ +

Markdown allows you to be lazy and only put the > before the first +line of a hard-wrapped paragraph:

+ +
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+
+> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.
+
+ +

Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of >:

+ +
> This is the first level of quoting.
+>
+> > This is nested blockquote.
+>
+> Back to the first level.
+
+ +

Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks:

+ +
> ## This is a header.
+> 
+> 1.   This is the first list item.
+> 2.   This is the second list item.
+> 
+> Here's some example code:
+> 
+>     return shell_exec("echo $input | $markdown_script");
+
+ +

Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu.

+ +

Lists

+ +

Markdown supports ordered (numbered) and unordered (bulleted) lists.

+ +

Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers:

+ +
*   Red
+*   Green
+*   Blue
+
+ +

is equivalent to:

+ +
+   Red
++   Green
++   Blue
+
+ +

and:

+ +
-   Red
+-   Green
+-   Blue
+
+ +

Ordered lists use numbers followed by periods:

+ +
1.  Bird
+2.  McHale
+3.  Parish
+
+ +

It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is:

+ +
<ol>
+<li>Bird</li>
+<li>McHale</li>
+<li>Parish</li>
+</ol>
+
+ +

If you instead wrote the list in Markdown like this:

+ +
1.  Bird
+1.  McHale
+1.  Parish
+
+ +

or even:

+ +
3. Bird
+1. McHale
+8. Parish
+
+ +

you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to.

+ +

If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number.

+ +

List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab.

+ +

To make lists look nice, you can wrap items with hanging indents:

+ +
*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+    viverra nec, fringilla in, laoreet vitae, risus.
+*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+    Suspendisse id sem consectetuer libero luctus adipiscing.
+
+ +

But if you want to be lazy, you don't have to:

+ +
*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.
+*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.
+
+ +

If list items are separated by blank lines, Markdown will wrap the +items in <p> tags in the HTML output. For example, this input:

+ +
*   Bird
+*   Magic
+
+ +

will turn into:

+ +
<ul>
+<li>Bird</li>
+<li>Magic</li>
+</ul>
+
+ +

But this:

+ +
*   Bird
+
+*   Magic
+
+ +

will turn into:

+ +
<ul>
+<li><p>Bird</p></li>
+<li><p>Magic</p></li>
+</ul>
+
+ +

List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab:

+ +
1.  This is a list item with two paragraphs. Lorem ipsum dolor
+    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
+    mi posuere lectus.
+
+    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
+    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
+    sit amet velit.
+
+2.  Suspendisse id sem consectetuer libero luctus adipiscing.
+
+ +

It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy:

+ +
*   This is a list item with two paragraphs.
+
+    This is the second paragraph in the list item. You're
+only required to indent the first line. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit.
+
+*   Another item in the same list.
+
+ +

To put a blockquote within a list item, the blockquote's > +delimiters need to be indented:

+ +
*   A list item with a blockquote:
+
+    > This is a blockquote
+    > inside a list item.
+
+ +

To put a code block within a list item, the code block needs +to be indented twice -- 8 spaces or two tabs:

+ +
*   A list item with a code block:
+
+        <code goes here>
+
+ +

It's worth noting that it's possible to trigger an ordered list by +accident, by writing something like this:

+ +
1986. What a great season.
+
+ +

In other words, a number-period-space sequence at the beginning of a +line. To avoid this, you can backslash-escape the period:

+ +
1986\. What a great season.
+
+ +

Code Blocks

+ +

Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both <pre> and <code> tags.

+ +

To produce a code block in Markdown, simply indent every line of the +block by at least 4 spaces or 1 tab. For example, given this input:

+ +
This is a normal paragraph:
+
+    This is a code block.
+
+ +

Markdown will generate:

+ +
<p>This is a normal paragraph:</p>
+
+<pre><code>This is a code block.
+</code></pre>
+
+ +

One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this:

+ +
Here is an example of AppleScript:
+
+    tell application "Foo"
+        beep
+    end tell
+
+ +

will turn into:

+ +
<p>Here is an example of AppleScript:</p>
+
+<pre><code>tell application "Foo"
+    beep
+end tell
+</code></pre>
+
+ +

A code block continues until it reaches a line that is not indented +(or the end of the article).

+ +

Within a code block, ampersands (&) and angle brackets (< and >) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this:

+ +
    <div class="footer">
+        &copy; 2004 Foo Corporation
+    </div>
+
+ +

will turn into:

+ +
<pre><code>&lt;div class="footer"&gt;
+    &amp;copy; 2004 Foo Corporation
+&lt;/div&gt;
+</code></pre>
+
+ +

Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax.

+ +

Horizontal Rules

+ +

You can produce a horizontal rule tag (<hr />) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule:

+ +
* * *
+
+***
+
+*****
+
+- - -
+
+---------------------------------------
+
+_ _ _
+
+ +
+ +

Span Elements

+ + + +

Markdown supports two style of links: inline and reference.

+ +

In both styles, the link text is delimited by [square brackets].

+ +

To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an optional +title for the link, surrounded in quotes. For example:

+ +
This is [an example](http://example.com/ "Title") inline link.
+
+[This link](http://example.net/) has no title attribute.
+
+ +

Will produce:

+ +
<p>This is <a href="http://example.com/" title="Title">
+an example</a> inline link.</p>
+
+<p><a href="http://example.net/">This link</a> has no
+title attribute.</p>
+
+ +

If you're referring to a local resource on the same server, you can +use relative paths:

+ +
See my [About](/about/) page for details.
+
+ +

Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link:

+ +
This is [an example][id] reference-style link.
+
+ +

You can optionally use a space to separate the sets of brackets:

+ +
This is [an example] [id] reference-style link.
+
+ +

Then, anywhere in the document, you define your link label like this, +on a line by itself:

+ +
[id]: http://example.com/  "Optional Title Here"
+
+ +

That is:

+ +
    +
  • Square brackets containing the link identifier (optionally +indented from the left margin using up to three spaces);
  • +
  • followed by a colon;
  • +
  • followed by one or more spaces (or tabs);
  • +
  • followed by the URL for the link;
  • +
  • optionally followed by a title attribute for the link, enclosed +in double or single quotes.
  • +
+ +

The link URL may, optionally, be surrounded by angle brackets:

+ +
[id]: <http://example.com/>  "Optional Title Here"
+
+ +

You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs:

+ +
[id]: http://example.com/longish/path/to/resource/here
+    "Optional Title Here"
+
+ +

Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output.

+ +

Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are not case sensitive. E.g. these two links:

+ +
[link text][a]
+[link text][A]
+
+ +

are equivalent.

+ +

The implicit link name shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write:

+ +
[Google][]
+
+ +

And then define the link:

+ +
[Google]: http://google.com/
+
+ +

Because link names may contain spaces, this shortcut even works for +multiple words in the link text:

+ +
Visit [Daring Fireball][] for more information.
+
+ +

And then define the link:

+ +
[Daring Fireball]: http://daringfireball.net/
+
+ +

Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of like footnotes.

+ +

Here's an example of reference links in action:

+ +
I get 10 times more traffic from [Google] [1] than from
+[Yahoo] [2] or [MSN] [3].
+
+  [1]: http://google.com/        "Google"
+  [2]: http://search.yahoo.com/  "Yahoo Search"
+  [3]: http://search.msn.com/    "MSN Search"
+
+ +

Using the implicit link name shortcut, you could instead write:

+ +
I get 10 times more traffic from [Google][] than from
+[Yahoo][] or [MSN][].
+
+  [google]: http://google.com/        "Google"
+  [yahoo]:  http://search.yahoo.com/  "Yahoo Search"
+  [msn]:    http://search.msn.com/    "MSN Search"
+
+ +

Both of the above examples will produce the following HTML output:

+ +
<p>I get 10 times more traffic from <a href="http://google.com/"
+title="Google">Google</a> than from
+<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
+or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
+
+ +

For comparison, here is the same paragraph written using +Markdown's inline link style:

+ +
I get 10 times more traffic from [Google](http://google.com/ "Google")
+than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
+[MSN](http://search.msn.com/ "MSN Search").
+
+ +

The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text.

+ +

With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose.

+ +

Emphasis

+ +

Markdown treats asterisks (*) and underscores (_) as indicators of +emphasis. Text wrapped with one * or _ will be wrapped with an +HTML <em> tag; double *'s or _'s will be wrapped with an HTML +<strong> tag. E.g., this input:

+ +
*single asterisks*
+
+_single underscores_
+
+**double asterisks**
+
+__double underscores__
+
+ +

will produce:

+ +
<em>single asterisks</em>
+
+<em>single underscores</em>
+
+<strong>double asterisks</strong>
+
+<strong>double underscores</strong>
+
+ +

You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span.

+ +

Emphasis can be used in the middle of a word:

+ +
un*fucking*believable
+
+ +

But if you surround an * or _ with spaces, it'll be treated as a +literal asterisk or underscore.

+ +

To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it:

+ +
\*this text is surrounded by literal asterisks\*
+
+ +

Code

+ +

To indicate a span of code, wrap it with backtick quotes (`). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example:

+ +
Use the `printf()` function.
+
+ +

will produce:

+ +
<p>Use the <code>printf()</code> function.</p>
+
+ +

To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters:

+ +
``There is a literal backtick (`) here.``
+
+ +

which will produce this:

+ +
<p><code>There is a literal backtick (`) here.</code></p>
+
+ +

The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span:

+ +
A single backtick in a code span: `` ` ``
+
+A backtick-delimited string in a code span: `` `foo` ``
+
+ +

will produce:

+ +
<p>A single backtick in a code span: <code>`</code></p>
+
+<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
+
+ +

With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this:

+ +
Please don't use any `<blink>` tags.
+
+ +

into:

+ +
<p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
+
+ +

You can write this:

+ +
`&#8212;` is the decimal-encoded equivalent of `&mdash;`.
+
+ +

to produce:

+ +
<p><code>&amp;#8212;</code> is the decimal-encoded
+equivalent of <code>&amp;mdash;</code>.</p>
+
+ +

Images

+ +

Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format.

+ +

Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: inline and reference.

+ +

Inline image syntax looks like this:

+ +
![Alt text](/path/to/img.jpg)
+
+![Alt text](/path/to/img.jpg "Optional title")
+
+ +

That is:

+ +
    +
  • An exclamation mark: !;
  • +
  • followed by a set of square brackets, containing the alt +attribute text for the image;
  • +
  • followed by a set of parentheses, containing the URL or path to +the image, and an optional title attribute enclosed in double +or single quotes.
  • +
+ +

Reference-style image syntax looks like this:

+ +
![Alt text][id]
+
+ +

Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references:

+ +
[id]: url/to/image  "Optional title attribute"
+
+ +

As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML <img> tags.

+ +
+ +

Miscellaneous

+ + + +

Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:

+ +
<http://example.com/>
+
+ +

Markdown will turn this into:

+ +
<a href="http://example.com/">http://example.com/</a>
+
+ +

Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this:

+ +
<address@example.com>
+
+ +

into something like this:

+ +
<a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;
+&#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;
+&#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;
+&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>
+
+ +

which will render in a browser as a clickable link to "address@example.com".

+ +

(This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.)

+ +

Backslash Escapes

+ +

Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML <em> tag), you can backslashes +before the asterisks, like this:

+ +
\*literal asterisks\*
+
+ +

Markdown provides backslash escapes for the following characters:

+ +
\   backslash
+`   backtick
+*   asterisk
+_   underscore
+{}  curly braces
+[]  square brackets
+()  parentheses
+#   hash mark
++   plus sign
+-   minus sign (hyphen)
+.   dot
+!   exclamation mark
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text new file mode 100644 index 000000000..57360a16c --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text @@ -0,0 +1,888 @@ +Markdown: Syntax +================ + + + + +* [Overview](#overview) + * [Philosophy](#philosophy) + * [Inline HTML](#html) + * [Automatic Escaping for Special Characters](#autoescape) +* [Block Elements](#block) + * [Paragraphs and Line Breaks](#p) + * [Headers](#header) + * [Blockquotes](#blockquote) + * [Lists](#list) + * [Code Blocks](#precode) + * [Horizontal Rules](#hr) +* [Span Elements](#span) + * [Links](#link) + * [Emphasis](#em) + * [Code](#code) + * [Images](#img) +* [Miscellaneous](#misc) + * [Backslash Escapes](#backslash) + * [Automatic Links](#autolink) + + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL][src]. + + [src]: /projects/markdown/syntax.text + +* * * + +

Overview

+ +

Philosophy

+ +Markdown is intended to be as easy-to-read and easy-to-write as is feasible. + +Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +like it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], +[Grutatext] [5], and [EtText] [6] -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email. + + [1]: http://docutils.sourceforge.net/mirror/setext.html + [2]: http://www.aaronsw.com/2002/atx/ + [3]: http://textism.com/tools/textile/ + [4]: http://docutils.sourceforge.net/rst.html + [5]: http://www.triptico.com/software/grutatxt.html + [6]: http://ettext.taint.org/doc/ + +To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look like what they mean. E.g., asterisks around a word actually +look like \*emphasis\*. Markdown lists look like, well, lists. Even +blockquotes look like quoted passages of text, assuming you've ever +used email. + + + +

Inline HTML

+ +Markdown's syntax is intended for one purpose: to be used as a +format for *writing* for the web. + +Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is *not* to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a *publishing* format; Markdown is a *writing* +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text. + +For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags. + +The only restrictions are that block-level HTML elements -- e.g. `
`, +``, `
`, `

`, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) `

` tags around HTML block-level tags. + +For example, to add an HTML table to a Markdown article: + + This is a regular paragraph. + +

+ + + +
Foo
+ + This is another regular paragraph. + +Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an +HTML block. + +Span-level HTML tags -- e.g. ``, ``, or `` -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML `` or `` tags instead of Markdown's +link or image syntax, go right ahead. + +Unlike block-level HTML tags, Markdown syntax *is* processed within +span-level tags. + + +

Automatic Escaping for Special Characters

+ +In HTML, there are two characters that demand special treatment: `<` +and `&`. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. `<`, and +`&`. + +Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write '`AT&T`'. You even need to +escape ampersands within URLs. Thus, if you want to link to: + + http://images.google.com/images?num=30&q=larry+bird + +you need to encode the URL as: + + http://images.google.com/images?num=30&q=larry+bird + +in your anchor tag `href` attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites. + +Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into `&`. + +So, if you want to include a copyright symbol in your article, you can write: + + © + +and Markdown will leave it alone. But if you write: + + AT&T + +Markdown will translate it to: + + AT&T + +Similarly, because Markdown supports [inline HTML](#html), if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write: + + 4 < 5 + +Markdown will translate it to: + + 4 < 5 + +However, inside Markdown code spans and blocks, angle brackets and +ampersands are *always* encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single `<` +and `&` in your example code needs to be escaped.) + + +* * * + + +

Block Elements

+ + +

Paragraphs and Line Breaks

+ +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks like a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a `
` tag. + +When you *do* want to insert a `
` break tag using Markdown, you +end a line with two or more spaces, then type return. + +Yes, this takes a tad more effort to create a `
`, but a simplistic +"every line break is a `
`" rule wouldn't work for Markdown. +Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] +work best -- and look better -- when you format them with hard breaks. + + [bq]: #blockquote + [l]: #list + + + + + +Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. + +Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example: + + This is an H1 + ============= + + This is an H2 + ------------- + +Any number of underlining `=`'s or `-`'s will work. + +Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example: + + # This is an H1 + + ## This is an H2 + + ###### This is an H6 + +Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) : + + # This is an H1 # + + ## This is an H2 ## + + ### This is an H3 ###### + + +

Blockquotes

+ +Markdown uses email-style `>` characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a `>` before every line: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + > + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + > id sem consectetuer libero luctus adipiscing. + +Markdown allows you to be lazy and only put the `>` before the first +line of a hard-wrapped paragraph: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + id sem consectetuer libero luctus adipiscing. + +Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of `>`: + + > This is the first level of quoting. + > + > > This is nested blockquote. + > + > Back to the first level. + +Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks: + + > ## This is a header. + > + > 1. This is the first list item. + > 2. This is the second list item. + > + > Here's some example code: + > + > return shell_exec("echo $input | $markdown_script"); + +Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu. + + +

Lists

+ +Markdown supports ordered (numbered) and unordered (bulleted) lists. + +Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers: + + * Red + * Green + * Blue + +is equivalent to: + + + Red + + Green + + Blue + +and: + + - Red + - Green + - Blue + +Ordered lists use numbers followed by periods: + + 1. Bird + 2. McHale + 3. Parish + +It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is: + +
    +
  1. Bird
  2. +
  3. McHale
  4. +
  5. Parish
  6. +
+ +If you instead wrote the list in Markdown like this: + + 1. Bird + 1. McHale + 1. Parish + +or even: + + 3. Bird + 1. McHale + 8. Parish + +you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to. + +If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number. + +List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab. + +To make lists look nice, you can wrap items with hanging indents: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +But if you want to be lazy, you don't have to: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +If list items are separated by blank lines, Markdown will wrap the +items in `

` tags in the HTML output. For example, this input: + + * Bird + * Magic + +will turn into: + +

    +
  • Bird
  • +
  • Magic
  • +
+ +But this: + + * Bird + + * Magic + +will turn into: + +
    +
  • Bird

  • +
  • Magic

  • +
+ +List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab: + + 1. This is a list item with two paragraphs. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. Aliquam hendrerit + mi posuere lectus. + + Vestibulum enim wisi, viverra nec, fringilla in, laoreet + vitae, risus. Donec sit amet nisl. Aliquam semper ipsum + sit amet velit. + + 2. Suspendisse id sem consectetuer libero luctus adipiscing. + +It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy: + + * This is a list item with two paragraphs. + + This is the second paragraph in the list item. You're + only required to indent the first line. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. + + * Another item in the same list. + +To put a blockquote within a list item, the blockquote's `>` +delimiters need to be indented: + + * A list item with a blockquote: + + > This is a blockquote + > inside a list item. + +To put a code block within a list item, the code block needs +to be indented *twice* -- 8 spaces or two tabs: + + * A list item with a code block: + + + + +It's worth noting that it's possible to trigger an ordered list by +accident, by writing something like this: + + 1986. What a great season. + +In other words, a *number-period-space* sequence at the beginning of a +line. To avoid this, you can backslash-escape the period: + + 1986\. What a great season. + + + +

Code Blocks

+ +Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both `
` and `` tags.
+
+To produce a code block in Markdown, simply indent every line of the
+block by at least 4 spaces or 1 tab. For example, given this input:
+
+    This is a normal paragraph:
+
+        This is a code block.
+
+Markdown will generate:
+
+    

This is a normal paragraph:

+ +
This is a code block.
+    
+ +One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this: + + Here is an example of AppleScript: + + tell application "Foo" + beep + end tell + +will turn into: + +

Here is an example of AppleScript:

+ +
tell application "Foo"
+        beep
+    end tell
+    
+ +A code block continues until it reaches a line that is not indented +(or the end of the article). + +Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this: + + + +will turn into: + +
<div class="footer">
+        &copy; 2004 Foo Corporation
+    </div>
+    
+ +Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax. + + + +

Horizontal Rules

+ +You can produce a horizontal rule tag (`
`) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule: + + * * * + + *** + + ***** + + - - - + + --------------------------------------- + + _ _ _ + + +* * * + +

Span Elements

+ + + +Markdown supports two style of links: *inline* and *reference*. + +In both styles, the link text is delimited by [square brackets]. + +To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an *optional* +title for the link, surrounded in quotes. For example: + + This is [an example](http://example.com/ "Title") inline link. + + [This link](http://example.net/) has no title attribute. + +Will produce: + +

This is + an example inline link.

+ +

This link has no + title attribute.

+ +If you're referring to a local resource on the same server, you can +use relative paths: + + See my [About](/about/) page for details. + +Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link: + + This is [an example][id] reference-style link. + +You can optionally use a space to separate the sets of brackets: + + This is [an example] [id] reference-style link. + +Then, anywhere in the document, you define your link label like this, +on a line by itself: + + [id]: http://example.com/ "Optional Title Here" + +That is: + +* Square brackets containing the link identifier (optionally + indented from the left margin using up to three spaces); +* followed by a colon; +* followed by one or more spaces (or tabs); +* followed by the URL for the link; +* optionally followed by a title attribute for the link, enclosed + in double or single quotes. + +The link URL may, optionally, be surrounded by angle brackets: + + [id]: "Optional Title Here" + +You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs: + + [id]: http://example.com/longish/path/to/resource/here + "Optional Title Here" + +Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output. + +Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: + + [link text][a] + [link text][A] + +are equivalent. + +The *implicit link name* shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write: + + [Google][] + +And then define the link: + + [Google]: http://google.com/ + +Because link names may contain spaces, this shortcut even works for +multiple words in the link text: + + Visit [Daring Fireball][] for more information. + +And then define the link: + + [Daring Fireball]: http://daringfireball.net/ + +Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of like footnotes. + +Here's an example of reference links in action: + + I get 10 times more traffic from [Google] [1] than from + [Yahoo] [2] or [MSN] [3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Using the implicit link name shortcut, you could instead write: + + I get 10 times more traffic from [Google][] than from + [Yahoo][] or [MSN][]. + + [google]: http://google.com/ "Google" + [yahoo]: http://search.yahoo.com/ "Yahoo Search" + [msn]: http://search.msn.com/ "MSN Search" + +Both of the above examples will produce the following HTML output: + +

I get 10 times more traffic from Google than from + Yahoo + or MSN.

+ +For comparison, here is the same paragraph written using +Markdown's inline link style: + + I get 10 times more traffic from [Google](http://google.com/ "Google") + than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or + [MSN](http://search.msn.com/ "MSN Search"). + +The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text. + +With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose. + + +

Emphasis

+ +Markdown treats asterisks (`*`) and underscores (`_`) as indicators of +emphasis. Text wrapped with one `*` or `_` will be wrapped with an +HTML `` tag; double `*`'s or `_`'s will be wrapped with an HTML +`` tag. E.g., this input: + + *single asterisks* + + _single underscores_ + + **double asterisks** + + __double underscores__ + +will produce: + + single asterisks + + single underscores + + double asterisks + + double underscores + +You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span. + +Emphasis can be used in the middle of a word: + + un*fucking*believable + +But if you surround an `*` or `_` with spaces, it'll be treated as a +literal asterisk or underscore. + +To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it: + + \*this text is surrounded by literal asterisks\* + + + +

Code

+ +To indicate a span of code, wrap it with backtick quotes (`` ` ``). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example: + + Use the `printf()` function. + +will produce: + +

Use the printf() function.

+ +To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters: + + ``There is a literal backtick (`) here.`` + +which will produce this: + +

There is a literal backtick (`) here.

+ +The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span: + + A single backtick in a code span: `` ` `` + + A backtick-delimited string in a code span: `` `foo` `` + +will produce: + +

A single backtick in a code span: `

+ +

A backtick-delimited string in a code span: `foo`

+ +With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this: + + Please don't use any `` tags. + +into: + +

Please don't use any <blink> tags.

+ +You can write this: + + `—` is the decimal-encoded equivalent of `—`. + +to produce: + +

&#8212; is the decimal-encoded + equivalent of &mdash;.

+ + + +

Images

+ +Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format. + +Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: *inline* and *reference*. + +Inline image syntax looks like this: + + ![Alt text](/path/to/img.jpg) + + ![Alt text](/path/to/img.jpg "Optional title") + +That is: + +* An exclamation mark: `!`; +* followed by a set of square brackets, containing the `alt` + attribute text for the image; +* followed by a set of parentheses, containing the URL or path to + the image, and an optional `title` attribute enclosed in double + or single quotes. + +Reference-style image syntax looks like this: + + ![Alt text][id] + +Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references: + + [id]: url/to/image "Optional title attribute" + +As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML `` tags. + + +* * * + + +

Miscellaneous

+ + + +Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: + + + +Markdown will turn this into: + + http://example.com/ + +Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this: + + + +into something like this: + + address@exa + mple.com + +which will render in a browser as a clickable link to "address@example.com". + +(This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.) + + + +

Backslash Escapes

+ +Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML `` tag), you can backslashes +before the asterisks, like this: + + \*literal asterisks\* + +Markdown provides backslash escapes for the following characters: + + \ backslash + ` backtick + * asterisk + _ underscore + {} curly braces + [] square brackets + () parentheses + # hash mark + + plus sign + - minus sign (hyphen) + . dot + ! exclamation mark + diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Nested blockquotes.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Nested blockquotes.html new file mode 100644 index 000000000..d8ec7f8e0 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Nested blockquotes.html @@ -0,0 +1,9 @@ +
+

foo

+ +
+

bar

+
+ +

foo

+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Nested blockquotes.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Nested blockquotes.text new file mode 100644 index 000000000..ed3c624ff --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Nested blockquotes.text @@ -0,0 +1,5 @@ +> foo +> +> > bar +> +> foo diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html new file mode 100644 index 000000000..ba71eab39 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html @@ -0,0 +1,148 @@ +

Unordered

+ +

Asterisks tight:

+ +
    +
  • asterisk 1
  • +
  • asterisk 2
  • +
  • asterisk 3
  • +
+ +

Asterisks loose:

+ +
    +
  • asterisk 1

  • +
  • asterisk 2

  • +
  • asterisk 3

  • +
+ +
+ +

Pluses tight:

+ +
    +
  • Plus 1
  • +
  • Plus 2
  • +
  • Plus 3
  • +
+ +

Pluses loose:

+ +
    +
  • Plus 1

  • +
  • Plus 2

  • +
  • Plus 3

  • +
+ +
+ +

Minuses tight:

+ +
    +
  • Minus 1
  • +
  • Minus 2
  • +
  • Minus 3
  • +
+ +

Minuses loose:

+ +
    +
  • Minus 1

  • +
  • Minus 2

  • +
  • Minus 3

  • +
+ +

Ordered

+ +

Tight:

+ +
    +
  1. First
  2. +
  3. Second
  4. +
  5. Third
  6. +
+ +

and:

+ +
    +
  1. One
  2. +
  3. Two
  4. +
  5. Three
  6. +
+ +

Loose using tabs:

+ +
    +
  1. First

  2. +
  3. Second

  4. +
  5. Third

  6. +
+ +

and using spaces:

+ +
    +
  1. One

  2. +
  3. Two

  4. +
  5. Three

  6. +
+ +

Multiple paragraphs:

+ +
    +
  1. Item 1, graf one.

    + +

    Item 2. graf two. The quick brown fox jumped over the lazy dog's +back.

  2. +
  3. Item 2.

  4. +
  5. Item 3.

  6. +
+ +

Nested

+ +
    +
  • Tab +
      +
    • Tab +
        +
      • Tab
      • +
    • +
  • +
+ +

Here's another:

+ +
    +
  1. First
  2. +
  3. Second: +
      +
    • Fee
    • +
    • Fie
    • +
    • Foe
    • +
  4. +
  5. Third
  6. +
+ +

Same thing but with paragraphs:

+ +
    +
  1. First

  2. +
  3. Second:

    + +
      +
    • Fee
    • +
    • Fie
    • +
    • Foe
    • +
  4. +
  5. Third

  6. +
+ + +

This was an error in Markdown 1.0.1:

+ +
    +
  • this

    + +
    • sub
    + +

    that

  • +
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text new file mode 100644 index 000000000..7f3b49777 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text @@ -0,0 +1,131 @@ +## Unordered + +Asterisks tight: + +* asterisk 1 +* asterisk 2 +* asterisk 3 + + +Asterisks loose: + +* asterisk 1 + +* asterisk 2 + +* asterisk 3 + +* * * + +Pluses tight: + ++ Plus 1 ++ Plus 2 ++ Plus 3 + + +Pluses loose: + ++ Plus 1 + ++ Plus 2 + ++ Plus 3 + +* * * + + +Minuses tight: + +- Minus 1 +- Minus 2 +- Minus 3 + + +Minuses loose: + +- Minus 1 + +- Minus 2 + +- Minus 3 + + +## Ordered + +Tight: + +1. First +2. Second +3. Third + +and: + +1. One +2. Two +3. Three + + +Loose using tabs: + +1. First + +2. Second + +3. Third + +and using spaces: + +1. One + +2. Two + +3. Three + +Multiple paragraphs: + +1. Item 1, graf one. + + Item 2. graf two. The quick brown fox jumped over the lazy dog's + back. + +2. Item 2. + +3. Item 3. + + + +## Nested + +* Tab + * Tab + * Tab + +Here's another: + +1. First +2. Second: + * Fee + * Fie + * Foe +3. Third + +Same thing but with paragraphs: + +1. First + +2. Second: + * Fee + * Fie + * Foe + +3. Third + + +This was an error in Markdown 1.0.1: + +* this + + * sub + + that diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Strong and em together.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Strong and em together.html new file mode 100644 index 000000000..71ec78c70 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Strong and em together.html @@ -0,0 +1,7 @@ +

This is strong and em.

+ +

So is this word.

+ +

This is strong and em.

+ +

So is this word.

diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Strong and em together.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Strong and em together.text new file mode 100644 index 000000000..95ee690db --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Strong and em together.text @@ -0,0 +1,7 @@ +***This is strong and em.*** + +So is ***this*** word. + +___This is strong and em.___ + +So is ___this___ word. diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tabs.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tabs.html new file mode 100644 index 000000000..3301ba803 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tabs.html @@ -0,0 +1,25 @@ +
    +
  • this is a list item +indented with tabs

  • +
  • this is a list item +indented with spaces

  • +
+ +

Code:

+ +
this code block is indented by one tab
+
+ +

And:

+ +
    this code block is indented by two tabs
+
+ +

And:

+ +
+   this is an example list item
+    indented with tabs
+
++   this is an example list item
+    indented with spaces
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tabs.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tabs.text new file mode 100644 index 000000000..589d1136e --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tabs.text @@ -0,0 +1,21 @@ ++ this is a list item + indented with tabs + ++ this is a list item + indented with spaces + +Code: + + this code block is indented by one tab + +And: + + this code block is indented by two tabs + +And: + + + this is an example list item + indented with tabs + + + this is an example list item + indented with spaces diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tidyness.html b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tidyness.html new file mode 100644 index 000000000..f2a8ce70f --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tidyness.html @@ -0,0 +1,8 @@ +
+

A list within a blockquote:

+
    +
  • asterisk 1
  • +
  • asterisk 2
  • +
  • asterisk 3
  • +
+
diff --git a/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tidyness.text b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tidyness.text new file mode 100644 index 000000000..5f18b8da2 --- /dev/null +++ b/supportlibs/pegmarkdown/MarkdownTest_1.0.3/Tests/Tidyness.text @@ -0,0 +1,5 @@ +> A list within a blockquote: +> +> * asterisk 1 +> * asterisk 2 +> * asterisk 3 diff --git a/supportlibs/pegmarkdown/README.markdown b/supportlibs/pegmarkdown/README.markdown new file mode 100644 index 000000000..409c5e3fe --- /dev/null +++ b/supportlibs/pegmarkdown/README.markdown @@ -0,0 +1,225 @@ + +This a forked version of peg-markdown.... only minor changes: + + * Switch to Qt .pro make system for easy x-platform. + + * build a library instead of exec. + + * Add GLibFacade from multimarkdown to allow Win32 compilations. + + * Added ifdefs for C++ linking, + + +What is this? +============= + +This is an implementation of John Gruber's [markdown][] in C. It uses a +[parsing expression grammar (PEG)][] to define the syntax. This should +allow easy modification and extension. It currently supports output in +HTML, LaTeX, ODF, or groff_mm formats, and adding new formats is +relatively easy. + +[parsing expression grammar (PEG)]: http://en.wikipedia.org/wiki/Parsing_expression_grammar +[markdown]: http://daringfireball.net/projects/markdown/ + +It is pretty fast. A 179K text file that takes 5.7 seconds for +Markdown.pl (v. 1.0.1) to parse takes less than 0.2 seconds for this +markdown. It does, however, use a lot of memory (up to 4M of heap space +while parsing the 179K file, and up to 80K for a 4K file). (Note that +the memory leaks in earlier versions of this program have now been +plugged.) + +Both a library and a standalone program are provided. + +peg-markdown is written and maintained by John MacFarlane (jgm on +github), with significant contributions by Ryan Tomayko (rtomayko). +It is released under both the GPL and the MIT license; see LICENSE for +details. + +Installing +========== + +On a linux or unix-based system +------------------------------- + +This program is written in portable ANSI C. It requires +[glib2](http://www.gtk.org/download/index.php). Most *nix systems will have +this installed already. The build system requires GNU make. + +The other required dependency, [Ian Piumarta's peg/leg PEG parser +generator](http://piumarta.com/software/peg/), is included in the source +directory. It will be built automatically. (However, it is not as portable +as peg-markdown itself, and seems to require gcc.) + +To make the 'markdown' executable: + + make + +(Or, on some systems, `gmake`.) Then, for usage instructions: + + ./markdown --help + +To run John Gruber's Markdown 1.0.3 test suite: + + make test + +The test suite will fail on one of the list tests. Here's why. +Markdown.pl encloses "item one" in the following list in `

` tags: + + 1. item one + * subitem + * subitem + + 2. item two + + 3. item three + +peg-markdown does not enclose "item one" in `

` tags unless it has a +following blank line. This is consistent with the official markdown +syntax description, and lets the author of the document choose whether +`

` tags are desired. + +Cross-compiling for Windows with MinGW on a linux box +----------------------------------------------------- + +Prerequisites: + +* Linux system with MinGW cross compiler For Ubuntu: + + sudo apt-get install mingw32 + +* [Windows glib-2.0 binary & development files](http://www.gtk.org/download-windows.html). + Unzip files into cross-compiler directory tree (e.g., `/usr/i586-mingw32msvc`). + +Steps: + +1. Create the markdown parser using Linux-compiled `leg` from peg-0.1.4: + + ./peg-0.1.4/leg markdown_parser.leg >markdown_parser.c + + (Note: The same thing could be accomplished by cross-compiling leg, + executing it on Windows, and copying the resulting C file to the Linux + cross-compiler host.) + +2. Run the cross compiler with include flag for the Windows glib-2.0 headers: + for example, + + /usr/bin/i586-mingw32msvc-cc -c \ + -I/usr/i586-mingw32msvc/include/glib-2.0 \ + -I/usr/i586-mingw32msvc/lib/glib-2.0/include -Wall -O3 -ansi markdown*.c + +3. Link against Windows glib-2.0 headers: for example, + + /usr/bin/i586-mingw32msvc-cc markdown*.o \ + -Wl,-L/usr/i586-mingw32msvc/lib/glib,--dy,--warn-unresolved-symbols,-lglib-2.0 \ + -o markdown.exe + +The resulting executable depends on the glib dll file, so be sure to +load the glib binary on the Windows host. + +Compiling with MinGW on Windows +------------------------------- + +These directions assume that MinGW is installed in `c:\MinGW` and glib-2.0 +is installed in the MinGW directory hierarchy (with the mingw bin directory +in the system path). + +Unzip peg-markdown in a temp directory. From the directory with the +peg-markdown source, execute: + + cd peg-0.1.4 + make PKG_CONFIG=c:/path/to/glib/bin/pkg-config.exe + +Extensions +========== + +peg-markdown supports extensions to standard markdown syntax. +These can be turned on using the command line flag `-x` or +`--extensions`. `-x` by itself turns on all extensions. Extensions +can also be turned on selectively, using individual command-line +options. To see the available extensions: + + ./markdown --help-extensions + +The `--smart` extension provides "smart quotes", dashes, and ellipses. + +The `--notes` extension provides a footnote syntax like that of +Pandoc or PHP Markdown Extra. + +Using the library +================= + +The library exports two functions: + + GString * markdown_to_g_string(char *text, int extensions, int output_format); + char * markdown_to_string(char *text, int extensions, int output_format); + +The only difference between these is that `markdown_to_g_string` returns a +`GString` (glib's automatically resizable string), while `markdown_to_string` +returns a regular character pointer. The memory allocated for these must be +freed by the calling program, using `g_string_free()` or `free()`. + +`text` is the markdown-formatted text to be converted. Note that tabs will +be converted to spaces, using a four-space tab stop. Character encodings are +ignored. + +`extensions` is a bit-field specifying which syntax extensions should be used. +If `extensions` is 0, no extensions will be used. If it is `0xFFFFFF`, +all extensions will be used. To set extensions selectively, use the +bitwise `&` operator and the following constants: + + - `EXT_SMART` turns on smart quotes, dashes, and ellipses. + - `EXT_NOTES` turns on footnote syntax. [Pandoc's footnote syntax][] is used here. + - `EXT_FILTER_HTML` filters out raw HTML (except for styles). + - `EXT_FILTER_STYLES` filters out styles in HTML. + + [Pandoc's footnote syntax]: http://johnmacfarlane.net/pandoc/README.html#footnotes + +`output_format` is either `HTML_FORMAT`, `LATEX_FORMAT`, `ODF_FORMAT`, +or `GROFF_MM_FORMAT`. + +To use the library, include `markdown_lib.h`. See `markdown.c` for an example. + +Hacking +======= + +It should be pretty easy to modify the program to produce other formats, +and to parse syntax extensions. A quick guide: + + * `markdown_parser.leg` contains the grammar itself. + + * `markdown_output.c` contains functions for printing the `Element` + structure in various output formats. + + * To add an output format, add the format to `markdown_formats` in + `markdown_lib.h`. Then modify `print_element` in `markdown_output.c`, + and add functions `print_XXXX_string`, `print_XXXX_element`, and + `print_XXXX_element_list`. Also add an option in the main program + that selects the new format. Don't forget to add it to the list of + formats in the usage message. + + * To add syntax extensions, define them in the PEG grammar + (`markdown_parser.leg`), using existing extensions as a guide. New + inline elements will need to be added to `Inline =`; new block + elements will need to be added to `Block =`. (Note: the order + of the alternatives does matter in PEG grammars.) + + * If you need to add new types of elements, modify the `keys` + enum in `markdown_peg.h`. + + * By using `&{ }` rules one can selectively disable extensions + depending on command-line options. For example, + `&{ extension(EXT_SMART) }` succeeds only if the `EXT_SMART` bit + of the global `syntax_extensions` is set. Add your option to + `markdown_extensions` in `markdown_lib.h`, and add an option in + `markdown.c` to turn on your extension. + + * Note: Avoid using `[^abc]` character classes in the grammar, because + they cause problems with non-ascii input. Instead, use: `( !'a' !'b' + !'c' . )` + +Acknowledgements +================ + +Support for ODF output was added by Fletcher T. Penney. + diff --git a/supportlibs/pegmarkdown/glib.h b/supportlibs/pegmarkdown/glib.h new file mode 100644 index 000000000..eafb859ff --- /dev/null +++ b/supportlibs/pegmarkdown/glib.h @@ -0,0 +1,11 @@ +/* + * glib.h + * MultiMarkdown + * + * Created by Daniel Jalkut on 7/26/11. + * Copyright 2011 __MyCompanyName__. All rights reserved. + * + */ + +/* Just a dummy file to keep the glib-dependent sources compiling as we would hope */ +#include "GLibFacade.h" diff --git a/supportlibs/pegmarkdown/markdown.c b/supportlibs/pegmarkdown/markdown.c new file mode 100644 index 000000000..ca277e529 --- /dev/null +++ b/supportlibs/pegmarkdown/markdown.c @@ -0,0 +1,183 @@ +/********************************************************************** + + markdown.c - markdown in C using a PEG grammar. + (c) 2008 John MacFarlane (jgm at berkeley dot edu). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License or the MIT + license. See LICENSE for details. + + 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. + + ***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "markdown_peg.h" + +static int extensions; + +/********************************************************************** + + The main program is just a wrapper around the library functions in + markdown_lib.c. It parses command-line options, reads the text to + be converted from input files or stdin, converts the text, and sends + the output to stdout or a file. Character encodings are ignored. + + ***********************************************************************/ + +#define VERSION "0.4.14" +#define COPYRIGHT "Copyright (c) 2008-2009 John MacFarlane. License GPLv2+ or MIT.\n" \ + "This is free software: you are free to change and redistribute it.\n" \ + "There is NO WARRANTY, to the extent permitted by law." + +/* print version and copyright information */ +void version(const char *progname) +{ + printf("peg-markdown version %s\n" + "%s\n", + VERSION, + COPYRIGHT); +} + +int main(int argc, char * argv[]) { + + int numargs; /* number of filename arguments */ + int i; + + GString *inputbuf; + char *out; /* string containing processed output */ + + FILE *input; + FILE *output; + char curchar; + char *progname = argv[0]; + + int output_format = HTML_FORMAT; + + /* Code for command-line option parsing. */ + + static gboolean opt_version = FALSE; + static gchar *opt_output = 0; + static gchar *opt_to = 0; + static gboolean opt_smart = FALSE; + static gboolean opt_notes = FALSE; + static gboolean opt_filter_html = FALSE; + static gboolean opt_filter_styles = FALSE; + static gboolean opt_allext = FALSE; + + static GOptionEntry entries[] = + { + { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, "print version and exit", NULL }, + { "output", 'o', 0, G_OPTION_ARG_STRING, &opt_output, "send output to FILE (default is stdout)", "FILE" }, + { "to", 't', 0, G_OPTION_ARG_STRING, &opt_to, "convert to FORMAT (default is html)", "FORMAT" }, + { "extensions", 'x', 0, G_OPTION_ARG_NONE, &opt_allext, "use all syntax extensions", NULL }, + { "filter-html", 0, 0, G_OPTION_ARG_NONE, &opt_filter_html, "filter out raw HTML (except styles)", NULL }, + { "filter-styles", 0, 0, G_OPTION_ARG_NONE, &opt_filter_styles, "filter out HTML styles", NULL }, + { NULL } + }; + + /* Options to active syntax extensions. These appear separately in --help. */ + static GOptionEntry ext_entries[] = + { + { "smart", 0, 0, G_OPTION_ARG_NONE, &opt_smart, "use smart typography extension", NULL }, + { "notes", 0, 0, G_OPTION_ARG_NONE, &opt_notes, "use notes extension", NULL }, + { NULL } + }; + + GError *error = NULL; + GOptionContext *context; + GOptionGroup *ext_group; + + context = g_option_context_new ("[FILE...]"); + g_option_context_add_main_entries (context, entries, NULL); + ext_group = g_option_group_new ("extensions", "Syntax extensions", "show available syntax extensions", NULL, NULL); + g_option_group_add_entries (ext_group, ext_entries); + g_option_context_add_group (context, ext_group); + g_option_context_set_description (context, "Converts text in specified files (or stdin) from markdown to FORMAT.\n" + "Available FORMATs: html, latex, groff-mm, odf"); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("option parsing failed: %s\n", error->message); + exit (1); + } + g_option_context_free(context); + + /* Process command-line options and arguments. */ + + if (opt_version) { + version(progname); + return EXIT_SUCCESS; + } + + extensions = 0; + if (opt_allext) + extensions = 0xFFFFFF; /* turn on all extensions */ + if (opt_smart) + extensions = extensions | EXT_SMART; + if (opt_notes) + extensions = extensions | EXT_NOTES; + if (opt_filter_html) + extensions = extensions | EXT_FILTER_HTML; + if (opt_filter_styles) + extensions = extensions | EXT_FILTER_STYLES; + + if (opt_to == NULL) + output_format = HTML_FORMAT; + else if (strcmp(opt_to, "html") == 0) + output_format = HTML_FORMAT; + else if (strcmp(opt_to, "latex") == 0) + output_format = LATEX_FORMAT; + else if (strcmp(opt_to, "groff-mm") == 0) + output_format = GROFF_MM_FORMAT; + else if (strcmp(opt_to, "odf") == 0) + output_format = ODF_FORMAT; + else { + fprintf(stderr, "%s: Unknown output format '%s'\n", progname, opt_to); + exit(EXIT_FAILURE); + } + + /* we allow "-" as a synonym for stdout here */ + if (opt_output == NULL || strcmp(opt_output, "-") == 0) + output = stdout; + else if (!(output = fopen(opt_output, "w"))) { + perror(opt_output); + return 1; + } + + inputbuf = g_string_new(""); /* string for concatenated input */ + + /* Read input from stdin or input files into inputbuf */ + + numargs = argc - 1; + if (numargs == 0) { /* use stdin if no files specified */ + while ((curchar = fgetc(stdin)) != EOF) + g_string_append_c(inputbuf, curchar); + fclose(stdin); + } + else { /* open all the files on command line */ + for (i = 0; i < numargs; i++) { + if ((input = fopen(argv[i+1], "r")) == NULL) { + perror(argv[i+1]); + exit(EXIT_FAILURE); + } + while ((curchar = fgetc(input)) != EOF) + g_string_append_c(inputbuf, curchar); + fclose(input); + } + } + + out = markdown_to_string(inputbuf->str, extensions, output_format); + fprintf(output, "%s\n", out); + free(out); + + g_string_free(inputbuf, true); + + return(EXIT_SUCCESS); +} diff --git a/supportlibs/pegmarkdown/markdown_lib.c b/supportlibs/pegmarkdown/markdown_lib.c new file mode 100644 index 000000000..628fce29f --- /dev/null +++ b/supportlibs/pegmarkdown/markdown_lib.c @@ -0,0 +1,181 @@ +/********************************************************************** + + markdown_lib.c - markdown in C using a PEG grammar. + (c) 2008 John MacFarlane (jgm at berkeley dot edu). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License or the MIT + license. See LICENSE for details. + + 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. + + ***********************************************************************/ + +#include +#include +#include +#include "markdown_peg.h" + +#define TABSTOP 4 + +/* preformat_text - allocate and copy text buffer while + * performing tab expansion. */ +static GString *preformat_text(char *text) { + GString *buf; + char next_char; + int charstotab; + + int len = 0; + + buf = g_string_new(""); + + charstotab = TABSTOP; + while ((next_char = *text++) != '\0') { + switch (next_char) { + case '\t': + while (charstotab > 0) + g_string_append_c(buf, ' '), len++, charstotab--; + break; + case '\n': + g_string_append_c(buf, '\n'), len++, charstotab = TABSTOP; + break; + default: + g_string_append_c(buf, next_char), len++, charstotab--; + } + if (charstotab == 0) + charstotab = TABSTOP; + } + g_string_append(buf, "\n\n"); + return(buf); +} + +/* print_tree - print tree of elements, for debugging only. */ +static void print_tree(element * elt, int indent) { + int i; + char * key; + while (elt != NULL) { + for (i = 0; i < indent; i++) + fputc(' ', stderr); + switch (elt->key) { + case LIST: key = "LIST"; break; + case RAW: key = "RAW"; break; + case SPACE: key = "SPACE"; break; + case LINEBREAK: key = "LINEBREAK"; break; + case ELLIPSIS: key = "ELLIPSIS"; break; + case EMDASH: key = "EMDASH"; break; + case ENDASH: key = "ENDASH"; break; + case APOSTROPHE: key = "APOSTROPHE"; break; + case SINGLEQUOTED: key = "SINGLEQUOTED"; break; + case DOUBLEQUOTED: key = "DOUBLEQUOTED"; break; + case STR: key = "STR"; break; + case LINK: key = "LINK"; break; + case IMAGE: key = "IMAGE"; break; + case CODE: key = "CODE"; break; + case HTML: key = "HTML"; break; + case EMPH: key = "EMPH"; break; + case STRONG: key = "STRONG"; break; + case PLAIN: key = "PLAIN"; break; + case PARA: key = "PARA"; break; + case LISTITEM: key = "LISTITEM"; break; + case BULLETLIST: key = "BULLETLIST"; break; + case ORDEREDLIST: key = "ORDEREDLIST"; break; + case H1: key = "H1"; break; + case H2: key = "H2"; break; + case H3: key = "H3"; break; + case H4: key = "H4"; break; + case H5: key = "H5"; break; + case H6: key = "H6"; break; + case BLOCKQUOTE: key = "BLOCKQUOTE"; break; + case VERBATIM: key = "VERBATIM"; break; + case HTMLBLOCK: key = "HTMLBLOCK"; break; + case HRULE: key = "HRULE"; break; + case REFERENCE: key = "REFERENCE"; break; + case NOTE: key = "NOTE"; break; + default: key = "?"; + } + if ( elt->key == STR ) { + fprintf(stderr, "0x%p: %s '%s'\n", (void *)elt, key, elt->contents.str); + } else { + fprintf(stderr, "0x%p: %s\n", (void *)elt, key); + } + if (elt->children) + print_tree(elt->children, indent + 4); + elt = elt->next; + } +} + +/* process_raw_blocks - traverses an element list, replacing any RAW elements with + * the result of parsing them as markdown text, and recursing into the children + * of parent elements. The result should be a tree of elements without any RAWs. */ +static element * process_raw_blocks(element *input, int extensions, element *references, element *notes) { + element *current = NULL; + element *last_child = NULL; + char *contents; + current = input; + + while (current != NULL) { + if (current->key == RAW) { + /* \001 is used to indicate boundaries between nested lists when there + * is no blank line. We split the string by \001 and parse + * each chunk separately. */ + contents = strtok(current->contents.str, "\001"); + current->key = LIST; + current->children = parse_markdown(contents, extensions, references, notes); + last_child = current->children; + while ((contents = strtok(NULL, "\001"))) { + while (last_child->next != NULL) + last_child = last_child->next; + last_child->next = parse_markdown(contents, extensions, references, notes); + } + free(current->contents.str); + current->contents.str = NULL; + } + if (current->children != NULL) + current->children = process_raw_blocks(current->children, extensions, references, notes); + current = current->next; + } + return input; +} + +/* markdown_to_gstring - convert markdown text to the output format specified. + * Returns a GString, which must be freed after use using g_string_free(). */ +GString * markdown_to_g_string(char *text, int extensions, int output_format) { + element *result; + element *references; + element *notes; + GString *formatted_text; + GString *out; + out = g_string_new(""); + + formatted_text = preformat_text(text); + + references = parse_references(formatted_text->str, extensions); + notes = parse_notes(formatted_text->str, extensions, references); + result = parse_markdown(formatted_text->str, extensions, references, notes); + + result = process_raw_blocks(result, extensions, references, notes); + + g_string_free(formatted_text, TRUE); + + print_element_list(out, result, output_format, extensions); + + free_element_list(result); + free_element_list(references); + return out; +} + +/* markdown_to_string - convert markdown text to the output format specified. + * Returns a null-terminated string, which must be freed after use. */ +char * markdown_to_string(char *text, int extensions, int output_format) { + GString *out; + char *char_out; + out = markdown_to_g_string(text, extensions, output_format); + char_out = out->str; + g_string_free(out, FALSE); + return char_out; +} + +/* vim:set ts=4 sw=4: */ diff --git a/supportlibs/pegmarkdown/markdown_lib.h b/supportlibs/pegmarkdown/markdown_lib.h new file mode 100644 index 000000000..c13a567d3 --- /dev/null +++ b/supportlibs/pegmarkdown/markdown_lib.h @@ -0,0 +1,38 @@ +#ifndef MARKDOWN_LIB_H +#define MARKDOWN_LIB_H + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +enum markdown_extensions { + EXT_SMART = 0x01, + EXT_NOTES = 0x02, + EXT_FILTER_HTML = 0x04, + EXT_FILTER_STYLES = 0x08 +}; + +enum markdown_formats { + HTML_FORMAT, + LATEX_FORMAT, + GROFF_MM_FORMAT, + ODF_FORMAT +}; + +GString * markdown_to_g_string(char *text, int extensions, int output_format); +char * markdown_to_string(char *text, int extensions, int output_format); + + +#ifdef __cplusplus +} +#endif + +/* vim: set ts=4 sw=4 : */ +#endif + diff --git a/supportlibs/pegmarkdown/markdown_output.c b/supportlibs/pegmarkdown/markdown_output.c new file mode 100644 index 000000000..99cbb6bb7 --- /dev/null +++ b/supportlibs/pegmarkdown/markdown_output.c @@ -0,0 +1,1121 @@ +/********************************************************************** + + markdown_output.c - functions for printing Elements parsed by + markdown_peg. + (c) 2008 John MacFarlane (jgm at berkeley dot edu). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License or the MIT + license. See LICENSE for details. + + 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. + + ***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "markdown_peg.h" +#include "odf.h" + +static int extensions; +static int odf_type = 0; + +static void print_html_string(GString *out, char *str, bool obfuscate); +static void print_html_element_list(GString *out, element *list, bool obfuscate); +static void print_html_element(GString *out, element *elt, bool obfuscate); +static void print_latex_string(GString *out, char *str); +static void print_latex_element_list(GString *out, element *list); +static void print_latex_element(GString *out, element *elt); +static void print_groff_string(GString *out, char *str); +static void print_groff_mm_element_list(GString *out, element *list); +static void print_groff_mm_element(GString *out, element *elt, int count); +static void print_odf_code_string(GString *out, char *str); +static void print_odf_string(GString *out, char *str); +static void print_odf_element_list(GString *out, element *list); +static void print_odf_element(GString *out, element *elt); +static bool list_contains_key(element *list, int key); + +/********************************************************************** + + Utility functions for printing + + ***********************************************************************/ + +static int padded = 2; /* Number of newlines after last output. + Starts at 2 so no newlines are needed at start. + */ + +static GSList *endnotes = NULL; /* List of endnotes to print after main content. */ +static int notenumber = 0; /* Number of footnote. */ + +/* pad - add newlines if needed */ +static void pad(GString *out, int num) { + while (num-- > padded) + g_string_append_printf(out, "\n");; + padded = num; +} + +/* determine whether a certain element is contained within a given list */ +static bool list_contains_key(element *list, int key) { + element *step = NULL; + + step = list; + while ( step != NULL ) { + if (step->key == key) { + return TRUE; + } + if (step->children != NULL) { + if (list_contains_key(step->children, key)) { + return TRUE; + } + } + step = step->next; + } + return FALSE; +} + +/********************************************************************** + + Functions for printing Elements as HTML + + ***********************************************************************/ + +/* print_html_string - print string, escaping for HTML + * If obfuscate selected, convert characters to hex or decimal entities at random */ +static void print_html_string(GString *out, char *str, bool obfuscate) { + while (*str != '\0') { + switch (*str) { + case '&': + g_string_append_printf(out, "&"); + break; + case '<': + g_string_append_printf(out, "<"); + break; + case '>': + g_string_append_printf(out, ">"); + break; + case '"': + g_string_append_printf(out, """); + break; + default: + if (obfuscate) { + if (rand() % 2 == 0) + g_string_append_printf(out, "&#%d;", (int) *str); + else + g_string_append_printf(out, "&#x%x;", (unsigned int) *str); + } + else + g_string_append_c(out, *str); + } + str++; + } +} + +/* print_html_element_list - print a list of elements as HTML */ +static void print_html_element_list(GString *out, element *list, bool obfuscate) { + while (list != NULL) { + print_html_element(out, list, obfuscate); + list = list->next; + } +} + +/* add_endnote - add an endnote to global endnotes list. */ +static void add_endnote(element *elt) { + endnotes = g_slist_prepend(endnotes, elt); +} + +/* print_html_element - print an element as HTML */ +static void print_html_element(GString *out, element *elt, bool obfuscate) { + int lev; + switch (elt->key) { + case SPACE: + g_string_append_printf(out, "%s", elt->contents.str); + break; + case LINEBREAK: + g_string_append_printf(out, "
\n"); + break; + case STR: + print_html_string(out, elt->contents.str, obfuscate); + break; + case ELLIPSIS: + g_string_append_printf(out, "…"); + break; + case EMDASH: + g_string_append_printf(out, "—"); + break; + case ENDASH: + g_string_append_printf(out, "–"); + break; + case APOSTROPHE: + g_string_append_printf(out, "’"); + break; + case SINGLEQUOTED: + g_string_append_printf(out, "‘"); + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, "’"); + break; + case DOUBLEQUOTED: + g_string_append_printf(out, "“"); + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, "”"); + break; + case CODE: + g_string_append_printf(out, ""); + print_html_string(out, elt->contents.str, obfuscate); + g_string_append_printf(out, ""); + break; + case HTML: + g_string_append_printf(out, "%s", elt->contents.str); + break; + case LINK: + if (strstr(elt->contents.link->url, "mailto:") == elt->contents.link->url) + obfuscate = true; /* obfuscate mailto: links */ + g_string_append_printf(out, "contents.link->url, obfuscate); + g_string_append_printf(out, "\""); + if (strlen(elt->contents.link->title) > 0) { + g_string_append_printf(out, " title=\""); + print_html_string(out, elt->contents.link->title, obfuscate); + g_string_append_printf(out, "\""); + } + g_string_append_printf(out, ">"); + print_html_element_list(out, elt->contents.link->label, obfuscate); + g_string_append_printf(out, ""); + break; + case IMAGE: + g_string_append_printf(out, "contents.link->url, obfuscate); + g_string_append_printf(out, "\" alt=\""); + print_html_element_list(out, elt->contents.link->label, obfuscate); + g_string_append_printf(out, "\""); + if (strlen(elt->contents.link->title) > 0) { + g_string_append_printf(out, " title=\""); + print_html_string(out, elt->contents.link->title, obfuscate); + g_string_append_printf(out, "\""); + } + g_string_append_printf(out, " />"); + break; + case EMPH: + g_string_append_printf(out, ""); + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, ""); + break; + case STRONG: + g_string_append_printf(out, ""); + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, ""); + break; + case LIST: + print_html_element_list(out, elt->children, obfuscate); + break; + case RAW: + /* Shouldn't occur - these are handled by process_raw_blocks() */ + assert(elt->key != RAW); + break; + case H1: case H2: case H3: case H4: case H5: case H6: + lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */ + pad(out, 2); + g_string_append_printf(out, "", lev); + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, "", lev); + padded = 0; + break; + case PLAIN: + pad(out, 1); + print_html_element_list(out, elt->children, obfuscate); + padded = 0; + break; + case PARA: + pad(out, 2); + g_string_append_printf(out, "

"); + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, "

"); + padded = 0; + break; + case HRULE: + pad(out, 2); + g_string_append_printf(out, "
"); + padded = 0; + break; + case HTMLBLOCK: + pad(out, 2); + g_string_append_printf(out, "%s", elt->contents.str); + padded = 0; + break; + case VERBATIM: + pad(out, 2); + g_string_append_printf(out, "%s", "
");
+        print_html_string(out, elt->contents.str, obfuscate);
+        g_string_append_printf(out, "%s", "
"); + padded = 0; + break; + case BULLETLIST: + pad(out, 2); + g_string_append_printf(out, "%s", "
    "); + padded = 0; + print_html_element_list(out, elt->children, obfuscate); + pad(out, 1); + g_string_append_printf(out, "%s", "
"); + padded = 0; + break; + case ORDEREDLIST: + pad(out, 2); + g_string_append_printf(out, "%s", "
    "); + padded = 0; + print_html_element_list(out, elt->children, obfuscate); + pad(out, 1); + g_string_append_printf(out, "
"); + padded = 0; + break; + case LISTITEM: + pad(out, 1); + g_string_append_printf(out, "
  • "); + padded = 2; + print_html_element_list(out, elt->children, obfuscate); + g_string_append_printf(out, "
  • "); + padded = 0; + break; + case BLOCKQUOTE: + pad(out, 2); + g_string_append_printf(out, "
    \n"); + padded = 2; + print_html_element_list(out, elt->children, obfuscate); + pad(out, 1); + g_string_append_printf(out, "
    "); + padded = 0; + break; + case REFERENCE: + /* Nonprinting */ + break; + case NOTE: + /* if contents.str == 0, then print note; else ignore, since this + * is a note block that has been incorporated into the notes list */ + if (elt->contents.str == 0) { + add_endnote(elt); + ++notenumber; + g_string_append_printf(out, "[%d]", + notenumber, notenumber, notenumber, notenumber); + } + break; + default: + fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key); + exit(EXIT_FAILURE); + } +} + +static void print_html_endnotes(GString *out) { + int counter = 0; + GSList *note; + element *note_elt; + if (endnotes == NULL) + return; + note = g_slist_reverse(endnotes); + g_string_append_printf(out, "
    \n
      "); + while (note != NULL) { + note_elt = note->data; + counter++; + pad(out, 1); + g_string_append_printf(out, "
    1. \n", counter); + padded = 2; + print_html_element_list(out, note_elt->children, false); + g_string_append_printf(out, " [back]", counter); + pad(out, 1); + g_string_append_printf(out, "
    2. "); + note = note->next; + } + pad(out, 1); + g_string_append_printf(out, "
    "); + g_slist_free(endnotes); +} + +/********************************************************************** + + Functions for printing Elements as LaTeX + + ***********************************************************************/ + +/* print_latex_string - print string, escaping for LaTeX */ +static void print_latex_string(GString *out, char *str) { + while (*str != '\0') { + switch (*str) { + case '{': case '}': case '$': case '%': + case '&': case '_': case '#': + g_string_append_printf(out, "\\%c", *str); + break; + case '^': + g_string_append_printf(out, "\\^{}"); + break; + case '\\': + g_string_append_printf(out, "\\textbackslash{}"); + break; + case '~': + g_string_append_printf(out, "\\ensuremath{\\sim}"); + break; + case '|': + g_string_append_printf(out, "\\textbar{}"); + break; + case '<': + g_string_append_printf(out, "\\textless{}"); + break; + case '>': + g_string_append_printf(out, "\\textgreater{}"); + break; + default: + g_string_append_c(out, *str); + } + str++; + } +} + +/* print_latex_element_list - print a list of elements as LaTeX */ +static void print_latex_element_list(GString *out, element *list) { + while (list != NULL) { + print_latex_element(out, list); + list = list->next; + } +} + +/* print_latex_element - print an element as LaTeX */ +static void print_latex_element(GString *out, element *elt) { + int lev; + int i; + switch (elt->key) { + case SPACE: + g_string_append_printf(out, "%s", elt->contents.str); + break; + case LINEBREAK: + g_string_append_printf(out, "\\\\\n"); + break; + case STR: + print_latex_string(out, elt->contents.str); + break; + case ELLIPSIS: + g_string_append_printf(out, "\\ldots{}"); + break; + case EMDASH: + g_string_append_printf(out, "---"); + break; + case ENDASH: + g_string_append_printf(out, "--"); + break; + case APOSTROPHE: + g_string_append_printf(out, "'"); + break; + case SINGLEQUOTED: + g_string_append_printf(out, "`"); + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "'"); + break; + case DOUBLEQUOTED: + g_string_append_printf(out, "``"); + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "''"); + break; + case CODE: + g_string_append_printf(out, "\\texttt{"); + print_latex_string(out, elt->contents.str); + g_string_append_printf(out, "}"); + break; + case HTML: + /* don't print HTML */ + break; + case LINK: + g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url); + print_latex_element_list(out, elt->contents.link->label); + g_string_append_printf(out, "}"); + break; + case IMAGE: + g_string_append_printf(out, "\\includegraphics{%s}", elt->contents.link->url); + break; + case EMPH: + g_string_append_printf(out, "\\emph{"); + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "}"); + break; + case STRONG: + g_string_append_printf(out, "\\textbf{"); + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "}"); + break; + case LIST: + print_latex_element_list(out, elt->children); + break; + case RAW: + /* Shouldn't occur - these are handled by process_raw_blocks() */ + assert(elt->key != RAW); + break; + case H1: case H2: case H3: + pad(out, 2); + lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */ + g_string_append_printf(out, "\\"); + for (i = elt->key; i > H1; i--) + g_string_append_printf(out, "sub"); + g_string_append_printf(out, "section{"); + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "}"); + padded = 0; + break; + case H4: case H5: case H6: + pad(out, 2); + g_string_append_printf(out, "\\noindent\\textbf{"); + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "}"); + padded = 0; + break; + case PLAIN: + pad(out, 1); + print_latex_element_list(out, elt->children); + padded = 0; + break; + case PARA: + pad(out, 2); + print_latex_element_list(out, elt->children); + padded = 0; + break; + case HRULE: + pad(out, 2); + g_string_append_printf(out, "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n"); + padded = 0; + break; + case HTMLBLOCK: + /* don't print HTML block */ + break; + case VERBATIM: + pad(out, 1); + g_string_append_printf(out, "\\begin{verbatim}\n"); + print_latex_string(out, elt->contents.str); + g_string_append_printf(out, "\n\\end{verbatim}"); + padded = 0; + break; + case BULLETLIST: + pad(out, 1); + g_string_append_printf(out, "\\begin{itemize}"); + padded = 0; + print_latex_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, "\\end{itemize}"); + padded = 0; + break; + case ORDEREDLIST: + pad(out, 1); + g_string_append_printf(out, "\\begin{enumerate}"); + padded = 0; + print_latex_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, "\\end{enumerate}"); + padded = 0; + break; + case LISTITEM: + pad(out, 1); + g_string_append_printf(out, "\\item "); + padded = 2; + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "\n"); + break; + case BLOCKQUOTE: + pad(out, 1); + g_string_append_printf(out, "\\begin{quote}"); + padded = 0; + print_latex_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, "\\end{quote}"); + padded = 0; + break; + case NOTE: + /* if contents.str == 0, then print note; else ignore, since this + * is a note block that has been incorporated into the notes list */ + if (elt->contents.str == 0) { + g_string_append_printf(out, "\\footnote{"); + padded = 2; + print_latex_element_list(out, elt->children); + g_string_append_printf(out, "}"); + padded = 0; + } + break; + case REFERENCE: + /* Nonprinting */ + break; + default: + fprintf(stderr, "print_latex_element encountered unknown element key = %d\n", elt->key); + exit(EXIT_FAILURE); + } +} + +/********************************************************************** + + Functions for printing Elements as groff (mm macros) + + ***********************************************************************/ + +static bool in_list_item = false; /* True if we're parsing contents of a list item. */ + +/* print_groff_string - print string, escaping for groff */ +static void print_groff_string(GString *out, char *str) { + while (*str != '\0') { + switch (*str) { + case '\\': + g_string_append_printf(out, "\\e"); + break; + default: + g_string_append_c(out, *str); + } + str++; + } +} + +/* print_groff_mm_element_list - print a list of elements as groff ms */ +static void print_groff_mm_element_list(GString *out, element *list) { + int count = 1; + while (list != NULL) { + print_groff_mm_element(out, list, count); + list = list->next; + count++; + } +} + +/* print_groff_mm_element - print an element as groff ms */ +static void print_groff_mm_element(GString *out, element *elt, int count) { + int lev; + switch (elt->key) { + case SPACE: + g_string_append_printf(out, "%s", elt->contents.str); + padded = 0; + break; + case LINEBREAK: + pad(out, 1); + g_string_append_printf(out, ".br\n"); + padded = 0; + break; + case STR: + print_groff_string(out, elt->contents.str); + padded = 0; + break; + case ELLIPSIS: + g_string_append_printf(out, "..."); + break; + case EMDASH: + g_string_append_printf(out, "\\[em]"); + break; + case ENDASH: + g_string_append_printf(out, "\\[en]"); + break; + case APOSTROPHE: + g_string_append_printf(out, "'"); + break; + case SINGLEQUOTED: + g_string_append_printf(out, "`"); + print_groff_mm_element_list(out, elt->children); + g_string_append_printf(out, "'"); + break; + case DOUBLEQUOTED: + g_string_append_printf(out, "\\[lq]"); + print_groff_mm_element_list(out, elt->children); + g_string_append_printf(out, "\\[rq]"); + break; + case CODE: + g_string_append_printf(out, "\\fC"); + print_groff_string(out, elt->contents.str); + g_string_append_printf(out, "\\fR"); + padded = 0; + break; + case HTML: + /* don't print HTML */ + break; + case LINK: + print_groff_mm_element_list(out, elt->contents.link->label); + g_string_append_printf(out, " (%s)", elt->contents.link->url); + padded = 0; + break; + case IMAGE: + g_string_append_printf(out, "[IMAGE: "); + print_groff_mm_element_list(out, elt->contents.link->label); + g_string_append_printf(out, "]"); + padded = 0; + /* not supported */ + break; + case EMPH: + g_string_append_printf(out, "\\fI"); + print_groff_mm_element_list(out, elt->children); + g_string_append_printf(out, "\\fR"); + padded = 0; + break; + case STRONG: + g_string_append_printf(out, "\\fB"); + print_groff_mm_element_list(out, elt->children); + g_string_append_printf(out, "\\fR"); + padded = 0; + break; + case LIST: + print_groff_mm_element_list(out, elt->children); + padded = 0; + break; + case RAW: + /* Shouldn't occur - these are handled by process_raw_blocks() */ + assert(elt->key != RAW); + break; + case H1: case H2: case H3: case H4: case H5: case H6: + lev = elt->key - H1 + 1; + pad(out, 1); + g_string_append_printf(out, ".H %d \"", lev); + print_groff_mm_element_list(out, elt->children); + g_string_append_printf(out, "\""); + padded = 0; + break; + case PLAIN: + pad(out, 1); + print_groff_mm_element_list(out, elt->children); + padded = 0; + break; + case PARA: + pad(out, 1); + if (!in_list_item || count != 1) + g_string_append_printf(out, ".P\n"); + print_groff_mm_element_list(out, elt->children); + padded = 0; + break; + case HRULE: + pad(out, 1); + g_string_append_printf(out, "\\l'\\n(.lu*8u/10u'"); + padded = 0; + break; + case HTMLBLOCK: + /* don't print HTML block */ + break; + case VERBATIM: + pad(out, 1); + g_string_append_printf(out, ".VERBON 2\n"); + print_groff_string(out, elt->contents.str); + g_string_append_printf(out, ".VERBOFF"); + padded = 0; + break; + case BULLETLIST: + pad(out, 1); + g_string_append_printf(out, ".BL"); + padded = 0; + print_groff_mm_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, ".LE 1"); + padded = 0; + break; + case ORDEREDLIST: + pad(out, 1); + g_string_append_printf(out, ".AL"); + padded = 0; + print_groff_mm_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, ".LE 1"); + padded = 0; + break; + case LISTITEM: + pad(out, 1); + g_string_append_printf(out, ".LI\n"); + in_list_item = true; + padded = 2; + print_groff_mm_element_list(out, elt->children); + in_list_item = false; + break; + case BLOCKQUOTE: + pad(out, 1); + g_string_append_printf(out, ".DS I\n"); + padded = 2; + print_groff_mm_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, ".DE"); + padded = 0; + break; + case NOTE: + /* if contents.str == 0, then print note; else ignore, since this + * is a note block that has been incorporated into the notes list */ + if (elt->contents.str == 0) { + g_string_append_printf(out, "\\*F\n"); + g_string_append_printf(out, ".FS\n"); + padded = 2; + print_groff_mm_element_list(out, elt->children); + pad(out, 1); + g_string_append_printf(out, ".FE\n"); + padded = 1; + } + break; + case REFERENCE: + /* Nonprinting */ + break; + default: + fprintf(stderr, "print_groff_mm_element encountered unknown element key = %d\n", elt->key); + exit(EXIT_FAILURE); + } +} + +/********************************************************************** + + Functions for printing Elements as ODF + + ***********************************************************************/ + +/* print_odf_code_string - print string, escaping for HTML and saving newlines +*/ +static void print_odf_code_string(GString *out, char *str) { + char *tmp; + while (*str != '\0') { + switch (*str) { + case '&': + g_string_append_printf(out, "&"); + break; + case '<': + g_string_append_printf(out, "<"); + break; + case '>': + g_string_append_printf(out, ">"); + break; + case '"': + g_string_append_printf(out, """); + break; + case '\n': + g_string_append_printf(out, ""); + break; + case ' ': + tmp = str; + tmp++; + if (*tmp == ' ') { + tmp++; + if (*tmp == ' ') { + tmp++; + if (*tmp == ' ') { + g_string_append_printf(out, ""); + str = tmp; + } else { + g_string_append_printf(out, " "); + } + } else { + g_string_append_printf(out, " "); + } + } else { + g_string_append_printf(out, " "); + } + break; + default: + g_string_append_c(out, *str); + } + str++; + } +} + +/* print_odf_string - print string, escaping for HTML and saving newlines */ +static void print_odf_string(GString *out, char *str) { + char *tmp; + while (*str != '\0') { + switch (*str) { + case '&': + g_string_append_printf(out, "&"); + break; + case '<': + g_string_append_printf(out, "<"); + break; + case '>': + g_string_append_printf(out, ">"); + break; + case '"': + g_string_append_printf(out, """); + break; + case '\n': + tmp = str; + tmp--; + if (*tmp == ' ') { + tmp--; + if (*tmp == ' ') { + g_string_append_printf(out, ""); + } else { + g_string_append_printf(out, "\n"); + } + } else { + g_string_append_printf(out, "\n"); + } + break; + case ' ': + tmp = str; + tmp++; + if (*tmp == ' ') { + tmp++; + if (*tmp == ' ') { + tmp++; + if (*tmp == ' ') { + g_string_append_printf(out, ""); + str = tmp; + } else { + g_string_append_printf(out, " "); + } + } else { + g_string_append_printf(out, " "); + } + } else { + g_string_append_printf(out, " "); + } + break; + default: + g_string_append_c(out, *str); + } + str++; + } +} + +/* print_odf_element_list - print an element list as ODF */ +static void print_odf_element_list(GString *out, element *list) { + while (list != NULL) { + print_odf_element(out, list); + list = list->next; + } +} + +/* print_odf_element - print an element as ODF */ +static void print_odf_element(GString *out, element *elt) { + int lev; + int old_type = 0; + switch (elt->key) { + case SPACE: + g_string_append_printf(out, "%s", elt->contents.str); + break; + case LINEBREAK: + g_string_append_printf(out, ""); + break; + case STR: + print_html_string(out, elt->contents.str, 0); + break; + case ELLIPSIS: + g_string_append_printf(out, "…"); + break; + case EMDASH: + g_string_append_printf(out, "—"); + break; + case ENDASH: + g_string_append_printf(out, "–"); + break; + case APOSTROPHE: + g_string_append_printf(out, "’"); + break; + case SINGLEQUOTED: + g_string_append_printf(out, "‘"); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "’"); + break; + case DOUBLEQUOTED: + g_string_append_printf(out, "“"); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "”"); + break; + case CODE: + g_string_append_printf(out, ""); + print_html_string(out, elt->contents.str, 0); + g_string_append_printf(out, ""); + break; + case HTML: + break; + case LINK: + g_string_append_printf(out, "contents.link->url, 0); + g_string_append_printf(out, "\""); + if (strlen(elt->contents.link->title) > 0) { + g_string_append_printf(out, " office:name=\""); + print_html_string(out, elt->contents.link->title, 0); + g_string_append_printf(out, "\""); + } + g_string_append_printf(out, ">"); + print_odf_element_list(out, elt->contents.link->label); + g_string_append_printf(out, ""); + break; + case IMAGE: + g_string_append_printf(out, "\ncontents.link->url); + g_string_append_printf(out,"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"<All formats>\"/>\n"); + g_string_append_printf(out, "\n"); + break; + case EMPH: + g_string_append_printf(out, + ""); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, ""); + break; + case STRONG: + g_string_append_printf(out, + ""); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, ""); + break; + case LIST: + print_odf_element_list(out, elt->children); + break; + case RAW: + /* Shouldn't occur - these are handled by process_raw_blocks() */ + assert(elt->key != RAW); + break; + case H1: case H2: case H3: case H4: case H5: case H6: + lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */ + g_string_append_printf(out, "", lev); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "\n"); + padded = 0; + break; + case PLAIN: + print_odf_element_list(out, elt->children); + padded = 0; + break; + case PARA: + g_string_append_printf(out, ""); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "\n"); + break; + case HRULE: + g_string_append_printf(out,"\n"); + break; + case HTMLBLOCK: + /* don't print HTML block */ + /* but do print HTML comments for raw ODF */ + if (strncmp(elt->contents.str,"" from end */ + elt->contents.str[strlen(elt->contents.str)-3] = '\0'; + g_string_append_printf(out, "%s", &elt->contents.str[4]); + } + break; + case VERBATIM: + old_type = odf_type; + odf_type = VERBATIM; + g_string_append_printf(out, ""); + print_odf_code_string(out, elt->contents.str); + g_string_append_printf(out, "\n"); + odf_type = old_type; + break; + case BULLETLIST: + if ((odf_type == BULLETLIST) || + (odf_type == ORDEREDLIST)) { + /* I think this was made unnecessary by another change. + Same for ORDEREDLIST below */ + /* g_string_append_printf(out, ""); */ + } + old_type = odf_type; + odf_type = BULLETLIST; + g_string_append_printf(out, "%s", ""); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "%s", ""); + odf_type = old_type; + break; + case ORDEREDLIST: + if ((odf_type == BULLETLIST) || + (odf_type == ORDEREDLIST)) { + /* g_string_append_printf(out, ""); */ + } + old_type = odf_type; + odf_type = ORDEREDLIST; + g_string_append_printf(out, "%s", "\n"); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "%s", "\n"); + odf_type = old_type; + break; + case LISTITEM: + g_string_append_printf(out, "\n"); + if (elt->children->children->key != PARA) { + g_string_append_printf(out, ""); + } + print_odf_element_list(out, elt->children); + + if ((list_contains_key(elt->children,BULLETLIST) || + (list_contains_key(elt->children,ORDEREDLIST)))) { + } else { + if (elt->children->children->key != PARA) { + g_string_append_printf(out, ""); + } + } + g_string_append_printf(out, "\n"); + break; + case BLOCKQUOTE: + old_type = odf_type; + odf_type = BLOCKQUOTE; + print_odf_element_list(out, elt->children); + odf_type = old_type; + break; + case REFERENCE: + break; + case NOTE: + old_type = odf_type; + odf_type = NOTE; + /* if contents.str == 0 then print; else ignore - like above */ + if (elt->contents.str == 0) { + g_string_append_printf(out, "\n"); + print_odf_element_list(out, elt->children); + g_string_append_printf(out, "\n\n"); + } + elt->children = NULL; + odf_type = old_type; + break; + break; default: + fprintf(stderr, "print_odf_element encountered unknown element key = %d\n", elt->key); + exit(EXIT_FAILURE); + } +} + +/********************************************************************** + + Parameterized function for printing an Element. + + ***********************************************************************/ + +void print_element_list(GString *out, element *elt, int format, int exts) { + /* Initialize globals */ + endnotes = NULL; + notenumber = 0; + + extensions = exts; + padded = 2; /* set padding to 2, so no extra blank lines at beginning */ + switch (format) { + case HTML_FORMAT: + print_html_element_list(out, elt, false); + if (endnotes != NULL) { + pad(out, 2); + print_html_endnotes(out); + } + break; + case LATEX_FORMAT: + print_latex_element_list(out, elt); + break; + case GROFF_MM_FORMAT: + print_groff_mm_element_list(out, elt); + break; + case ODF_FORMAT: + print_odf_header(out); + g_string_append_printf(out, "\n\n"); + if (elt != NULL) print_odf_element_list(out,elt); + print_odf_footer(out); + break; + default: + fprintf(stderr, "print_element - unknown format = %d\n", format); + exit(EXIT_FAILURE); + } +} diff --git a/supportlibs/pegmarkdown/markdown_parser.c b/supportlibs/pegmarkdown/markdown_parser.c new file mode 100644 index 000000000..582b35c3c --- /dev/null +++ b/supportlibs/pegmarkdown/markdown_parser.c @@ -0,0 +1,6665 @@ +/* A recursive-descent parser generated by peg 0.1.9 */ + +#include +#include +#include +#define YYRULECOUNT 237 + +/********************************************************************** + + markdown_parser.leg - markdown parser in C using a PEG grammar. + (c) 2008 John MacFarlane (jgm at berkeley dot edu). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License or the MIT + license. See LICENSE for details. + + 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. + + ***********************************************************************/ + +#include +#include +#include "markdown_peg.h" +#include "utility_functions.h" + + + +/********************************************************************** + + Definitions for leg parser generator. + YY_INPUT is the function the parser calls to get new input. + We take all new input from (static) charbuf. + + ***********************************************************************/ + + + +# define YYSTYPE element * +#ifdef __DEBUG__ +# define YY_DEBUG 1 +#endif + +#define YY_INPUT(buf, result, max_size) \ +{ \ + int yyc; \ + if (charbuf && *charbuf != '\0') { \ + yyc= *charbuf++; \ + } else { \ + yyc= EOF; \ + } \ + result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ +} + +#define YY_RULE(T) T + + +/********************************************************************** + + PEG grammar and parser actions for markdown syntax. + + ***********************************************************************/ + + +#ifndef YY_LOCAL +#define YY_LOCAL(T) static T +#endif +#ifndef YY_ACTION +#define YY_ACTION(T) static T +#endif +#ifndef YY_RULE +#define YY_RULE(T) static T +#endif +#ifndef YY_PARSE +#define YY_PARSE(T) T +#endif +#ifndef YYPARSE +#define YYPARSE yyparse +#endif +#ifndef YYPARSEFROM +#define YYPARSEFROM yyparsefrom +#endif +#ifndef YY_INPUT +#define YY_INPUT(buf, result, max_size) \ + { \ + int yyc= getchar(); \ + result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ + yyprintf((stderr, "<%c>", yyc)); \ + } +#endif +#ifndef YY_BEGIN +#define YY_BEGIN ( ctx->begin= ctx->pos, 1) +#endif +#ifndef YY_END +#define YY_END ( ctx->end= ctx->pos, 1) +#endif +#ifdef YY_DEBUG +# define yyprintf(args) fprintf args +#else +# define yyprintf(args) +#endif +#ifndef YYSTYPE +#define YYSTYPE int +#endif + +#ifndef YY_PART + +typedef struct _yycontext yycontext; +typedef void (*yyaction)(yycontext *ctx, char *yytext, int yyleng); +typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk; + +struct _yycontext { + char *buf; + int buflen; + int pos; + int limit; + char *text; + int textlen; + int begin; + int end; + int textmax; + yythunk *thunks; + int thunkslen; + int thunkpos; + YYSTYPE yy; + YYSTYPE *val; + YYSTYPE *vals; + int valslen; +#ifdef YY_CTX_MEMBERS + YY_CTX_MEMBERS +#endif +}; + +#ifdef YY_CTX_LOCAL +#define YY_CTX_PARAM_ yycontext *yyctx, +#define YY_CTX_PARAM yycontext *yyctx +#define YY_CTX_ARG_ yyctx, +#define YY_CTX_ARG yyctx +#else +#define YY_CTX_PARAM_ +#define YY_CTX_PARAM +#define YY_CTX_ARG_ +#define YY_CTX_ARG +yycontext yyctx0; +yycontext *yyctx= &yyctx0; +#endif + +YY_LOCAL(int) yyrefill(yycontext *ctx) +{ + int yyn; + while (ctx->buflen - ctx->pos < 512) + { + ctx->buflen *= 2; + ctx->buf= (char *)realloc(ctx->buf, ctx->buflen); + } + YY_INPUT((ctx->buf + ctx->pos), yyn, (ctx->buflen - ctx->pos)); + if (!yyn) return 0; + ctx->limit += yyn; + return 1; +} + +YY_LOCAL(int) yymatchDot(yycontext *ctx) +{ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + ++ctx->pos; + return 1; +} + +YY_LOCAL(int) yymatchChar(yycontext *ctx, int c) +{ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + if ((unsigned char)ctx->buf[ctx->pos] == c) + { + ++ctx->pos; + yyprintf((stderr, " ok yymatchChar(ctx, %c) @ %s\n", c, ctx->buf+ctx->pos)); + return 1; + } + yyprintf((stderr, " fail yymatchChar(ctx, %c) @ %s\n", c, ctx->buf+ctx->pos)); + return 0; +} + +YY_LOCAL(int) yymatchString(yycontext *ctx, char *s) +{ + int yysav= ctx->pos; + while (*s) + { + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + if (ctx->buf[ctx->pos] != *s) + { + ctx->pos= yysav; + return 0; + } + ++s; + ++ctx->pos; + } + return 1; +} + +YY_LOCAL(int) yymatchClass(yycontext *ctx, unsigned char *bits) +{ + int c; + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + c= (unsigned char)ctx->buf[ctx->pos]; + if (bits[c >> 3] & (1 << (c & 7))) + { + ++ctx->pos; + yyprintf((stderr, " ok yymatchClass @ %s\n", ctx->buf+ctx->pos)); + return 1; + } + yyprintf((stderr, " fail yymatchClass @ %s\n", ctx->buf+ctx->pos)); + return 0; +} + +YY_LOCAL(void) yyDo(yycontext *ctx, yyaction action, int begin, int end) +{ + while (ctx->thunkpos >= ctx->thunkslen) + { + ctx->thunkslen *= 2; + ctx->thunks= (yythunk *)realloc(ctx->thunks, sizeof(yythunk) * ctx->thunkslen); + } + ctx->thunks[ctx->thunkpos].begin= begin; + ctx->thunks[ctx->thunkpos].end= end; + ctx->thunks[ctx->thunkpos].action= action; + ++ctx->thunkpos; +} + +YY_LOCAL(int) yyText(yycontext *ctx, int begin, int end) +{ + int yyleng= end - begin; + if (yyleng <= 0) + yyleng= 0; + else + { + while (ctx->textlen < (yyleng + 1)) + { + ctx->textlen *= 2; + ctx->text= (char *)realloc(ctx->text, ctx->textlen); + } + memcpy(ctx->text, ctx->buf + begin, yyleng); + } + ctx->text[yyleng]= '\0'; + return yyleng; +} + +YY_LOCAL(void) yyDone(yycontext *ctx) +{ + int pos; + for (pos= 0; pos < ctx->thunkpos; ++pos) + { + yythunk *thunk= &ctx->thunks[pos]; + int yyleng= thunk->end ? yyText(ctx, thunk->begin, thunk->end) : thunk->begin; + yyprintf((stderr, "DO [%d] %p %s\n", pos, thunk->action, ctx->text)); + thunk->action(ctx, ctx->text, yyleng); + } + ctx->thunkpos= 0; +} + +YY_LOCAL(void) yyCommit(yycontext *ctx) +{ + if ((ctx->limit -= ctx->pos)) + { + memmove(ctx->buf, ctx->buf + ctx->pos, ctx->limit); + } + ctx->begin -= ctx->pos; + ctx->end -= ctx->pos; + ctx->pos= ctx->thunkpos= 0; +} + +YY_LOCAL(int) yyAccept(yycontext *ctx, int tp0) +{ + if (tp0) + { + fprintf(stderr, "accept denied at %d\n", tp0); + return 0; + } + else + { + yyDone(ctx); + yyCommit(ctx); + } + return 1; +} + +YY_LOCAL(void) yyPush(yycontext *ctx, char *text, int count) { ctx->val += count; } +YY_LOCAL(void) yyPop(yycontext *ctx, char *text, int count) { ctx->val -= count; } +YY_LOCAL(void) yySet(yycontext *ctx, char *text, int count) { ctx->val[count]= ctx->yy; } + +#endif /* YY_PART */ + +#define YYACCEPT yyAccept(ctx, yythunkpos0) + +YY_RULE(int) yy_Notes(yycontext *ctx); /* 237 */ +YY_RULE(int) yy_RawNoteBlock(yycontext *ctx); /* 236 */ +YY_RULE(int) yy_RawNoteReference(yycontext *ctx); /* 235 */ +YY_RULE(int) yy_DoubleQuoteEnd(yycontext *ctx); /* 234 */ +YY_RULE(int) yy_DoubleQuoteStart(yycontext *ctx); /* 233 */ +YY_RULE(int) yy_SingleQuoteEnd(yycontext *ctx); /* 232 */ +YY_RULE(int) yy_SingleQuoteStart(yycontext *ctx); /* 231 */ +YY_RULE(int) yy_EnDash(yycontext *ctx); /* 230 */ +YY_RULE(int) yy_EmDash(yycontext *ctx); /* 229 */ +YY_RULE(int) yy_Apostrophe(yycontext *ctx); /* 228 */ +YY_RULE(int) yy_DoubleQuoted(yycontext *ctx); /* 227 */ +YY_RULE(int) yy_SingleQuoted(yycontext *ctx); /* 226 */ +YY_RULE(int) yy_Dash(yycontext *ctx); /* 225 */ +YY_RULE(int) yy_Ellipsis(yycontext *ctx); /* 224 */ +YY_RULE(int) yy_Digit(yycontext *ctx); /* 223 */ +YY_RULE(int) yy_ExtendedSpecialChar(yycontext *ctx); /* 222 */ +YY_RULE(int) yy_AlphanumericAscii(yycontext *ctx); /* 221 */ +YY_RULE(int) yy_Quoted(yycontext *ctx); /* 220 */ +YY_RULE(int) yy_HtmlTag(yycontext *ctx); /* 219 */ +YY_RULE(int) yy_Ticks5(yycontext *ctx); /* 218 */ +YY_RULE(int) yy_Ticks4(yycontext *ctx); /* 217 */ +YY_RULE(int) yy_Ticks3(yycontext *ctx); /* 216 */ +YY_RULE(int) yy_Ticks2(yycontext *ctx); /* 215 */ +YY_RULE(int) yy_Ticks1(yycontext *ctx); /* 214 */ +YY_RULE(int) yy_SkipBlock(yycontext *ctx); /* 213 */ +YY_RULE(int) yy_References(yycontext *ctx); /* 212 */ +YY_RULE(int) yy_EmptyTitle(yycontext *ctx); /* 211 */ +YY_RULE(int) yy_RefTitleParens(yycontext *ctx); /* 210 */ +YY_RULE(int) yy_RefTitleDouble(yycontext *ctx); /* 209 */ +YY_RULE(int) yy_RefTitleSingle(yycontext *ctx); /* 208 */ +YY_RULE(int) yy_RefTitle(yycontext *ctx); /* 207 */ +YY_RULE(int) yy_RefSrc(yycontext *ctx); /* 206 */ +YY_RULE(int) yy_AutoLinkEmail(yycontext *ctx); /* 205 */ +YY_RULE(int) yy_AutoLinkUrl(yycontext *ctx); /* 204 */ +YY_RULE(int) yy_TitleDouble(yycontext *ctx); /* 203 */ +YY_RULE(int) yy_TitleSingle(yycontext *ctx); /* 202 */ +YY_RULE(int) yy_Nonspacechar(yycontext *ctx); /* 201 */ +YY_RULE(int) yy_SourceContents(yycontext *ctx); /* 200 */ +YY_RULE(int) yy_Title(yycontext *ctx); /* 199 */ +YY_RULE(int) yy_Source(yycontext *ctx); /* 198 */ +YY_RULE(int) yy_Label(yycontext *ctx); /* 197 */ +YY_RULE(int) yy_ReferenceLinkSingle(yycontext *ctx); /* 196 */ +YY_RULE(int) yy_ReferenceLinkDouble(yycontext *ctx); /* 195 */ +YY_RULE(int) yy_AutoLink(yycontext *ctx); /* 194 */ +YY_RULE(int) yy_ReferenceLink(yycontext *ctx); /* 193 */ +YY_RULE(int) yy_ExplicitLink(yycontext *ctx); /* 192 */ +YY_RULE(int) yy_StrongUl(yycontext *ctx); /* 191 */ +YY_RULE(int) yy_StrongStar(yycontext *ctx); /* 190 */ +YY_RULE(int) yy_Whitespace(yycontext *ctx); /* 189 */ +YY_RULE(int) yy_EmphUl(yycontext *ctx); /* 188 */ +YY_RULE(int) yy_EmphStar(yycontext *ctx); /* 187 */ +YY_RULE(int) yy_StarLine(yycontext *ctx); /* 186 */ +YY_RULE(int) yy_UlLine(yycontext *ctx); /* 185 */ +YY_RULE(int) yy_SpecialChar(yycontext *ctx); /* 184 */ +YY_RULE(int) yy_Eof(yycontext *ctx); /* 183 */ +YY_RULE(int) yy_NormalEndline(yycontext *ctx); /* 182 */ +YY_RULE(int) yy_TerminalEndline(yycontext *ctx); /* 181 */ +YY_RULE(int) yy_LineBreak(yycontext *ctx); /* 180 */ +YY_RULE(int) yy_CharEntity(yycontext *ctx); /* 179 */ +YY_RULE(int) yy_DecEntity(yycontext *ctx); /* 178 */ +YY_RULE(int) yy_HexEntity(yycontext *ctx); /* 177 */ +YY_RULE(int) yy_AposChunk(yycontext *ctx); /* 176 */ +YY_RULE(int) yy_Alphanumeric(yycontext *ctx); /* 175 */ +YY_RULE(int) yy_StrChunk(yycontext *ctx); /* 174 */ +YY_RULE(int) yy_NormalChar(yycontext *ctx); /* 173 */ +YY_RULE(int) yy_Symbol(yycontext *ctx); /* 172 */ +YY_RULE(int) yy_Smart(yycontext *ctx); /* 171 */ +YY_RULE(int) yy_EscapedChar(yycontext *ctx); /* 170 */ +YY_RULE(int) yy_Entity(yycontext *ctx); /* 169 */ +YY_RULE(int) yy_RawHtml(yycontext *ctx); /* 168 */ +YY_RULE(int) yy_Code(yycontext *ctx); /* 167 */ +YY_RULE(int) yy_InlineNote(yycontext *ctx); /* 166 */ +YY_RULE(int) yy_NoteReference(yycontext *ctx); /* 165 */ +YY_RULE(int) yy_Link(yycontext *ctx); /* 164 */ +YY_RULE(int) yy_Image(yycontext *ctx); /* 163 */ +YY_RULE(int) yy_Emph(yycontext *ctx); /* 162 */ +YY_RULE(int) yy_Strong(yycontext *ctx); /* 161 */ +YY_RULE(int) yy_Space(yycontext *ctx); /* 160 */ +YY_RULE(int) yy_UlOrStarLine(yycontext *ctx); /* 159 */ +YY_RULE(int) yy_Str(yycontext *ctx); /* 158 */ +YY_RULE(int) yy_InStyleTags(yycontext *ctx); /* 157 */ +YY_RULE(int) yy_StyleClose(yycontext *ctx); /* 156 */ +YY_RULE(int) yy_StyleOpen(yycontext *ctx); /* 155 */ +YY_RULE(int) yy_HtmlBlockType(yycontext *ctx); /* 154 */ +YY_RULE(int) yy_HtmlBlockSelfClosing(yycontext *ctx); /* 153 */ +YY_RULE(int) yy_HtmlComment(yycontext *ctx); /* 152 */ +YY_RULE(int) yy_HtmlBlockInTags(yycontext *ctx); /* 151 */ +YY_RULE(int) yy_HtmlBlockScript(yycontext *ctx); /* 150 */ +YY_RULE(int) yy_HtmlBlockCloseScript(yycontext *ctx); /* 149 */ +YY_RULE(int) yy_HtmlBlockOpenScript(yycontext *ctx); /* 148 */ +YY_RULE(int) yy_HtmlBlockTr(yycontext *ctx); /* 147 */ +YY_RULE(int) yy_HtmlBlockCloseTr(yycontext *ctx); /* 146 */ +YY_RULE(int) yy_HtmlBlockOpenTr(yycontext *ctx); /* 145 */ +YY_RULE(int) yy_HtmlBlockThead(yycontext *ctx); /* 144 */ +YY_RULE(int) yy_HtmlBlockCloseThead(yycontext *ctx); /* 143 */ +YY_RULE(int) yy_HtmlBlockOpenThead(yycontext *ctx); /* 142 */ +YY_RULE(int) yy_HtmlBlockTh(yycontext *ctx); /* 141 */ +YY_RULE(int) yy_HtmlBlockCloseTh(yycontext *ctx); /* 140 */ +YY_RULE(int) yy_HtmlBlockOpenTh(yycontext *ctx); /* 139 */ +YY_RULE(int) yy_HtmlBlockTfoot(yycontext *ctx); /* 138 */ +YY_RULE(int) yy_HtmlBlockCloseTfoot(yycontext *ctx); /* 137 */ +YY_RULE(int) yy_HtmlBlockOpenTfoot(yycontext *ctx); /* 136 */ +YY_RULE(int) yy_HtmlBlockTd(yycontext *ctx); /* 135 */ +YY_RULE(int) yy_HtmlBlockCloseTd(yycontext *ctx); /* 134 */ +YY_RULE(int) yy_HtmlBlockOpenTd(yycontext *ctx); /* 133 */ +YY_RULE(int) yy_HtmlBlockTbody(yycontext *ctx); /* 132 */ +YY_RULE(int) yy_HtmlBlockCloseTbody(yycontext *ctx); /* 131 */ +YY_RULE(int) yy_HtmlBlockOpenTbody(yycontext *ctx); /* 130 */ +YY_RULE(int) yy_HtmlBlockLi(yycontext *ctx); /* 129 */ +YY_RULE(int) yy_HtmlBlockCloseLi(yycontext *ctx); /* 128 */ +YY_RULE(int) yy_HtmlBlockOpenLi(yycontext *ctx); /* 127 */ +YY_RULE(int) yy_HtmlBlockFrameset(yycontext *ctx); /* 126 */ +YY_RULE(int) yy_HtmlBlockCloseFrameset(yycontext *ctx); /* 125 */ +YY_RULE(int) yy_HtmlBlockOpenFrameset(yycontext *ctx); /* 124 */ +YY_RULE(int) yy_HtmlBlockDt(yycontext *ctx); /* 123 */ +YY_RULE(int) yy_HtmlBlockCloseDt(yycontext *ctx); /* 122 */ +YY_RULE(int) yy_HtmlBlockOpenDt(yycontext *ctx); /* 121 */ +YY_RULE(int) yy_HtmlBlockDd(yycontext *ctx); /* 120 */ +YY_RULE(int) yy_HtmlBlockCloseDd(yycontext *ctx); /* 119 */ +YY_RULE(int) yy_HtmlBlockOpenDd(yycontext *ctx); /* 118 */ +YY_RULE(int) yy_HtmlBlockUl(yycontext *ctx); /* 117 */ +YY_RULE(int) yy_HtmlBlockCloseUl(yycontext *ctx); /* 116 */ +YY_RULE(int) yy_HtmlBlockOpenUl(yycontext *ctx); /* 115 */ +YY_RULE(int) yy_HtmlBlockTable(yycontext *ctx); /* 114 */ +YY_RULE(int) yy_HtmlBlockCloseTable(yycontext *ctx); /* 113 */ +YY_RULE(int) yy_HtmlBlockOpenTable(yycontext *ctx); /* 112 */ +YY_RULE(int) yy_HtmlBlockPre(yycontext *ctx); /* 111 */ +YY_RULE(int) yy_HtmlBlockClosePre(yycontext *ctx); /* 110 */ +YY_RULE(int) yy_HtmlBlockOpenPre(yycontext *ctx); /* 109 */ +YY_RULE(int) yy_HtmlBlockP(yycontext *ctx); /* 108 */ +YY_RULE(int) yy_HtmlBlockCloseP(yycontext *ctx); /* 107 */ +YY_RULE(int) yy_HtmlBlockOpenP(yycontext *ctx); /* 106 */ +YY_RULE(int) yy_HtmlBlockOl(yycontext *ctx); /* 105 */ +YY_RULE(int) yy_HtmlBlockCloseOl(yycontext *ctx); /* 104 */ +YY_RULE(int) yy_HtmlBlockOpenOl(yycontext *ctx); /* 103 */ +YY_RULE(int) yy_HtmlBlockNoscript(yycontext *ctx); /* 102 */ +YY_RULE(int) yy_HtmlBlockCloseNoscript(yycontext *ctx); /* 101 */ +YY_RULE(int) yy_HtmlBlockOpenNoscript(yycontext *ctx); /* 100 */ +YY_RULE(int) yy_HtmlBlockNoframes(yycontext *ctx); /* 99 */ +YY_RULE(int) yy_HtmlBlockCloseNoframes(yycontext *ctx); /* 98 */ +YY_RULE(int) yy_HtmlBlockOpenNoframes(yycontext *ctx); /* 97 */ +YY_RULE(int) yy_HtmlBlockMenu(yycontext *ctx); /* 96 */ +YY_RULE(int) yy_HtmlBlockCloseMenu(yycontext *ctx); /* 95 */ +YY_RULE(int) yy_HtmlBlockOpenMenu(yycontext *ctx); /* 94 */ +YY_RULE(int) yy_HtmlBlockH6(yycontext *ctx); /* 93 */ +YY_RULE(int) yy_HtmlBlockCloseH6(yycontext *ctx); /* 92 */ +YY_RULE(int) yy_HtmlBlockOpenH6(yycontext *ctx); /* 91 */ +YY_RULE(int) yy_HtmlBlockH5(yycontext *ctx); /* 90 */ +YY_RULE(int) yy_HtmlBlockCloseH5(yycontext *ctx); /* 89 */ +YY_RULE(int) yy_HtmlBlockOpenH5(yycontext *ctx); /* 88 */ +YY_RULE(int) yy_HtmlBlockH4(yycontext *ctx); /* 87 */ +YY_RULE(int) yy_HtmlBlockCloseH4(yycontext *ctx); /* 86 */ +YY_RULE(int) yy_HtmlBlockOpenH4(yycontext *ctx); /* 85 */ +YY_RULE(int) yy_HtmlBlockH3(yycontext *ctx); /* 84 */ +YY_RULE(int) yy_HtmlBlockCloseH3(yycontext *ctx); /* 83 */ +YY_RULE(int) yy_HtmlBlockOpenH3(yycontext *ctx); /* 82 */ +YY_RULE(int) yy_HtmlBlockH2(yycontext *ctx); /* 81 */ +YY_RULE(int) yy_HtmlBlockCloseH2(yycontext *ctx); /* 80 */ +YY_RULE(int) yy_HtmlBlockOpenH2(yycontext *ctx); /* 79 */ +YY_RULE(int) yy_HtmlBlockH1(yycontext *ctx); /* 78 */ +YY_RULE(int) yy_HtmlBlockCloseH1(yycontext *ctx); /* 77 */ +YY_RULE(int) yy_HtmlBlockOpenH1(yycontext *ctx); /* 76 */ +YY_RULE(int) yy_HtmlBlockForm(yycontext *ctx); /* 75 */ +YY_RULE(int) yy_HtmlBlockCloseForm(yycontext *ctx); /* 74 */ +YY_RULE(int) yy_HtmlBlockOpenForm(yycontext *ctx); /* 73 */ +YY_RULE(int) yy_HtmlBlockFieldset(yycontext *ctx); /* 72 */ +YY_RULE(int) yy_HtmlBlockCloseFieldset(yycontext *ctx); /* 71 */ +YY_RULE(int) yy_HtmlBlockOpenFieldset(yycontext *ctx); /* 70 */ +YY_RULE(int) yy_HtmlBlockDl(yycontext *ctx); /* 69 */ +YY_RULE(int) yy_HtmlBlockCloseDl(yycontext *ctx); /* 68 */ +YY_RULE(int) yy_HtmlBlockOpenDl(yycontext *ctx); /* 67 */ +YY_RULE(int) yy_HtmlBlockDiv(yycontext *ctx); /* 66 */ +YY_RULE(int) yy_HtmlBlockCloseDiv(yycontext *ctx); /* 65 */ +YY_RULE(int) yy_HtmlBlockOpenDiv(yycontext *ctx); /* 64 */ +YY_RULE(int) yy_HtmlBlockDir(yycontext *ctx); /* 63 */ +YY_RULE(int) yy_HtmlBlockCloseDir(yycontext *ctx); /* 62 */ +YY_RULE(int) yy_HtmlBlockOpenDir(yycontext *ctx); /* 61 */ +YY_RULE(int) yy_HtmlBlockCenter(yycontext *ctx); /* 60 */ +YY_RULE(int) yy_HtmlBlockCloseCenter(yycontext *ctx); /* 59 */ +YY_RULE(int) yy_HtmlBlockOpenCenter(yycontext *ctx); /* 58 */ +YY_RULE(int) yy_HtmlBlockBlockquote(yycontext *ctx); /* 57 */ +YY_RULE(int) yy_HtmlBlockCloseBlockquote(yycontext *ctx); /* 56 */ +YY_RULE(int) yy_HtmlBlockOpenBlockquote(yycontext *ctx); /* 55 */ +YY_RULE(int) yy_HtmlBlockAddress(yycontext *ctx); /* 54 */ +YY_RULE(int) yy_HtmlBlockCloseAddress(yycontext *ctx); /* 53 */ +YY_RULE(int) yy_HtmlAttribute(yycontext *ctx); /* 52 */ +YY_RULE(int) yy_Spnl(yycontext *ctx); /* 51 */ +YY_RULE(int) yy_HtmlBlockOpenAddress(yycontext *ctx); /* 50 */ +YY_RULE(int) yy_OptionallyIndentedLine(yycontext *ctx); /* 49 */ +YY_RULE(int) yy_Indent(yycontext *ctx); /* 48 */ +YY_RULE(int) yy_ListBlockLine(yycontext *ctx); /* 47 */ +YY_RULE(int) yy_ListContinuationBlock(yycontext *ctx); /* 46 */ +YY_RULE(int) yy_ListBlock(yycontext *ctx); /* 45 */ +YY_RULE(int) yy_ListItem(yycontext *ctx); /* 44 */ +YY_RULE(int) yy_Enumerator(yycontext *ctx); /* 43 */ +YY_RULE(int) yy_ListItemTight(yycontext *ctx); /* 42 */ +YY_RULE(int) yy_ListLoose(yycontext *ctx); /* 41 */ +YY_RULE(int) yy_ListTight(yycontext *ctx); /* 40 */ +YY_RULE(int) yy_Spacechar(yycontext *ctx); /* 39 */ +YY_RULE(int) yy_Bullet(yycontext *ctx); /* 38 */ +YY_RULE(int) yy_VerbatimChunk(yycontext *ctx); /* 37 */ +YY_RULE(int) yy_IndentedLine(yycontext *ctx); /* 36 */ +YY_RULE(int) yy_NonblankIndentedLine(yycontext *ctx); /* 35 */ +YY_RULE(int) yy_Line(yycontext *ctx); /* 34 */ +YY_RULE(int) yy_BlockQuoteRaw(yycontext *ctx); /* 33 */ +YY_RULE(int) yy_Endline(yycontext *ctx); /* 32 */ +YY_RULE(int) yy_RawLine(yycontext *ctx); /* 31 */ +YY_RULE(int) yy_SetextBottom2(yycontext *ctx); /* 30 */ +YY_RULE(int) yy_SetextBottom1(yycontext *ctx); /* 29 */ +YY_RULE(int) yy_SetextHeading2(yycontext *ctx); /* 28 */ +YY_RULE(int) yy_SetextHeading1(yycontext *ctx); /* 27 */ +YY_RULE(int) yy_SetextHeading(yycontext *ctx); /* 26 */ +YY_RULE(int) yy_AtxHeading(yycontext *ctx); /* 25 */ +YY_RULE(int) yy_AtxStart(yycontext *ctx); /* 24 */ +YY_RULE(int) yy_Inline(yycontext *ctx); /* 23 */ +YY_RULE(int) yy_Sp(yycontext *ctx); /* 22 */ +YY_RULE(int) yy_Newline(yycontext *ctx); /* 21 */ +YY_RULE(int) yy_AtxInline(yycontext *ctx); /* 20 */ +YY_RULE(int) yy_Inlines(yycontext *ctx); /* 19 */ +YY_RULE(int) yy_NonindentSpace(yycontext *ctx); /* 18 */ +YY_RULE(int) yy_Plain(yycontext *ctx); /* 17 */ +YY_RULE(int) yy_Para(yycontext *ctx); /* 16 */ +YY_RULE(int) yy_StyleBlock(yycontext *ctx); /* 15 */ +YY_RULE(int) yy_HtmlBlock(yycontext *ctx); /* 14 */ +YY_RULE(int) yy_BulletList(yycontext *ctx); /* 13 */ +YY_RULE(int) yy_OrderedList(yycontext *ctx); /* 12 */ +YY_RULE(int) yy_Heading(yycontext *ctx); /* 11 */ +YY_RULE(int) yy_HorizontalRule(yycontext *ctx); /* 10 */ +YY_RULE(int) yy_Reference(yycontext *ctx); /* 9 */ +YY_RULE(int) yy_Note(yycontext *ctx); /* 8 */ +YY_RULE(int) yy_Verbatim(yycontext *ctx); /* 7 */ +YY_RULE(int) yy_BlockQuote(yycontext *ctx); /* 6 */ +YY_RULE(int) yy_BlankLine(yycontext *ctx); /* 5 */ +YY_RULE(int) yy_Block(yycontext *ctx); /* 4 */ +YY_RULE(int) yy_StartList(yycontext *ctx); /* 3 */ +YY_RULE(int) yy_BOM(yycontext *ctx); /* 2 */ +YY_RULE(int) yy_Doc(yycontext *ctx); /* 1 */ + +YY_ACTION(void) yy_3_RawNoteBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_RawNoteBlock\n")); + yy = mk_str_from_list(a, true); + yy->key = RAW; + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_RawNoteBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_RawNoteBlock\n")); + a = cons(mk_str(yytext), a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_RawNoteBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_RawNoteBlock\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_Notes(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Notes\n")); + notes = reverse(a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_Notes(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Notes\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_2_InlineNote(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_InlineNote\n")); + yy = mk_list(NOTE, a); + yy->contents.str = 0; ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_InlineNote(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_InlineNote\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_3_Note(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define ref ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_Note\n")); + yy = mk_list(NOTE, a); + yy->contents.str = strdup(ref->contents.str); + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +#undef ref +} +YY_ACTION(void) yy_2_Note(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define ref ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Note\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +#undef ref +} +YY_ACTION(void) yy_1_Note(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define ref ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Note\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +#undef ref +} +YY_ACTION(void) yy_1_RawNoteReference(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_RawNoteReference\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_NoteReference(yycontext *ctx, char *yytext, int yyleng) +{ +#define ref ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_NoteReference\n")); + element *match; + if (find_note(&match, ref->contents.str)) { + yy = mk_element(NOTE); + assert(match->children != NULL); + yy->children = match->children; + yy->contents.str = 0; + } else { + char *s; + s = malloc(strlen(ref->contents.str) + 4); + sprintf(s, "[^%s]", ref->contents.str); + yy = mk_str(s); + free(s); + } + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef ref +} +YY_ACTION(void) yy_2_DoubleQuoted(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_DoubleQuoted\n")); + yy = mk_list(DOUBLEQUOTED, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_DoubleQuoted(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_DoubleQuoted\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_2_SingleQuoted(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_SingleQuoted\n")); + yy = mk_list(SINGLEQUOTED, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_SingleQuoted(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_SingleQuoted\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_EmDash(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_EmDash\n")); + yy = mk_element(EMDASH); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_EnDash(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_EnDash\n")); + yy = mk_element(ENDASH); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Ellipsis(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Ellipsis\n")); + yy = mk_element(ELLIPSIS); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Apostrophe(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Apostrophe\n")); + yy = mk_element(APOSTROPHE); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Line(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Line\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_StartList(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_StartList\n")); + yy = NULL; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_RawHtml(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_RawHtml\n")); + if (extension(EXT_FILTER_HTML)) { + yy = mk_list(LIST, NULL); + } else { + yy = mk_str(yytext); + yy->key = HTML; + } + ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Code(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Code\n")); + yy = mk_str(yytext); yy->key = CODE; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_References(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_References\n")); + references = reverse(a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_References(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_References\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_RefTitle(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_RefTitle\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_RefSrc(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_RefSrc\n")); + yy = mk_str(yytext); + yy->key = HTML; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_Label(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Label\n")); + yy = mk_list(LIST, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Label(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Label\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Reference(yycontext *ctx, char *yytext, int yyleng) +{ +#define t ctx->val[-1] +#define s ctx->val[-2] +#define l ctx->val[-3] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Reference\n")); + yy = mk_link(l->children, s->contents.str, t->contents.str); + free_element(s); + free_element(t); + free(l); + yy->key = REFERENCE; ; +#undef yythunkpos +#undef yypos +#undef yy +#undef t +#undef s +#undef l +} +YY_ACTION(void) yy_1_AutoLinkEmail(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_AutoLinkEmail\n")); + char *mailto = malloc(strlen(yytext) + 8); + sprintf(mailto, "mailto:%s", yytext); + yy = mk_link(mk_str(yytext), mailto, ""); + free(mailto); + ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_AutoLinkUrl(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_AutoLinkUrl\n")); + yy = mk_link(mk_str(yytext), yytext, ""); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Title(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Title\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Source(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Source\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_ExplicitLink(yycontext *ctx, char *yytext, int yyleng) +{ +#define t ctx->val[-1] +#define s ctx->val[-2] +#define l ctx->val[-3] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ExplicitLink\n")); + yy = mk_link(l->children, s->contents.str, t->contents.str); + free_element(s); + free_element(t); + free(l); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef t +#undef s +#undef l +} +YY_ACTION(void) yy_1_ReferenceLinkSingle(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ReferenceLinkSingle\n")); + link match; + if (find_reference(&match, a->children)) { + yy = mk_link(a->children, match.url, match.title); + free(a); + } + else { + element *result; + result = mk_element(LIST); + result->children = cons(mk_str("["), cons(a, cons(mk_str("]"), mk_str(yytext)))); + yy = result; + } + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_ReferenceLinkDouble(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ReferenceLinkDouble\n")); + link match; + if (find_reference(&match, b->children)) { + yy = mk_link(a->children, match.url, match.title); + free(a); + free_element_list(b); + } else { + element *result; + result = mk_element(LIST); + result->children = cons(mk_str("["), cons(a, cons(mk_str("]"), cons(mk_str(yytext), + cons(mk_str("["), cons(b, mk_str("]"))))))); + yy = result; + } + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_Image(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Image\n")); + if (yy->key == LINK) { + yy->key = IMAGE; + } else { + element *result; + result = yy; + yy->children = cons(mk_str("!"), result->children); + } ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_StrongUl(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_StrongUl\n")); + yy = mk_list(STRONG, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_StrongUl(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_StrongUl\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_2_StrongStar(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_StrongStar\n")); + yy = mk_list(STRONG, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_StrongStar(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_StrongStar\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_3_EmphUl(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_EmphUl\n")); + yy = mk_list(EMPH, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_2_EmphUl(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_EmphUl\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_EmphUl(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_EmphUl\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_3_EmphStar(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_EmphStar\n")); + yy = mk_list(EMPH, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_2_EmphStar(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_EmphStar\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_EmphStar(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_EmphStar\n")); + a = cons(b, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_UlOrStarLine(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_UlOrStarLine\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Symbol(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Symbol\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_LineBreak(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_LineBreak\n")); + yy = mk_element(LINEBREAK); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_TerminalEndline(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_TerminalEndline\n")); + yy = NULL; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_NormalEndline(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_NormalEndline\n")); + yy = mk_str("\n"); + yy->key = SPACE; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Entity(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Entity\n")); + yy = mk_str(yytext); yy->key = HTML; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_EscapedChar(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_EscapedChar\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_AposChunk(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_AposChunk\n")); + yy = mk_element(APOSTROPHE); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_StrChunk(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_StrChunk\n")); + yy = mk_str(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_3_Str(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_Str\n")); + if (a->next == NULL) { yy = a; } else { yy = mk_list(LIST, a); } ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_Str(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Str\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Str(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Str\n")); + a = cons(mk_str(yytext), a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Space(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Space\n")); + yy = mk_str(" "); + yy->key = SPACE; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_3_Inlines(yycontext *ctx, char *yytext, int yyleng) +{ +#define c ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_Inlines\n")); + yy = mk_list(LIST, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef c +#undef a +} +YY_ACTION(void) yy_2_Inlines(yycontext *ctx, char *yytext, int yyleng) +{ +#define c ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Inlines\n")); + a = cons(c, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef c +#undef a +} +YY_ACTION(void) yy_1_Inlines(yycontext *ctx, char *yytext, int yyleng) +{ +#define c ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Inlines\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef c +#undef a +} +YY_ACTION(void) yy_1_StyleBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_StyleBlock\n")); + if (extension(EXT_FILTER_STYLES)) { + yy = mk_list(LIST, NULL); + } else { + yy = mk_str(yytext); + yy->key = HTMLBLOCK; + } + ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_HtmlBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_HtmlBlock\n")); + if (extension(EXT_FILTER_HTML)) { + yy = mk_list(LIST, NULL); + } else { + yy = mk_str(yytext); + yy->key = HTMLBLOCK; + } + ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_OrderedList(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_OrderedList\n")); + yy->key = ORDEREDLIST; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_3_ListContinuationBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_ListContinuationBlock\n")); + yy = mk_str_from_list(a, false); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_ListContinuationBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_ListContinuationBlock\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_ListContinuationBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ListContinuationBlock\n")); + if (strlen(yytext) == 0) + a = cons(mk_str("\001"), a); /* block separator */ + else + a = cons(mk_str(yytext), a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_3_ListBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_ListBlock\n")); + yy = mk_str_from_list(a, false); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_ListBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_ListBlock\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_ListBlock(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ListBlock\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_3_ListItemTight(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_ListItemTight\n")); + element *raw; + raw = mk_str_from_list(a, false); + raw->key = RAW; + yy = mk_element(LISTITEM); + yy->children = raw; + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_ListItemTight(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_ListItemTight\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_ListItemTight(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ListItemTight\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_3_ListItem(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_ListItem\n")); + element *raw; + raw = mk_str_from_list(a, false); + raw->key = RAW; + yy = mk_element(LISTITEM); + yy->children = raw; + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_ListItem(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_ListItem\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_ListItem(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ListItem\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_ListLoose(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_ListLoose\n")); + yy = mk_list(LIST, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_1_ListLoose(yycontext *ctx, char *yytext, int yyleng) +{ +#define b ctx->val[-1] +#define a ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ListLoose\n")); + element *li; + li = b->children; + li->contents.str = realloc(li->contents.str, strlen(li->contents.str) + 3); + strcat(li->contents.str, "\n\n"); /* In loose list, \n\n added to end of each element */ + a = cons(b, a); + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef b +#undef a +} +YY_ACTION(void) yy_2_ListTight(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_ListTight\n")); + yy = mk_list(LIST, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_ListTight(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_ListTight\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_BulletList(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_BulletList\n")); + yy->key = BULLETLIST; ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_HorizontalRule(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_HorizontalRule\n")); + yy = mk_element(HRULE); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_Verbatim(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Verbatim\n")); + yy = mk_str_from_list(a, false); + yy->key = VERBATIM; ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Verbatim(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Verbatim\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_3_VerbatimChunk(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_VerbatimChunk\n")); + yy = mk_str_from_list(a, false); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_VerbatimChunk(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_VerbatimChunk\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_VerbatimChunk(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_VerbatimChunk\n")); + a = cons(mk_str("\n"), a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_4_BlockQuoteRaw(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_4_BlockQuoteRaw\n")); + yy = mk_str_from_list(a, true); + yy->key = RAW; + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_3_BlockQuoteRaw(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_BlockQuoteRaw\n")); + a = cons(mk_str("\n"), a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_BlockQuoteRaw(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_BlockQuoteRaw\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_BlockQuoteRaw(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_BlockQuoteRaw\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_BlockQuote(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_BlockQuote\n")); + yy = mk_element(BLOCKQUOTE); + yy->children = a; + ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_SetextHeading2(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_SetextHeading2\n")); + yy = mk_list(H2, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_SetextHeading2(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_SetextHeading2\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_SetextHeading1(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_SetextHeading1\n")); + yy = mk_list(H1, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_SetextHeading1(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_SetextHeading1\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_AtxHeading(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define s ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_AtxHeading\n")); + yy = mk_list(s->key, a); + free(s); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +#undef s +} +YY_ACTION(void) yy_1_AtxHeading(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define s ctx->val[-2] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_AtxHeading\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +#undef s +} +YY_ACTION(void) yy_1_AtxStart(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_AtxStart\n")); + yy = mk_element(H1 + (strlen(yytext) - 1)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_Plain(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Plain\n")); + yy = a; yy->key = PLAIN; ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Para(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Para\n")); + yy = a; yy->key = PARA; ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_2_Doc(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_Doc\n")); + parse_result = reverse(a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} +YY_ACTION(void) yy_1_Doc(yycontext *ctx, char *yytext, int yyleng) +{ +#define a ctx->val[-1] +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_Doc\n")); + a = cons(yy, a); ; +#undef yythunkpos +#undef yypos +#undef yy +#undef a +} + +YY_RULE(int) yy_Notes(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "Notes")); if (!yy_StartList(ctx)) goto l1; yyDo(ctx, yySet, -2, 0); + l2:; + { int yypos3= ctx->pos, yythunkpos3= ctx->thunkpos; + { int yypos4= ctx->pos, yythunkpos4= ctx->thunkpos; if (!yy_Note(ctx)) goto l5; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_Notes, ctx->begin, ctx->end); goto l4; + l5:; ctx->pos= yypos4; ctx->thunkpos= yythunkpos4; if (!yy_SkipBlock(ctx)) goto l3; + } + l4:; goto l2; + l3:; ctx->pos= yypos3; ctx->thunkpos= yythunkpos3; + } yyDo(ctx, yy_2_Notes, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Notes", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l1:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Notes", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RawNoteBlock(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "RawNoteBlock")); if (!yy_StartList(ctx)) goto l6; yyDo(ctx, yySet, -1, 0); + { int yypos9= ctx->pos, yythunkpos9= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l9; goto l6; + l9:; ctx->pos= yypos9; ctx->thunkpos= yythunkpos9; + } if (!yy_OptionallyIndentedLine(ctx)) goto l6; yyDo(ctx, yy_1_RawNoteBlock, ctx->begin, ctx->end); + l7:; + { int yypos8= ctx->pos, yythunkpos8= ctx->thunkpos; + { int yypos10= ctx->pos, yythunkpos10= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l10; goto l8; + l10:; ctx->pos= yypos10; ctx->thunkpos= yythunkpos10; + } if (!yy_OptionallyIndentedLine(ctx)) goto l8; yyDo(ctx, yy_1_RawNoteBlock, ctx->begin, ctx->end); goto l7; + l8:; ctx->pos= yypos8; ctx->thunkpos= yythunkpos8; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l6; + l11:; + { int yypos12= ctx->pos, yythunkpos12= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l12; goto l11; + l12:; ctx->pos= yypos12; ctx->thunkpos= yythunkpos12; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l6; yyDo(ctx, yy_2_RawNoteBlock, ctx->begin, ctx->end); yyDo(ctx, yy_3_RawNoteBlock, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "RawNoteBlock", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l6:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RawNoteBlock", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RawNoteReference(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RawNoteReference")); if (!yymatchString(ctx, "[^")) goto l13; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l13; + { int yypos16= ctx->pos, yythunkpos16= ctx->thunkpos; if (!yy_Newline(ctx)) goto l16; goto l13; + l16:; ctx->pos= yypos16; ctx->thunkpos= yythunkpos16; + } + { int yypos17= ctx->pos, yythunkpos17= ctx->thunkpos; if (!yymatchChar(ctx, ']')) goto l17; goto l13; + l17:; ctx->pos= yypos17; ctx->thunkpos= yythunkpos17; + } if (!yymatchDot(ctx)) goto l13; + l14:; + { int yypos15= ctx->pos, yythunkpos15= ctx->thunkpos; + { int yypos18= ctx->pos, yythunkpos18= ctx->thunkpos; if (!yy_Newline(ctx)) goto l18; goto l15; + l18:; ctx->pos= yypos18; ctx->thunkpos= yythunkpos18; + } + { int yypos19= ctx->pos, yythunkpos19= ctx->thunkpos; if (!yymatchChar(ctx, ']')) goto l19; goto l15; + l19:; ctx->pos= yypos19; ctx->thunkpos= yythunkpos19; + } if (!yymatchDot(ctx)) goto l15; goto l14; + l15:; ctx->pos= yypos15; ctx->thunkpos= yythunkpos15; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l13; if (!yymatchChar(ctx, ']')) goto l13; yyDo(ctx, yy_1_RawNoteReference, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "RawNoteReference", ctx->buf+ctx->pos)); + return 1; + l13:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RawNoteReference", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_DoubleQuoteEnd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "DoubleQuoteEnd")); if (!yymatchChar(ctx, '"')) goto l20; + yyprintf((stderr, " ok %s @ %s\n", "DoubleQuoteEnd", ctx->buf+ctx->pos)); + return 1; + l20:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "DoubleQuoteEnd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_DoubleQuoteStart(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "DoubleQuoteStart")); if (!yymatchChar(ctx, '"')) goto l21; + yyprintf((stderr, " ok %s @ %s\n", "DoubleQuoteStart", ctx->buf+ctx->pos)); + return 1; + l21:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "DoubleQuoteStart", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SingleQuoteEnd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SingleQuoteEnd")); if (!yymatchChar(ctx, '\'')) goto l22; + { int yypos23= ctx->pos, yythunkpos23= ctx->thunkpos; if (!yy_Alphanumeric(ctx)) goto l23; goto l22; + l23:; ctx->pos= yypos23; ctx->thunkpos= yythunkpos23; + } + yyprintf((stderr, " ok %s @ %s\n", "SingleQuoteEnd", ctx->buf+ctx->pos)); + return 1; + l22:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SingleQuoteEnd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SingleQuoteStart(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SingleQuoteStart")); if (!yymatchChar(ctx, '\'')) goto l24; + { int yypos25= ctx->pos, yythunkpos25= ctx->thunkpos; + { int yypos26= ctx->pos, yythunkpos26= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l27; goto l26; + l27:; ctx->pos= yypos26; ctx->thunkpos= yythunkpos26; if (!yy_Newline(ctx)) goto l25; + } + l26:; goto l24; + l25:; ctx->pos= yypos25; ctx->thunkpos= yythunkpos25; + } + yyprintf((stderr, " ok %s @ %s\n", "SingleQuoteStart", ctx->buf+ctx->pos)); + return 1; + l24:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SingleQuoteStart", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EnDash(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "EnDash")); if (!yymatchChar(ctx, '-')) goto l28; + { int yypos29= ctx->pos, yythunkpos29= ctx->thunkpos; if (!yy_Digit(ctx)) goto l28; ctx->pos= yypos29; ctx->thunkpos= yythunkpos29; + } yyDo(ctx, yy_1_EnDash, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "EnDash", ctx->buf+ctx->pos)); + return 1; + l28:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EnDash", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EmDash(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "EmDash")); + { int yypos31= ctx->pos, yythunkpos31= ctx->thunkpos; if (!yymatchString(ctx, "---")) goto l32; goto l31; + l32:; ctx->pos= yypos31; ctx->thunkpos= yythunkpos31; if (!yymatchString(ctx, "--")) goto l30; + } + l31:; yyDo(ctx, yy_1_EmDash, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "EmDash", ctx->buf+ctx->pos)); + return 1; + l30:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EmDash", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Apostrophe(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Apostrophe")); if (!yymatchChar(ctx, '\'')) goto l33; yyDo(ctx, yy_1_Apostrophe, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Apostrophe", ctx->buf+ctx->pos)); + return 1; + l33:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Apostrophe", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_DoubleQuoted(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "DoubleQuoted")); if (!yy_DoubleQuoteStart(ctx)) goto l34; if (!yy_StartList(ctx)) goto l34; yyDo(ctx, yySet, -2, 0); + { int yypos37= ctx->pos, yythunkpos37= ctx->thunkpos; if (!yy_DoubleQuoteEnd(ctx)) goto l37; goto l34; + l37:; ctx->pos= yypos37; ctx->thunkpos= yythunkpos37; + } if (!yy_Inline(ctx)) goto l34; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_DoubleQuoted, ctx->begin, ctx->end); + l35:; + { int yypos36= ctx->pos, yythunkpos36= ctx->thunkpos; + { int yypos38= ctx->pos, yythunkpos38= ctx->thunkpos; if (!yy_DoubleQuoteEnd(ctx)) goto l38; goto l36; + l38:; ctx->pos= yypos38; ctx->thunkpos= yythunkpos38; + } if (!yy_Inline(ctx)) goto l36; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_DoubleQuoted, ctx->begin, ctx->end); goto l35; + l36:; ctx->pos= yypos36; ctx->thunkpos= yythunkpos36; + } if (!yy_DoubleQuoteEnd(ctx)) goto l34; yyDo(ctx, yy_2_DoubleQuoted, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "DoubleQuoted", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l34:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "DoubleQuoted", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SingleQuoted(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "SingleQuoted")); if (!yy_SingleQuoteStart(ctx)) goto l39; if (!yy_StartList(ctx)) goto l39; yyDo(ctx, yySet, -2, 0); + { int yypos42= ctx->pos, yythunkpos42= ctx->thunkpos; if (!yy_SingleQuoteEnd(ctx)) goto l42; goto l39; + l42:; ctx->pos= yypos42; ctx->thunkpos= yythunkpos42; + } if (!yy_Inline(ctx)) goto l39; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_SingleQuoted, ctx->begin, ctx->end); + l40:; + { int yypos41= ctx->pos, yythunkpos41= ctx->thunkpos; + { int yypos43= ctx->pos, yythunkpos43= ctx->thunkpos; if (!yy_SingleQuoteEnd(ctx)) goto l43; goto l41; + l43:; ctx->pos= yypos43; ctx->thunkpos= yythunkpos43; + } if (!yy_Inline(ctx)) goto l41; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_SingleQuoted, ctx->begin, ctx->end); goto l40; + l41:; ctx->pos= yypos41; ctx->thunkpos= yythunkpos41; + } if (!yy_SingleQuoteEnd(ctx)) goto l39; yyDo(ctx, yy_2_SingleQuoted, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "SingleQuoted", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l39:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SingleQuoted", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Dash(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Dash")); + { int yypos45= ctx->pos, yythunkpos45= ctx->thunkpos; if (!yy_EmDash(ctx)) goto l46; goto l45; + l46:; ctx->pos= yypos45; ctx->thunkpos= yythunkpos45; if (!yy_EnDash(ctx)) goto l44; + } + l45:; + yyprintf((stderr, " ok %s @ %s\n", "Dash", ctx->buf+ctx->pos)); + return 1; + l44:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Dash", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Ellipsis(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Ellipsis")); + { int yypos48= ctx->pos, yythunkpos48= ctx->thunkpos; if (!yymatchString(ctx, "...")) goto l49; goto l48; + l49:; ctx->pos= yypos48; ctx->thunkpos= yythunkpos48; if (!yymatchString(ctx, ". . .")) goto l47; + } + l48:; yyDo(ctx, yy_1_Ellipsis, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Ellipsis", ctx->buf+ctx->pos)); + return 1; + l47:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Ellipsis", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Digit(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Digit")); if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l50; + yyprintf((stderr, " ok %s @ %s\n", "Digit", ctx->buf+ctx->pos)); + return 1; + l50:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Digit", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ExtendedSpecialChar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "ExtendedSpecialChar")); + { int yypos52= ctx->pos, yythunkpos52= ctx->thunkpos; yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_SMART) )) goto l53; + { int yypos54= ctx->pos, yythunkpos54= ctx->thunkpos; if (!yymatchChar(ctx, '.')) goto l55; goto l54; + l55:; ctx->pos= yypos54; ctx->thunkpos= yythunkpos54; if (!yymatchChar(ctx, '-')) goto l56; goto l54; + l56:; ctx->pos= yypos54; ctx->thunkpos= yythunkpos54; if (!yymatchChar(ctx, '\'')) goto l57; goto l54; + l57:; ctx->pos= yypos54; ctx->thunkpos= yythunkpos54; if (!yymatchChar(ctx, '"')) goto l53; + } + l54:; goto l52; + l53:; ctx->pos= yypos52; ctx->thunkpos= yythunkpos52; yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_NOTES) )) goto l51; if (!yymatchChar(ctx, '^')) goto l51; + } + l52:; + yyprintf((stderr, " ok %s @ %s\n", "ExtendedSpecialChar", ctx->buf+ctx->pos)); + return 1; + l51:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ExtendedSpecialChar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AlphanumericAscii(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AlphanumericAscii")); if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l58; + yyprintf((stderr, " ok %s @ %s\n", "AlphanumericAscii", ctx->buf+ctx->pos)); + return 1; + l58:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AlphanumericAscii", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Quoted(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Quoted")); + { int yypos60= ctx->pos, yythunkpos60= ctx->thunkpos; if (!yymatchChar(ctx, '"')) goto l61; + l62:; + { int yypos63= ctx->pos, yythunkpos63= ctx->thunkpos; + { int yypos64= ctx->pos, yythunkpos64= ctx->thunkpos; if (!yymatchChar(ctx, '"')) goto l64; goto l63; + l64:; ctx->pos= yypos64; ctx->thunkpos= yythunkpos64; + } if (!yymatchDot(ctx)) goto l63; goto l62; + l63:; ctx->pos= yypos63; ctx->thunkpos= yythunkpos63; + } if (!yymatchChar(ctx, '"')) goto l61; goto l60; + l61:; ctx->pos= yypos60; ctx->thunkpos= yythunkpos60; if (!yymatchChar(ctx, '\'')) goto l59; + l65:; + { int yypos66= ctx->pos, yythunkpos66= ctx->thunkpos; + { int yypos67= ctx->pos, yythunkpos67= ctx->thunkpos; if (!yymatchChar(ctx, '\'')) goto l67; goto l66; + l67:; ctx->pos= yypos67; ctx->thunkpos= yythunkpos67; + } if (!yymatchDot(ctx)) goto l66; goto l65; + l66:; ctx->pos= yypos66; ctx->thunkpos= yythunkpos66; + } if (!yymatchChar(ctx, '\'')) goto l59; + } + l60:; + yyprintf((stderr, " ok %s @ %s\n", "Quoted", ctx->buf+ctx->pos)); + return 1; + l59:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Quoted", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlTag(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlTag")); if (!yymatchChar(ctx, '<')) goto l68; if (!yy_Spnl(ctx)) goto l68; + { int yypos69= ctx->pos, yythunkpos69= ctx->thunkpos; if (!yymatchChar(ctx, '/')) goto l69; goto l70; + l69:; ctx->pos= yypos69; ctx->thunkpos= yythunkpos69; + } + l70:; if (!yy_AlphanumericAscii(ctx)) goto l68; + l71:; + { int yypos72= ctx->pos, yythunkpos72= ctx->thunkpos; if (!yy_AlphanumericAscii(ctx)) goto l72; goto l71; + l72:; ctx->pos= yypos72; ctx->thunkpos= yythunkpos72; + } if (!yy_Spnl(ctx)) goto l68; + l73:; + { int yypos74= ctx->pos, yythunkpos74= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l74; goto l73; + l74:; ctx->pos= yypos74; ctx->thunkpos= yythunkpos74; + } + { int yypos75= ctx->pos, yythunkpos75= ctx->thunkpos; if (!yymatchChar(ctx, '/')) goto l75; goto l76; + l75:; ctx->pos= yypos75; ctx->thunkpos= yythunkpos75; + } + l76:; if (!yy_Spnl(ctx)) goto l68; if (!yymatchChar(ctx, '>')) goto l68; + yyprintf((stderr, " ok %s @ %s\n", "HtmlTag", ctx->buf+ctx->pos)); + return 1; + l68:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlTag", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Ticks5(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Ticks5")); if (!yymatchString(ctx, "`````")) goto l77; + { int yypos78= ctx->pos, yythunkpos78= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l78; goto l77; + l78:; ctx->pos= yypos78; ctx->thunkpos= yythunkpos78; + } + yyprintf((stderr, " ok %s @ %s\n", "Ticks5", ctx->buf+ctx->pos)); + return 1; + l77:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Ticks5", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Ticks4(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Ticks4")); if (!yymatchString(ctx, "````")) goto l79; + { int yypos80= ctx->pos, yythunkpos80= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l80; goto l79; + l80:; ctx->pos= yypos80; ctx->thunkpos= yythunkpos80; + } + yyprintf((stderr, " ok %s @ %s\n", "Ticks4", ctx->buf+ctx->pos)); + return 1; + l79:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Ticks4", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Ticks3(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Ticks3")); if (!yymatchString(ctx, "```")) goto l81; + { int yypos82= ctx->pos, yythunkpos82= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l82; goto l81; + l82:; ctx->pos= yypos82; ctx->thunkpos= yythunkpos82; + } + yyprintf((stderr, " ok %s @ %s\n", "Ticks3", ctx->buf+ctx->pos)); + return 1; + l81:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Ticks3", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Ticks2(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Ticks2")); if (!yymatchString(ctx, "``")) goto l83; + { int yypos84= ctx->pos, yythunkpos84= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l84; goto l83; + l84:; ctx->pos= yypos84; ctx->thunkpos= yythunkpos84; + } + yyprintf((stderr, " ok %s @ %s\n", "Ticks2", ctx->buf+ctx->pos)); + return 1; + l83:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Ticks2", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Ticks1(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Ticks1")); if (!yymatchChar(ctx, '`')) goto l85; + { int yypos86= ctx->pos, yythunkpos86= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l86; goto l85; + l86:; ctx->pos= yypos86; ctx->thunkpos= yythunkpos86; + } + yyprintf((stderr, " ok %s @ %s\n", "Ticks1", ctx->buf+ctx->pos)); + return 1; + l85:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Ticks1", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SkipBlock(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SkipBlock")); + { int yypos88= ctx->pos, yythunkpos88= ctx->thunkpos; if (!yy_HtmlBlock(ctx)) goto l89; goto l88; + l89:; ctx->pos= yypos88; ctx->thunkpos= yythunkpos88; + { int yypos93= ctx->pos, yythunkpos93= ctx->thunkpos; if (!yymatchChar(ctx, '#')) goto l93; goto l90; + l93:; ctx->pos= yypos93; ctx->thunkpos= yythunkpos93; + } + { int yypos94= ctx->pos, yythunkpos94= ctx->thunkpos; if (!yy_SetextBottom1(ctx)) goto l94; goto l90; + l94:; ctx->pos= yypos94; ctx->thunkpos= yythunkpos94; + } + { int yypos95= ctx->pos, yythunkpos95= ctx->thunkpos; if (!yy_SetextBottom2(ctx)) goto l95; goto l90; + l95:; ctx->pos= yypos95; ctx->thunkpos= yythunkpos95; + } + { int yypos96= ctx->pos, yythunkpos96= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l96; goto l90; + l96:; ctx->pos= yypos96; ctx->thunkpos= yythunkpos96; + } if (!yy_RawLine(ctx)) goto l90; + l91:; + { int yypos92= ctx->pos, yythunkpos92= ctx->thunkpos; + { int yypos97= ctx->pos, yythunkpos97= ctx->thunkpos; if (!yymatchChar(ctx, '#')) goto l97; goto l92; + l97:; ctx->pos= yypos97; ctx->thunkpos= yythunkpos97; + } + { int yypos98= ctx->pos, yythunkpos98= ctx->thunkpos; if (!yy_SetextBottom1(ctx)) goto l98; goto l92; + l98:; ctx->pos= yypos98; ctx->thunkpos= yythunkpos98; + } + { int yypos99= ctx->pos, yythunkpos99= ctx->thunkpos; if (!yy_SetextBottom2(ctx)) goto l99; goto l92; + l99:; ctx->pos= yypos99; ctx->thunkpos= yythunkpos99; + } + { int yypos100= ctx->pos, yythunkpos100= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l100; goto l92; + l100:; ctx->pos= yypos100; ctx->thunkpos= yythunkpos100; + } if (!yy_RawLine(ctx)) goto l92; goto l91; + l92:; ctx->pos= yypos92; ctx->thunkpos= yythunkpos92; + } + l101:; + { int yypos102= ctx->pos, yythunkpos102= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l102; goto l101; + l102:; ctx->pos= yypos102; ctx->thunkpos= yythunkpos102; + } goto l88; + l90:; ctx->pos= yypos88; ctx->thunkpos= yythunkpos88; if (!yy_BlankLine(ctx)) goto l103; + l104:; + { int yypos105= ctx->pos, yythunkpos105= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l105; goto l104; + l105:; ctx->pos= yypos105; ctx->thunkpos= yythunkpos105; + } goto l88; + l103:; ctx->pos= yypos88; ctx->thunkpos= yythunkpos88; if (!yy_RawLine(ctx)) goto l87; + } + l88:; + yyprintf((stderr, " ok %s @ %s\n", "SkipBlock", ctx->buf+ctx->pos)); + return 1; + l87:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SkipBlock", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_References(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "References")); if (!yy_StartList(ctx)) goto l106; yyDo(ctx, yySet, -2, 0); + l107:; + { int yypos108= ctx->pos, yythunkpos108= ctx->thunkpos; + { int yypos109= ctx->pos, yythunkpos109= ctx->thunkpos; if (!yy_Reference(ctx)) goto l110; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_References, ctx->begin, ctx->end); goto l109; + l110:; ctx->pos= yypos109; ctx->thunkpos= yythunkpos109; if (!yy_SkipBlock(ctx)) goto l108; + } + l109:; goto l107; + l108:; ctx->pos= yypos108; ctx->thunkpos= yythunkpos108; + } yyDo(ctx, yy_2_References, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "References", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l106:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "References", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EmptyTitle(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "EmptyTitle")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l111; if (!yymatchString(ctx, "")) goto l111; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l111; + yyprintf((stderr, " ok %s @ %s\n", "EmptyTitle", ctx->buf+ctx->pos)); + return 1; + l111:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EmptyTitle", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RefTitleParens(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RefTitleParens")); if (!yy_Spnl(ctx)) goto l112; if (!yymatchChar(ctx, '(')) goto l112; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l112; + l113:; + { int yypos114= ctx->pos, yythunkpos114= ctx->thunkpos; + { int yypos115= ctx->pos, yythunkpos115= ctx->thunkpos; + { int yypos116= ctx->pos, yythunkpos116= ctx->thunkpos; if (!yymatchChar(ctx, ')')) goto l117; if (!yy_Sp(ctx)) goto l117; if (!yy_Newline(ctx)) goto l117; goto l116; + l117:; ctx->pos= yypos116; ctx->thunkpos= yythunkpos116; if (!yy_Newline(ctx)) goto l115; + } + l116:; goto l114; + l115:; ctx->pos= yypos115; ctx->thunkpos= yythunkpos115; + } if (!yymatchDot(ctx)) goto l114; goto l113; + l114:; ctx->pos= yypos114; ctx->thunkpos= yythunkpos114; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l112; if (!yymatchChar(ctx, ')')) goto l112; + yyprintf((stderr, " ok %s @ %s\n", "RefTitleParens", ctx->buf+ctx->pos)); + return 1; + l112:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RefTitleParens", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RefTitleDouble(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RefTitleDouble")); if (!yy_Spnl(ctx)) goto l118; if (!yymatchChar(ctx, '"')) goto l118; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l118; + l119:; + { int yypos120= ctx->pos, yythunkpos120= ctx->thunkpos; + { int yypos121= ctx->pos, yythunkpos121= ctx->thunkpos; + { int yypos122= ctx->pos, yythunkpos122= ctx->thunkpos; if (!yymatchChar(ctx, '"')) goto l123; if (!yy_Sp(ctx)) goto l123; if (!yy_Newline(ctx)) goto l123; goto l122; + l123:; ctx->pos= yypos122; ctx->thunkpos= yythunkpos122; if (!yy_Newline(ctx)) goto l121; + } + l122:; goto l120; + l121:; ctx->pos= yypos121; ctx->thunkpos= yythunkpos121; + } if (!yymatchDot(ctx)) goto l120; goto l119; + l120:; ctx->pos= yypos120; ctx->thunkpos= yythunkpos120; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l118; if (!yymatchChar(ctx, '"')) goto l118; + yyprintf((stderr, " ok %s @ %s\n", "RefTitleDouble", ctx->buf+ctx->pos)); + return 1; + l118:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RefTitleDouble", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RefTitleSingle(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RefTitleSingle")); if (!yy_Spnl(ctx)) goto l124; if (!yymatchChar(ctx, '\'')) goto l124; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l124; + l125:; + { int yypos126= ctx->pos, yythunkpos126= ctx->thunkpos; + { int yypos127= ctx->pos, yythunkpos127= ctx->thunkpos; + { int yypos128= ctx->pos, yythunkpos128= ctx->thunkpos; if (!yymatchChar(ctx, '\'')) goto l129; if (!yy_Sp(ctx)) goto l129; if (!yy_Newline(ctx)) goto l129; goto l128; + l129:; ctx->pos= yypos128; ctx->thunkpos= yythunkpos128; if (!yy_Newline(ctx)) goto l127; + } + l128:; goto l126; + l127:; ctx->pos= yypos127; ctx->thunkpos= yythunkpos127; + } if (!yymatchDot(ctx)) goto l126; goto l125; + l126:; ctx->pos= yypos126; ctx->thunkpos= yythunkpos126; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l124; if (!yymatchChar(ctx, '\'')) goto l124; + yyprintf((stderr, " ok %s @ %s\n", "RefTitleSingle", ctx->buf+ctx->pos)); + return 1; + l124:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RefTitleSingle", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RefTitle(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RefTitle")); + { int yypos131= ctx->pos, yythunkpos131= ctx->thunkpos; if (!yy_RefTitleSingle(ctx)) goto l132; goto l131; + l132:; ctx->pos= yypos131; ctx->thunkpos= yythunkpos131; if (!yy_RefTitleDouble(ctx)) goto l133; goto l131; + l133:; ctx->pos= yypos131; ctx->thunkpos= yythunkpos131; if (!yy_RefTitleParens(ctx)) goto l134; goto l131; + l134:; ctx->pos= yypos131; ctx->thunkpos= yythunkpos131; if (!yy_EmptyTitle(ctx)) goto l130; + } + l131:; yyDo(ctx, yy_1_RefTitle, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "RefTitle", ctx->buf+ctx->pos)); + return 1; + l130:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RefTitle", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RefSrc(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RefSrc")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l135; if (!yy_Nonspacechar(ctx)) goto l135; + l136:; + { int yypos137= ctx->pos, yythunkpos137= ctx->thunkpos; if (!yy_Nonspacechar(ctx)) goto l137; goto l136; + l137:; ctx->pos= yypos137; ctx->thunkpos= yythunkpos137; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l135; yyDo(ctx, yy_1_RefSrc, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "RefSrc", ctx->buf+ctx->pos)); + return 1; + l135:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RefSrc", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AutoLinkEmail(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AutoLinkEmail")); if (!yymatchChar(ctx, '<')) goto l138; + { int yypos139= ctx->pos, yythunkpos139= ctx->thunkpos; if (!yymatchString(ctx, "mailto:")) goto l139; goto l140; + l139:; ctx->pos= yypos139; ctx->thunkpos= yythunkpos139; + } + l140:; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l138; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\062\350\377\003\376\377\377\207\376\377\377\107\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l138; + l141:; + { int yypos142= ctx->pos, yythunkpos142= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\062\350\377\003\376\377\377\207\376\377\377\107\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l142; goto l141; + l142:; ctx->pos= yypos142; ctx->thunkpos= yythunkpos142; + } if (!yymatchChar(ctx, '@')) goto l138; + { int yypos145= ctx->pos, yythunkpos145= ctx->thunkpos; if (!yy_Newline(ctx)) goto l145; goto l138; + l145:; ctx->pos= yypos145; ctx->thunkpos= yythunkpos145; + } + { int yypos146= ctx->pos, yythunkpos146= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l146; goto l138; + l146:; ctx->pos= yypos146; ctx->thunkpos= yythunkpos146; + } if (!yymatchDot(ctx)) goto l138; + l143:; + { int yypos144= ctx->pos, yythunkpos144= ctx->thunkpos; + { int yypos147= ctx->pos, yythunkpos147= ctx->thunkpos; if (!yy_Newline(ctx)) goto l147; goto l144; + l147:; ctx->pos= yypos147; ctx->thunkpos= yythunkpos147; + } + { int yypos148= ctx->pos, yythunkpos148= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l148; goto l144; + l148:; ctx->pos= yypos148; ctx->thunkpos= yythunkpos148; + } if (!yymatchDot(ctx)) goto l144; goto l143; + l144:; ctx->pos= yypos144; ctx->thunkpos= yythunkpos144; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l138; if (!yymatchChar(ctx, '>')) goto l138; yyDo(ctx, yy_1_AutoLinkEmail, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "AutoLinkEmail", ctx->buf+ctx->pos)); + return 1; + l138:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AutoLinkEmail", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AutoLinkUrl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AutoLinkUrl")); if (!yymatchChar(ctx, '<')) goto l149; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l149; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\000\000\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l149; + l150:; + { int yypos151= ctx->pos, yythunkpos151= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\000\000\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l151; goto l150; + l151:; ctx->pos= yypos151; ctx->thunkpos= yythunkpos151; + } if (!yymatchString(ctx, "://")) goto l149; + { int yypos154= ctx->pos, yythunkpos154= ctx->thunkpos; if (!yy_Newline(ctx)) goto l154; goto l149; + l154:; ctx->pos= yypos154; ctx->thunkpos= yythunkpos154; + } + { int yypos155= ctx->pos, yythunkpos155= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l155; goto l149; + l155:; ctx->pos= yypos155; ctx->thunkpos= yythunkpos155; + } if (!yymatchDot(ctx)) goto l149; + l152:; + { int yypos153= ctx->pos, yythunkpos153= ctx->thunkpos; + { int yypos156= ctx->pos, yythunkpos156= ctx->thunkpos; if (!yy_Newline(ctx)) goto l156; goto l153; + l156:; ctx->pos= yypos156; ctx->thunkpos= yythunkpos156; + } + { int yypos157= ctx->pos, yythunkpos157= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l157; goto l153; + l157:; ctx->pos= yypos157; ctx->thunkpos= yythunkpos157; + } if (!yymatchDot(ctx)) goto l153; goto l152; + l153:; ctx->pos= yypos153; ctx->thunkpos= yythunkpos153; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l149; if (!yymatchChar(ctx, '>')) goto l149; yyDo(ctx, yy_1_AutoLinkUrl, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "AutoLinkUrl", ctx->buf+ctx->pos)); + return 1; + l149:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AutoLinkUrl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_TitleDouble(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "TitleDouble")); if (!yymatchChar(ctx, '"')) goto l158; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l158; + l159:; + { int yypos160= ctx->pos, yythunkpos160= ctx->thunkpos; + { int yypos161= ctx->pos, yythunkpos161= ctx->thunkpos; if (!yymatchChar(ctx, '"')) goto l161; if (!yy_Sp(ctx)) goto l161; + { int yypos162= ctx->pos, yythunkpos162= ctx->thunkpos; if (!yymatchChar(ctx, ')')) goto l163; goto l162; + l163:; ctx->pos= yypos162; ctx->thunkpos= yythunkpos162; if (!yy_Newline(ctx)) goto l161; + } + l162:; goto l160; + l161:; ctx->pos= yypos161; ctx->thunkpos= yythunkpos161; + } if (!yymatchDot(ctx)) goto l160; goto l159; + l160:; ctx->pos= yypos160; ctx->thunkpos= yythunkpos160; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l158; if (!yymatchChar(ctx, '"')) goto l158; + yyprintf((stderr, " ok %s @ %s\n", "TitleDouble", ctx->buf+ctx->pos)); + return 1; + l158:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "TitleDouble", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_TitleSingle(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "TitleSingle")); if (!yymatchChar(ctx, '\'')) goto l164; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l164; + l165:; + { int yypos166= ctx->pos, yythunkpos166= ctx->thunkpos; + { int yypos167= ctx->pos, yythunkpos167= ctx->thunkpos; if (!yymatchChar(ctx, '\'')) goto l167; if (!yy_Sp(ctx)) goto l167; + { int yypos168= ctx->pos, yythunkpos168= ctx->thunkpos; if (!yymatchChar(ctx, ')')) goto l169; goto l168; + l169:; ctx->pos= yypos168; ctx->thunkpos= yythunkpos168; if (!yy_Newline(ctx)) goto l167; + } + l168:; goto l166; + l167:; ctx->pos= yypos167; ctx->thunkpos= yythunkpos167; + } if (!yymatchDot(ctx)) goto l166; goto l165; + l166:; ctx->pos= yypos166; ctx->thunkpos= yythunkpos166; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l164; if (!yymatchChar(ctx, '\'')) goto l164; + yyprintf((stderr, " ok %s @ %s\n", "TitleSingle", ctx->buf+ctx->pos)); + return 1; + l164:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "TitleSingle", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Nonspacechar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Nonspacechar")); + { int yypos171= ctx->pos, yythunkpos171= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l171; goto l170; + l171:; ctx->pos= yypos171; ctx->thunkpos= yythunkpos171; + } + { int yypos172= ctx->pos, yythunkpos172= ctx->thunkpos; if (!yy_Newline(ctx)) goto l172; goto l170; + l172:; ctx->pos= yypos172; ctx->thunkpos= yythunkpos172; + } if (!yymatchDot(ctx)) goto l170; + yyprintf((stderr, " ok %s @ %s\n", "Nonspacechar", ctx->buf+ctx->pos)); + return 1; + l170:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Nonspacechar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SourceContents(yycontext *ctx) +{ + yyprintf((stderr, "%s\n", "SourceContents")); + l174:; + { int yypos175= ctx->pos, yythunkpos175= ctx->thunkpos; + { int yypos176= ctx->pos, yythunkpos176= ctx->thunkpos; + { int yypos180= ctx->pos, yythunkpos180= ctx->thunkpos; if (!yymatchChar(ctx, '(')) goto l180; goto l177; + l180:; ctx->pos= yypos180; ctx->thunkpos= yythunkpos180; + } + { int yypos181= ctx->pos, yythunkpos181= ctx->thunkpos; if (!yymatchChar(ctx, ')')) goto l181; goto l177; + l181:; ctx->pos= yypos181; ctx->thunkpos= yythunkpos181; + } + { int yypos182= ctx->pos, yythunkpos182= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l182; goto l177; + l182:; ctx->pos= yypos182; ctx->thunkpos= yythunkpos182; + } if (!yy_Nonspacechar(ctx)) goto l177; + l178:; + { int yypos179= ctx->pos, yythunkpos179= ctx->thunkpos; + { int yypos183= ctx->pos, yythunkpos183= ctx->thunkpos; if (!yymatchChar(ctx, '(')) goto l183; goto l179; + l183:; ctx->pos= yypos183; ctx->thunkpos= yythunkpos183; + } + { int yypos184= ctx->pos, yythunkpos184= ctx->thunkpos; if (!yymatchChar(ctx, ')')) goto l184; goto l179; + l184:; ctx->pos= yypos184; ctx->thunkpos= yythunkpos184; + } + { int yypos185= ctx->pos, yythunkpos185= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l185; goto l179; + l185:; ctx->pos= yypos185; ctx->thunkpos= yythunkpos185; + } if (!yy_Nonspacechar(ctx)) goto l179; goto l178; + l179:; ctx->pos= yypos179; ctx->thunkpos= yythunkpos179; + } goto l176; + l177:; ctx->pos= yypos176; ctx->thunkpos= yythunkpos176; if (!yymatchChar(ctx, '(')) goto l175; if (!yy_SourceContents(ctx)) goto l175; if (!yymatchChar(ctx, ')')) goto l175; + } + l176:; goto l174; + l175:; ctx->pos= yypos175; ctx->thunkpos= yythunkpos175; + } + yyprintf((stderr, " ok %s @ %s\n", "SourceContents", ctx->buf+ctx->pos)); + return 1; +} +YY_RULE(int) yy_Title(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Title")); + { int yypos187= ctx->pos, yythunkpos187= ctx->thunkpos; if (!yy_TitleSingle(ctx)) goto l188; goto l187; + l188:; ctx->pos= yypos187; ctx->thunkpos= yythunkpos187; if (!yy_TitleDouble(ctx)) goto l189; goto l187; + l189:; ctx->pos= yypos187; ctx->thunkpos= yythunkpos187; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l186; if (!yymatchString(ctx, "")) goto l186; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l186; + } + l187:; yyDo(ctx, yy_1_Title, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Title", ctx->buf+ctx->pos)); + return 1; + l186:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Title", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Source(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Source")); + { int yypos191= ctx->pos, yythunkpos191= ctx->thunkpos; if (!yymatchChar(ctx, '<')) goto l192; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l192; if (!yy_SourceContents(ctx)) goto l192; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l192; if (!yymatchChar(ctx, '>')) goto l192; goto l191; + l192:; ctx->pos= yypos191; ctx->thunkpos= yythunkpos191; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l190; if (!yy_SourceContents(ctx)) goto l190; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l190; + } + l191:; yyDo(ctx, yy_1_Source, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Source", ctx->buf+ctx->pos)); + return 1; + l190:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Source", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Label(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "Label")); if (!yymatchChar(ctx, '[')) goto l193; + { int yypos194= ctx->pos, yythunkpos194= ctx->thunkpos; + { int yypos196= ctx->pos, yythunkpos196= ctx->thunkpos; if (!yymatchChar(ctx, '^')) goto l196; goto l195; + l196:; ctx->pos= yypos196; ctx->thunkpos= yythunkpos196; + } yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_NOTES) )) goto l195; goto l194; + l195:; ctx->pos= yypos194; ctx->thunkpos= yythunkpos194; + { int yypos197= ctx->pos, yythunkpos197= ctx->thunkpos; if (!yymatchDot(ctx)) goto l193; ctx->pos= yypos197; ctx->thunkpos= yythunkpos197; + } yyText(ctx, ctx->begin, ctx->end); if (!( !extension(EXT_NOTES) )) goto l193; + } + l194:; if (!yy_StartList(ctx)) goto l193; yyDo(ctx, yySet, -1, 0); + l198:; + { int yypos199= ctx->pos, yythunkpos199= ctx->thunkpos; + { int yypos200= ctx->pos, yythunkpos200= ctx->thunkpos; if (!yymatchChar(ctx, ']')) goto l200; goto l199; + l200:; ctx->pos= yypos200; ctx->thunkpos= yythunkpos200; + } if (!yy_Inline(ctx)) goto l199; yyDo(ctx, yy_1_Label, ctx->begin, ctx->end); goto l198; + l199:; ctx->pos= yypos199; ctx->thunkpos= yythunkpos199; + } if (!yymatchChar(ctx, ']')) goto l193; yyDo(ctx, yy_2_Label, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Label", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l193:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Label", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ReferenceLinkSingle(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "ReferenceLinkSingle")); if (!yy_Label(ctx)) goto l201; yyDo(ctx, yySet, -1, 0); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l201; + { int yypos202= ctx->pos, yythunkpos202= ctx->thunkpos; if (!yy_Spnl(ctx)) goto l202; if (!yymatchString(ctx, "[]")) goto l202; goto l203; + l202:; ctx->pos= yypos202; ctx->thunkpos= yythunkpos202; + } + l203:; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l201; yyDo(ctx, yy_1_ReferenceLinkSingle, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ReferenceLinkSingle", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l201:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ReferenceLinkSingle", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ReferenceLinkDouble(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "ReferenceLinkDouble")); if (!yy_Label(ctx)) goto l204; yyDo(ctx, yySet, -2, 0); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l204; if (!yy_Spnl(ctx)) goto l204; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l204; + { int yypos205= ctx->pos, yythunkpos205= ctx->thunkpos; if (!yymatchString(ctx, "[]")) goto l205; goto l204; + l205:; ctx->pos= yypos205; ctx->thunkpos= yythunkpos205; + } if (!yy_Label(ctx)) goto l204; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_ReferenceLinkDouble, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ReferenceLinkDouble", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l204:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ReferenceLinkDouble", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AutoLink(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AutoLink")); + { int yypos207= ctx->pos, yythunkpos207= ctx->thunkpos; if (!yy_AutoLinkUrl(ctx)) goto l208; goto l207; + l208:; ctx->pos= yypos207; ctx->thunkpos= yythunkpos207; if (!yy_AutoLinkEmail(ctx)) goto l206; + } + l207:; + yyprintf((stderr, " ok %s @ %s\n", "AutoLink", ctx->buf+ctx->pos)); + return 1; + l206:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AutoLink", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ReferenceLink(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "ReferenceLink")); + { int yypos210= ctx->pos, yythunkpos210= ctx->thunkpos; if (!yy_ReferenceLinkDouble(ctx)) goto l211; goto l210; + l211:; ctx->pos= yypos210; ctx->thunkpos= yythunkpos210; if (!yy_ReferenceLinkSingle(ctx)) goto l209; + } + l210:; + yyprintf((stderr, " ok %s @ %s\n", "ReferenceLink", ctx->buf+ctx->pos)); + return 1; + l209:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ReferenceLink", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ExplicitLink(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 3, 0); + yyprintf((stderr, "%s\n", "ExplicitLink")); if (!yy_Label(ctx)) goto l212; yyDo(ctx, yySet, -3, 0); if (!yymatchChar(ctx, '(')) goto l212; if (!yy_Sp(ctx)) goto l212; if (!yy_Source(ctx)) goto l212; yyDo(ctx, yySet, -2, 0); if (!yy_Spnl(ctx)) goto l212; if (!yy_Title(ctx)) goto l212; yyDo(ctx, yySet, -1, 0); if (!yy_Sp(ctx)) goto l212; if (!yymatchChar(ctx, ')')) goto l212; yyDo(ctx, yy_1_ExplicitLink, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ExplicitLink", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 3, 0); + return 1; + l212:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ExplicitLink", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StrongUl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "StrongUl")); if (!yymatchString(ctx, "__")) goto l213; + { int yypos214= ctx->pos, yythunkpos214= ctx->thunkpos; if (!yy_Whitespace(ctx)) goto l214; goto l213; + l214:; ctx->pos= yypos214; ctx->thunkpos= yythunkpos214; + } if (!yy_StartList(ctx)) goto l213; yyDo(ctx, yySet, -2, 0); + { int yypos217= ctx->pos, yythunkpos217= ctx->thunkpos; if (!yymatchString(ctx, "__")) goto l217; goto l213; + l217:; ctx->pos= yypos217; ctx->thunkpos= yythunkpos217; + } if (!yy_Inline(ctx)) goto l213; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_StrongUl, ctx->begin, ctx->end); + l215:; + { int yypos216= ctx->pos, yythunkpos216= ctx->thunkpos; + { int yypos218= ctx->pos, yythunkpos218= ctx->thunkpos; if (!yymatchString(ctx, "__")) goto l218; goto l216; + l218:; ctx->pos= yypos218; ctx->thunkpos= yythunkpos218; + } if (!yy_Inline(ctx)) goto l216; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_StrongUl, ctx->begin, ctx->end); goto l215; + l216:; ctx->pos= yypos216; ctx->thunkpos= yythunkpos216; + } if (!yymatchString(ctx, "__")) goto l213; yyDo(ctx, yy_2_StrongUl, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "StrongUl", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l213:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StrongUl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StrongStar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "StrongStar")); if (!yymatchString(ctx, "**")) goto l219; + { int yypos220= ctx->pos, yythunkpos220= ctx->thunkpos; if (!yy_Whitespace(ctx)) goto l220; goto l219; + l220:; ctx->pos= yypos220; ctx->thunkpos= yythunkpos220; + } if (!yy_StartList(ctx)) goto l219; yyDo(ctx, yySet, -2, 0); + { int yypos223= ctx->pos, yythunkpos223= ctx->thunkpos; if (!yymatchString(ctx, "**")) goto l223; goto l219; + l223:; ctx->pos= yypos223; ctx->thunkpos= yythunkpos223; + } if (!yy_Inline(ctx)) goto l219; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_StrongStar, ctx->begin, ctx->end); + l221:; + { int yypos222= ctx->pos, yythunkpos222= ctx->thunkpos; + { int yypos224= ctx->pos, yythunkpos224= ctx->thunkpos; if (!yymatchString(ctx, "**")) goto l224; goto l222; + l224:; ctx->pos= yypos224; ctx->thunkpos= yythunkpos224; + } if (!yy_Inline(ctx)) goto l222; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_StrongStar, ctx->begin, ctx->end); goto l221; + l222:; ctx->pos= yypos222; ctx->thunkpos= yythunkpos222; + } if (!yymatchString(ctx, "**")) goto l219; yyDo(ctx, yy_2_StrongStar, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "StrongStar", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l219:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StrongStar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Whitespace(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Whitespace")); + { int yypos226= ctx->pos, yythunkpos226= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l227; goto l226; + l227:; ctx->pos= yypos226; ctx->thunkpos= yythunkpos226; if (!yy_Newline(ctx)) goto l225; + } + l226:; + yyprintf((stderr, " ok %s @ %s\n", "Whitespace", ctx->buf+ctx->pos)); + return 1; + l225:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Whitespace", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EmphUl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "EmphUl")); if (!yymatchChar(ctx, '_')) goto l228; + { int yypos229= ctx->pos, yythunkpos229= ctx->thunkpos; if (!yy_Whitespace(ctx)) goto l229; goto l228; + l229:; ctx->pos= yypos229; ctx->thunkpos= yythunkpos229; + } if (!yy_StartList(ctx)) goto l228; yyDo(ctx, yySet, -2, 0); + { int yypos232= ctx->pos, yythunkpos232= ctx->thunkpos; + { int yypos234= ctx->pos, yythunkpos234= ctx->thunkpos; if (!yymatchChar(ctx, '_')) goto l234; goto l233; + l234:; ctx->pos= yypos234; ctx->thunkpos= yythunkpos234; + } if (!yy_Inline(ctx)) goto l233; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_EmphUl, ctx->begin, ctx->end); goto l232; + l233:; ctx->pos= yypos232; ctx->thunkpos= yythunkpos232; if (!yy_StrongUl(ctx)) goto l228; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_2_EmphUl, ctx->begin, ctx->end); + } + l232:; + l230:; + { int yypos231= ctx->pos, yythunkpos231= ctx->thunkpos; + { int yypos235= ctx->pos, yythunkpos235= ctx->thunkpos; + { int yypos237= ctx->pos, yythunkpos237= ctx->thunkpos; if (!yymatchChar(ctx, '_')) goto l237; goto l236; + l237:; ctx->pos= yypos237; ctx->thunkpos= yythunkpos237; + } if (!yy_Inline(ctx)) goto l236; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_EmphUl, ctx->begin, ctx->end); goto l235; + l236:; ctx->pos= yypos235; ctx->thunkpos= yythunkpos235; if (!yy_StrongUl(ctx)) goto l231; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_2_EmphUl, ctx->begin, ctx->end); + } + l235:; goto l230; + l231:; ctx->pos= yypos231; ctx->thunkpos= yythunkpos231; + } if (!yymatchChar(ctx, '_')) goto l228; yyDo(ctx, yy_3_EmphUl, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "EmphUl", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l228:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EmphUl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EmphStar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "EmphStar")); if (!yymatchChar(ctx, '*')) goto l238; + { int yypos239= ctx->pos, yythunkpos239= ctx->thunkpos; if (!yy_Whitespace(ctx)) goto l239; goto l238; + l239:; ctx->pos= yypos239; ctx->thunkpos= yythunkpos239; + } if (!yy_StartList(ctx)) goto l238; yyDo(ctx, yySet, -2, 0); + { int yypos242= ctx->pos, yythunkpos242= ctx->thunkpos; + { int yypos244= ctx->pos, yythunkpos244= ctx->thunkpos; if (!yymatchChar(ctx, '*')) goto l244; goto l243; + l244:; ctx->pos= yypos244; ctx->thunkpos= yythunkpos244; + } if (!yy_Inline(ctx)) goto l243; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_EmphStar, ctx->begin, ctx->end); goto l242; + l243:; ctx->pos= yypos242; ctx->thunkpos= yythunkpos242; if (!yy_StrongStar(ctx)) goto l238; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_2_EmphStar, ctx->begin, ctx->end); + } + l242:; + l240:; + { int yypos241= ctx->pos, yythunkpos241= ctx->thunkpos; + { int yypos245= ctx->pos, yythunkpos245= ctx->thunkpos; + { int yypos247= ctx->pos, yythunkpos247= ctx->thunkpos; if (!yymatchChar(ctx, '*')) goto l247; goto l246; + l247:; ctx->pos= yypos247; ctx->thunkpos= yythunkpos247; + } if (!yy_Inline(ctx)) goto l246; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_EmphStar, ctx->begin, ctx->end); goto l245; + l246:; ctx->pos= yypos245; ctx->thunkpos= yythunkpos245; if (!yy_StrongStar(ctx)) goto l241; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_2_EmphStar, ctx->begin, ctx->end); + } + l245:; goto l240; + l241:; ctx->pos= yypos241; ctx->thunkpos= yythunkpos241; + } if (!yymatchChar(ctx, '*')) goto l238; yyDo(ctx, yy_3_EmphStar, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "EmphStar", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l238:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EmphStar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StarLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "StarLine")); + { int yypos249= ctx->pos, yythunkpos249= ctx->thunkpos; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l250; if (!yymatchString(ctx, "****")) goto l250; + l251:; + { int yypos252= ctx->pos, yythunkpos252= ctx->thunkpos; if (!yymatchChar(ctx, '*')) goto l252; goto l251; + l252:; ctx->pos= yypos252; ctx->thunkpos= yythunkpos252; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l250; goto l249; + l250:; ctx->pos= yypos249; ctx->thunkpos= yythunkpos249; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l248; if (!yy_Spacechar(ctx)) goto l248; if (!yymatchChar(ctx, '*')) goto l248; + l253:; + { int yypos254= ctx->pos, yythunkpos254= ctx->thunkpos; if (!yymatchChar(ctx, '*')) goto l254; goto l253; + l254:; ctx->pos= yypos254; ctx->thunkpos= yythunkpos254; + } + { int yypos255= ctx->pos, yythunkpos255= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l248; ctx->pos= yypos255; ctx->thunkpos= yythunkpos255; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l248; + } + l249:; + yyprintf((stderr, " ok %s @ %s\n", "StarLine", ctx->buf+ctx->pos)); + return 1; + l248:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StarLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_UlLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "UlLine")); + { int yypos257= ctx->pos, yythunkpos257= ctx->thunkpos; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l258; if (!yymatchString(ctx, "____")) goto l258; + l259:; + { int yypos260= ctx->pos, yythunkpos260= ctx->thunkpos; if (!yymatchChar(ctx, '_')) goto l260; goto l259; + l260:; ctx->pos= yypos260; ctx->thunkpos= yythunkpos260; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l258; goto l257; + l258:; ctx->pos= yypos257; ctx->thunkpos= yythunkpos257; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l256; if (!yy_Spacechar(ctx)) goto l256; if (!yymatchChar(ctx, '_')) goto l256; + l261:; + { int yypos262= ctx->pos, yythunkpos262= ctx->thunkpos; if (!yymatchChar(ctx, '_')) goto l262; goto l261; + l262:; ctx->pos= yypos262; ctx->thunkpos= yythunkpos262; + } + { int yypos263= ctx->pos, yythunkpos263= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l256; ctx->pos= yypos263; ctx->thunkpos= yythunkpos263; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l256; + } + l257:; + yyprintf((stderr, " ok %s @ %s\n", "UlLine", ctx->buf+ctx->pos)); + return 1; + l256:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "UlLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SpecialChar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SpecialChar")); + { int yypos265= ctx->pos, yythunkpos265= ctx->thunkpos; if (!yymatchChar(ctx, '*')) goto l266; goto l265; + l266:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '_')) goto l267; goto l265; + l267:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '`')) goto l268; goto l265; + l268:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '&')) goto l269; goto l265; + l269:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '[')) goto l270; goto l265; + l270:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, ']')) goto l271; goto l265; + l271:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '(')) goto l272; goto l265; + l272:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, ')')) goto l273; goto l265; + l273:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '<')) goto l274; goto l265; + l274:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '!')) goto l275; goto l265; + l275:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '#')) goto l276; goto l265; + l276:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '\\')) goto l277; goto l265; + l277:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '\'')) goto l278; goto l265; + l278:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yymatchChar(ctx, '"')) goto l279; goto l265; + l279:; ctx->pos= yypos265; ctx->thunkpos= yythunkpos265; if (!yy_ExtendedSpecialChar(ctx)) goto l264; + } + l265:; + yyprintf((stderr, " ok %s @ %s\n", "SpecialChar", ctx->buf+ctx->pos)); + return 1; + l264:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SpecialChar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Eof(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Eof")); + { int yypos281= ctx->pos, yythunkpos281= ctx->thunkpos; if (!yymatchDot(ctx)) goto l281; goto l280; + l281:; ctx->pos= yypos281; ctx->thunkpos= yythunkpos281; + } + yyprintf((stderr, " ok %s @ %s\n", "Eof", ctx->buf+ctx->pos)); + return 1; + l280:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Eof", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_NormalEndline(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "NormalEndline")); if (!yy_Sp(ctx)) goto l282; if (!yy_Newline(ctx)) goto l282; + { int yypos283= ctx->pos, yythunkpos283= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l283; goto l282; + l283:; ctx->pos= yypos283; ctx->thunkpos= yythunkpos283; + } + { int yypos284= ctx->pos, yythunkpos284= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l284; goto l282; + l284:; ctx->pos= yypos284; ctx->thunkpos= yythunkpos284; + } + { int yypos285= ctx->pos, yythunkpos285= ctx->thunkpos; if (!yy_AtxStart(ctx)) goto l285; goto l282; + l285:; ctx->pos= yypos285; ctx->thunkpos= yythunkpos285; + } + { int yypos286= ctx->pos, yythunkpos286= ctx->thunkpos; if (!yy_Line(ctx)) goto l286; + { int yypos287= ctx->pos, yythunkpos287= ctx->thunkpos; if (!yymatchChar(ctx, '=')) goto l288; + l289:; + { int yypos290= ctx->pos, yythunkpos290= ctx->thunkpos; if (!yymatchChar(ctx, '=')) goto l290; goto l289; + l290:; ctx->pos= yypos290; ctx->thunkpos= yythunkpos290; + } goto l287; + l288:; ctx->pos= yypos287; ctx->thunkpos= yythunkpos287; if (!yymatchChar(ctx, '-')) goto l286; + l291:; + { int yypos292= ctx->pos, yythunkpos292= ctx->thunkpos; if (!yymatchChar(ctx, '-')) goto l292; goto l291; + l292:; ctx->pos= yypos292; ctx->thunkpos= yythunkpos292; + } + } + l287:; if (!yy_Newline(ctx)) goto l286; goto l282; + l286:; ctx->pos= yypos286; ctx->thunkpos= yythunkpos286; + } yyDo(ctx, yy_1_NormalEndline, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "NormalEndline", ctx->buf+ctx->pos)); + return 1; + l282:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "NormalEndline", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_TerminalEndline(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "TerminalEndline")); if (!yy_Sp(ctx)) goto l293; if (!yy_Newline(ctx)) goto l293; if (!yy_Eof(ctx)) goto l293; yyDo(ctx, yy_1_TerminalEndline, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "TerminalEndline", ctx->buf+ctx->pos)); + return 1; + l293:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "TerminalEndline", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_LineBreak(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "LineBreak")); if (!yymatchString(ctx, " ")) goto l294; if (!yy_NormalEndline(ctx)) goto l294; yyDo(ctx, yy_1_LineBreak, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "LineBreak", ctx->buf+ctx->pos)); + return 1; + l294:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "LineBreak", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_CharEntity(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "CharEntity")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l295; if (!yymatchChar(ctx, '&')) goto l295; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l295; + l296:; + { int yypos297= ctx->pos, yythunkpos297= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l297; goto l296; + l297:; ctx->pos= yypos297; ctx->thunkpos= yythunkpos297; + } if (!yymatchChar(ctx, ';')) goto l295; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l295; + yyprintf((stderr, " ok %s @ %s\n", "CharEntity", ctx->buf+ctx->pos)); + return 1; + l295:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "CharEntity", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_DecEntity(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "DecEntity")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l298; if (!yymatchChar(ctx, '&')) goto l298; if (!yymatchChar(ctx, '#')) goto l298; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l298; + l299:; + { int yypos300= ctx->pos, yythunkpos300= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l300; goto l299; + l300:; ctx->pos= yypos300; ctx->thunkpos= yythunkpos300; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l298; if (!yymatchChar(ctx, ';')) goto l298; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l298; + yyprintf((stderr, " ok %s @ %s\n", "DecEntity", ctx->buf+ctx->pos)); + return 1; + l298:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "DecEntity", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HexEntity(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HexEntity")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l301; if (!yymatchChar(ctx, '&')) goto l301; if (!yymatchChar(ctx, '#')) goto l301; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l301; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\176\000\000\000\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l301; + l302:; + { int yypos303= ctx->pos, yythunkpos303= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\176\000\000\000\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l303; goto l302; + l303:; ctx->pos= yypos303; ctx->thunkpos= yythunkpos303; + } if (!yymatchChar(ctx, ';')) goto l301; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l301; + yyprintf((stderr, " ok %s @ %s\n", "HexEntity", ctx->buf+ctx->pos)); + return 1; + l301:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HexEntity", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AposChunk(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AposChunk")); yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_SMART) )) goto l304; if (!yymatchChar(ctx, '\'')) goto l304; + { int yypos305= ctx->pos, yythunkpos305= ctx->thunkpos; if (!yy_Alphanumeric(ctx)) goto l304; ctx->pos= yypos305; ctx->thunkpos= yythunkpos305; + } yyDo(ctx, yy_1_AposChunk, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "AposChunk", ctx->buf+ctx->pos)); + return 1; + l304:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AposChunk", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Alphanumeric(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Alphanumeric")); + { int yypos307= ctx->pos, yythunkpos307= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l308; goto l307; + l308:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\200")) goto l309; goto l307; + l309:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\201")) goto l310; goto l307; + l310:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\202")) goto l311; goto l307; + l311:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\203")) goto l312; goto l307; + l312:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\204")) goto l313; goto l307; + l313:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\205")) goto l314; goto l307; + l314:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\206")) goto l315; goto l307; + l315:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\207")) goto l316; goto l307; + l316:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\210")) goto l317; goto l307; + l317:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\211")) goto l318; goto l307; + l318:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\212")) goto l319; goto l307; + l319:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\213")) goto l320; goto l307; + l320:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\214")) goto l321; goto l307; + l321:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\215")) goto l322; goto l307; + l322:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\216")) goto l323; goto l307; + l323:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\217")) goto l324; goto l307; + l324:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\220")) goto l325; goto l307; + l325:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\221")) goto l326; goto l307; + l326:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\222")) goto l327; goto l307; + l327:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\223")) goto l328; goto l307; + l328:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\224")) goto l329; goto l307; + l329:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\225")) goto l330; goto l307; + l330:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\226")) goto l331; goto l307; + l331:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\227")) goto l332; goto l307; + l332:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\230")) goto l333; goto l307; + l333:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\231")) goto l334; goto l307; + l334:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\232")) goto l335; goto l307; + l335:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\233")) goto l336; goto l307; + l336:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\234")) goto l337; goto l307; + l337:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\235")) goto l338; goto l307; + l338:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\236")) goto l339; goto l307; + l339:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\237")) goto l340; goto l307; + l340:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\240")) goto l341; goto l307; + l341:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\241")) goto l342; goto l307; + l342:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\242")) goto l343; goto l307; + l343:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\243")) goto l344; goto l307; + l344:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\244")) goto l345; goto l307; + l345:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\245")) goto l346; goto l307; + l346:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\246")) goto l347; goto l307; + l347:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\247")) goto l348; goto l307; + l348:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\250")) goto l349; goto l307; + l349:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\251")) goto l350; goto l307; + l350:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\252")) goto l351; goto l307; + l351:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\253")) goto l352; goto l307; + l352:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\254")) goto l353; goto l307; + l353:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\255")) goto l354; goto l307; + l354:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\256")) goto l355; goto l307; + l355:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\257")) goto l356; goto l307; + l356:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\260")) goto l357; goto l307; + l357:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\261")) goto l358; goto l307; + l358:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\262")) goto l359; goto l307; + l359:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\263")) goto l360; goto l307; + l360:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\264")) goto l361; goto l307; + l361:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\265")) goto l362; goto l307; + l362:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\266")) goto l363; goto l307; + l363:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\267")) goto l364; goto l307; + l364:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\270")) goto l365; goto l307; + l365:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\271")) goto l366; goto l307; + l366:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\272")) goto l367; goto l307; + l367:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\273")) goto l368; goto l307; + l368:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\274")) goto l369; goto l307; + l369:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\275")) goto l370; goto l307; + l370:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\276")) goto l371; goto l307; + l371:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\277")) goto l372; goto l307; + l372:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\300")) goto l373; goto l307; + l373:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\301")) goto l374; goto l307; + l374:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\302")) goto l375; goto l307; + l375:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\303")) goto l376; goto l307; + l376:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\304")) goto l377; goto l307; + l377:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\305")) goto l378; goto l307; + l378:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\306")) goto l379; goto l307; + l379:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\307")) goto l380; goto l307; + l380:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\310")) goto l381; goto l307; + l381:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\311")) goto l382; goto l307; + l382:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\312")) goto l383; goto l307; + l383:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\313")) goto l384; goto l307; + l384:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\314")) goto l385; goto l307; + l385:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\315")) goto l386; goto l307; + l386:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\316")) goto l387; goto l307; + l387:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\317")) goto l388; goto l307; + l388:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\320")) goto l389; goto l307; + l389:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\321")) goto l390; goto l307; + l390:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\322")) goto l391; goto l307; + l391:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\323")) goto l392; goto l307; + l392:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\324")) goto l393; goto l307; + l393:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\325")) goto l394; goto l307; + l394:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\326")) goto l395; goto l307; + l395:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\327")) goto l396; goto l307; + l396:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\330")) goto l397; goto l307; + l397:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\331")) goto l398; goto l307; + l398:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\332")) goto l399; goto l307; + l399:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\333")) goto l400; goto l307; + l400:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\334")) goto l401; goto l307; + l401:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\335")) goto l402; goto l307; + l402:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\336")) goto l403; goto l307; + l403:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\337")) goto l404; goto l307; + l404:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\340")) goto l405; goto l307; + l405:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\341")) goto l406; goto l307; + l406:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\342")) goto l407; goto l307; + l407:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\343")) goto l408; goto l307; + l408:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\344")) goto l409; goto l307; + l409:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\345")) goto l410; goto l307; + l410:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\346")) goto l411; goto l307; + l411:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\347")) goto l412; goto l307; + l412:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\350")) goto l413; goto l307; + l413:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\351")) goto l414; goto l307; + l414:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\352")) goto l415; goto l307; + l415:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\353")) goto l416; goto l307; + l416:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\354")) goto l417; goto l307; + l417:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\355")) goto l418; goto l307; + l418:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\356")) goto l419; goto l307; + l419:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\357")) goto l420; goto l307; + l420:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\360")) goto l421; goto l307; + l421:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\361")) goto l422; goto l307; + l422:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\362")) goto l423; goto l307; + l423:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\363")) goto l424; goto l307; + l424:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\364")) goto l425; goto l307; + l425:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\365")) goto l426; goto l307; + l426:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\366")) goto l427; goto l307; + l427:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\367")) goto l428; goto l307; + l428:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\370")) goto l429; goto l307; + l429:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\371")) goto l430; goto l307; + l430:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\372")) goto l431; goto l307; + l431:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\373")) goto l432; goto l307; + l432:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\374")) goto l433; goto l307; + l433:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\375")) goto l434; goto l307; + l434:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\376")) goto l435; goto l307; + l435:; ctx->pos= yypos307; ctx->thunkpos= yythunkpos307; if (!yymatchString(ctx, "\377")) goto l306; + } + l307:; + yyprintf((stderr, " ok %s @ %s\n", "Alphanumeric", ctx->buf+ctx->pos)); + return 1; + l306:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Alphanumeric", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StrChunk(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "StrChunk")); + { int yypos437= ctx->pos, yythunkpos437= ctx->thunkpos; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l438; + { int yypos441= ctx->pos, yythunkpos441= ctx->thunkpos; if (!yy_NormalChar(ctx)) goto l442; goto l441; + l442:; ctx->pos= yypos441; ctx->thunkpos= yythunkpos441; if (!yymatchChar(ctx, '_')) goto l438; + l443:; + { int yypos444= ctx->pos, yythunkpos444= ctx->thunkpos; if (!yymatchChar(ctx, '_')) goto l444; goto l443; + l444:; ctx->pos= yypos444; ctx->thunkpos= yythunkpos444; + } + { int yypos445= ctx->pos, yythunkpos445= ctx->thunkpos; if (!yy_Alphanumeric(ctx)) goto l438; ctx->pos= yypos445; ctx->thunkpos= yythunkpos445; + } + } + l441:; + l439:; + { int yypos440= ctx->pos, yythunkpos440= ctx->thunkpos; + { int yypos446= ctx->pos, yythunkpos446= ctx->thunkpos; if (!yy_NormalChar(ctx)) goto l447; goto l446; + l447:; ctx->pos= yypos446; ctx->thunkpos= yythunkpos446; if (!yymatchChar(ctx, '_')) goto l440; + l448:; + { int yypos449= ctx->pos, yythunkpos449= ctx->thunkpos; if (!yymatchChar(ctx, '_')) goto l449; goto l448; + l449:; ctx->pos= yypos449; ctx->thunkpos= yythunkpos449; + } + { int yypos450= ctx->pos, yythunkpos450= ctx->thunkpos; if (!yy_Alphanumeric(ctx)) goto l440; ctx->pos= yypos450; ctx->thunkpos= yythunkpos450; + } + } + l446:; goto l439; + l440:; ctx->pos= yypos440; ctx->thunkpos= yythunkpos440; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l438; yyDo(ctx, yy_1_StrChunk, ctx->begin, ctx->end); goto l437; + l438:; ctx->pos= yypos437; ctx->thunkpos= yythunkpos437; if (!yy_AposChunk(ctx)) goto l436; + } + l437:; + yyprintf((stderr, " ok %s @ %s\n", "StrChunk", ctx->buf+ctx->pos)); + return 1; + l436:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StrChunk", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_NormalChar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "NormalChar")); + { int yypos452= ctx->pos, yythunkpos452= ctx->thunkpos; + { int yypos453= ctx->pos, yythunkpos453= ctx->thunkpos; if (!yy_SpecialChar(ctx)) goto l454; goto l453; + l454:; ctx->pos= yypos453; ctx->thunkpos= yythunkpos453; if (!yy_Spacechar(ctx)) goto l455; goto l453; + l455:; ctx->pos= yypos453; ctx->thunkpos= yythunkpos453; if (!yy_Newline(ctx)) goto l452; + } + l453:; goto l451; + l452:; ctx->pos= yypos452; ctx->thunkpos= yythunkpos452; + } if (!yymatchDot(ctx)) goto l451; + yyprintf((stderr, " ok %s @ %s\n", "NormalChar", ctx->buf+ctx->pos)); + return 1; + l451:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "NormalChar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Symbol(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Symbol")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l456; if (!yy_SpecialChar(ctx)) goto l456; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l456; yyDo(ctx, yy_1_Symbol, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Symbol", ctx->buf+ctx->pos)); + return 1; + l456:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Symbol", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Smart(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Smart")); yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_SMART) )) goto l457; + { int yypos458= ctx->pos, yythunkpos458= ctx->thunkpos; if (!yy_Ellipsis(ctx)) goto l459; goto l458; + l459:; ctx->pos= yypos458; ctx->thunkpos= yythunkpos458; if (!yy_Dash(ctx)) goto l460; goto l458; + l460:; ctx->pos= yypos458; ctx->thunkpos= yythunkpos458; if (!yy_SingleQuoted(ctx)) goto l461; goto l458; + l461:; ctx->pos= yypos458; ctx->thunkpos= yythunkpos458; if (!yy_DoubleQuoted(ctx)) goto l462; goto l458; + l462:; ctx->pos= yypos458; ctx->thunkpos= yythunkpos458; if (!yy_Apostrophe(ctx)) goto l457; + } + l458:; + yyprintf((stderr, " ok %s @ %s\n", "Smart", ctx->buf+ctx->pos)); + return 1; + l457:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Smart", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EscapedChar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "EscapedChar")); if (!yymatchChar(ctx, '\\')) goto l463; + { int yypos464= ctx->pos, yythunkpos464= ctx->thunkpos; if (!yy_Newline(ctx)) goto l464; goto l463; + l464:; ctx->pos= yypos464; ctx->thunkpos= yythunkpos464; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l463; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\012\157\000\120\000\000\000\270\001\000\000\070\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l463; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l463; yyDo(ctx, yy_1_EscapedChar, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "EscapedChar", ctx->buf+ctx->pos)); + return 1; + l463:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EscapedChar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Entity(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Entity")); + { int yypos466= ctx->pos, yythunkpos466= ctx->thunkpos; if (!yy_HexEntity(ctx)) goto l467; goto l466; + l467:; ctx->pos= yypos466; ctx->thunkpos= yythunkpos466; if (!yy_DecEntity(ctx)) goto l468; goto l466; + l468:; ctx->pos= yypos466; ctx->thunkpos= yythunkpos466; if (!yy_CharEntity(ctx)) goto l465; + } + l466:; yyDo(ctx, yy_1_Entity, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Entity", ctx->buf+ctx->pos)); + return 1; + l465:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Entity", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RawHtml(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RawHtml")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l469; + { int yypos470= ctx->pos, yythunkpos470= ctx->thunkpos; if (!yy_HtmlComment(ctx)) goto l471; goto l470; + l471:; ctx->pos= yypos470; ctx->thunkpos= yythunkpos470; if (!yy_HtmlBlockScript(ctx)) goto l472; goto l470; + l472:; ctx->pos= yypos470; ctx->thunkpos= yythunkpos470; if (!yy_HtmlTag(ctx)) goto l469; + } + l470:; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l469; yyDo(ctx, yy_1_RawHtml, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "RawHtml", ctx->buf+ctx->pos)); + return 1; + l469:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RawHtml", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Code(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Code")); + { int yypos474= ctx->pos, yythunkpos474= ctx->thunkpos; if (!yy_Ticks1(ctx)) goto l475; if (!yy_Sp(ctx)) goto l475; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l475; + { int yypos478= ctx->pos, yythunkpos478= ctx->thunkpos; + { int yypos482= ctx->pos, yythunkpos482= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l482; goto l479; + l482:; ctx->pos= yypos482; ctx->thunkpos= yythunkpos482; + } if (!yy_Nonspacechar(ctx)) goto l479; + l480:; + { int yypos481= ctx->pos, yythunkpos481= ctx->thunkpos; + { int yypos483= ctx->pos, yythunkpos483= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l483; goto l481; + l483:; ctx->pos= yypos483; ctx->thunkpos= yythunkpos483; + } if (!yy_Nonspacechar(ctx)) goto l481; goto l480; + l481:; ctx->pos= yypos481; ctx->thunkpos= yythunkpos481; + } goto l478; + l479:; ctx->pos= yypos478; ctx->thunkpos= yythunkpos478; + { int yypos485= ctx->pos, yythunkpos485= ctx->thunkpos; if (!yy_Ticks1(ctx)) goto l485; goto l484; + l485:; ctx->pos= yypos485; ctx->thunkpos= yythunkpos485; + } if (!yymatchChar(ctx, '`')) goto l484; + l486:; + { int yypos487= ctx->pos, yythunkpos487= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l487; goto l486; + l487:; ctx->pos= yypos487; ctx->thunkpos= yythunkpos487; + } goto l478; + l484:; ctx->pos= yypos478; ctx->thunkpos= yythunkpos478; + { int yypos488= ctx->pos, yythunkpos488= ctx->thunkpos; if (!yy_Sp(ctx)) goto l488; if (!yy_Ticks1(ctx)) goto l488; goto l475; + l488:; ctx->pos= yypos488; ctx->thunkpos= yythunkpos488; + } + { int yypos489= ctx->pos, yythunkpos489= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l490; goto l489; + l490:; ctx->pos= yypos489; ctx->thunkpos= yythunkpos489; if (!yy_Newline(ctx)) goto l475; + { int yypos491= ctx->pos, yythunkpos491= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l491; goto l475; + l491:; ctx->pos= yypos491; ctx->thunkpos= yythunkpos491; + } + } + l489:; + } + l478:; + l476:; + { int yypos477= ctx->pos, yythunkpos477= ctx->thunkpos; + { int yypos492= ctx->pos, yythunkpos492= ctx->thunkpos; + { int yypos496= ctx->pos, yythunkpos496= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l496; goto l493; + l496:; ctx->pos= yypos496; ctx->thunkpos= yythunkpos496; + } if (!yy_Nonspacechar(ctx)) goto l493; + l494:; + { int yypos495= ctx->pos, yythunkpos495= ctx->thunkpos; + { int yypos497= ctx->pos, yythunkpos497= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l497; goto l495; + l497:; ctx->pos= yypos497; ctx->thunkpos= yythunkpos497; + } if (!yy_Nonspacechar(ctx)) goto l495; goto l494; + l495:; ctx->pos= yypos495; ctx->thunkpos= yythunkpos495; + } goto l492; + l493:; ctx->pos= yypos492; ctx->thunkpos= yythunkpos492; + { int yypos499= ctx->pos, yythunkpos499= ctx->thunkpos; if (!yy_Ticks1(ctx)) goto l499; goto l498; + l499:; ctx->pos= yypos499; ctx->thunkpos= yythunkpos499; + } if (!yymatchChar(ctx, '`')) goto l498; + l500:; + { int yypos501= ctx->pos, yythunkpos501= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l501; goto l500; + l501:; ctx->pos= yypos501; ctx->thunkpos= yythunkpos501; + } goto l492; + l498:; ctx->pos= yypos492; ctx->thunkpos= yythunkpos492; + { int yypos502= ctx->pos, yythunkpos502= ctx->thunkpos; if (!yy_Sp(ctx)) goto l502; if (!yy_Ticks1(ctx)) goto l502; goto l477; + l502:; ctx->pos= yypos502; ctx->thunkpos= yythunkpos502; + } + { int yypos503= ctx->pos, yythunkpos503= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l504; goto l503; + l504:; ctx->pos= yypos503; ctx->thunkpos= yythunkpos503; if (!yy_Newline(ctx)) goto l477; + { int yypos505= ctx->pos, yythunkpos505= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l505; goto l477; + l505:; ctx->pos= yypos505; ctx->thunkpos= yythunkpos505; + } + } + l503:; + } + l492:; goto l476; + l477:; ctx->pos= yypos477; ctx->thunkpos= yythunkpos477; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l475; if (!yy_Sp(ctx)) goto l475; if (!yy_Ticks1(ctx)) goto l475; goto l474; + l475:; ctx->pos= yypos474; ctx->thunkpos= yythunkpos474; if (!yy_Ticks2(ctx)) goto l506; if (!yy_Sp(ctx)) goto l506; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l506; + { int yypos509= ctx->pos, yythunkpos509= ctx->thunkpos; + { int yypos513= ctx->pos, yythunkpos513= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l513; goto l510; + l513:; ctx->pos= yypos513; ctx->thunkpos= yythunkpos513; + } if (!yy_Nonspacechar(ctx)) goto l510; + l511:; + { int yypos512= ctx->pos, yythunkpos512= ctx->thunkpos; + { int yypos514= ctx->pos, yythunkpos514= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l514; goto l512; + l514:; ctx->pos= yypos514; ctx->thunkpos= yythunkpos514; + } if (!yy_Nonspacechar(ctx)) goto l512; goto l511; + l512:; ctx->pos= yypos512; ctx->thunkpos= yythunkpos512; + } goto l509; + l510:; ctx->pos= yypos509; ctx->thunkpos= yythunkpos509; + { int yypos516= ctx->pos, yythunkpos516= ctx->thunkpos; if (!yy_Ticks2(ctx)) goto l516; goto l515; + l516:; ctx->pos= yypos516; ctx->thunkpos= yythunkpos516; + } if (!yymatchChar(ctx, '`')) goto l515; + l517:; + { int yypos518= ctx->pos, yythunkpos518= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l518; goto l517; + l518:; ctx->pos= yypos518; ctx->thunkpos= yythunkpos518; + } goto l509; + l515:; ctx->pos= yypos509; ctx->thunkpos= yythunkpos509; + { int yypos519= ctx->pos, yythunkpos519= ctx->thunkpos; if (!yy_Sp(ctx)) goto l519; if (!yy_Ticks2(ctx)) goto l519; goto l506; + l519:; ctx->pos= yypos519; ctx->thunkpos= yythunkpos519; + } + { int yypos520= ctx->pos, yythunkpos520= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l521; goto l520; + l521:; ctx->pos= yypos520; ctx->thunkpos= yythunkpos520; if (!yy_Newline(ctx)) goto l506; + { int yypos522= ctx->pos, yythunkpos522= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l522; goto l506; + l522:; ctx->pos= yypos522; ctx->thunkpos= yythunkpos522; + } + } + l520:; + } + l509:; + l507:; + { int yypos508= ctx->pos, yythunkpos508= ctx->thunkpos; + { int yypos523= ctx->pos, yythunkpos523= ctx->thunkpos; + { int yypos527= ctx->pos, yythunkpos527= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l527; goto l524; + l527:; ctx->pos= yypos527; ctx->thunkpos= yythunkpos527; + } if (!yy_Nonspacechar(ctx)) goto l524; + l525:; + { int yypos526= ctx->pos, yythunkpos526= ctx->thunkpos; + { int yypos528= ctx->pos, yythunkpos528= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l528; goto l526; + l528:; ctx->pos= yypos528; ctx->thunkpos= yythunkpos528; + } if (!yy_Nonspacechar(ctx)) goto l526; goto l525; + l526:; ctx->pos= yypos526; ctx->thunkpos= yythunkpos526; + } goto l523; + l524:; ctx->pos= yypos523; ctx->thunkpos= yythunkpos523; + { int yypos530= ctx->pos, yythunkpos530= ctx->thunkpos; if (!yy_Ticks2(ctx)) goto l530; goto l529; + l530:; ctx->pos= yypos530; ctx->thunkpos= yythunkpos530; + } if (!yymatchChar(ctx, '`')) goto l529; + l531:; + { int yypos532= ctx->pos, yythunkpos532= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l532; goto l531; + l532:; ctx->pos= yypos532; ctx->thunkpos= yythunkpos532; + } goto l523; + l529:; ctx->pos= yypos523; ctx->thunkpos= yythunkpos523; + { int yypos533= ctx->pos, yythunkpos533= ctx->thunkpos; if (!yy_Sp(ctx)) goto l533; if (!yy_Ticks2(ctx)) goto l533; goto l508; + l533:; ctx->pos= yypos533; ctx->thunkpos= yythunkpos533; + } + { int yypos534= ctx->pos, yythunkpos534= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l535; goto l534; + l535:; ctx->pos= yypos534; ctx->thunkpos= yythunkpos534; if (!yy_Newline(ctx)) goto l508; + { int yypos536= ctx->pos, yythunkpos536= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l536; goto l508; + l536:; ctx->pos= yypos536; ctx->thunkpos= yythunkpos536; + } + } + l534:; + } + l523:; goto l507; + l508:; ctx->pos= yypos508; ctx->thunkpos= yythunkpos508; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l506; if (!yy_Sp(ctx)) goto l506; if (!yy_Ticks2(ctx)) goto l506; goto l474; + l506:; ctx->pos= yypos474; ctx->thunkpos= yythunkpos474; if (!yy_Ticks3(ctx)) goto l537; if (!yy_Sp(ctx)) goto l537; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l537; + { int yypos540= ctx->pos, yythunkpos540= ctx->thunkpos; + { int yypos544= ctx->pos, yythunkpos544= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l544; goto l541; + l544:; ctx->pos= yypos544; ctx->thunkpos= yythunkpos544; + } if (!yy_Nonspacechar(ctx)) goto l541; + l542:; + { int yypos543= ctx->pos, yythunkpos543= ctx->thunkpos; + { int yypos545= ctx->pos, yythunkpos545= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l545; goto l543; + l545:; ctx->pos= yypos545; ctx->thunkpos= yythunkpos545; + } if (!yy_Nonspacechar(ctx)) goto l543; goto l542; + l543:; ctx->pos= yypos543; ctx->thunkpos= yythunkpos543; + } goto l540; + l541:; ctx->pos= yypos540; ctx->thunkpos= yythunkpos540; + { int yypos547= ctx->pos, yythunkpos547= ctx->thunkpos; if (!yy_Ticks3(ctx)) goto l547; goto l546; + l547:; ctx->pos= yypos547; ctx->thunkpos= yythunkpos547; + } if (!yymatchChar(ctx, '`')) goto l546; + l548:; + { int yypos549= ctx->pos, yythunkpos549= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l549; goto l548; + l549:; ctx->pos= yypos549; ctx->thunkpos= yythunkpos549; + } goto l540; + l546:; ctx->pos= yypos540; ctx->thunkpos= yythunkpos540; + { int yypos550= ctx->pos, yythunkpos550= ctx->thunkpos; if (!yy_Sp(ctx)) goto l550; if (!yy_Ticks3(ctx)) goto l550; goto l537; + l550:; ctx->pos= yypos550; ctx->thunkpos= yythunkpos550; + } + { int yypos551= ctx->pos, yythunkpos551= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l552; goto l551; + l552:; ctx->pos= yypos551; ctx->thunkpos= yythunkpos551; if (!yy_Newline(ctx)) goto l537; + { int yypos553= ctx->pos, yythunkpos553= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l553; goto l537; + l553:; ctx->pos= yypos553; ctx->thunkpos= yythunkpos553; + } + } + l551:; + } + l540:; + l538:; + { int yypos539= ctx->pos, yythunkpos539= ctx->thunkpos; + { int yypos554= ctx->pos, yythunkpos554= ctx->thunkpos; + { int yypos558= ctx->pos, yythunkpos558= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l558; goto l555; + l558:; ctx->pos= yypos558; ctx->thunkpos= yythunkpos558; + } if (!yy_Nonspacechar(ctx)) goto l555; + l556:; + { int yypos557= ctx->pos, yythunkpos557= ctx->thunkpos; + { int yypos559= ctx->pos, yythunkpos559= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l559; goto l557; + l559:; ctx->pos= yypos559; ctx->thunkpos= yythunkpos559; + } if (!yy_Nonspacechar(ctx)) goto l557; goto l556; + l557:; ctx->pos= yypos557; ctx->thunkpos= yythunkpos557; + } goto l554; + l555:; ctx->pos= yypos554; ctx->thunkpos= yythunkpos554; + { int yypos561= ctx->pos, yythunkpos561= ctx->thunkpos; if (!yy_Ticks3(ctx)) goto l561; goto l560; + l561:; ctx->pos= yypos561; ctx->thunkpos= yythunkpos561; + } if (!yymatchChar(ctx, '`')) goto l560; + l562:; + { int yypos563= ctx->pos, yythunkpos563= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l563; goto l562; + l563:; ctx->pos= yypos563; ctx->thunkpos= yythunkpos563; + } goto l554; + l560:; ctx->pos= yypos554; ctx->thunkpos= yythunkpos554; + { int yypos564= ctx->pos, yythunkpos564= ctx->thunkpos; if (!yy_Sp(ctx)) goto l564; if (!yy_Ticks3(ctx)) goto l564; goto l539; + l564:; ctx->pos= yypos564; ctx->thunkpos= yythunkpos564; + } + { int yypos565= ctx->pos, yythunkpos565= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l566; goto l565; + l566:; ctx->pos= yypos565; ctx->thunkpos= yythunkpos565; if (!yy_Newline(ctx)) goto l539; + { int yypos567= ctx->pos, yythunkpos567= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l567; goto l539; + l567:; ctx->pos= yypos567; ctx->thunkpos= yythunkpos567; + } + } + l565:; + } + l554:; goto l538; + l539:; ctx->pos= yypos539; ctx->thunkpos= yythunkpos539; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l537; if (!yy_Sp(ctx)) goto l537; if (!yy_Ticks3(ctx)) goto l537; goto l474; + l537:; ctx->pos= yypos474; ctx->thunkpos= yythunkpos474; if (!yy_Ticks4(ctx)) goto l568; if (!yy_Sp(ctx)) goto l568; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l568; + { int yypos571= ctx->pos, yythunkpos571= ctx->thunkpos; + { int yypos575= ctx->pos, yythunkpos575= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l575; goto l572; + l575:; ctx->pos= yypos575; ctx->thunkpos= yythunkpos575; + } if (!yy_Nonspacechar(ctx)) goto l572; + l573:; + { int yypos574= ctx->pos, yythunkpos574= ctx->thunkpos; + { int yypos576= ctx->pos, yythunkpos576= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l576; goto l574; + l576:; ctx->pos= yypos576; ctx->thunkpos= yythunkpos576; + } if (!yy_Nonspacechar(ctx)) goto l574; goto l573; + l574:; ctx->pos= yypos574; ctx->thunkpos= yythunkpos574; + } goto l571; + l572:; ctx->pos= yypos571; ctx->thunkpos= yythunkpos571; + { int yypos578= ctx->pos, yythunkpos578= ctx->thunkpos; if (!yy_Ticks4(ctx)) goto l578; goto l577; + l578:; ctx->pos= yypos578; ctx->thunkpos= yythunkpos578; + } if (!yymatchChar(ctx, '`')) goto l577; + l579:; + { int yypos580= ctx->pos, yythunkpos580= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l580; goto l579; + l580:; ctx->pos= yypos580; ctx->thunkpos= yythunkpos580; + } goto l571; + l577:; ctx->pos= yypos571; ctx->thunkpos= yythunkpos571; + { int yypos581= ctx->pos, yythunkpos581= ctx->thunkpos; if (!yy_Sp(ctx)) goto l581; if (!yy_Ticks4(ctx)) goto l581; goto l568; + l581:; ctx->pos= yypos581; ctx->thunkpos= yythunkpos581; + } + { int yypos582= ctx->pos, yythunkpos582= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l583; goto l582; + l583:; ctx->pos= yypos582; ctx->thunkpos= yythunkpos582; if (!yy_Newline(ctx)) goto l568; + { int yypos584= ctx->pos, yythunkpos584= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l584; goto l568; + l584:; ctx->pos= yypos584; ctx->thunkpos= yythunkpos584; + } + } + l582:; + } + l571:; + l569:; + { int yypos570= ctx->pos, yythunkpos570= ctx->thunkpos; + { int yypos585= ctx->pos, yythunkpos585= ctx->thunkpos; + { int yypos589= ctx->pos, yythunkpos589= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l589; goto l586; + l589:; ctx->pos= yypos589; ctx->thunkpos= yythunkpos589; + } if (!yy_Nonspacechar(ctx)) goto l586; + l587:; + { int yypos588= ctx->pos, yythunkpos588= ctx->thunkpos; + { int yypos590= ctx->pos, yythunkpos590= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l590; goto l588; + l590:; ctx->pos= yypos590; ctx->thunkpos= yythunkpos590; + } if (!yy_Nonspacechar(ctx)) goto l588; goto l587; + l588:; ctx->pos= yypos588; ctx->thunkpos= yythunkpos588; + } goto l585; + l586:; ctx->pos= yypos585; ctx->thunkpos= yythunkpos585; + { int yypos592= ctx->pos, yythunkpos592= ctx->thunkpos; if (!yy_Ticks4(ctx)) goto l592; goto l591; + l592:; ctx->pos= yypos592; ctx->thunkpos= yythunkpos592; + } if (!yymatchChar(ctx, '`')) goto l591; + l593:; + { int yypos594= ctx->pos, yythunkpos594= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l594; goto l593; + l594:; ctx->pos= yypos594; ctx->thunkpos= yythunkpos594; + } goto l585; + l591:; ctx->pos= yypos585; ctx->thunkpos= yythunkpos585; + { int yypos595= ctx->pos, yythunkpos595= ctx->thunkpos; if (!yy_Sp(ctx)) goto l595; if (!yy_Ticks4(ctx)) goto l595; goto l570; + l595:; ctx->pos= yypos595; ctx->thunkpos= yythunkpos595; + } + { int yypos596= ctx->pos, yythunkpos596= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l597; goto l596; + l597:; ctx->pos= yypos596; ctx->thunkpos= yythunkpos596; if (!yy_Newline(ctx)) goto l570; + { int yypos598= ctx->pos, yythunkpos598= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l598; goto l570; + l598:; ctx->pos= yypos598; ctx->thunkpos= yythunkpos598; + } + } + l596:; + } + l585:; goto l569; + l570:; ctx->pos= yypos570; ctx->thunkpos= yythunkpos570; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l568; if (!yy_Sp(ctx)) goto l568; if (!yy_Ticks4(ctx)) goto l568; goto l474; + l568:; ctx->pos= yypos474; ctx->thunkpos= yythunkpos474; if (!yy_Ticks5(ctx)) goto l473; if (!yy_Sp(ctx)) goto l473; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l473; + { int yypos601= ctx->pos, yythunkpos601= ctx->thunkpos; + { int yypos605= ctx->pos, yythunkpos605= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l605; goto l602; + l605:; ctx->pos= yypos605; ctx->thunkpos= yythunkpos605; + } if (!yy_Nonspacechar(ctx)) goto l602; + l603:; + { int yypos604= ctx->pos, yythunkpos604= ctx->thunkpos; + { int yypos606= ctx->pos, yythunkpos606= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l606; goto l604; + l606:; ctx->pos= yypos606; ctx->thunkpos= yythunkpos606; + } if (!yy_Nonspacechar(ctx)) goto l604; goto l603; + l604:; ctx->pos= yypos604; ctx->thunkpos= yythunkpos604; + } goto l601; + l602:; ctx->pos= yypos601; ctx->thunkpos= yythunkpos601; + { int yypos608= ctx->pos, yythunkpos608= ctx->thunkpos; if (!yy_Ticks5(ctx)) goto l608; goto l607; + l608:; ctx->pos= yypos608; ctx->thunkpos= yythunkpos608; + } if (!yymatchChar(ctx, '`')) goto l607; + l609:; + { int yypos610= ctx->pos, yythunkpos610= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l610; goto l609; + l610:; ctx->pos= yypos610; ctx->thunkpos= yythunkpos610; + } goto l601; + l607:; ctx->pos= yypos601; ctx->thunkpos= yythunkpos601; + { int yypos611= ctx->pos, yythunkpos611= ctx->thunkpos; if (!yy_Sp(ctx)) goto l611; if (!yy_Ticks5(ctx)) goto l611; goto l473; + l611:; ctx->pos= yypos611; ctx->thunkpos= yythunkpos611; + } + { int yypos612= ctx->pos, yythunkpos612= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l613; goto l612; + l613:; ctx->pos= yypos612; ctx->thunkpos= yythunkpos612; if (!yy_Newline(ctx)) goto l473; + { int yypos614= ctx->pos, yythunkpos614= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l614; goto l473; + l614:; ctx->pos= yypos614; ctx->thunkpos= yythunkpos614; + } + } + l612:; + } + l601:; + l599:; + { int yypos600= ctx->pos, yythunkpos600= ctx->thunkpos; + { int yypos615= ctx->pos, yythunkpos615= ctx->thunkpos; + { int yypos619= ctx->pos, yythunkpos619= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l619; goto l616; + l619:; ctx->pos= yypos619; ctx->thunkpos= yythunkpos619; + } if (!yy_Nonspacechar(ctx)) goto l616; + l617:; + { int yypos618= ctx->pos, yythunkpos618= ctx->thunkpos; + { int yypos620= ctx->pos, yythunkpos620= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l620; goto l618; + l620:; ctx->pos= yypos620; ctx->thunkpos= yythunkpos620; + } if (!yy_Nonspacechar(ctx)) goto l618; goto l617; + l618:; ctx->pos= yypos618; ctx->thunkpos= yythunkpos618; + } goto l615; + l616:; ctx->pos= yypos615; ctx->thunkpos= yythunkpos615; + { int yypos622= ctx->pos, yythunkpos622= ctx->thunkpos; if (!yy_Ticks5(ctx)) goto l622; goto l621; + l622:; ctx->pos= yypos622; ctx->thunkpos= yythunkpos622; + } if (!yymatchChar(ctx, '`')) goto l621; + l623:; + { int yypos624= ctx->pos, yythunkpos624= ctx->thunkpos; if (!yymatchChar(ctx, '`')) goto l624; goto l623; + l624:; ctx->pos= yypos624; ctx->thunkpos= yythunkpos624; + } goto l615; + l621:; ctx->pos= yypos615; ctx->thunkpos= yythunkpos615; + { int yypos625= ctx->pos, yythunkpos625= ctx->thunkpos; if (!yy_Sp(ctx)) goto l625; if (!yy_Ticks5(ctx)) goto l625; goto l600; + l625:; ctx->pos= yypos625; ctx->thunkpos= yythunkpos625; + } + { int yypos626= ctx->pos, yythunkpos626= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l627; goto l626; + l627:; ctx->pos= yypos626; ctx->thunkpos= yythunkpos626; if (!yy_Newline(ctx)) goto l600; + { int yypos628= ctx->pos, yythunkpos628= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l628; goto l600; + l628:; ctx->pos= yypos628; ctx->thunkpos= yythunkpos628; + } + } + l626:; + } + l615:; goto l599; + l600:; ctx->pos= yypos600; ctx->thunkpos= yythunkpos600; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l473; if (!yy_Sp(ctx)) goto l473; if (!yy_Ticks5(ctx)) goto l473; + } + l474:; yyDo(ctx, yy_1_Code, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Code", ctx->buf+ctx->pos)); + return 1; + l473:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Code", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_InlineNote(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "InlineNote")); yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_NOTES) )) goto l629; if (!yymatchString(ctx, "^[")) goto l629; if (!yy_StartList(ctx)) goto l629; yyDo(ctx, yySet, -1, 0); + { int yypos632= ctx->pos, yythunkpos632= ctx->thunkpos; if (!yymatchChar(ctx, ']')) goto l632; goto l629; + l632:; ctx->pos= yypos632; ctx->thunkpos= yythunkpos632; + } if (!yy_Inline(ctx)) goto l629; yyDo(ctx, yy_1_InlineNote, ctx->begin, ctx->end); + l630:; + { int yypos631= ctx->pos, yythunkpos631= ctx->thunkpos; + { int yypos633= ctx->pos, yythunkpos633= ctx->thunkpos; if (!yymatchChar(ctx, ']')) goto l633; goto l631; + l633:; ctx->pos= yypos633; ctx->thunkpos= yythunkpos633; + } if (!yy_Inline(ctx)) goto l631; yyDo(ctx, yy_1_InlineNote, ctx->begin, ctx->end); goto l630; + l631:; ctx->pos= yypos631; ctx->thunkpos= yythunkpos631; + } if (!yymatchChar(ctx, ']')) goto l629; yyDo(ctx, yy_2_InlineNote, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "InlineNote", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l629:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "InlineNote", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_NoteReference(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "NoteReference")); yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_NOTES) )) goto l634; if (!yy_RawNoteReference(ctx)) goto l634; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_NoteReference, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "NoteReference", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l634:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "NoteReference", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Link(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Link")); + { int yypos636= ctx->pos, yythunkpos636= ctx->thunkpos; if (!yy_ExplicitLink(ctx)) goto l637; goto l636; + l637:; ctx->pos= yypos636; ctx->thunkpos= yythunkpos636; if (!yy_ReferenceLink(ctx)) goto l638; goto l636; + l638:; ctx->pos= yypos636; ctx->thunkpos= yythunkpos636; if (!yy_AutoLink(ctx)) goto l635; + } + l636:; + yyprintf((stderr, " ok %s @ %s\n", "Link", ctx->buf+ctx->pos)); + return 1; + l635:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Link", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Image(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Image")); if (!yymatchChar(ctx, '!')) goto l639; + { int yypos640= ctx->pos, yythunkpos640= ctx->thunkpos; if (!yy_ExplicitLink(ctx)) goto l641; goto l640; + l641:; ctx->pos= yypos640; ctx->thunkpos= yythunkpos640; if (!yy_ReferenceLink(ctx)) goto l639; + } + l640:; yyDo(ctx, yy_1_Image, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Image", ctx->buf+ctx->pos)); + return 1; + l639:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Image", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Emph(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Emph")); + { int yypos643= ctx->pos, yythunkpos643= ctx->thunkpos; if (!yy_EmphStar(ctx)) goto l644; goto l643; + l644:; ctx->pos= yypos643; ctx->thunkpos= yythunkpos643; if (!yy_EmphUl(ctx)) goto l642; + } + l643:; + yyprintf((stderr, " ok %s @ %s\n", "Emph", ctx->buf+ctx->pos)); + return 1; + l642:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Emph", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Strong(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Strong")); + { int yypos646= ctx->pos, yythunkpos646= ctx->thunkpos; if (!yy_StrongStar(ctx)) goto l647; goto l646; + l647:; ctx->pos= yypos646; ctx->thunkpos= yythunkpos646; if (!yy_StrongUl(ctx)) goto l645; + } + l646:; + yyprintf((stderr, " ok %s @ %s\n", "Strong", ctx->buf+ctx->pos)); + return 1; + l645:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Strong", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Space(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Space")); if (!yy_Spacechar(ctx)) goto l648; + l649:; + { int yypos650= ctx->pos, yythunkpos650= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l650; goto l649; + l650:; ctx->pos= yypos650; ctx->thunkpos= yythunkpos650; + } yyDo(ctx, yy_1_Space, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Space", ctx->buf+ctx->pos)); + return 1; + l648:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Space", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_UlOrStarLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "UlOrStarLine")); + { int yypos652= ctx->pos, yythunkpos652= ctx->thunkpos; if (!yy_UlLine(ctx)) goto l653; goto l652; + l653:; ctx->pos= yypos652; ctx->thunkpos= yythunkpos652; if (!yy_StarLine(ctx)) goto l651; + } + l652:; yyDo(ctx, yy_1_UlOrStarLine, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "UlOrStarLine", ctx->buf+ctx->pos)); + return 1; + l651:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "UlOrStarLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Str(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "Str")); if (!yy_StartList(ctx)) goto l654; yyDo(ctx, yySet, -1, 0); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l654; if (!yy_NormalChar(ctx)) goto l654; + l655:; + { int yypos656= ctx->pos, yythunkpos656= ctx->thunkpos; if (!yy_NormalChar(ctx)) goto l656; goto l655; + l656:; ctx->pos= yypos656; ctx->thunkpos= yythunkpos656; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l654; yyDo(ctx, yy_1_Str, ctx->begin, ctx->end); + l657:; + { int yypos658= ctx->pos, yythunkpos658= ctx->thunkpos; if (!yy_StrChunk(ctx)) goto l658; yyDo(ctx, yy_2_Str, ctx->begin, ctx->end); goto l657; + l658:; ctx->pos= yypos658; ctx->thunkpos= yythunkpos658; + } yyDo(ctx, yy_3_Str, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Str", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l654:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Str", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_InStyleTags(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "InStyleTags")); if (!yy_StyleOpen(ctx)) goto l659; + l660:; + { int yypos661= ctx->pos, yythunkpos661= ctx->thunkpos; + { int yypos662= ctx->pos, yythunkpos662= ctx->thunkpos; if (!yy_StyleClose(ctx)) goto l662; goto l661; + l662:; ctx->pos= yypos662; ctx->thunkpos= yythunkpos662; + } if (!yymatchDot(ctx)) goto l661; goto l660; + l661:; ctx->pos= yypos661; ctx->thunkpos= yythunkpos661; + } if (!yy_StyleClose(ctx)) goto l659; + yyprintf((stderr, " ok %s @ %s\n", "InStyleTags", ctx->buf+ctx->pos)); + return 1; + l659:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "InStyleTags", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StyleClose(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "StyleClose")); if (!yymatchChar(ctx, '<')) goto l663; if (!yy_Spnl(ctx)) goto l663; if (!yymatchChar(ctx, '/')) goto l663; + { int yypos664= ctx->pos, yythunkpos664= ctx->thunkpos; if (!yymatchString(ctx, "style")) goto l665; goto l664; + l665:; ctx->pos= yypos664; ctx->thunkpos= yythunkpos664; if (!yymatchString(ctx, "STYLE")) goto l663; + } + l664:; if (!yy_Spnl(ctx)) goto l663; if (!yymatchChar(ctx, '>')) goto l663; + yyprintf((stderr, " ok %s @ %s\n", "StyleClose", ctx->buf+ctx->pos)); + return 1; + l663:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StyleClose", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StyleOpen(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "StyleOpen")); if (!yymatchChar(ctx, '<')) goto l666; if (!yy_Spnl(ctx)) goto l666; + { int yypos667= ctx->pos, yythunkpos667= ctx->thunkpos; if (!yymatchString(ctx, "style")) goto l668; goto l667; + l668:; ctx->pos= yypos667; ctx->thunkpos= yythunkpos667; if (!yymatchString(ctx, "STYLE")) goto l666; + } + l667:; if (!yy_Spnl(ctx)) goto l666; + l669:; + { int yypos670= ctx->pos, yythunkpos670= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l670; goto l669; + l670:; ctx->pos= yypos670; ctx->thunkpos= yythunkpos670; + } if (!yymatchChar(ctx, '>')) goto l666; + yyprintf((stderr, " ok %s @ %s\n", "StyleOpen", ctx->buf+ctx->pos)); + return 1; + l666:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StyleOpen", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockType(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockType")); + { int yypos672= ctx->pos, yythunkpos672= ctx->thunkpos; if (!yymatchString(ctx, "address")) goto l673; goto l672; + l673:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "blockquote")) goto l674; goto l672; + l674:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "center")) goto l675; goto l672; + l675:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "dir")) goto l676; goto l672; + l676:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "div")) goto l677; goto l672; + l677:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "dl")) goto l678; goto l672; + l678:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "fieldset")) goto l679; goto l672; + l679:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "form")) goto l680; goto l672; + l680:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "h1")) goto l681; goto l672; + l681:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "h2")) goto l682; goto l672; + l682:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "h3")) goto l683; goto l672; + l683:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "h4")) goto l684; goto l672; + l684:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "h5")) goto l685; goto l672; + l685:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "h6")) goto l686; goto l672; + l686:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "hr")) goto l687; goto l672; + l687:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "isindex")) goto l688; goto l672; + l688:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "menu")) goto l689; goto l672; + l689:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "noframes")) goto l690; goto l672; + l690:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "noscript")) goto l691; goto l672; + l691:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "ol")) goto l692; goto l672; + l692:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchChar(ctx, 'p')) goto l693; goto l672; + l693:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "pre")) goto l694; goto l672; + l694:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "table")) goto l695; goto l672; + l695:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "ul")) goto l696; goto l672; + l696:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "dd")) goto l697; goto l672; + l697:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "dt")) goto l698; goto l672; + l698:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "frameset")) goto l699; goto l672; + l699:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "li")) goto l700; goto l672; + l700:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "tbody")) goto l701; goto l672; + l701:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "td")) goto l702; goto l672; + l702:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "tfoot")) goto l703; goto l672; + l703:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "th")) goto l704; goto l672; + l704:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "thead")) goto l705; goto l672; + l705:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "tr")) goto l706; goto l672; + l706:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "script")) goto l707; goto l672; + l707:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "ADDRESS")) goto l708; goto l672; + l708:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "BLOCKQUOTE")) goto l709; goto l672; + l709:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "CENTER")) goto l710; goto l672; + l710:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "DIR")) goto l711; goto l672; + l711:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "DIV")) goto l712; goto l672; + l712:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "DL")) goto l713; goto l672; + l713:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "FIELDSET")) goto l714; goto l672; + l714:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "FORM")) goto l715; goto l672; + l715:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "H1")) goto l716; goto l672; + l716:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "H2")) goto l717; goto l672; + l717:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "H3")) goto l718; goto l672; + l718:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "H4")) goto l719; goto l672; + l719:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "H5")) goto l720; goto l672; + l720:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "H6")) goto l721; goto l672; + l721:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "HR")) goto l722; goto l672; + l722:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "ISINDEX")) goto l723; goto l672; + l723:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "MENU")) goto l724; goto l672; + l724:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "NOFRAMES")) goto l725; goto l672; + l725:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "NOSCRIPT")) goto l726; goto l672; + l726:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "OL")) goto l727; goto l672; + l727:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchChar(ctx, 'P')) goto l728; goto l672; + l728:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "PRE")) goto l729; goto l672; + l729:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "TABLE")) goto l730; goto l672; + l730:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "UL")) goto l731; goto l672; + l731:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "DD")) goto l732; goto l672; + l732:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "DT")) goto l733; goto l672; + l733:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "FRAMESET")) goto l734; goto l672; + l734:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "LI")) goto l735; goto l672; + l735:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "TBODY")) goto l736; goto l672; + l736:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "TD")) goto l737; goto l672; + l737:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "TFOOT")) goto l738; goto l672; + l738:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "TH")) goto l739; goto l672; + l739:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "THEAD")) goto l740; goto l672; + l740:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "TR")) goto l741; goto l672; + l741:; ctx->pos= yypos672; ctx->thunkpos= yythunkpos672; if (!yymatchString(ctx, "SCRIPT")) goto l671; + } + l672:; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockType", ctx->buf+ctx->pos)); + return 1; + l671:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockType", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockSelfClosing(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockSelfClosing")); if (!yymatchChar(ctx, '<')) goto l742; if (!yy_Spnl(ctx)) goto l742; if (!yy_HtmlBlockType(ctx)) goto l742; if (!yy_Spnl(ctx)) goto l742; + l743:; + { int yypos744= ctx->pos, yythunkpos744= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l744; goto l743; + l744:; ctx->pos= yypos744; ctx->thunkpos= yythunkpos744; + } if (!yymatchChar(ctx, '/')) goto l742; if (!yy_Spnl(ctx)) goto l742; if (!yymatchChar(ctx, '>')) goto l742; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockSelfClosing", ctx->buf+ctx->pos)); + return 1; + l742:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockSelfClosing", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlComment(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlComment")); if (!yymatchString(ctx, "")) goto l748; goto l747; + l748:; ctx->pos= yypos748; ctx->thunkpos= yythunkpos748; + } if (!yymatchDot(ctx)) goto l747; goto l746; + l747:; ctx->pos= yypos747; ctx->thunkpos= yythunkpos747; + } if (!yymatchString(ctx, "-->")) goto l745; + yyprintf((stderr, " ok %s @ %s\n", "HtmlComment", ctx->buf+ctx->pos)); + return 1; + l745:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlComment", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockInTags(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockInTags")); + { int yypos750= ctx->pos, yythunkpos750= ctx->thunkpos; if (!yy_HtmlBlockAddress(ctx)) goto l751; goto l750; + l751:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockBlockquote(ctx)) goto l752; goto l750; + l752:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockCenter(ctx)) goto l753; goto l750; + l753:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockDir(ctx)) goto l754; goto l750; + l754:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockDiv(ctx)) goto l755; goto l750; + l755:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockDl(ctx)) goto l756; goto l750; + l756:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockFieldset(ctx)) goto l757; goto l750; + l757:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockForm(ctx)) goto l758; goto l750; + l758:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockH1(ctx)) goto l759; goto l750; + l759:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockH2(ctx)) goto l760; goto l750; + l760:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockH3(ctx)) goto l761; goto l750; + l761:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockH4(ctx)) goto l762; goto l750; + l762:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockH5(ctx)) goto l763; goto l750; + l763:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockH6(ctx)) goto l764; goto l750; + l764:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockMenu(ctx)) goto l765; goto l750; + l765:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockNoframes(ctx)) goto l766; goto l750; + l766:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockNoscript(ctx)) goto l767; goto l750; + l767:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockOl(ctx)) goto l768; goto l750; + l768:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockP(ctx)) goto l769; goto l750; + l769:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockPre(ctx)) goto l770; goto l750; + l770:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockTable(ctx)) goto l771; goto l750; + l771:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockUl(ctx)) goto l772; goto l750; + l772:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockDd(ctx)) goto l773; goto l750; + l773:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockDt(ctx)) goto l774; goto l750; + l774:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockFrameset(ctx)) goto l775; goto l750; + l775:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockLi(ctx)) goto l776; goto l750; + l776:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockTbody(ctx)) goto l777; goto l750; + l777:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockTd(ctx)) goto l778; goto l750; + l778:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockTfoot(ctx)) goto l779; goto l750; + l779:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockTh(ctx)) goto l780; goto l750; + l780:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockThead(ctx)) goto l781; goto l750; + l781:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockTr(ctx)) goto l782; goto l750; + l782:; ctx->pos= yypos750; ctx->thunkpos= yythunkpos750; if (!yy_HtmlBlockScript(ctx)) goto l749; + } + l750:; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockInTags", ctx->buf+ctx->pos)); + return 1; + l749:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockInTags", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockScript(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockScript")); if (!yy_HtmlBlockOpenScript(ctx)) goto l783; + l784:; + { int yypos785= ctx->pos, yythunkpos785= ctx->thunkpos; + { int yypos786= ctx->pos, yythunkpos786= ctx->thunkpos; if (!yy_HtmlBlockCloseScript(ctx)) goto l786; goto l785; + l786:; ctx->pos= yypos786; ctx->thunkpos= yythunkpos786; + } if (!yymatchDot(ctx)) goto l785; goto l784; + l785:; ctx->pos= yypos785; ctx->thunkpos= yythunkpos785; + } if (!yy_HtmlBlockCloseScript(ctx)) goto l783; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockScript", ctx->buf+ctx->pos)); + return 1; + l783:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockScript", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseScript(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseScript")); if (!yymatchChar(ctx, '<')) goto l787; if (!yy_Spnl(ctx)) goto l787; if (!yymatchChar(ctx, '/')) goto l787; + { int yypos788= ctx->pos, yythunkpos788= ctx->thunkpos; if (!yymatchString(ctx, "script")) goto l789; goto l788; + l789:; ctx->pos= yypos788; ctx->thunkpos= yythunkpos788; if (!yymatchString(ctx, "SCRIPT")) goto l787; + } + l788:; if (!yy_Spnl(ctx)) goto l787; if (!yymatchChar(ctx, '>')) goto l787; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseScript", ctx->buf+ctx->pos)); + return 1; + l787:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseScript", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenScript(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenScript")); if (!yymatchChar(ctx, '<')) goto l790; if (!yy_Spnl(ctx)) goto l790; + { int yypos791= ctx->pos, yythunkpos791= ctx->thunkpos; if (!yymatchString(ctx, "script")) goto l792; goto l791; + l792:; ctx->pos= yypos791; ctx->thunkpos= yythunkpos791; if (!yymatchString(ctx, "SCRIPT")) goto l790; + } + l791:; if (!yy_Spnl(ctx)) goto l790; + l793:; + { int yypos794= ctx->pos, yythunkpos794= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l794; goto l793; + l794:; ctx->pos= yypos794; ctx->thunkpos= yythunkpos794; + } if (!yymatchChar(ctx, '>')) goto l790; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenScript", ctx->buf+ctx->pos)); + return 1; + l790:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenScript", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockTr(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockTr")); if (!yy_HtmlBlockOpenTr(ctx)) goto l795; + l796:; + { int yypos797= ctx->pos, yythunkpos797= ctx->thunkpos; + { int yypos798= ctx->pos, yythunkpos798= ctx->thunkpos; if (!yy_HtmlBlockTr(ctx)) goto l799; goto l798; + l799:; ctx->pos= yypos798; ctx->thunkpos= yythunkpos798; + { int yypos800= ctx->pos, yythunkpos800= ctx->thunkpos; if (!yy_HtmlBlockCloseTr(ctx)) goto l800; goto l797; + l800:; ctx->pos= yypos800; ctx->thunkpos= yythunkpos800; + } if (!yymatchDot(ctx)) goto l797; + } + l798:; goto l796; + l797:; ctx->pos= yypos797; ctx->thunkpos= yythunkpos797; + } if (!yy_HtmlBlockCloseTr(ctx)) goto l795; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockTr", ctx->buf+ctx->pos)); + return 1; + l795:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockTr", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseTr(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseTr")); if (!yymatchChar(ctx, '<')) goto l801; if (!yy_Spnl(ctx)) goto l801; if (!yymatchChar(ctx, '/')) goto l801; + { int yypos802= ctx->pos, yythunkpos802= ctx->thunkpos; if (!yymatchString(ctx, "tr")) goto l803; goto l802; + l803:; ctx->pos= yypos802; ctx->thunkpos= yythunkpos802; if (!yymatchString(ctx, "TR")) goto l801; + } + l802:; if (!yy_Spnl(ctx)) goto l801; if (!yymatchChar(ctx, '>')) goto l801; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseTr", ctx->buf+ctx->pos)); + return 1; + l801:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseTr", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenTr(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenTr")); if (!yymatchChar(ctx, '<')) goto l804; if (!yy_Spnl(ctx)) goto l804; + { int yypos805= ctx->pos, yythunkpos805= ctx->thunkpos; if (!yymatchString(ctx, "tr")) goto l806; goto l805; + l806:; ctx->pos= yypos805; ctx->thunkpos= yythunkpos805; if (!yymatchString(ctx, "TR")) goto l804; + } + l805:; if (!yy_Spnl(ctx)) goto l804; + l807:; + { int yypos808= ctx->pos, yythunkpos808= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l808; goto l807; + l808:; ctx->pos= yypos808; ctx->thunkpos= yythunkpos808; + } if (!yymatchChar(ctx, '>')) goto l804; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenTr", ctx->buf+ctx->pos)); + return 1; + l804:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenTr", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockThead(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockThead")); if (!yy_HtmlBlockOpenThead(ctx)) goto l809; + l810:; + { int yypos811= ctx->pos, yythunkpos811= ctx->thunkpos; + { int yypos812= ctx->pos, yythunkpos812= ctx->thunkpos; if (!yy_HtmlBlockThead(ctx)) goto l813; goto l812; + l813:; ctx->pos= yypos812; ctx->thunkpos= yythunkpos812; + { int yypos814= ctx->pos, yythunkpos814= ctx->thunkpos; if (!yy_HtmlBlockCloseThead(ctx)) goto l814; goto l811; + l814:; ctx->pos= yypos814; ctx->thunkpos= yythunkpos814; + } if (!yymatchDot(ctx)) goto l811; + } + l812:; goto l810; + l811:; ctx->pos= yypos811; ctx->thunkpos= yythunkpos811; + } if (!yy_HtmlBlockCloseThead(ctx)) goto l809; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockThead", ctx->buf+ctx->pos)); + return 1; + l809:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockThead", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseThead(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseThead")); if (!yymatchChar(ctx, '<')) goto l815; if (!yy_Spnl(ctx)) goto l815; if (!yymatchChar(ctx, '/')) goto l815; + { int yypos816= ctx->pos, yythunkpos816= ctx->thunkpos; if (!yymatchString(ctx, "thead")) goto l817; goto l816; + l817:; ctx->pos= yypos816; ctx->thunkpos= yythunkpos816; if (!yymatchString(ctx, "THEAD")) goto l815; + } + l816:; if (!yy_Spnl(ctx)) goto l815; if (!yymatchChar(ctx, '>')) goto l815; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseThead", ctx->buf+ctx->pos)); + return 1; + l815:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseThead", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenThead(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenThead")); if (!yymatchChar(ctx, '<')) goto l818; if (!yy_Spnl(ctx)) goto l818; + { int yypos819= ctx->pos, yythunkpos819= ctx->thunkpos; if (!yymatchString(ctx, "thead")) goto l820; goto l819; + l820:; ctx->pos= yypos819; ctx->thunkpos= yythunkpos819; if (!yymatchString(ctx, "THEAD")) goto l818; + } + l819:; if (!yy_Spnl(ctx)) goto l818; + l821:; + { int yypos822= ctx->pos, yythunkpos822= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l822; goto l821; + l822:; ctx->pos= yypos822; ctx->thunkpos= yythunkpos822; + } if (!yymatchChar(ctx, '>')) goto l818; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenThead", ctx->buf+ctx->pos)); + return 1; + l818:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenThead", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockTh(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockTh")); if (!yy_HtmlBlockOpenTh(ctx)) goto l823; + l824:; + { int yypos825= ctx->pos, yythunkpos825= ctx->thunkpos; + { int yypos826= ctx->pos, yythunkpos826= ctx->thunkpos; if (!yy_HtmlBlockTh(ctx)) goto l827; goto l826; + l827:; ctx->pos= yypos826; ctx->thunkpos= yythunkpos826; + { int yypos828= ctx->pos, yythunkpos828= ctx->thunkpos; if (!yy_HtmlBlockCloseTh(ctx)) goto l828; goto l825; + l828:; ctx->pos= yypos828; ctx->thunkpos= yythunkpos828; + } if (!yymatchDot(ctx)) goto l825; + } + l826:; goto l824; + l825:; ctx->pos= yypos825; ctx->thunkpos= yythunkpos825; + } if (!yy_HtmlBlockCloseTh(ctx)) goto l823; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockTh", ctx->buf+ctx->pos)); + return 1; + l823:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockTh", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseTh(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseTh")); if (!yymatchChar(ctx, '<')) goto l829; if (!yy_Spnl(ctx)) goto l829; if (!yymatchChar(ctx, '/')) goto l829; + { int yypos830= ctx->pos, yythunkpos830= ctx->thunkpos; if (!yymatchString(ctx, "th")) goto l831; goto l830; + l831:; ctx->pos= yypos830; ctx->thunkpos= yythunkpos830; if (!yymatchString(ctx, "TH")) goto l829; + } + l830:; if (!yy_Spnl(ctx)) goto l829; if (!yymatchChar(ctx, '>')) goto l829; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseTh", ctx->buf+ctx->pos)); + return 1; + l829:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseTh", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenTh(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenTh")); if (!yymatchChar(ctx, '<')) goto l832; if (!yy_Spnl(ctx)) goto l832; + { int yypos833= ctx->pos, yythunkpos833= ctx->thunkpos; if (!yymatchString(ctx, "th")) goto l834; goto l833; + l834:; ctx->pos= yypos833; ctx->thunkpos= yythunkpos833; if (!yymatchString(ctx, "TH")) goto l832; + } + l833:; if (!yy_Spnl(ctx)) goto l832; + l835:; + { int yypos836= ctx->pos, yythunkpos836= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l836; goto l835; + l836:; ctx->pos= yypos836; ctx->thunkpos= yythunkpos836; + } if (!yymatchChar(ctx, '>')) goto l832; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenTh", ctx->buf+ctx->pos)); + return 1; + l832:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenTh", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockTfoot(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockTfoot")); if (!yy_HtmlBlockOpenTfoot(ctx)) goto l837; + l838:; + { int yypos839= ctx->pos, yythunkpos839= ctx->thunkpos; + { int yypos840= ctx->pos, yythunkpos840= ctx->thunkpos; if (!yy_HtmlBlockTfoot(ctx)) goto l841; goto l840; + l841:; ctx->pos= yypos840; ctx->thunkpos= yythunkpos840; + { int yypos842= ctx->pos, yythunkpos842= ctx->thunkpos; if (!yy_HtmlBlockCloseTfoot(ctx)) goto l842; goto l839; + l842:; ctx->pos= yypos842; ctx->thunkpos= yythunkpos842; + } if (!yymatchDot(ctx)) goto l839; + } + l840:; goto l838; + l839:; ctx->pos= yypos839; ctx->thunkpos= yythunkpos839; + } if (!yy_HtmlBlockCloseTfoot(ctx)) goto l837; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockTfoot", ctx->buf+ctx->pos)); + return 1; + l837:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockTfoot", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseTfoot(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseTfoot")); if (!yymatchChar(ctx, '<')) goto l843; if (!yy_Spnl(ctx)) goto l843; if (!yymatchChar(ctx, '/')) goto l843; + { int yypos844= ctx->pos, yythunkpos844= ctx->thunkpos; if (!yymatchString(ctx, "tfoot")) goto l845; goto l844; + l845:; ctx->pos= yypos844; ctx->thunkpos= yythunkpos844; if (!yymatchString(ctx, "TFOOT")) goto l843; + } + l844:; if (!yy_Spnl(ctx)) goto l843; if (!yymatchChar(ctx, '>')) goto l843; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseTfoot", ctx->buf+ctx->pos)); + return 1; + l843:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseTfoot", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenTfoot(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenTfoot")); if (!yymatchChar(ctx, '<')) goto l846; if (!yy_Spnl(ctx)) goto l846; + { int yypos847= ctx->pos, yythunkpos847= ctx->thunkpos; if (!yymatchString(ctx, "tfoot")) goto l848; goto l847; + l848:; ctx->pos= yypos847; ctx->thunkpos= yythunkpos847; if (!yymatchString(ctx, "TFOOT")) goto l846; + } + l847:; if (!yy_Spnl(ctx)) goto l846; + l849:; + { int yypos850= ctx->pos, yythunkpos850= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l850; goto l849; + l850:; ctx->pos= yypos850; ctx->thunkpos= yythunkpos850; + } if (!yymatchChar(ctx, '>')) goto l846; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenTfoot", ctx->buf+ctx->pos)); + return 1; + l846:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenTfoot", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockTd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockTd")); if (!yy_HtmlBlockOpenTd(ctx)) goto l851; + l852:; + { int yypos853= ctx->pos, yythunkpos853= ctx->thunkpos; + { int yypos854= ctx->pos, yythunkpos854= ctx->thunkpos; if (!yy_HtmlBlockTd(ctx)) goto l855; goto l854; + l855:; ctx->pos= yypos854; ctx->thunkpos= yythunkpos854; + { int yypos856= ctx->pos, yythunkpos856= ctx->thunkpos; if (!yy_HtmlBlockCloseTd(ctx)) goto l856; goto l853; + l856:; ctx->pos= yypos856; ctx->thunkpos= yythunkpos856; + } if (!yymatchDot(ctx)) goto l853; + } + l854:; goto l852; + l853:; ctx->pos= yypos853; ctx->thunkpos= yythunkpos853; + } if (!yy_HtmlBlockCloseTd(ctx)) goto l851; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockTd", ctx->buf+ctx->pos)); + return 1; + l851:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockTd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseTd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseTd")); if (!yymatchChar(ctx, '<')) goto l857; if (!yy_Spnl(ctx)) goto l857; if (!yymatchChar(ctx, '/')) goto l857; + { int yypos858= ctx->pos, yythunkpos858= ctx->thunkpos; if (!yymatchString(ctx, "td")) goto l859; goto l858; + l859:; ctx->pos= yypos858; ctx->thunkpos= yythunkpos858; if (!yymatchString(ctx, "TD")) goto l857; + } + l858:; if (!yy_Spnl(ctx)) goto l857; if (!yymatchChar(ctx, '>')) goto l857; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseTd", ctx->buf+ctx->pos)); + return 1; + l857:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseTd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenTd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenTd")); if (!yymatchChar(ctx, '<')) goto l860; if (!yy_Spnl(ctx)) goto l860; + { int yypos861= ctx->pos, yythunkpos861= ctx->thunkpos; if (!yymatchString(ctx, "td")) goto l862; goto l861; + l862:; ctx->pos= yypos861; ctx->thunkpos= yythunkpos861; if (!yymatchString(ctx, "TD")) goto l860; + } + l861:; if (!yy_Spnl(ctx)) goto l860; + l863:; + { int yypos864= ctx->pos, yythunkpos864= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l864; goto l863; + l864:; ctx->pos= yypos864; ctx->thunkpos= yythunkpos864; + } if (!yymatchChar(ctx, '>')) goto l860; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenTd", ctx->buf+ctx->pos)); + return 1; + l860:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenTd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockTbody(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockTbody")); if (!yy_HtmlBlockOpenTbody(ctx)) goto l865; + l866:; + { int yypos867= ctx->pos, yythunkpos867= ctx->thunkpos; + { int yypos868= ctx->pos, yythunkpos868= ctx->thunkpos; if (!yy_HtmlBlockTbody(ctx)) goto l869; goto l868; + l869:; ctx->pos= yypos868; ctx->thunkpos= yythunkpos868; + { int yypos870= ctx->pos, yythunkpos870= ctx->thunkpos; if (!yy_HtmlBlockCloseTbody(ctx)) goto l870; goto l867; + l870:; ctx->pos= yypos870; ctx->thunkpos= yythunkpos870; + } if (!yymatchDot(ctx)) goto l867; + } + l868:; goto l866; + l867:; ctx->pos= yypos867; ctx->thunkpos= yythunkpos867; + } if (!yy_HtmlBlockCloseTbody(ctx)) goto l865; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockTbody", ctx->buf+ctx->pos)); + return 1; + l865:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockTbody", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseTbody(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseTbody")); if (!yymatchChar(ctx, '<')) goto l871; if (!yy_Spnl(ctx)) goto l871; if (!yymatchChar(ctx, '/')) goto l871; + { int yypos872= ctx->pos, yythunkpos872= ctx->thunkpos; if (!yymatchString(ctx, "tbody")) goto l873; goto l872; + l873:; ctx->pos= yypos872; ctx->thunkpos= yythunkpos872; if (!yymatchString(ctx, "TBODY")) goto l871; + } + l872:; if (!yy_Spnl(ctx)) goto l871; if (!yymatchChar(ctx, '>')) goto l871; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseTbody", ctx->buf+ctx->pos)); + return 1; + l871:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseTbody", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenTbody(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenTbody")); if (!yymatchChar(ctx, '<')) goto l874; if (!yy_Spnl(ctx)) goto l874; + { int yypos875= ctx->pos, yythunkpos875= ctx->thunkpos; if (!yymatchString(ctx, "tbody")) goto l876; goto l875; + l876:; ctx->pos= yypos875; ctx->thunkpos= yythunkpos875; if (!yymatchString(ctx, "TBODY")) goto l874; + } + l875:; if (!yy_Spnl(ctx)) goto l874; + l877:; + { int yypos878= ctx->pos, yythunkpos878= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l878; goto l877; + l878:; ctx->pos= yypos878; ctx->thunkpos= yythunkpos878; + } if (!yymatchChar(ctx, '>')) goto l874; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenTbody", ctx->buf+ctx->pos)); + return 1; + l874:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenTbody", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockLi(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockLi")); if (!yy_HtmlBlockOpenLi(ctx)) goto l879; + l880:; + { int yypos881= ctx->pos, yythunkpos881= ctx->thunkpos; + { int yypos882= ctx->pos, yythunkpos882= ctx->thunkpos; if (!yy_HtmlBlockLi(ctx)) goto l883; goto l882; + l883:; ctx->pos= yypos882; ctx->thunkpos= yythunkpos882; + { int yypos884= ctx->pos, yythunkpos884= ctx->thunkpos; if (!yy_HtmlBlockCloseLi(ctx)) goto l884; goto l881; + l884:; ctx->pos= yypos884; ctx->thunkpos= yythunkpos884; + } if (!yymatchDot(ctx)) goto l881; + } + l882:; goto l880; + l881:; ctx->pos= yypos881; ctx->thunkpos= yythunkpos881; + } if (!yy_HtmlBlockCloseLi(ctx)) goto l879; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockLi", ctx->buf+ctx->pos)); + return 1; + l879:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockLi", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseLi(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseLi")); if (!yymatchChar(ctx, '<')) goto l885; if (!yy_Spnl(ctx)) goto l885; if (!yymatchChar(ctx, '/')) goto l885; + { int yypos886= ctx->pos, yythunkpos886= ctx->thunkpos; if (!yymatchString(ctx, "li")) goto l887; goto l886; + l887:; ctx->pos= yypos886; ctx->thunkpos= yythunkpos886; if (!yymatchString(ctx, "LI")) goto l885; + } + l886:; if (!yy_Spnl(ctx)) goto l885; if (!yymatchChar(ctx, '>')) goto l885; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseLi", ctx->buf+ctx->pos)); + return 1; + l885:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseLi", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenLi(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenLi")); if (!yymatchChar(ctx, '<')) goto l888; if (!yy_Spnl(ctx)) goto l888; + { int yypos889= ctx->pos, yythunkpos889= ctx->thunkpos; if (!yymatchString(ctx, "li")) goto l890; goto l889; + l890:; ctx->pos= yypos889; ctx->thunkpos= yythunkpos889; if (!yymatchString(ctx, "LI")) goto l888; + } + l889:; if (!yy_Spnl(ctx)) goto l888; + l891:; + { int yypos892= ctx->pos, yythunkpos892= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l892; goto l891; + l892:; ctx->pos= yypos892; ctx->thunkpos= yythunkpos892; + } if (!yymatchChar(ctx, '>')) goto l888; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenLi", ctx->buf+ctx->pos)); + return 1; + l888:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenLi", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockFrameset(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockFrameset")); if (!yy_HtmlBlockOpenFrameset(ctx)) goto l893; + l894:; + { int yypos895= ctx->pos, yythunkpos895= ctx->thunkpos; + { int yypos896= ctx->pos, yythunkpos896= ctx->thunkpos; if (!yy_HtmlBlockFrameset(ctx)) goto l897; goto l896; + l897:; ctx->pos= yypos896; ctx->thunkpos= yythunkpos896; + { int yypos898= ctx->pos, yythunkpos898= ctx->thunkpos; if (!yy_HtmlBlockCloseFrameset(ctx)) goto l898; goto l895; + l898:; ctx->pos= yypos898; ctx->thunkpos= yythunkpos898; + } if (!yymatchDot(ctx)) goto l895; + } + l896:; goto l894; + l895:; ctx->pos= yypos895; ctx->thunkpos= yythunkpos895; + } if (!yy_HtmlBlockCloseFrameset(ctx)) goto l893; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockFrameset", ctx->buf+ctx->pos)); + return 1; + l893:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockFrameset", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseFrameset(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseFrameset")); if (!yymatchChar(ctx, '<')) goto l899; if (!yy_Spnl(ctx)) goto l899; if (!yymatchChar(ctx, '/')) goto l899; + { int yypos900= ctx->pos, yythunkpos900= ctx->thunkpos; if (!yymatchString(ctx, "frameset")) goto l901; goto l900; + l901:; ctx->pos= yypos900; ctx->thunkpos= yythunkpos900; if (!yymatchString(ctx, "FRAMESET")) goto l899; + } + l900:; if (!yy_Spnl(ctx)) goto l899; if (!yymatchChar(ctx, '>')) goto l899; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseFrameset", ctx->buf+ctx->pos)); + return 1; + l899:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseFrameset", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenFrameset(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenFrameset")); if (!yymatchChar(ctx, '<')) goto l902; if (!yy_Spnl(ctx)) goto l902; + { int yypos903= ctx->pos, yythunkpos903= ctx->thunkpos; if (!yymatchString(ctx, "frameset")) goto l904; goto l903; + l904:; ctx->pos= yypos903; ctx->thunkpos= yythunkpos903; if (!yymatchString(ctx, "FRAMESET")) goto l902; + } + l903:; if (!yy_Spnl(ctx)) goto l902; + l905:; + { int yypos906= ctx->pos, yythunkpos906= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l906; goto l905; + l906:; ctx->pos= yypos906; ctx->thunkpos= yythunkpos906; + } if (!yymatchChar(ctx, '>')) goto l902; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenFrameset", ctx->buf+ctx->pos)); + return 1; + l902:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenFrameset", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockDt(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockDt")); if (!yy_HtmlBlockOpenDt(ctx)) goto l907; + l908:; + { int yypos909= ctx->pos, yythunkpos909= ctx->thunkpos; + { int yypos910= ctx->pos, yythunkpos910= ctx->thunkpos; if (!yy_HtmlBlockDt(ctx)) goto l911; goto l910; + l911:; ctx->pos= yypos910; ctx->thunkpos= yythunkpos910; + { int yypos912= ctx->pos, yythunkpos912= ctx->thunkpos; if (!yy_HtmlBlockCloseDt(ctx)) goto l912; goto l909; + l912:; ctx->pos= yypos912; ctx->thunkpos= yythunkpos912; + } if (!yymatchDot(ctx)) goto l909; + } + l910:; goto l908; + l909:; ctx->pos= yypos909; ctx->thunkpos= yythunkpos909; + } if (!yy_HtmlBlockCloseDt(ctx)) goto l907; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockDt", ctx->buf+ctx->pos)); + return 1; + l907:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockDt", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseDt(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseDt")); if (!yymatchChar(ctx, '<')) goto l913; if (!yy_Spnl(ctx)) goto l913; if (!yymatchChar(ctx, '/')) goto l913; + { int yypos914= ctx->pos, yythunkpos914= ctx->thunkpos; if (!yymatchString(ctx, "dt")) goto l915; goto l914; + l915:; ctx->pos= yypos914; ctx->thunkpos= yythunkpos914; if (!yymatchString(ctx, "DT")) goto l913; + } + l914:; if (!yy_Spnl(ctx)) goto l913; if (!yymatchChar(ctx, '>')) goto l913; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseDt", ctx->buf+ctx->pos)); + return 1; + l913:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseDt", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenDt(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenDt")); if (!yymatchChar(ctx, '<')) goto l916; if (!yy_Spnl(ctx)) goto l916; + { int yypos917= ctx->pos, yythunkpos917= ctx->thunkpos; if (!yymatchString(ctx, "dt")) goto l918; goto l917; + l918:; ctx->pos= yypos917; ctx->thunkpos= yythunkpos917; if (!yymatchString(ctx, "DT")) goto l916; + } + l917:; if (!yy_Spnl(ctx)) goto l916; + l919:; + { int yypos920= ctx->pos, yythunkpos920= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l920; goto l919; + l920:; ctx->pos= yypos920; ctx->thunkpos= yythunkpos920; + } if (!yymatchChar(ctx, '>')) goto l916; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenDt", ctx->buf+ctx->pos)); + return 1; + l916:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenDt", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockDd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockDd")); if (!yy_HtmlBlockOpenDd(ctx)) goto l921; + l922:; + { int yypos923= ctx->pos, yythunkpos923= ctx->thunkpos; + { int yypos924= ctx->pos, yythunkpos924= ctx->thunkpos; if (!yy_HtmlBlockDd(ctx)) goto l925; goto l924; + l925:; ctx->pos= yypos924; ctx->thunkpos= yythunkpos924; + { int yypos926= ctx->pos, yythunkpos926= ctx->thunkpos; if (!yy_HtmlBlockCloseDd(ctx)) goto l926; goto l923; + l926:; ctx->pos= yypos926; ctx->thunkpos= yythunkpos926; + } if (!yymatchDot(ctx)) goto l923; + } + l924:; goto l922; + l923:; ctx->pos= yypos923; ctx->thunkpos= yythunkpos923; + } if (!yy_HtmlBlockCloseDd(ctx)) goto l921; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockDd", ctx->buf+ctx->pos)); + return 1; + l921:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockDd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseDd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseDd")); if (!yymatchChar(ctx, '<')) goto l927; if (!yy_Spnl(ctx)) goto l927; if (!yymatchChar(ctx, '/')) goto l927; + { int yypos928= ctx->pos, yythunkpos928= ctx->thunkpos; if (!yymatchString(ctx, "dd")) goto l929; goto l928; + l929:; ctx->pos= yypos928; ctx->thunkpos= yythunkpos928; if (!yymatchString(ctx, "DD")) goto l927; + } + l928:; if (!yy_Spnl(ctx)) goto l927; if (!yymatchChar(ctx, '>')) goto l927; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseDd", ctx->buf+ctx->pos)); + return 1; + l927:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseDd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenDd(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenDd")); if (!yymatchChar(ctx, '<')) goto l930; if (!yy_Spnl(ctx)) goto l930; + { int yypos931= ctx->pos, yythunkpos931= ctx->thunkpos; if (!yymatchString(ctx, "dd")) goto l932; goto l931; + l932:; ctx->pos= yypos931; ctx->thunkpos= yythunkpos931; if (!yymatchString(ctx, "DD")) goto l930; + } + l931:; if (!yy_Spnl(ctx)) goto l930; + l933:; + { int yypos934= ctx->pos, yythunkpos934= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l934; goto l933; + l934:; ctx->pos= yypos934; ctx->thunkpos= yythunkpos934; + } if (!yymatchChar(ctx, '>')) goto l930; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenDd", ctx->buf+ctx->pos)); + return 1; + l930:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenDd", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockUl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockUl")); if (!yy_HtmlBlockOpenUl(ctx)) goto l935; + l936:; + { int yypos937= ctx->pos, yythunkpos937= ctx->thunkpos; + { int yypos938= ctx->pos, yythunkpos938= ctx->thunkpos; if (!yy_HtmlBlockUl(ctx)) goto l939; goto l938; + l939:; ctx->pos= yypos938; ctx->thunkpos= yythunkpos938; + { int yypos940= ctx->pos, yythunkpos940= ctx->thunkpos; if (!yy_HtmlBlockCloseUl(ctx)) goto l940; goto l937; + l940:; ctx->pos= yypos940; ctx->thunkpos= yythunkpos940; + } if (!yymatchDot(ctx)) goto l937; + } + l938:; goto l936; + l937:; ctx->pos= yypos937; ctx->thunkpos= yythunkpos937; + } if (!yy_HtmlBlockCloseUl(ctx)) goto l935; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockUl", ctx->buf+ctx->pos)); + return 1; + l935:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockUl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseUl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseUl")); if (!yymatchChar(ctx, '<')) goto l941; if (!yy_Spnl(ctx)) goto l941; if (!yymatchChar(ctx, '/')) goto l941; + { int yypos942= ctx->pos, yythunkpos942= ctx->thunkpos; if (!yymatchString(ctx, "ul")) goto l943; goto l942; + l943:; ctx->pos= yypos942; ctx->thunkpos= yythunkpos942; if (!yymatchString(ctx, "UL")) goto l941; + } + l942:; if (!yy_Spnl(ctx)) goto l941; if (!yymatchChar(ctx, '>')) goto l941; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseUl", ctx->buf+ctx->pos)); + return 1; + l941:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseUl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenUl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenUl")); if (!yymatchChar(ctx, '<')) goto l944; if (!yy_Spnl(ctx)) goto l944; + { int yypos945= ctx->pos, yythunkpos945= ctx->thunkpos; if (!yymatchString(ctx, "ul")) goto l946; goto l945; + l946:; ctx->pos= yypos945; ctx->thunkpos= yythunkpos945; if (!yymatchString(ctx, "UL")) goto l944; + } + l945:; if (!yy_Spnl(ctx)) goto l944; + l947:; + { int yypos948= ctx->pos, yythunkpos948= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l948; goto l947; + l948:; ctx->pos= yypos948; ctx->thunkpos= yythunkpos948; + } if (!yymatchChar(ctx, '>')) goto l944; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenUl", ctx->buf+ctx->pos)); + return 1; + l944:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenUl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockTable(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockTable")); if (!yy_HtmlBlockOpenTable(ctx)) goto l949; + l950:; + { int yypos951= ctx->pos, yythunkpos951= ctx->thunkpos; + { int yypos952= ctx->pos, yythunkpos952= ctx->thunkpos; if (!yy_HtmlBlockTable(ctx)) goto l953; goto l952; + l953:; ctx->pos= yypos952; ctx->thunkpos= yythunkpos952; + { int yypos954= ctx->pos, yythunkpos954= ctx->thunkpos; if (!yy_HtmlBlockCloseTable(ctx)) goto l954; goto l951; + l954:; ctx->pos= yypos954; ctx->thunkpos= yythunkpos954; + } if (!yymatchDot(ctx)) goto l951; + } + l952:; goto l950; + l951:; ctx->pos= yypos951; ctx->thunkpos= yythunkpos951; + } if (!yy_HtmlBlockCloseTable(ctx)) goto l949; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockTable", ctx->buf+ctx->pos)); + return 1; + l949:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockTable", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseTable(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseTable")); if (!yymatchChar(ctx, '<')) goto l955; if (!yy_Spnl(ctx)) goto l955; if (!yymatchChar(ctx, '/')) goto l955; + { int yypos956= ctx->pos, yythunkpos956= ctx->thunkpos; if (!yymatchString(ctx, "table")) goto l957; goto l956; + l957:; ctx->pos= yypos956; ctx->thunkpos= yythunkpos956; if (!yymatchString(ctx, "TABLE")) goto l955; + } + l956:; if (!yy_Spnl(ctx)) goto l955; if (!yymatchChar(ctx, '>')) goto l955; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseTable", ctx->buf+ctx->pos)); + return 1; + l955:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseTable", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenTable(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenTable")); if (!yymatchChar(ctx, '<')) goto l958; if (!yy_Spnl(ctx)) goto l958; + { int yypos959= ctx->pos, yythunkpos959= ctx->thunkpos; if (!yymatchString(ctx, "table")) goto l960; goto l959; + l960:; ctx->pos= yypos959; ctx->thunkpos= yythunkpos959; if (!yymatchString(ctx, "TABLE")) goto l958; + } + l959:; if (!yy_Spnl(ctx)) goto l958; + l961:; + { int yypos962= ctx->pos, yythunkpos962= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l962; goto l961; + l962:; ctx->pos= yypos962; ctx->thunkpos= yythunkpos962; + } if (!yymatchChar(ctx, '>')) goto l958; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenTable", ctx->buf+ctx->pos)); + return 1; + l958:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenTable", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockPre(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockPre")); if (!yy_HtmlBlockOpenPre(ctx)) goto l963; + l964:; + { int yypos965= ctx->pos, yythunkpos965= ctx->thunkpos; + { int yypos966= ctx->pos, yythunkpos966= ctx->thunkpos; if (!yy_HtmlBlockPre(ctx)) goto l967; goto l966; + l967:; ctx->pos= yypos966; ctx->thunkpos= yythunkpos966; + { int yypos968= ctx->pos, yythunkpos968= ctx->thunkpos; if (!yy_HtmlBlockClosePre(ctx)) goto l968; goto l965; + l968:; ctx->pos= yypos968; ctx->thunkpos= yythunkpos968; + } if (!yymatchDot(ctx)) goto l965; + } + l966:; goto l964; + l965:; ctx->pos= yypos965; ctx->thunkpos= yythunkpos965; + } if (!yy_HtmlBlockClosePre(ctx)) goto l963; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockPre", ctx->buf+ctx->pos)); + return 1; + l963:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockPre", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockClosePre(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockClosePre")); if (!yymatchChar(ctx, '<')) goto l969; if (!yy_Spnl(ctx)) goto l969; if (!yymatchChar(ctx, '/')) goto l969; + { int yypos970= ctx->pos, yythunkpos970= ctx->thunkpos; if (!yymatchString(ctx, "pre")) goto l971; goto l970; + l971:; ctx->pos= yypos970; ctx->thunkpos= yythunkpos970; if (!yymatchString(ctx, "PRE")) goto l969; + } + l970:; if (!yy_Spnl(ctx)) goto l969; if (!yymatchChar(ctx, '>')) goto l969; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockClosePre", ctx->buf+ctx->pos)); + return 1; + l969:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockClosePre", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenPre(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenPre")); if (!yymatchChar(ctx, '<')) goto l972; if (!yy_Spnl(ctx)) goto l972; + { int yypos973= ctx->pos, yythunkpos973= ctx->thunkpos; if (!yymatchString(ctx, "pre")) goto l974; goto l973; + l974:; ctx->pos= yypos973; ctx->thunkpos= yythunkpos973; if (!yymatchString(ctx, "PRE")) goto l972; + } + l973:; if (!yy_Spnl(ctx)) goto l972; + l975:; + { int yypos976= ctx->pos, yythunkpos976= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l976; goto l975; + l976:; ctx->pos= yypos976; ctx->thunkpos= yythunkpos976; + } if (!yymatchChar(ctx, '>')) goto l972; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenPre", ctx->buf+ctx->pos)); + return 1; + l972:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenPre", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockP(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockP")); if (!yy_HtmlBlockOpenP(ctx)) goto l977; + l978:; + { int yypos979= ctx->pos, yythunkpos979= ctx->thunkpos; + { int yypos980= ctx->pos, yythunkpos980= ctx->thunkpos; if (!yy_HtmlBlockP(ctx)) goto l981; goto l980; + l981:; ctx->pos= yypos980; ctx->thunkpos= yythunkpos980; + { int yypos982= ctx->pos, yythunkpos982= ctx->thunkpos; if (!yy_HtmlBlockCloseP(ctx)) goto l982; goto l979; + l982:; ctx->pos= yypos982; ctx->thunkpos= yythunkpos982; + } if (!yymatchDot(ctx)) goto l979; + } + l980:; goto l978; + l979:; ctx->pos= yypos979; ctx->thunkpos= yythunkpos979; + } if (!yy_HtmlBlockCloseP(ctx)) goto l977; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockP", ctx->buf+ctx->pos)); + return 1; + l977:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockP", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseP(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseP")); if (!yymatchChar(ctx, '<')) goto l983; if (!yy_Spnl(ctx)) goto l983; if (!yymatchChar(ctx, '/')) goto l983; + { int yypos984= ctx->pos, yythunkpos984= ctx->thunkpos; if (!yymatchChar(ctx, 'p')) goto l985; goto l984; + l985:; ctx->pos= yypos984; ctx->thunkpos= yythunkpos984; if (!yymatchChar(ctx, 'P')) goto l983; + } + l984:; if (!yy_Spnl(ctx)) goto l983; if (!yymatchChar(ctx, '>')) goto l983; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseP", ctx->buf+ctx->pos)); + return 1; + l983:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseP", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenP(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenP")); if (!yymatchChar(ctx, '<')) goto l986; if (!yy_Spnl(ctx)) goto l986; + { int yypos987= ctx->pos, yythunkpos987= ctx->thunkpos; if (!yymatchChar(ctx, 'p')) goto l988; goto l987; + l988:; ctx->pos= yypos987; ctx->thunkpos= yythunkpos987; if (!yymatchChar(ctx, 'P')) goto l986; + } + l987:; if (!yy_Spnl(ctx)) goto l986; + l989:; + { int yypos990= ctx->pos, yythunkpos990= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l990; goto l989; + l990:; ctx->pos= yypos990; ctx->thunkpos= yythunkpos990; + } if (!yymatchChar(ctx, '>')) goto l986; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenP", ctx->buf+ctx->pos)); + return 1; + l986:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenP", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOl")); if (!yy_HtmlBlockOpenOl(ctx)) goto l991; + l992:; + { int yypos993= ctx->pos, yythunkpos993= ctx->thunkpos; + { int yypos994= ctx->pos, yythunkpos994= ctx->thunkpos; if (!yy_HtmlBlockOl(ctx)) goto l995; goto l994; + l995:; ctx->pos= yypos994; ctx->thunkpos= yythunkpos994; + { int yypos996= ctx->pos, yythunkpos996= ctx->thunkpos; if (!yy_HtmlBlockCloseOl(ctx)) goto l996; goto l993; + l996:; ctx->pos= yypos996; ctx->thunkpos= yythunkpos996; + } if (!yymatchDot(ctx)) goto l993; + } + l994:; goto l992; + l993:; ctx->pos= yypos993; ctx->thunkpos= yythunkpos993; + } if (!yy_HtmlBlockCloseOl(ctx)) goto l991; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOl", ctx->buf+ctx->pos)); + return 1; + l991:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseOl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseOl")); if (!yymatchChar(ctx, '<')) goto l997; if (!yy_Spnl(ctx)) goto l997; if (!yymatchChar(ctx, '/')) goto l997; + { int yypos998= ctx->pos, yythunkpos998= ctx->thunkpos; if (!yymatchString(ctx, "ol")) goto l999; goto l998; + l999:; ctx->pos= yypos998; ctx->thunkpos= yythunkpos998; if (!yymatchString(ctx, "OL")) goto l997; + } + l998:; if (!yy_Spnl(ctx)) goto l997; if (!yymatchChar(ctx, '>')) goto l997; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseOl", ctx->buf+ctx->pos)); + return 1; + l997:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseOl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenOl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenOl")); if (!yymatchChar(ctx, '<')) goto l1000; if (!yy_Spnl(ctx)) goto l1000; + { int yypos1001= ctx->pos, yythunkpos1001= ctx->thunkpos; if (!yymatchString(ctx, "ol")) goto l1002; goto l1001; + l1002:; ctx->pos= yypos1001; ctx->thunkpos= yythunkpos1001; if (!yymatchString(ctx, "OL")) goto l1000; + } + l1001:; if (!yy_Spnl(ctx)) goto l1000; + l1003:; + { int yypos1004= ctx->pos, yythunkpos1004= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1004; goto l1003; + l1004:; ctx->pos= yypos1004; ctx->thunkpos= yythunkpos1004; + } if (!yymatchChar(ctx, '>')) goto l1000; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenOl", ctx->buf+ctx->pos)); + return 1; + l1000:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenOl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockNoscript(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockNoscript")); if (!yy_HtmlBlockOpenNoscript(ctx)) goto l1005; + l1006:; + { int yypos1007= ctx->pos, yythunkpos1007= ctx->thunkpos; + { int yypos1008= ctx->pos, yythunkpos1008= ctx->thunkpos; if (!yy_HtmlBlockNoscript(ctx)) goto l1009; goto l1008; + l1009:; ctx->pos= yypos1008; ctx->thunkpos= yythunkpos1008; + { int yypos1010= ctx->pos, yythunkpos1010= ctx->thunkpos; if (!yy_HtmlBlockCloseNoscript(ctx)) goto l1010; goto l1007; + l1010:; ctx->pos= yypos1010; ctx->thunkpos= yythunkpos1010; + } if (!yymatchDot(ctx)) goto l1007; + } + l1008:; goto l1006; + l1007:; ctx->pos= yypos1007; ctx->thunkpos= yythunkpos1007; + } if (!yy_HtmlBlockCloseNoscript(ctx)) goto l1005; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockNoscript", ctx->buf+ctx->pos)); + return 1; + l1005:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockNoscript", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseNoscript(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseNoscript")); if (!yymatchChar(ctx, '<')) goto l1011; if (!yy_Spnl(ctx)) goto l1011; if (!yymatchChar(ctx, '/')) goto l1011; + { int yypos1012= ctx->pos, yythunkpos1012= ctx->thunkpos; if (!yymatchString(ctx, "noscript")) goto l1013; goto l1012; + l1013:; ctx->pos= yypos1012; ctx->thunkpos= yythunkpos1012; if (!yymatchString(ctx, "NOSCRIPT")) goto l1011; + } + l1012:; if (!yy_Spnl(ctx)) goto l1011; if (!yymatchChar(ctx, '>')) goto l1011; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseNoscript", ctx->buf+ctx->pos)); + return 1; + l1011:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseNoscript", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenNoscript(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenNoscript")); if (!yymatchChar(ctx, '<')) goto l1014; if (!yy_Spnl(ctx)) goto l1014; + { int yypos1015= ctx->pos, yythunkpos1015= ctx->thunkpos; if (!yymatchString(ctx, "noscript")) goto l1016; goto l1015; + l1016:; ctx->pos= yypos1015; ctx->thunkpos= yythunkpos1015; if (!yymatchString(ctx, "NOSCRIPT")) goto l1014; + } + l1015:; if (!yy_Spnl(ctx)) goto l1014; + l1017:; + { int yypos1018= ctx->pos, yythunkpos1018= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1018; goto l1017; + l1018:; ctx->pos= yypos1018; ctx->thunkpos= yythunkpos1018; + } if (!yymatchChar(ctx, '>')) goto l1014; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenNoscript", ctx->buf+ctx->pos)); + return 1; + l1014:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenNoscript", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockNoframes(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockNoframes")); if (!yy_HtmlBlockOpenNoframes(ctx)) goto l1019; + l1020:; + { int yypos1021= ctx->pos, yythunkpos1021= ctx->thunkpos; + { int yypos1022= ctx->pos, yythunkpos1022= ctx->thunkpos; if (!yy_HtmlBlockNoframes(ctx)) goto l1023; goto l1022; + l1023:; ctx->pos= yypos1022; ctx->thunkpos= yythunkpos1022; + { int yypos1024= ctx->pos, yythunkpos1024= ctx->thunkpos; if (!yy_HtmlBlockCloseNoframes(ctx)) goto l1024; goto l1021; + l1024:; ctx->pos= yypos1024; ctx->thunkpos= yythunkpos1024; + } if (!yymatchDot(ctx)) goto l1021; + } + l1022:; goto l1020; + l1021:; ctx->pos= yypos1021; ctx->thunkpos= yythunkpos1021; + } if (!yy_HtmlBlockCloseNoframes(ctx)) goto l1019; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockNoframes", ctx->buf+ctx->pos)); + return 1; + l1019:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockNoframes", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseNoframes(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseNoframes")); if (!yymatchChar(ctx, '<')) goto l1025; if (!yy_Spnl(ctx)) goto l1025; if (!yymatchChar(ctx, '/')) goto l1025; + { int yypos1026= ctx->pos, yythunkpos1026= ctx->thunkpos; if (!yymatchString(ctx, "noframes")) goto l1027; goto l1026; + l1027:; ctx->pos= yypos1026; ctx->thunkpos= yythunkpos1026; if (!yymatchString(ctx, "NOFRAMES")) goto l1025; + } + l1026:; if (!yy_Spnl(ctx)) goto l1025; if (!yymatchChar(ctx, '>')) goto l1025; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseNoframes", ctx->buf+ctx->pos)); + return 1; + l1025:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseNoframes", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenNoframes(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenNoframes")); if (!yymatchChar(ctx, '<')) goto l1028; if (!yy_Spnl(ctx)) goto l1028; + { int yypos1029= ctx->pos, yythunkpos1029= ctx->thunkpos; if (!yymatchString(ctx, "noframes")) goto l1030; goto l1029; + l1030:; ctx->pos= yypos1029; ctx->thunkpos= yythunkpos1029; if (!yymatchString(ctx, "NOFRAMES")) goto l1028; + } + l1029:; if (!yy_Spnl(ctx)) goto l1028; + l1031:; + { int yypos1032= ctx->pos, yythunkpos1032= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1032; goto l1031; + l1032:; ctx->pos= yypos1032; ctx->thunkpos= yythunkpos1032; + } if (!yymatchChar(ctx, '>')) goto l1028; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenNoframes", ctx->buf+ctx->pos)); + return 1; + l1028:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenNoframes", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockMenu(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockMenu")); if (!yy_HtmlBlockOpenMenu(ctx)) goto l1033; + l1034:; + { int yypos1035= ctx->pos, yythunkpos1035= ctx->thunkpos; + { int yypos1036= ctx->pos, yythunkpos1036= ctx->thunkpos; if (!yy_HtmlBlockMenu(ctx)) goto l1037; goto l1036; + l1037:; ctx->pos= yypos1036; ctx->thunkpos= yythunkpos1036; + { int yypos1038= ctx->pos, yythunkpos1038= ctx->thunkpos; if (!yy_HtmlBlockCloseMenu(ctx)) goto l1038; goto l1035; + l1038:; ctx->pos= yypos1038; ctx->thunkpos= yythunkpos1038; + } if (!yymatchDot(ctx)) goto l1035; + } + l1036:; goto l1034; + l1035:; ctx->pos= yypos1035; ctx->thunkpos= yythunkpos1035; + } if (!yy_HtmlBlockCloseMenu(ctx)) goto l1033; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockMenu", ctx->buf+ctx->pos)); + return 1; + l1033:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockMenu", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseMenu(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseMenu")); if (!yymatchChar(ctx, '<')) goto l1039; if (!yy_Spnl(ctx)) goto l1039; if (!yymatchChar(ctx, '/')) goto l1039; + { int yypos1040= ctx->pos, yythunkpos1040= ctx->thunkpos; if (!yymatchString(ctx, "menu")) goto l1041; goto l1040; + l1041:; ctx->pos= yypos1040; ctx->thunkpos= yythunkpos1040; if (!yymatchString(ctx, "MENU")) goto l1039; + } + l1040:; if (!yy_Spnl(ctx)) goto l1039; if (!yymatchChar(ctx, '>')) goto l1039; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseMenu", ctx->buf+ctx->pos)); + return 1; + l1039:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseMenu", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenMenu(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenMenu")); if (!yymatchChar(ctx, '<')) goto l1042; if (!yy_Spnl(ctx)) goto l1042; + { int yypos1043= ctx->pos, yythunkpos1043= ctx->thunkpos; if (!yymatchString(ctx, "menu")) goto l1044; goto l1043; + l1044:; ctx->pos= yypos1043; ctx->thunkpos= yythunkpos1043; if (!yymatchString(ctx, "MENU")) goto l1042; + } + l1043:; if (!yy_Spnl(ctx)) goto l1042; + l1045:; + { int yypos1046= ctx->pos, yythunkpos1046= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1046; goto l1045; + l1046:; ctx->pos= yypos1046; ctx->thunkpos= yythunkpos1046; + } if (!yymatchChar(ctx, '>')) goto l1042; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenMenu", ctx->buf+ctx->pos)); + return 1; + l1042:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenMenu", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockH6(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockH6")); if (!yy_HtmlBlockOpenH6(ctx)) goto l1047; + l1048:; + { int yypos1049= ctx->pos, yythunkpos1049= ctx->thunkpos; + { int yypos1050= ctx->pos, yythunkpos1050= ctx->thunkpos; if (!yy_HtmlBlockH6(ctx)) goto l1051; goto l1050; + l1051:; ctx->pos= yypos1050; ctx->thunkpos= yythunkpos1050; + { int yypos1052= ctx->pos, yythunkpos1052= ctx->thunkpos; if (!yy_HtmlBlockCloseH6(ctx)) goto l1052; goto l1049; + l1052:; ctx->pos= yypos1052; ctx->thunkpos= yythunkpos1052; + } if (!yymatchDot(ctx)) goto l1049; + } + l1050:; goto l1048; + l1049:; ctx->pos= yypos1049; ctx->thunkpos= yythunkpos1049; + } if (!yy_HtmlBlockCloseH6(ctx)) goto l1047; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockH6", ctx->buf+ctx->pos)); + return 1; + l1047:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockH6", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseH6(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseH6")); if (!yymatchChar(ctx, '<')) goto l1053; if (!yy_Spnl(ctx)) goto l1053; if (!yymatchChar(ctx, '/')) goto l1053; + { int yypos1054= ctx->pos, yythunkpos1054= ctx->thunkpos; if (!yymatchString(ctx, "h6")) goto l1055; goto l1054; + l1055:; ctx->pos= yypos1054; ctx->thunkpos= yythunkpos1054; if (!yymatchString(ctx, "H6")) goto l1053; + } + l1054:; if (!yy_Spnl(ctx)) goto l1053; if (!yymatchChar(ctx, '>')) goto l1053; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseH6", ctx->buf+ctx->pos)); + return 1; + l1053:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseH6", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenH6(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenH6")); if (!yymatchChar(ctx, '<')) goto l1056; if (!yy_Spnl(ctx)) goto l1056; + { int yypos1057= ctx->pos, yythunkpos1057= ctx->thunkpos; if (!yymatchString(ctx, "h6")) goto l1058; goto l1057; + l1058:; ctx->pos= yypos1057; ctx->thunkpos= yythunkpos1057; if (!yymatchString(ctx, "H6")) goto l1056; + } + l1057:; if (!yy_Spnl(ctx)) goto l1056; + l1059:; + { int yypos1060= ctx->pos, yythunkpos1060= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1060; goto l1059; + l1060:; ctx->pos= yypos1060; ctx->thunkpos= yythunkpos1060; + } if (!yymatchChar(ctx, '>')) goto l1056; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenH6", ctx->buf+ctx->pos)); + return 1; + l1056:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenH6", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockH5(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockH5")); if (!yy_HtmlBlockOpenH5(ctx)) goto l1061; + l1062:; + { int yypos1063= ctx->pos, yythunkpos1063= ctx->thunkpos; + { int yypos1064= ctx->pos, yythunkpos1064= ctx->thunkpos; if (!yy_HtmlBlockH5(ctx)) goto l1065; goto l1064; + l1065:; ctx->pos= yypos1064; ctx->thunkpos= yythunkpos1064; + { int yypos1066= ctx->pos, yythunkpos1066= ctx->thunkpos; if (!yy_HtmlBlockCloseH5(ctx)) goto l1066; goto l1063; + l1066:; ctx->pos= yypos1066; ctx->thunkpos= yythunkpos1066; + } if (!yymatchDot(ctx)) goto l1063; + } + l1064:; goto l1062; + l1063:; ctx->pos= yypos1063; ctx->thunkpos= yythunkpos1063; + } if (!yy_HtmlBlockCloseH5(ctx)) goto l1061; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockH5", ctx->buf+ctx->pos)); + return 1; + l1061:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockH5", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseH5(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseH5")); if (!yymatchChar(ctx, '<')) goto l1067; if (!yy_Spnl(ctx)) goto l1067; if (!yymatchChar(ctx, '/')) goto l1067; + { int yypos1068= ctx->pos, yythunkpos1068= ctx->thunkpos; if (!yymatchString(ctx, "h5")) goto l1069; goto l1068; + l1069:; ctx->pos= yypos1068; ctx->thunkpos= yythunkpos1068; if (!yymatchString(ctx, "H5")) goto l1067; + } + l1068:; if (!yy_Spnl(ctx)) goto l1067; if (!yymatchChar(ctx, '>')) goto l1067; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseH5", ctx->buf+ctx->pos)); + return 1; + l1067:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseH5", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenH5(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenH5")); if (!yymatchChar(ctx, '<')) goto l1070; if (!yy_Spnl(ctx)) goto l1070; + { int yypos1071= ctx->pos, yythunkpos1071= ctx->thunkpos; if (!yymatchString(ctx, "h5")) goto l1072; goto l1071; + l1072:; ctx->pos= yypos1071; ctx->thunkpos= yythunkpos1071; if (!yymatchString(ctx, "H5")) goto l1070; + } + l1071:; if (!yy_Spnl(ctx)) goto l1070; + l1073:; + { int yypos1074= ctx->pos, yythunkpos1074= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1074; goto l1073; + l1074:; ctx->pos= yypos1074; ctx->thunkpos= yythunkpos1074; + } if (!yymatchChar(ctx, '>')) goto l1070; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenH5", ctx->buf+ctx->pos)); + return 1; + l1070:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenH5", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockH4(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockH4")); if (!yy_HtmlBlockOpenH4(ctx)) goto l1075; + l1076:; + { int yypos1077= ctx->pos, yythunkpos1077= ctx->thunkpos; + { int yypos1078= ctx->pos, yythunkpos1078= ctx->thunkpos; if (!yy_HtmlBlockH4(ctx)) goto l1079; goto l1078; + l1079:; ctx->pos= yypos1078; ctx->thunkpos= yythunkpos1078; + { int yypos1080= ctx->pos, yythunkpos1080= ctx->thunkpos; if (!yy_HtmlBlockCloseH4(ctx)) goto l1080; goto l1077; + l1080:; ctx->pos= yypos1080; ctx->thunkpos= yythunkpos1080; + } if (!yymatchDot(ctx)) goto l1077; + } + l1078:; goto l1076; + l1077:; ctx->pos= yypos1077; ctx->thunkpos= yythunkpos1077; + } if (!yy_HtmlBlockCloseH4(ctx)) goto l1075; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockH4", ctx->buf+ctx->pos)); + return 1; + l1075:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockH4", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseH4(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseH4")); if (!yymatchChar(ctx, '<')) goto l1081; if (!yy_Spnl(ctx)) goto l1081; if (!yymatchChar(ctx, '/')) goto l1081; + { int yypos1082= ctx->pos, yythunkpos1082= ctx->thunkpos; if (!yymatchString(ctx, "h4")) goto l1083; goto l1082; + l1083:; ctx->pos= yypos1082; ctx->thunkpos= yythunkpos1082; if (!yymatchString(ctx, "H4")) goto l1081; + } + l1082:; if (!yy_Spnl(ctx)) goto l1081; if (!yymatchChar(ctx, '>')) goto l1081; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseH4", ctx->buf+ctx->pos)); + return 1; + l1081:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseH4", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenH4(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenH4")); if (!yymatchChar(ctx, '<')) goto l1084; if (!yy_Spnl(ctx)) goto l1084; + { int yypos1085= ctx->pos, yythunkpos1085= ctx->thunkpos; if (!yymatchString(ctx, "h4")) goto l1086; goto l1085; + l1086:; ctx->pos= yypos1085; ctx->thunkpos= yythunkpos1085; if (!yymatchString(ctx, "H4")) goto l1084; + } + l1085:; if (!yy_Spnl(ctx)) goto l1084; + l1087:; + { int yypos1088= ctx->pos, yythunkpos1088= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1088; goto l1087; + l1088:; ctx->pos= yypos1088; ctx->thunkpos= yythunkpos1088; + } if (!yymatchChar(ctx, '>')) goto l1084; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenH4", ctx->buf+ctx->pos)); + return 1; + l1084:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenH4", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockH3(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockH3")); if (!yy_HtmlBlockOpenH3(ctx)) goto l1089; + l1090:; + { int yypos1091= ctx->pos, yythunkpos1091= ctx->thunkpos; + { int yypos1092= ctx->pos, yythunkpos1092= ctx->thunkpos; if (!yy_HtmlBlockH3(ctx)) goto l1093; goto l1092; + l1093:; ctx->pos= yypos1092; ctx->thunkpos= yythunkpos1092; + { int yypos1094= ctx->pos, yythunkpos1094= ctx->thunkpos; if (!yy_HtmlBlockCloseH3(ctx)) goto l1094; goto l1091; + l1094:; ctx->pos= yypos1094; ctx->thunkpos= yythunkpos1094; + } if (!yymatchDot(ctx)) goto l1091; + } + l1092:; goto l1090; + l1091:; ctx->pos= yypos1091; ctx->thunkpos= yythunkpos1091; + } if (!yy_HtmlBlockCloseH3(ctx)) goto l1089; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockH3", ctx->buf+ctx->pos)); + return 1; + l1089:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockH3", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseH3(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseH3")); if (!yymatchChar(ctx, '<')) goto l1095; if (!yy_Spnl(ctx)) goto l1095; if (!yymatchChar(ctx, '/')) goto l1095; + { int yypos1096= ctx->pos, yythunkpos1096= ctx->thunkpos; if (!yymatchString(ctx, "h3")) goto l1097; goto l1096; + l1097:; ctx->pos= yypos1096; ctx->thunkpos= yythunkpos1096; if (!yymatchString(ctx, "H3")) goto l1095; + } + l1096:; if (!yy_Spnl(ctx)) goto l1095; if (!yymatchChar(ctx, '>')) goto l1095; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseH3", ctx->buf+ctx->pos)); + return 1; + l1095:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseH3", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenH3(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenH3")); if (!yymatchChar(ctx, '<')) goto l1098; if (!yy_Spnl(ctx)) goto l1098; + { int yypos1099= ctx->pos, yythunkpos1099= ctx->thunkpos; if (!yymatchString(ctx, "h3")) goto l1100; goto l1099; + l1100:; ctx->pos= yypos1099; ctx->thunkpos= yythunkpos1099; if (!yymatchString(ctx, "H3")) goto l1098; + } + l1099:; if (!yy_Spnl(ctx)) goto l1098; + l1101:; + { int yypos1102= ctx->pos, yythunkpos1102= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1102; goto l1101; + l1102:; ctx->pos= yypos1102; ctx->thunkpos= yythunkpos1102; + } if (!yymatchChar(ctx, '>')) goto l1098; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenH3", ctx->buf+ctx->pos)); + return 1; + l1098:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenH3", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockH2(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockH2")); if (!yy_HtmlBlockOpenH2(ctx)) goto l1103; + l1104:; + { int yypos1105= ctx->pos, yythunkpos1105= ctx->thunkpos; + { int yypos1106= ctx->pos, yythunkpos1106= ctx->thunkpos; if (!yy_HtmlBlockH2(ctx)) goto l1107; goto l1106; + l1107:; ctx->pos= yypos1106; ctx->thunkpos= yythunkpos1106; + { int yypos1108= ctx->pos, yythunkpos1108= ctx->thunkpos; if (!yy_HtmlBlockCloseH2(ctx)) goto l1108; goto l1105; + l1108:; ctx->pos= yypos1108; ctx->thunkpos= yythunkpos1108; + } if (!yymatchDot(ctx)) goto l1105; + } + l1106:; goto l1104; + l1105:; ctx->pos= yypos1105; ctx->thunkpos= yythunkpos1105; + } if (!yy_HtmlBlockCloseH2(ctx)) goto l1103; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockH2", ctx->buf+ctx->pos)); + return 1; + l1103:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockH2", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseH2(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseH2")); if (!yymatchChar(ctx, '<')) goto l1109; if (!yy_Spnl(ctx)) goto l1109; if (!yymatchChar(ctx, '/')) goto l1109; + { int yypos1110= ctx->pos, yythunkpos1110= ctx->thunkpos; if (!yymatchString(ctx, "h2")) goto l1111; goto l1110; + l1111:; ctx->pos= yypos1110; ctx->thunkpos= yythunkpos1110; if (!yymatchString(ctx, "H2")) goto l1109; + } + l1110:; if (!yy_Spnl(ctx)) goto l1109; if (!yymatchChar(ctx, '>')) goto l1109; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseH2", ctx->buf+ctx->pos)); + return 1; + l1109:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseH2", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenH2(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenH2")); if (!yymatchChar(ctx, '<')) goto l1112; if (!yy_Spnl(ctx)) goto l1112; + { int yypos1113= ctx->pos, yythunkpos1113= ctx->thunkpos; if (!yymatchString(ctx, "h2")) goto l1114; goto l1113; + l1114:; ctx->pos= yypos1113; ctx->thunkpos= yythunkpos1113; if (!yymatchString(ctx, "H2")) goto l1112; + } + l1113:; if (!yy_Spnl(ctx)) goto l1112; + l1115:; + { int yypos1116= ctx->pos, yythunkpos1116= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1116; goto l1115; + l1116:; ctx->pos= yypos1116; ctx->thunkpos= yythunkpos1116; + } if (!yymatchChar(ctx, '>')) goto l1112; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenH2", ctx->buf+ctx->pos)); + return 1; + l1112:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenH2", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockH1(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockH1")); if (!yy_HtmlBlockOpenH1(ctx)) goto l1117; + l1118:; + { int yypos1119= ctx->pos, yythunkpos1119= ctx->thunkpos; + { int yypos1120= ctx->pos, yythunkpos1120= ctx->thunkpos; if (!yy_HtmlBlockH1(ctx)) goto l1121; goto l1120; + l1121:; ctx->pos= yypos1120; ctx->thunkpos= yythunkpos1120; + { int yypos1122= ctx->pos, yythunkpos1122= ctx->thunkpos; if (!yy_HtmlBlockCloseH1(ctx)) goto l1122; goto l1119; + l1122:; ctx->pos= yypos1122; ctx->thunkpos= yythunkpos1122; + } if (!yymatchDot(ctx)) goto l1119; + } + l1120:; goto l1118; + l1119:; ctx->pos= yypos1119; ctx->thunkpos= yythunkpos1119; + } if (!yy_HtmlBlockCloseH1(ctx)) goto l1117; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockH1", ctx->buf+ctx->pos)); + return 1; + l1117:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockH1", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseH1(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseH1")); if (!yymatchChar(ctx, '<')) goto l1123; if (!yy_Spnl(ctx)) goto l1123; if (!yymatchChar(ctx, '/')) goto l1123; + { int yypos1124= ctx->pos, yythunkpos1124= ctx->thunkpos; if (!yymatchString(ctx, "h1")) goto l1125; goto l1124; + l1125:; ctx->pos= yypos1124; ctx->thunkpos= yythunkpos1124; if (!yymatchString(ctx, "H1")) goto l1123; + } + l1124:; if (!yy_Spnl(ctx)) goto l1123; if (!yymatchChar(ctx, '>')) goto l1123; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseH1", ctx->buf+ctx->pos)); + return 1; + l1123:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseH1", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenH1(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenH1")); if (!yymatchChar(ctx, '<')) goto l1126; if (!yy_Spnl(ctx)) goto l1126; + { int yypos1127= ctx->pos, yythunkpos1127= ctx->thunkpos; if (!yymatchString(ctx, "h1")) goto l1128; goto l1127; + l1128:; ctx->pos= yypos1127; ctx->thunkpos= yythunkpos1127; if (!yymatchString(ctx, "H1")) goto l1126; + } + l1127:; if (!yy_Spnl(ctx)) goto l1126; + l1129:; + { int yypos1130= ctx->pos, yythunkpos1130= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1130; goto l1129; + l1130:; ctx->pos= yypos1130; ctx->thunkpos= yythunkpos1130; + } if (!yymatchChar(ctx, '>')) goto l1126; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenH1", ctx->buf+ctx->pos)); + return 1; + l1126:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenH1", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockForm(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockForm")); if (!yy_HtmlBlockOpenForm(ctx)) goto l1131; + l1132:; + { int yypos1133= ctx->pos, yythunkpos1133= ctx->thunkpos; + { int yypos1134= ctx->pos, yythunkpos1134= ctx->thunkpos; if (!yy_HtmlBlockForm(ctx)) goto l1135; goto l1134; + l1135:; ctx->pos= yypos1134; ctx->thunkpos= yythunkpos1134; + { int yypos1136= ctx->pos, yythunkpos1136= ctx->thunkpos; if (!yy_HtmlBlockCloseForm(ctx)) goto l1136; goto l1133; + l1136:; ctx->pos= yypos1136; ctx->thunkpos= yythunkpos1136; + } if (!yymatchDot(ctx)) goto l1133; + } + l1134:; goto l1132; + l1133:; ctx->pos= yypos1133; ctx->thunkpos= yythunkpos1133; + } if (!yy_HtmlBlockCloseForm(ctx)) goto l1131; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockForm", ctx->buf+ctx->pos)); + return 1; + l1131:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockForm", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseForm(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseForm")); if (!yymatchChar(ctx, '<')) goto l1137; if (!yy_Spnl(ctx)) goto l1137; if (!yymatchChar(ctx, '/')) goto l1137; + { int yypos1138= ctx->pos, yythunkpos1138= ctx->thunkpos; if (!yymatchString(ctx, "form")) goto l1139; goto l1138; + l1139:; ctx->pos= yypos1138; ctx->thunkpos= yythunkpos1138; if (!yymatchString(ctx, "FORM")) goto l1137; + } + l1138:; if (!yy_Spnl(ctx)) goto l1137; if (!yymatchChar(ctx, '>')) goto l1137; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseForm", ctx->buf+ctx->pos)); + return 1; + l1137:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseForm", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenForm(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenForm")); if (!yymatchChar(ctx, '<')) goto l1140; if (!yy_Spnl(ctx)) goto l1140; + { int yypos1141= ctx->pos, yythunkpos1141= ctx->thunkpos; if (!yymatchString(ctx, "form")) goto l1142; goto l1141; + l1142:; ctx->pos= yypos1141; ctx->thunkpos= yythunkpos1141; if (!yymatchString(ctx, "FORM")) goto l1140; + } + l1141:; if (!yy_Spnl(ctx)) goto l1140; + l1143:; + { int yypos1144= ctx->pos, yythunkpos1144= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1144; goto l1143; + l1144:; ctx->pos= yypos1144; ctx->thunkpos= yythunkpos1144; + } if (!yymatchChar(ctx, '>')) goto l1140; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenForm", ctx->buf+ctx->pos)); + return 1; + l1140:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenForm", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockFieldset(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockFieldset")); if (!yy_HtmlBlockOpenFieldset(ctx)) goto l1145; + l1146:; + { int yypos1147= ctx->pos, yythunkpos1147= ctx->thunkpos; + { int yypos1148= ctx->pos, yythunkpos1148= ctx->thunkpos; if (!yy_HtmlBlockFieldset(ctx)) goto l1149; goto l1148; + l1149:; ctx->pos= yypos1148; ctx->thunkpos= yythunkpos1148; + { int yypos1150= ctx->pos, yythunkpos1150= ctx->thunkpos; if (!yy_HtmlBlockCloseFieldset(ctx)) goto l1150; goto l1147; + l1150:; ctx->pos= yypos1150; ctx->thunkpos= yythunkpos1150; + } if (!yymatchDot(ctx)) goto l1147; + } + l1148:; goto l1146; + l1147:; ctx->pos= yypos1147; ctx->thunkpos= yythunkpos1147; + } if (!yy_HtmlBlockCloseFieldset(ctx)) goto l1145; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockFieldset", ctx->buf+ctx->pos)); + return 1; + l1145:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockFieldset", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseFieldset(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseFieldset")); if (!yymatchChar(ctx, '<')) goto l1151; if (!yy_Spnl(ctx)) goto l1151; if (!yymatchChar(ctx, '/')) goto l1151; + { int yypos1152= ctx->pos, yythunkpos1152= ctx->thunkpos; if (!yymatchString(ctx, "fieldset")) goto l1153; goto l1152; + l1153:; ctx->pos= yypos1152; ctx->thunkpos= yythunkpos1152; if (!yymatchString(ctx, "FIELDSET")) goto l1151; + } + l1152:; if (!yy_Spnl(ctx)) goto l1151; if (!yymatchChar(ctx, '>')) goto l1151; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseFieldset", ctx->buf+ctx->pos)); + return 1; + l1151:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseFieldset", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenFieldset(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenFieldset")); if (!yymatchChar(ctx, '<')) goto l1154; if (!yy_Spnl(ctx)) goto l1154; + { int yypos1155= ctx->pos, yythunkpos1155= ctx->thunkpos; if (!yymatchString(ctx, "fieldset")) goto l1156; goto l1155; + l1156:; ctx->pos= yypos1155; ctx->thunkpos= yythunkpos1155; if (!yymatchString(ctx, "FIELDSET")) goto l1154; + } + l1155:; if (!yy_Spnl(ctx)) goto l1154; + l1157:; + { int yypos1158= ctx->pos, yythunkpos1158= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1158; goto l1157; + l1158:; ctx->pos= yypos1158; ctx->thunkpos= yythunkpos1158; + } if (!yymatchChar(ctx, '>')) goto l1154; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenFieldset", ctx->buf+ctx->pos)); + return 1; + l1154:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenFieldset", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockDl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockDl")); if (!yy_HtmlBlockOpenDl(ctx)) goto l1159; + l1160:; + { int yypos1161= ctx->pos, yythunkpos1161= ctx->thunkpos; + { int yypos1162= ctx->pos, yythunkpos1162= ctx->thunkpos; if (!yy_HtmlBlockDl(ctx)) goto l1163; goto l1162; + l1163:; ctx->pos= yypos1162; ctx->thunkpos= yythunkpos1162; + { int yypos1164= ctx->pos, yythunkpos1164= ctx->thunkpos; if (!yy_HtmlBlockCloseDl(ctx)) goto l1164; goto l1161; + l1164:; ctx->pos= yypos1164; ctx->thunkpos= yythunkpos1164; + } if (!yymatchDot(ctx)) goto l1161; + } + l1162:; goto l1160; + l1161:; ctx->pos= yypos1161; ctx->thunkpos= yythunkpos1161; + } if (!yy_HtmlBlockCloseDl(ctx)) goto l1159; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockDl", ctx->buf+ctx->pos)); + return 1; + l1159:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockDl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseDl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseDl")); if (!yymatchChar(ctx, '<')) goto l1165; if (!yy_Spnl(ctx)) goto l1165; if (!yymatchChar(ctx, '/')) goto l1165; + { int yypos1166= ctx->pos, yythunkpos1166= ctx->thunkpos; if (!yymatchString(ctx, "dl")) goto l1167; goto l1166; + l1167:; ctx->pos= yypos1166; ctx->thunkpos= yythunkpos1166; if (!yymatchString(ctx, "DL")) goto l1165; + } + l1166:; if (!yy_Spnl(ctx)) goto l1165; if (!yymatchChar(ctx, '>')) goto l1165; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseDl", ctx->buf+ctx->pos)); + return 1; + l1165:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseDl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenDl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenDl")); if (!yymatchChar(ctx, '<')) goto l1168; if (!yy_Spnl(ctx)) goto l1168; + { int yypos1169= ctx->pos, yythunkpos1169= ctx->thunkpos; if (!yymatchString(ctx, "dl")) goto l1170; goto l1169; + l1170:; ctx->pos= yypos1169; ctx->thunkpos= yythunkpos1169; if (!yymatchString(ctx, "DL")) goto l1168; + } + l1169:; if (!yy_Spnl(ctx)) goto l1168; + l1171:; + { int yypos1172= ctx->pos, yythunkpos1172= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1172; goto l1171; + l1172:; ctx->pos= yypos1172; ctx->thunkpos= yythunkpos1172; + } if (!yymatchChar(ctx, '>')) goto l1168; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenDl", ctx->buf+ctx->pos)); + return 1; + l1168:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenDl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockDiv(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockDiv")); if (!yy_HtmlBlockOpenDiv(ctx)) goto l1173; + l1174:; + { int yypos1175= ctx->pos, yythunkpos1175= ctx->thunkpos; + { int yypos1176= ctx->pos, yythunkpos1176= ctx->thunkpos; if (!yy_HtmlBlockDiv(ctx)) goto l1177; goto l1176; + l1177:; ctx->pos= yypos1176; ctx->thunkpos= yythunkpos1176; + { int yypos1178= ctx->pos, yythunkpos1178= ctx->thunkpos; if (!yy_HtmlBlockCloseDiv(ctx)) goto l1178; goto l1175; + l1178:; ctx->pos= yypos1178; ctx->thunkpos= yythunkpos1178; + } if (!yymatchDot(ctx)) goto l1175; + } + l1176:; goto l1174; + l1175:; ctx->pos= yypos1175; ctx->thunkpos= yythunkpos1175; + } if (!yy_HtmlBlockCloseDiv(ctx)) goto l1173; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockDiv", ctx->buf+ctx->pos)); + return 1; + l1173:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockDiv", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseDiv(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseDiv")); if (!yymatchChar(ctx, '<')) goto l1179; if (!yy_Spnl(ctx)) goto l1179; if (!yymatchChar(ctx, '/')) goto l1179; + { int yypos1180= ctx->pos, yythunkpos1180= ctx->thunkpos; if (!yymatchString(ctx, "div")) goto l1181; goto l1180; + l1181:; ctx->pos= yypos1180; ctx->thunkpos= yythunkpos1180; if (!yymatchString(ctx, "DIV")) goto l1179; + } + l1180:; if (!yy_Spnl(ctx)) goto l1179; if (!yymatchChar(ctx, '>')) goto l1179; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseDiv", ctx->buf+ctx->pos)); + return 1; + l1179:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseDiv", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenDiv(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenDiv")); if (!yymatchChar(ctx, '<')) goto l1182; if (!yy_Spnl(ctx)) goto l1182; + { int yypos1183= ctx->pos, yythunkpos1183= ctx->thunkpos; if (!yymatchString(ctx, "div")) goto l1184; goto l1183; + l1184:; ctx->pos= yypos1183; ctx->thunkpos= yythunkpos1183; if (!yymatchString(ctx, "DIV")) goto l1182; + } + l1183:; if (!yy_Spnl(ctx)) goto l1182; + l1185:; + { int yypos1186= ctx->pos, yythunkpos1186= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1186; goto l1185; + l1186:; ctx->pos= yypos1186; ctx->thunkpos= yythunkpos1186; + } if (!yymatchChar(ctx, '>')) goto l1182; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenDiv", ctx->buf+ctx->pos)); + return 1; + l1182:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenDiv", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockDir(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockDir")); if (!yy_HtmlBlockOpenDir(ctx)) goto l1187; + l1188:; + { int yypos1189= ctx->pos, yythunkpos1189= ctx->thunkpos; + { int yypos1190= ctx->pos, yythunkpos1190= ctx->thunkpos; if (!yy_HtmlBlockDir(ctx)) goto l1191; goto l1190; + l1191:; ctx->pos= yypos1190; ctx->thunkpos= yythunkpos1190; + { int yypos1192= ctx->pos, yythunkpos1192= ctx->thunkpos; if (!yy_HtmlBlockCloseDir(ctx)) goto l1192; goto l1189; + l1192:; ctx->pos= yypos1192; ctx->thunkpos= yythunkpos1192; + } if (!yymatchDot(ctx)) goto l1189; + } + l1190:; goto l1188; + l1189:; ctx->pos= yypos1189; ctx->thunkpos= yythunkpos1189; + } if (!yy_HtmlBlockCloseDir(ctx)) goto l1187; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockDir", ctx->buf+ctx->pos)); + return 1; + l1187:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockDir", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseDir(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseDir")); if (!yymatchChar(ctx, '<')) goto l1193; if (!yy_Spnl(ctx)) goto l1193; if (!yymatchChar(ctx, '/')) goto l1193; + { int yypos1194= ctx->pos, yythunkpos1194= ctx->thunkpos; if (!yymatchString(ctx, "dir")) goto l1195; goto l1194; + l1195:; ctx->pos= yypos1194; ctx->thunkpos= yythunkpos1194; if (!yymatchString(ctx, "DIR")) goto l1193; + } + l1194:; if (!yy_Spnl(ctx)) goto l1193; if (!yymatchChar(ctx, '>')) goto l1193; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseDir", ctx->buf+ctx->pos)); + return 1; + l1193:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseDir", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenDir(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenDir")); if (!yymatchChar(ctx, '<')) goto l1196; if (!yy_Spnl(ctx)) goto l1196; + { int yypos1197= ctx->pos, yythunkpos1197= ctx->thunkpos; if (!yymatchString(ctx, "dir")) goto l1198; goto l1197; + l1198:; ctx->pos= yypos1197; ctx->thunkpos= yythunkpos1197; if (!yymatchString(ctx, "DIR")) goto l1196; + } + l1197:; if (!yy_Spnl(ctx)) goto l1196; + l1199:; + { int yypos1200= ctx->pos, yythunkpos1200= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1200; goto l1199; + l1200:; ctx->pos= yypos1200; ctx->thunkpos= yythunkpos1200; + } if (!yymatchChar(ctx, '>')) goto l1196; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenDir", ctx->buf+ctx->pos)); + return 1; + l1196:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenDir", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCenter(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCenter")); if (!yy_HtmlBlockOpenCenter(ctx)) goto l1201; + l1202:; + { int yypos1203= ctx->pos, yythunkpos1203= ctx->thunkpos; + { int yypos1204= ctx->pos, yythunkpos1204= ctx->thunkpos; if (!yy_HtmlBlockCenter(ctx)) goto l1205; goto l1204; + l1205:; ctx->pos= yypos1204; ctx->thunkpos= yythunkpos1204; + { int yypos1206= ctx->pos, yythunkpos1206= ctx->thunkpos; if (!yy_HtmlBlockCloseCenter(ctx)) goto l1206; goto l1203; + l1206:; ctx->pos= yypos1206; ctx->thunkpos= yythunkpos1206; + } if (!yymatchDot(ctx)) goto l1203; + } + l1204:; goto l1202; + l1203:; ctx->pos= yypos1203; ctx->thunkpos= yythunkpos1203; + } if (!yy_HtmlBlockCloseCenter(ctx)) goto l1201; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCenter", ctx->buf+ctx->pos)); + return 1; + l1201:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCenter", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseCenter(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseCenter")); if (!yymatchChar(ctx, '<')) goto l1207; if (!yy_Spnl(ctx)) goto l1207; if (!yymatchChar(ctx, '/')) goto l1207; + { int yypos1208= ctx->pos, yythunkpos1208= ctx->thunkpos; if (!yymatchString(ctx, "center")) goto l1209; goto l1208; + l1209:; ctx->pos= yypos1208; ctx->thunkpos= yythunkpos1208; if (!yymatchString(ctx, "CENTER")) goto l1207; + } + l1208:; if (!yy_Spnl(ctx)) goto l1207; if (!yymatchChar(ctx, '>')) goto l1207; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseCenter", ctx->buf+ctx->pos)); + return 1; + l1207:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseCenter", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenCenter(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenCenter")); if (!yymatchChar(ctx, '<')) goto l1210; if (!yy_Spnl(ctx)) goto l1210; + { int yypos1211= ctx->pos, yythunkpos1211= ctx->thunkpos; if (!yymatchString(ctx, "center")) goto l1212; goto l1211; + l1212:; ctx->pos= yypos1211; ctx->thunkpos= yythunkpos1211; if (!yymatchString(ctx, "CENTER")) goto l1210; + } + l1211:; if (!yy_Spnl(ctx)) goto l1210; + l1213:; + { int yypos1214= ctx->pos, yythunkpos1214= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1214; goto l1213; + l1214:; ctx->pos= yypos1214; ctx->thunkpos= yythunkpos1214; + } if (!yymatchChar(ctx, '>')) goto l1210; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenCenter", ctx->buf+ctx->pos)); + return 1; + l1210:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenCenter", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockBlockquote(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockBlockquote")); if (!yy_HtmlBlockOpenBlockquote(ctx)) goto l1215; + l1216:; + { int yypos1217= ctx->pos, yythunkpos1217= ctx->thunkpos; + { int yypos1218= ctx->pos, yythunkpos1218= ctx->thunkpos; if (!yy_HtmlBlockBlockquote(ctx)) goto l1219; goto l1218; + l1219:; ctx->pos= yypos1218; ctx->thunkpos= yythunkpos1218; + { int yypos1220= ctx->pos, yythunkpos1220= ctx->thunkpos; if (!yy_HtmlBlockCloseBlockquote(ctx)) goto l1220; goto l1217; + l1220:; ctx->pos= yypos1220; ctx->thunkpos= yythunkpos1220; + } if (!yymatchDot(ctx)) goto l1217; + } + l1218:; goto l1216; + l1217:; ctx->pos= yypos1217; ctx->thunkpos= yythunkpos1217; + } if (!yy_HtmlBlockCloseBlockquote(ctx)) goto l1215; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockBlockquote", ctx->buf+ctx->pos)); + return 1; + l1215:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockBlockquote", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseBlockquote(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseBlockquote")); if (!yymatchChar(ctx, '<')) goto l1221; if (!yy_Spnl(ctx)) goto l1221; if (!yymatchChar(ctx, '/')) goto l1221; + { int yypos1222= ctx->pos, yythunkpos1222= ctx->thunkpos; if (!yymatchString(ctx, "blockquote")) goto l1223; goto l1222; + l1223:; ctx->pos= yypos1222; ctx->thunkpos= yythunkpos1222; if (!yymatchString(ctx, "BLOCKQUOTE")) goto l1221; + } + l1222:; if (!yy_Spnl(ctx)) goto l1221; if (!yymatchChar(ctx, '>')) goto l1221; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseBlockquote", ctx->buf+ctx->pos)); + return 1; + l1221:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseBlockquote", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenBlockquote(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenBlockquote")); if (!yymatchChar(ctx, '<')) goto l1224; if (!yy_Spnl(ctx)) goto l1224; + { int yypos1225= ctx->pos, yythunkpos1225= ctx->thunkpos; if (!yymatchString(ctx, "blockquote")) goto l1226; goto l1225; + l1226:; ctx->pos= yypos1225; ctx->thunkpos= yythunkpos1225; if (!yymatchString(ctx, "BLOCKQUOTE")) goto l1224; + } + l1225:; if (!yy_Spnl(ctx)) goto l1224; + l1227:; + { int yypos1228= ctx->pos, yythunkpos1228= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1228; goto l1227; + l1228:; ctx->pos= yypos1228; ctx->thunkpos= yythunkpos1228; + } if (!yymatchChar(ctx, '>')) goto l1224; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenBlockquote", ctx->buf+ctx->pos)); + return 1; + l1224:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenBlockquote", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockAddress(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockAddress")); if (!yy_HtmlBlockOpenAddress(ctx)) goto l1229; + l1230:; + { int yypos1231= ctx->pos, yythunkpos1231= ctx->thunkpos; + { int yypos1232= ctx->pos, yythunkpos1232= ctx->thunkpos; if (!yy_HtmlBlockAddress(ctx)) goto l1233; goto l1232; + l1233:; ctx->pos= yypos1232; ctx->thunkpos= yythunkpos1232; + { int yypos1234= ctx->pos, yythunkpos1234= ctx->thunkpos; if (!yy_HtmlBlockCloseAddress(ctx)) goto l1234; goto l1231; + l1234:; ctx->pos= yypos1234; ctx->thunkpos= yythunkpos1234; + } if (!yymatchDot(ctx)) goto l1231; + } + l1232:; goto l1230; + l1231:; ctx->pos= yypos1231; ctx->thunkpos= yythunkpos1231; + } if (!yy_HtmlBlockCloseAddress(ctx)) goto l1229; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockAddress", ctx->buf+ctx->pos)); + return 1; + l1229:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockAddress", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockCloseAddress(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockCloseAddress")); if (!yymatchChar(ctx, '<')) goto l1235; if (!yy_Spnl(ctx)) goto l1235; if (!yymatchChar(ctx, '/')) goto l1235; + { int yypos1236= ctx->pos, yythunkpos1236= ctx->thunkpos; if (!yymatchString(ctx, "address")) goto l1237; goto l1236; + l1237:; ctx->pos= yypos1236; ctx->thunkpos= yythunkpos1236; if (!yymatchString(ctx, "ADDRESS")) goto l1235; + } + l1236:; if (!yy_Spnl(ctx)) goto l1235; if (!yymatchChar(ctx, '>')) goto l1235; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockCloseAddress", ctx->buf+ctx->pos)); + return 1; + l1235:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockCloseAddress", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlAttribute(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlAttribute")); + { int yypos1241= ctx->pos, yythunkpos1241= ctx->thunkpos; if (!yy_AlphanumericAscii(ctx)) goto l1242; goto l1241; + l1242:; ctx->pos= yypos1241; ctx->thunkpos= yythunkpos1241; if (!yymatchChar(ctx, '-')) goto l1238; + } + l1241:; + l1239:; + { int yypos1240= ctx->pos, yythunkpos1240= ctx->thunkpos; + { int yypos1243= ctx->pos, yythunkpos1243= ctx->thunkpos; if (!yy_AlphanumericAscii(ctx)) goto l1244; goto l1243; + l1244:; ctx->pos= yypos1243; ctx->thunkpos= yythunkpos1243; if (!yymatchChar(ctx, '-')) goto l1240; + } + l1243:; goto l1239; + l1240:; ctx->pos= yypos1240; ctx->thunkpos= yythunkpos1240; + } if (!yy_Spnl(ctx)) goto l1238; + { int yypos1245= ctx->pos, yythunkpos1245= ctx->thunkpos; if (!yymatchChar(ctx, '=')) goto l1245; if (!yy_Spnl(ctx)) goto l1245; + { int yypos1247= ctx->pos, yythunkpos1247= ctx->thunkpos; if (!yy_Quoted(ctx)) goto l1248; goto l1247; + l1248:; ctx->pos= yypos1247; ctx->thunkpos= yythunkpos1247; + { int yypos1251= ctx->pos, yythunkpos1251= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l1251; goto l1245; + l1251:; ctx->pos= yypos1251; ctx->thunkpos= yythunkpos1251; + } if (!yy_Nonspacechar(ctx)) goto l1245; + l1249:; + { int yypos1250= ctx->pos, yythunkpos1250= ctx->thunkpos; + { int yypos1252= ctx->pos, yythunkpos1252= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l1252; goto l1250; + l1252:; ctx->pos= yypos1252; ctx->thunkpos= yythunkpos1252; + } if (!yy_Nonspacechar(ctx)) goto l1250; goto l1249; + l1250:; ctx->pos= yypos1250; ctx->thunkpos= yythunkpos1250; + } + } + l1247:; goto l1246; + l1245:; ctx->pos= yypos1245; ctx->thunkpos= yythunkpos1245; + } + l1246:; if (!yy_Spnl(ctx)) goto l1238; + yyprintf((stderr, " ok %s @ %s\n", "HtmlAttribute", ctx->buf+ctx->pos)); + return 1; + l1238:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlAttribute", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Spnl(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Spnl")); if (!yy_Sp(ctx)) goto l1253; + { int yypos1254= ctx->pos, yythunkpos1254= ctx->thunkpos; if (!yy_Newline(ctx)) goto l1254; if (!yy_Sp(ctx)) goto l1254; goto l1255; + l1254:; ctx->pos= yypos1254; ctx->thunkpos= yythunkpos1254; + } + l1255:; + yyprintf((stderr, " ok %s @ %s\n", "Spnl", ctx->buf+ctx->pos)); + return 1; + l1253:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Spnl", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlockOpenAddress(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlockOpenAddress")); if (!yymatchChar(ctx, '<')) goto l1256; if (!yy_Spnl(ctx)) goto l1256; + { int yypos1257= ctx->pos, yythunkpos1257= ctx->thunkpos; if (!yymatchString(ctx, "address")) goto l1258; goto l1257; + l1258:; ctx->pos= yypos1257; ctx->thunkpos= yythunkpos1257; if (!yymatchString(ctx, "ADDRESS")) goto l1256; + } + l1257:; if (!yy_Spnl(ctx)) goto l1256; + l1259:; + { int yypos1260= ctx->pos, yythunkpos1260= ctx->thunkpos; if (!yy_HtmlAttribute(ctx)) goto l1260; goto l1259; + l1260:; ctx->pos= yypos1260; ctx->thunkpos= yythunkpos1260; + } if (!yymatchChar(ctx, '>')) goto l1256; + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlockOpenAddress", ctx->buf+ctx->pos)); + return 1; + l1256:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlockOpenAddress", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_OptionallyIndentedLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "OptionallyIndentedLine")); + { int yypos1262= ctx->pos, yythunkpos1262= ctx->thunkpos; if (!yy_Indent(ctx)) goto l1262; goto l1263; + l1262:; ctx->pos= yypos1262; ctx->thunkpos= yythunkpos1262; + } + l1263:; if (!yy_Line(ctx)) goto l1261; + yyprintf((stderr, " ok %s @ %s\n", "OptionallyIndentedLine", ctx->buf+ctx->pos)); + return 1; + l1261:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "OptionallyIndentedLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Indent(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Indent")); + { int yypos1265= ctx->pos, yythunkpos1265= ctx->thunkpos; if (!yymatchChar(ctx, '\t')) goto l1266; goto l1265; + l1266:; ctx->pos= yypos1265; ctx->thunkpos= yythunkpos1265; if (!yymatchString(ctx, " ")) goto l1264; + } + l1265:; + yyprintf((stderr, " ok %s @ %s\n", "Indent", ctx->buf+ctx->pos)); + return 1; + l1264:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Indent", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListBlockLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "ListBlockLine")); + { int yypos1268= ctx->pos, yythunkpos1268= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1268; goto l1267; + l1268:; ctx->pos= yypos1268; ctx->thunkpos= yythunkpos1268; + } + { int yypos1269= ctx->pos, yythunkpos1269= ctx->thunkpos; + { int yypos1270= ctx->pos, yythunkpos1270= ctx->thunkpos; if (!yy_Indent(ctx)) goto l1270; goto l1271; + l1270:; ctx->pos= yypos1270; ctx->thunkpos= yythunkpos1270; + } + l1271:; + { int yypos1272= ctx->pos, yythunkpos1272= ctx->thunkpos; if (!yy_Bullet(ctx)) goto l1273; goto l1272; + l1273:; ctx->pos= yypos1272; ctx->thunkpos= yythunkpos1272; if (!yy_Enumerator(ctx)) goto l1269; + } + l1272:; goto l1267; + l1269:; ctx->pos= yypos1269; ctx->thunkpos= yythunkpos1269; + } + { int yypos1274= ctx->pos, yythunkpos1274= ctx->thunkpos; if (!yy_HorizontalRule(ctx)) goto l1274; goto l1267; + l1274:; ctx->pos= yypos1274; ctx->thunkpos= yythunkpos1274; + } if (!yy_OptionallyIndentedLine(ctx)) goto l1267; + yyprintf((stderr, " ok %s @ %s\n", "ListBlockLine", ctx->buf+ctx->pos)); + return 1; + l1267:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListBlockLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListContinuationBlock(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "ListContinuationBlock")); if (!yy_StartList(ctx)) goto l1275; yyDo(ctx, yySet, -1, 0); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l1275; + l1276:; + { int yypos1277= ctx->pos, yythunkpos1277= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1277; goto l1276; + l1277:; ctx->pos= yypos1277; ctx->thunkpos= yythunkpos1277; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l1275; yyDo(ctx, yy_1_ListContinuationBlock, ctx->begin, ctx->end); if (!yy_Indent(ctx)) goto l1275; if (!yy_ListBlock(ctx)) goto l1275; yyDo(ctx, yy_2_ListContinuationBlock, ctx->begin, ctx->end); + l1278:; + { int yypos1279= ctx->pos, yythunkpos1279= ctx->thunkpos; if (!yy_Indent(ctx)) goto l1279; if (!yy_ListBlock(ctx)) goto l1279; yyDo(ctx, yy_2_ListContinuationBlock, ctx->begin, ctx->end); goto l1278; + l1279:; ctx->pos= yypos1279; ctx->thunkpos= yythunkpos1279; + } yyDo(ctx, yy_3_ListContinuationBlock, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ListContinuationBlock", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1275:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListContinuationBlock", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListBlock(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "ListBlock")); if (!yy_StartList(ctx)) goto l1280; yyDo(ctx, yySet, -1, 0); + { int yypos1281= ctx->pos, yythunkpos1281= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1281; goto l1280; + l1281:; ctx->pos= yypos1281; ctx->thunkpos= yythunkpos1281; + } if (!yy_Line(ctx)) goto l1280; yyDo(ctx, yy_1_ListBlock, ctx->begin, ctx->end); + l1282:; + { int yypos1283= ctx->pos, yythunkpos1283= ctx->thunkpos; if (!yy_ListBlockLine(ctx)) goto l1283; yyDo(ctx, yy_2_ListBlock, ctx->begin, ctx->end); goto l1282; + l1283:; ctx->pos= yypos1283; ctx->thunkpos= yythunkpos1283; + } yyDo(ctx, yy_3_ListBlock, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ListBlock", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1280:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListBlock", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListItem(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "ListItem")); + { int yypos1285= ctx->pos, yythunkpos1285= ctx->thunkpos; if (!yy_Bullet(ctx)) goto l1286; goto l1285; + l1286:; ctx->pos= yypos1285; ctx->thunkpos= yythunkpos1285; if (!yy_Enumerator(ctx)) goto l1284; + } + l1285:; if (!yy_StartList(ctx)) goto l1284; yyDo(ctx, yySet, -1, 0); if (!yy_ListBlock(ctx)) goto l1284; yyDo(ctx, yy_1_ListItem, ctx->begin, ctx->end); + l1287:; + { int yypos1288= ctx->pos, yythunkpos1288= ctx->thunkpos; if (!yy_ListContinuationBlock(ctx)) goto l1288; yyDo(ctx, yy_2_ListItem, ctx->begin, ctx->end); goto l1287; + l1288:; ctx->pos= yypos1288; ctx->thunkpos= yythunkpos1288; + } yyDo(ctx, yy_3_ListItem, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ListItem", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1284:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListItem", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Enumerator(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Enumerator")); if (!yy_NonindentSpace(ctx)) goto l1289; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l1289; + l1290:; + { int yypos1291= ctx->pos, yythunkpos1291= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l1291; goto l1290; + l1291:; ctx->pos= yypos1291; ctx->thunkpos= yythunkpos1291; + } if (!yymatchChar(ctx, '.')) goto l1289; if (!yy_Spacechar(ctx)) goto l1289; + l1292:; + { int yypos1293= ctx->pos, yythunkpos1293= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l1293; goto l1292; + l1293:; ctx->pos= yypos1293; ctx->thunkpos= yythunkpos1293; + } + yyprintf((stderr, " ok %s @ %s\n", "Enumerator", ctx->buf+ctx->pos)); + return 1; + l1289:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Enumerator", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListItemTight(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "ListItemTight")); + { int yypos1295= ctx->pos, yythunkpos1295= ctx->thunkpos; if (!yy_Bullet(ctx)) goto l1296; goto l1295; + l1296:; ctx->pos= yypos1295; ctx->thunkpos= yythunkpos1295; if (!yy_Enumerator(ctx)) goto l1294; + } + l1295:; if (!yy_StartList(ctx)) goto l1294; yyDo(ctx, yySet, -1, 0); if (!yy_ListBlock(ctx)) goto l1294; yyDo(ctx, yy_1_ListItemTight, ctx->begin, ctx->end); + l1297:; + { int yypos1298= ctx->pos, yythunkpos1298= ctx->thunkpos; + { int yypos1299= ctx->pos, yythunkpos1299= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1299; goto l1298; + l1299:; ctx->pos= yypos1299; ctx->thunkpos= yythunkpos1299; + } if (!yy_ListContinuationBlock(ctx)) goto l1298; yyDo(ctx, yy_2_ListItemTight, ctx->begin, ctx->end); goto l1297; + l1298:; ctx->pos= yypos1298; ctx->thunkpos= yythunkpos1298; + } + { int yypos1300= ctx->pos, yythunkpos1300= ctx->thunkpos; if (!yy_ListContinuationBlock(ctx)) goto l1300; goto l1294; + l1300:; ctx->pos= yypos1300; ctx->thunkpos= yythunkpos1300; + } yyDo(ctx, yy_3_ListItemTight, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ListItemTight", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1294:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListItemTight", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListLoose(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "ListLoose")); if (!yy_StartList(ctx)) goto l1301; yyDo(ctx, yySet, -2, 0); if (!yy_ListItem(ctx)) goto l1301; yyDo(ctx, yySet, -1, 0); + l1304:; + { int yypos1305= ctx->pos, yythunkpos1305= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1305; goto l1304; + l1305:; ctx->pos= yypos1305; ctx->thunkpos= yythunkpos1305; + } yyDo(ctx, yy_1_ListLoose, ctx->begin, ctx->end); + l1302:; + { int yypos1303= ctx->pos, yythunkpos1303= ctx->thunkpos; if (!yy_ListItem(ctx)) goto l1303; yyDo(ctx, yySet, -1, 0); + l1306:; + { int yypos1307= ctx->pos, yythunkpos1307= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1307; goto l1306; + l1307:; ctx->pos= yypos1307; ctx->thunkpos= yythunkpos1307; + } yyDo(ctx, yy_1_ListLoose, ctx->begin, ctx->end); goto l1302; + l1303:; ctx->pos= yypos1303; ctx->thunkpos= yythunkpos1303; + } yyDo(ctx, yy_2_ListLoose, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ListLoose", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l1301:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListLoose", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_ListTight(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "ListTight")); if (!yy_StartList(ctx)) goto l1308; yyDo(ctx, yySet, -1, 0); if (!yy_ListItemTight(ctx)) goto l1308; yyDo(ctx, yy_1_ListTight, ctx->begin, ctx->end); + l1309:; + { int yypos1310= ctx->pos, yythunkpos1310= ctx->thunkpos; if (!yy_ListItemTight(ctx)) goto l1310; yyDo(ctx, yy_1_ListTight, ctx->begin, ctx->end); goto l1309; + l1310:; ctx->pos= yypos1310; ctx->thunkpos= yythunkpos1310; + } + l1311:; + { int yypos1312= ctx->pos, yythunkpos1312= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1312; goto l1311; + l1312:; ctx->pos= yypos1312; ctx->thunkpos= yythunkpos1312; + } + { int yypos1313= ctx->pos, yythunkpos1313= ctx->thunkpos; + { int yypos1314= ctx->pos, yythunkpos1314= ctx->thunkpos; if (!yy_Bullet(ctx)) goto l1315; goto l1314; + l1315:; ctx->pos= yypos1314; ctx->thunkpos= yythunkpos1314; if (!yy_Enumerator(ctx)) goto l1313; + } + l1314:; goto l1308; + l1313:; ctx->pos= yypos1313; ctx->thunkpos= yythunkpos1313; + } yyDo(ctx, yy_2_ListTight, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "ListTight", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1308:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "ListTight", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Spacechar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Spacechar")); + { int yypos1317= ctx->pos, yythunkpos1317= ctx->thunkpos; if (!yymatchChar(ctx, ' ')) goto l1318; goto l1317; + l1318:; ctx->pos= yypos1317; ctx->thunkpos= yythunkpos1317; if (!yymatchChar(ctx, '\t')) goto l1316; + } + l1317:; + yyprintf((stderr, " ok %s @ %s\n", "Spacechar", ctx->buf+ctx->pos)); + return 1; + l1316:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Spacechar", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Bullet(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Bullet")); + { int yypos1320= ctx->pos, yythunkpos1320= ctx->thunkpos; if (!yy_HorizontalRule(ctx)) goto l1320; goto l1319; + l1320:; ctx->pos= yypos1320; ctx->thunkpos= yythunkpos1320; + } if (!yy_NonindentSpace(ctx)) goto l1319; + { int yypos1321= ctx->pos, yythunkpos1321= ctx->thunkpos; if (!yymatchChar(ctx, '+')) goto l1322; goto l1321; + l1322:; ctx->pos= yypos1321; ctx->thunkpos= yythunkpos1321; if (!yymatchChar(ctx, '*')) goto l1323; goto l1321; + l1323:; ctx->pos= yypos1321; ctx->thunkpos= yythunkpos1321; if (!yymatchChar(ctx, '-')) goto l1319; + } + l1321:; if (!yy_Spacechar(ctx)) goto l1319; + l1324:; + { int yypos1325= ctx->pos, yythunkpos1325= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l1325; goto l1324; + l1325:; ctx->pos= yypos1325; ctx->thunkpos= yythunkpos1325; + } + yyprintf((stderr, " ok %s @ %s\n", "Bullet", ctx->buf+ctx->pos)); + return 1; + l1319:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Bullet", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_VerbatimChunk(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "VerbatimChunk")); if (!yy_StartList(ctx)) goto l1326; yyDo(ctx, yySet, -1, 0); + l1327:; + { int yypos1328= ctx->pos, yythunkpos1328= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1328; yyDo(ctx, yy_1_VerbatimChunk, ctx->begin, ctx->end); goto l1327; + l1328:; ctx->pos= yypos1328; ctx->thunkpos= yythunkpos1328; + } if (!yy_NonblankIndentedLine(ctx)) goto l1326; yyDo(ctx, yy_2_VerbatimChunk, ctx->begin, ctx->end); + l1329:; + { int yypos1330= ctx->pos, yythunkpos1330= ctx->thunkpos; if (!yy_NonblankIndentedLine(ctx)) goto l1330; yyDo(ctx, yy_2_VerbatimChunk, ctx->begin, ctx->end); goto l1329; + l1330:; ctx->pos= yypos1330; ctx->thunkpos= yythunkpos1330; + } yyDo(ctx, yy_3_VerbatimChunk, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "VerbatimChunk", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1326:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "VerbatimChunk", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_IndentedLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "IndentedLine")); if (!yy_Indent(ctx)) goto l1331; if (!yy_Line(ctx)) goto l1331; + yyprintf((stderr, " ok %s @ %s\n", "IndentedLine", ctx->buf+ctx->pos)); + return 1; + l1331:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "IndentedLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_NonblankIndentedLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "NonblankIndentedLine")); + { int yypos1333= ctx->pos, yythunkpos1333= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1333; goto l1332; + l1333:; ctx->pos= yypos1333; ctx->thunkpos= yythunkpos1333; + } if (!yy_IndentedLine(ctx)) goto l1332; + yyprintf((stderr, " ok %s @ %s\n", "NonblankIndentedLine", ctx->buf+ctx->pos)); + return 1; + l1332:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "NonblankIndentedLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Line(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Line")); if (!yy_RawLine(ctx)) goto l1334; yyDo(ctx, yy_1_Line, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Line", ctx->buf+ctx->pos)); + return 1; + l1334:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Line", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BlockQuoteRaw(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "BlockQuoteRaw")); if (!yy_StartList(ctx)) goto l1335; yyDo(ctx, yySet, -1, 0); if (!yymatchChar(ctx, '>')) goto l1335; + { int yypos1338= ctx->pos, yythunkpos1338= ctx->thunkpos; if (!yymatchChar(ctx, ' ')) goto l1338; goto l1339; + l1338:; ctx->pos= yypos1338; ctx->thunkpos= yythunkpos1338; + } + l1339:; if (!yy_Line(ctx)) goto l1335; yyDo(ctx, yy_1_BlockQuoteRaw, ctx->begin, ctx->end); + l1340:; + { int yypos1341= ctx->pos, yythunkpos1341= ctx->thunkpos; + { int yypos1342= ctx->pos, yythunkpos1342= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l1342; goto l1341; + l1342:; ctx->pos= yypos1342; ctx->thunkpos= yythunkpos1342; + } + { int yypos1343= ctx->pos, yythunkpos1343= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1343; goto l1341; + l1343:; ctx->pos= yypos1343; ctx->thunkpos= yythunkpos1343; + } if (!yy_Line(ctx)) goto l1341; yyDo(ctx, yy_2_BlockQuoteRaw, ctx->begin, ctx->end); goto l1340; + l1341:; ctx->pos= yypos1341; ctx->thunkpos= yythunkpos1341; + } + l1344:; + { int yypos1345= ctx->pos, yythunkpos1345= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1345; yyDo(ctx, yy_3_BlockQuoteRaw, ctx->begin, ctx->end); goto l1344; + l1345:; ctx->pos= yypos1345; ctx->thunkpos= yythunkpos1345; + } + l1336:; + { int yypos1337= ctx->pos, yythunkpos1337= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l1337; + { int yypos1346= ctx->pos, yythunkpos1346= ctx->thunkpos; if (!yymatchChar(ctx, ' ')) goto l1346; goto l1347; + l1346:; ctx->pos= yypos1346; ctx->thunkpos= yythunkpos1346; + } + l1347:; if (!yy_Line(ctx)) goto l1337; yyDo(ctx, yy_1_BlockQuoteRaw, ctx->begin, ctx->end); + l1348:; + { int yypos1349= ctx->pos, yythunkpos1349= ctx->thunkpos; + { int yypos1350= ctx->pos, yythunkpos1350= ctx->thunkpos; if (!yymatchChar(ctx, '>')) goto l1350; goto l1349; + l1350:; ctx->pos= yypos1350; ctx->thunkpos= yythunkpos1350; + } + { int yypos1351= ctx->pos, yythunkpos1351= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1351; goto l1349; + l1351:; ctx->pos= yypos1351; ctx->thunkpos= yythunkpos1351; + } if (!yy_Line(ctx)) goto l1349; yyDo(ctx, yy_2_BlockQuoteRaw, ctx->begin, ctx->end); goto l1348; + l1349:; ctx->pos= yypos1349; ctx->thunkpos= yythunkpos1349; + } + l1352:; + { int yypos1353= ctx->pos, yythunkpos1353= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1353; yyDo(ctx, yy_3_BlockQuoteRaw, ctx->begin, ctx->end); goto l1352; + l1353:; ctx->pos= yypos1353; ctx->thunkpos= yythunkpos1353; + } goto l1336; + l1337:; ctx->pos= yypos1337; ctx->thunkpos= yythunkpos1337; + } yyDo(ctx, yy_4_BlockQuoteRaw, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "BlockQuoteRaw", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1335:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BlockQuoteRaw", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Endline(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Endline")); + { int yypos1355= ctx->pos, yythunkpos1355= ctx->thunkpos; if (!yy_LineBreak(ctx)) goto l1356; goto l1355; + l1356:; ctx->pos= yypos1355; ctx->thunkpos= yythunkpos1355; if (!yy_TerminalEndline(ctx)) goto l1357; goto l1355; + l1357:; ctx->pos= yypos1355; ctx->thunkpos= yythunkpos1355; if (!yy_NormalEndline(ctx)) goto l1354; + } + l1355:; + yyprintf((stderr, " ok %s @ %s\n", "Endline", ctx->buf+ctx->pos)); + return 1; + l1354:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Endline", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RawLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RawLine")); + { int yypos1359= ctx->pos, yythunkpos1359= ctx->thunkpos; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l1360; + l1361:; + { int yypos1362= ctx->pos, yythunkpos1362= ctx->thunkpos; + { int yypos1363= ctx->pos, yythunkpos1363= ctx->thunkpos; if (!yymatchChar(ctx, '\r')) goto l1363; goto l1362; + l1363:; ctx->pos= yypos1363; ctx->thunkpos= yythunkpos1363; + } + { int yypos1364= ctx->pos, yythunkpos1364= ctx->thunkpos; if (!yymatchChar(ctx, '\n')) goto l1364; goto l1362; + l1364:; ctx->pos= yypos1364; ctx->thunkpos= yythunkpos1364; + } if (!yymatchDot(ctx)) goto l1362; goto l1361; + l1362:; ctx->pos= yypos1362; ctx->thunkpos= yythunkpos1362; + } if (!yy_Newline(ctx)) goto l1360; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l1360; goto l1359; + l1360:; ctx->pos= yypos1359; ctx->thunkpos= yythunkpos1359; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l1358; if (!yymatchDot(ctx)) goto l1358; + l1365:; + { int yypos1366= ctx->pos, yythunkpos1366= ctx->thunkpos; if (!yymatchDot(ctx)) goto l1366; goto l1365; + l1366:; ctx->pos= yypos1366; ctx->thunkpos= yythunkpos1366; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l1358; if (!yy_Eof(ctx)) goto l1358; + } + l1359:; + yyprintf((stderr, " ok %s @ %s\n", "RawLine", ctx->buf+ctx->pos)); + return 1; + l1358:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RawLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SetextBottom2(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SetextBottom2")); if (!yymatchChar(ctx, '-')) goto l1367; + l1368:; + { int yypos1369= ctx->pos, yythunkpos1369= ctx->thunkpos; if (!yymatchChar(ctx, '-')) goto l1369; goto l1368; + l1369:; ctx->pos= yypos1369; ctx->thunkpos= yythunkpos1369; + } if (!yy_Newline(ctx)) goto l1367; + yyprintf((stderr, " ok %s @ %s\n", "SetextBottom2", ctx->buf+ctx->pos)); + return 1; + l1367:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SetextBottom2", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SetextBottom1(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SetextBottom1")); if (!yymatchChar(ctx, '=')) goto l1370; + l1371:; + { int yypos1372= ctx->pos, yythunkpos1372= ctx->thunkpos; if (!yymatchChar(ctx, '=')) goto l1372; goto l1371; + l1372:; ctx->pos= yypos1372; ctx->thunkpos= yythunkpos1372; + } if (!yy_Newline(ctx)) goto l1370; + yyprintf((stderr, " ok %s @ %s\n", "SetextBottom1", ctx->buf+ctx->pos)); + return 1; + l1370:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SetextBottom1", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SetextHeading2(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "SetextHeading2")); + { int yypos1374= ctx->pos, yythunkpos1374= ctx->thunkpos; if (!yy_RawLine(ctx)) goto l1373; if (!yy_SetextBottom2(ctx)) goto l1373; ctx->pos= yypos1374; ctx->thunkpos= yythunkpos1374; + } if (!yy_StartList(ctx)) goto l1373; yyDo(ctx, yySet, -1, 0); + { int yypos1377= ctx->pos, yythunkpos1377= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1377; goto l1373; + l1377:; ctx->pos= yypos1377; ctx->thunkpos= yythunkpos1377; + } if (!yy_Inline(ctx)) goto l1373; yyDo(ctx, yy_1_SetextHeading2, ctx->begin, ctx->end); + l1375:; + { int yypos1376= ctx->pos, yythunkpos1376= ctx->thunkpos; + { int yypos1378= ctx->pos, yythunkpos1378= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1378; goto l1376; + l1378:; ctx->pos= yypos1378; ctx->thunkpos= yythunkpos1378; + } if (!yy_Inline(ctx)) goto l1376; yyDo(ctx, yy_1_SetextHeading2, ctx->begin, ctx->end); goto l1375; + l1376:; ctx->pos= yypos1376; ctx->thunkpos= yythunkpos1376; + } + { int yypos1379= ctx->pos, yythunkpos1379= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1379; goto l1380; + l1379:; ctx->pos= yypos1379; ctx->thunkpos= yythunkpos1379; + } + l1380:; if (!yy_Newline(ctx)) goto l1373; if (!yy_SetextBottom2(ctx)) goto l1373; yyDo(ctx, yy_2_SetextHeading2, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "SetextHeading2", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1373:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SetextHeading2", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SetextHeading1(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "SetextHeading1")); + { int yypos1382= ctx->pos, yythunkpos1382= ctx->thunkpos; if (!yy_RawLine(ctx)) goto l1381; if (!yy_SetextBottom1(ctx)) goto l1381; ctx->pos= yypos1382; ctx->thunkpos= yythunkpos1382; + } if (!yy_StartList(ctx)) goto l1381; yyDo(ctx, yySet, -1, 0); + { int yypos1385= ctx->pos, yythunkpos1385= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1385; goto l1381; + l1385:; ctx->pos= yypos1385; ctx->thunkpos= yythunkpos1385; + } if (!yy_Inline(ctx)) goto l1381; yyDo(ctx, yy_1_SetextHeading1, ctx->begin, ctx->end); + l1383:; + { int yypos1384= ctx->pos, yythunkpos1384= ctx->thunkpos; + { int yypos1386= ctx->pos, yythunkpos1386= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1386; goto l1384; + l1386:; ctx->pos= yypos1386; ctx->thunkpos= yythunkpos1386; + } if (!yy_Inline(ctx)) goto l1384; yyDo(ctx, yy_1_SetextHeading1, ctx->begin, ctx->end); goto l1383; + l1384:; ctx->pos= yypos1384; ctx->thunkpos= yythunkpos1384; + } + { int yypos1387= ctx->pos, yythunkpos1387= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1387; goto l1388; + l1387:; ctx->pos= yypos1387; ctx->thunkpos= yythunkpos1387; + } + l1388:; if (!yy_Newline(ctx)) goto l1381; if (!yy_SetextBottom1(ctx)) goto l1381; yyDo(ctx, yy_2_SetextHeading1, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "SetextHeading1", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1381:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SetextHeading1", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SetextHeading(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SetextHeading")); + { int yypos1390= ctx->pos, yythunkpos1390= ctx->thunkpos; if (!yy_SetextHeading1(ctx)) goto l1391; goto l1390; + l1391:; ctx->pos= yypos1390; ctx->thunkpos= yythunkpos1390; if (!yy_SetextHeading2(ctx)) goto l1389; + } + l1390:; + yyprintf((stderr, " ok %s @ %s\n", "SetextHeading", ctx->buf+ctx->pos)); + return 1; + l1389:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SetextHeading", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AtxHeading(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "AtxHeading")); if (!yy_AtxStart(ctx)) goto l1392; yyDo(ctx, yySet, -2, 0); + { int yypos1393= ctx->pos, yythunkpos1393= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1393; goto l1394; + l1393:; ctx->pos= yypos1393; ctx->thunkpos= yythunkpos1393; + } + l1394:; if (!yy_StartList(ctx)) goto l1392; yyDo(ctx, yySet, -1, 0); if (!yy_AtxInline(ctx)) goto l1392; yyDo(ctx, yy_1_AtxHeading, ctx->begin, ctx->end); + l1395:; + { int yypos1396= ctx->pos, yythunkpos1396= ctx->thunkpos; if (!yy_AtxInline(ctx)) goto l1396; yyDo(ctx, yy_1_AtxHeading, ctx->begin, ctx->end); goto l1395; + l1396:; ctx->pos= yypos1396; ctx->thunkpos= yythunkpos1396; + } + { int yypos1397= ctx->pos, yythunkpos1397= ctx->thunkpos; + { int yypos1399= ctx->pos, yythunkpos1399= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1399; goto l1400; + l1399:; ctx->pos= yypos1399; ctx->thunkpos= yythunkpos1399; + } + l1400:; + l1401:; + { int yypos1402= ctx->pos, yythunkpos1402= ctx->thunkpos; if (!yymatchChar(ctx, '#')) goto l1402; goto l1401; + l1402:; ctx->pos= yypos1402; ctx->thunkpos= yythunkpos1402; + } if (!yy_Sp(ctx)) goto l1397; goto l1398; + l1397:; ctx->pos= yypos1397; ctx->thunkpos= yythunkpos1397; + } + l1398:; if (!yy_Newline(ctx)) goto l1392; yyDo(ctx, yy_2_AtxHeading, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "AtxHeading", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l1392:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AtxHeading", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AtxStart(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AtxStart")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l1403; + { int yypos1404= ctx->pos, yythunkpos1404= ctx->thunkpos; if (!yymatchString(ctx, "######")) goto l1405; goto l1404; + l1405:; ctx->pos= yypos1404; ctx->thunkpos= yythunkpos1404; if (!yymatchString(ctx, "#####")) goto l1406; goto l1404; + l1406:; ctx->pos= yypos1404; ctx->thunkpos= yythunkpos1404; if (!yymatchString(ctx, "####")) goto l1407; goto l1404; + l1407:; ctx->pos= yypos1404; ctx->thunkpos= yythunkpos1404; if (!yymatchString(ctx, "###")) goto l1408; goto l1404; + l1408:; ctx->pos= yypos1404; ctx->thunkpos= yythunkpos1404; if (!yymatchString(ctx, "##")) goto l1409; goto l1404; + l1409:; ctx->pos= yypos1404; ctx->thunkpos= yythunkpos1404; if (!yymatchChar(ctx, '#')) goto l1403; + } + l1404:; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l1403; yyDo(ctx, yy_1_AtxStart, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "AtxStart", ctx->buf+ctx->pos)); + return 1; + l1403:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AtxStart", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Inline(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Inline")); + { int yypos1411= ctx->pos, yythunkpos1411= ctx->thunkpos; if (!yy_Str(ctx)) goto l1412; goto l1411; + l1412:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Endline(ctx)) goto l1413; goto l1411; + l1413:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_UlOrStarLine(ctx)) goto l1414; goto l1411; + l1414:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Space(ctx)) goto l1415; goto l1411; + l1415:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Strong(ctx)) goto l1416; goto l1411; + l1416:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Emph(ctx)) goto l1417; goto l1411; + l1417:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Image(ctx)) goto l1418; goto l1411; + l1418:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Link(ctx)) goto l1419; goto l1411; + l1419:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_NoteReference(ctx)) goto l1420; goto l1411; + l1420:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_InlineNote(ctx)) goto l1421; goto l1411; + l1421:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Code(ctx)) goto l1422; goto l1411; + l1422:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_RawHtml(ctx)) goto l1423; goto l1411; + l1423:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Entity(ctx)) goto l1424; goto l1411; + l1424:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_EscapedChar(ctx)) goto l1425; goto l1411; + l1425:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Smart(ctx)) goto l1426; goto l1411; + l1426:; ctx->pos= yypos1411; ctx->thunkpos= yythunkpos1411; if (!yy_Symbol(ctx)) goto l1410; + } + l1411:; + yyprintf((stderr, " ok %s @ %s\n", "Inline", ctx->buf+ctx->pos)); + return 1; + l1410:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Inline", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Sp(yycontext *ctx) +{ + yyprintf((stderr, "%s\n", "Sp")); + l1428:; + { int yypos1429= ctx->pos, yythunkpos1429= ctx->thunkpos; if (!yy_Spacechar(ctx)) goto l1429; goto l1428; + l1429:; ctx->pos= yypos1429; ctx->thunkpos= yythunkpos1429; + } + yyprintf((stderr, " ok %s @ %s\n", "Sp", ctx->buf+ctx->pos)); + return 1; +} +YY_RULE(int) yy_Newline(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Newline")); + { int yypos1431= ctx->pos, yythunkpos1431= ctx->thunkpos; if (!yymatchChar(ctx, '\n')) goto l1432; goto l1431; + l1432:; ctx->pos= yypos1431; ctx->thunkpos= yythunkpos1431; if (!yymatchChar(ctx, '\r')) goto l1430; + { int yypos1433= ctx->pos, yythunkpos1433= ctx->thunkpos; if (!yymatchChar(ctx, '\n')) goto l1433; goto l1434; + l1433:; ctx->pos= yypos1433; ctx->thunkpos= yythunkpos1433; + } + l1434:; + } + l1431:; + yyprintf((stderr, " ok %s @ %s\n", "Newline", ctx->buf+ctx->pos)); + return 1; + l1430:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Newline", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AtxInline(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AtxInline")); + { int yypos1436= ctx->pos, yythunkpos1436= ctx->thunkpos; if (!yy_Newline(ctx)) goto l1436; goto l1435; + l1436:; ctx->pos= yypos1436; ctx->thunkpos= yythunkpos1436; + } + { int yypos1437= ctx->pos, yythunkpos1437= ctx->thunkpos; + { int yypos1438= ctx->pos, yythunkpos1438= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1438; goto l1439; + l1438:; ctx->pos= yypos1438; ctx->thunkpos= yythunkpos1438; + } + l1439:; + l1440:; + { int yypos1441= ctx->pos, yythunkpos1441= ctx->thunkpos; if (!yymatchChar(ctx, '#')) goto l1441; goto l1440; + l1441:; ctx->pos= yypos1441; ctx->thunkpos= yythunkpos1441; + } if (!yy_Sp(ctx)) goto l1437; if (!yy_Newline(ctx)) goto l1437; goto l1435; + l1437:; ctx->pos= yypos1437; ctx->thunkpos= yythunkpos1437; + } if (!yy_Inline(ctx)) goto l1435; + yyprintf((stderr, " ok %s @ %s\n", "AtxInline", ctx->buf+ctx->pos)); + return 1; + l1435:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AtxInline", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Inlines(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "Inlines")); if (!yy_StartList(ctx)) goto l1442; yyDo(ctx, yySet, -2, 0); + { int yypos1445= ctx->pos, yythunkpos1445= ctx->thunkpos; + { int yypos1447= ctx->pos, yythunkpos1447= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1447; goto l1446; + l1447:; ctx->pos= yypos1447; ctx->thunkpos= yythunkpos1447; + } if (!yy_Inline(ctx)) goto l1446; yyDo(ctx, yy_1_Inlines, ctx->begin, ctx->end); goto l1445; + l1446:; ctx->pos= yypos1445; ctx->thunkpos= yythunkpos1445; if (!yy_Endline(ctx)) goto l1442; yyDo(ctx, yySet, -1, 0); + { int yypos1448= ctx->pos, yythunkpos1448= ctx->thunkpos; if (!yy_Inline(ctx)) goto l1442; ctx->pos= yypos1448; ctx->thunkpos= yythunkpos1448; + } yyDo(ctx, yy_2_Inlines, ctx->begin, ctx->end); + } + l1445:; + l1443:; + { int yypos1444= ctx->pos, yythunkpos1444= ctx->thunkpos; + { int yypos1449= ctx->pos, yythunkpos1449= ctx->thunkpos; + { int yypos1451= ctx->pos, yythunkpos1451= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1451; goto l1450; + l1451:; ctx->pos= yypos1451; ctx->thunkpos= yythunkpos1451; + } if (!yy_Inline(ctx)) goto l1450; yyDo(ctx, yy_1_Inlines, ctx->begin, ctx->end); goto l1449; + l1450:; ctx->pos= yypos1449; ctx->thunkpos= yythunkpos1449; if (!yy_Endline(ctx)) goto l1444; yyDo(ctx, yySet, -1, 0); + { int yypos1452= ctx->pos, yythunkpos1452= ctx->thunkpos; if (!yy_Inline(ctx)) goto l1444; ctx->pos= yypos1452; ctx->thunkpos= yythunkpos1452; + } yyDo(ctx, yy_2_Inlines, ctx->begin, ctx->end); + } + l1449:; goto l1443; + l1444:; ctx->pos= yypos1444; ctx->thunkpos= yythunkpos1444; + } + { int yypos1453= ctx->pos, yythunkpos1453= ctx->thunkpos; if (!yy_Endline(ctx)) goto l1453; goto l1454; + l1453:; ctx->pos= yypos1453; ctx->thunkpos= yythunkpos1453; + } + l1454:; yyDo(ctx, yy_3_Inlines, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Inlines", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l1442:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Inlines", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_NonindentSpace(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "NonindentSpace")); + { int yypos1456= ctx->pos, yythunkpos1456= ctx->thunkpos; if (!yymatchString(ctx, " ")) goto l1457; goto l1456; + l1457:; ctx->pos= yypos1456; ctx->thunkpos= yythunkpos1456; if (!yymatchString(ctx, " ")) goto l1458; goto l1456; + l1458:; ctx->pos= yypos1456; ctx->thunkpos= yythunkpos1456; if (!yymatchChar(ctx, ' ')) goto l1459; goto l1456; + l1459:; ctx->pos= yypos1456; ctx->thunkpos= yythunkpos1456; if (!yymatchString(ctx, "")) goto l1455; + } + l1456:; + yyprintf((stderr, " ok %s @ %s\n", "NonindentSpace", ctx->buf+ctx->pos)); + return 1; + l1455:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "NonindentSpace", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Plain(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "Plain")); if (!yy_Inlines(ctx)) goto l1460; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_Plain, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Plain", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1460:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Plain", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Para(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "Para")); if (!yy_NonindentSpace(ctx)) goto l1461; if (!yy_Inlines(ctx)) goto l1461; yyDo(ctx, yySet, -1, 0); if (!yy_BlankLine(ctx)) goto l1461; + l1462:; + { int yypos1463= ctx->pos, yythunkpos1463= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1463; goto l1462; + l1463:; ctx->pos= yypos1463; ctx->thunkpos= yythunkpos1463; + } yyDo(ctx, yy_1_Para, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Para", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1461:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Para", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StyleBlock(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "StyleBlock")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l1464; if (!yy_InStyleTags(ctx)) goto l1464; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l1464; + l1465:; + { int yypos1466= ctx->pos, yythunkpos1466= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1466; goto l1465; + l1466:; ctx->pos= yypos1466; ctx->thunkpos= yythunkpos1466; + } yyDo(ctx, yy_1_StyleBlock, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "StyleBlock", ctx->buf+ctx->pos)); + return 1; + l1464:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StyleBlock", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HtmlBlock(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HtmlBlock")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l1467; + { int yypos1468= ctx->pos, yythunkpos1468= ctx->thunkpos; if (!yy_HtmlBlockInTags(ctx)) goto l1469; goto l1468; + l1469:; ctx->pos= yypos1468; ctx->thunkpos= yythunkpos1468; if (!yy_HtmlComment(ctx)) goto l1470; goto l1468; + l1470:; ctx->pos= yypos1468; ctx->thunkpos= yythunkpos1468; if (!yy_HtmlBlockSelfClosing(ctx)) goto l1467; + } + l1468:; yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l1467; if (!yy_BlankLine(ctx)) goto l1467; + l1471:; + { int yypos1472= ctx->pos, yythunkpos1472= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1472; goto l1471; + l1472:; ctx->pos= yypos1472; ctx->thunkpos= yythunkpos1472; + } yyDo(ctx, yy_1_HtmlBlock, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "HtmlBlock", ctx->buf+ctx->pos)); + return 1; + l1467:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HtmlBlock", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BulletList(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "BulletList")); + { int yypos1474= ctx->pos, yythunkpos1474= ctx->thunkpos; if (!yy_Bullet(ctx)) goto l1473; ctx->pos= yypos1474; ctx->thunkpos= yythunkpos1474; + } + { int yypos1475= ctx->pos, yythunkpos1475= ctx->thunkpos; if (!yy_ListTight(ctx)) goto l1476; goto l1475; + l1476:; ctx->pos= yypos1475; ctx->thunkpos= yythunkpos1475; if (!yy_ListLoose(ctx)) goto l1473; + } + l1475:; yyDo(ctx, yy_1_BulletList, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "BulletList", ctx->buf+ctx->pos)); + return 1; + l1473:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BulletList", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_OrderedList(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "OrderedList")); + { int yypos1478= ctx->pos, yythunkpos1478= ctx->thunkpos; if (!yy_Enumerator(ctx)) goto l1477; ctx->pos= yypos1478; ctx->thunkpos= yythunkpos1478; + } + { int yypos1479= ctx->pos, yythunkpos1479= ctx->thunkpos; if (!yy_ListTight(ctx)) goto l1480; goto l1479; + l1480:; ctx->pos= yypos1479; ctx->thunkpos= yythunkpos1479; if (!yy_ListLoose(ctx)) goto l1477; + } + l1479:; yyDo(ctx, yy_1_OrderedList, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "OrderedList", ctx->buf+ctx->pos)); + return 1; + l1477:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "OrderedList", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Heading(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Heading")); + { int yypos1482= ctx->pos, yythunkpos1482= ctx->thunkpos; if (!yy_SetextHeading(ctx)) goto l1483; goto l1482; + l1483:; ctx->pos= yypos1482; ctx->thunkpos= yythunkpos1482; if (!yy_AtxHeading(ctx)) goto l1481; + } + l1482:; + yyprintf((stderr, " ok %s @ %s\n", "Heading", ctx->buf+ctx->pos)); + return 1; + l1481:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Heading", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_HorizontalRule(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "HorizontalRule")); if (!yy_NonindentSpace(ctx)) goto l1484; + { int yypos1485= ctx->pos, yythunkpos1485= ctx->thunkpos; if (!yymatchChar(ctx, '*')) goto l1486; if (!yy_Sp(ctx)) goto l1486; if (!yymatchChar(ctx, '*')) goto l1486; if (!yy_Sp(ctx)) goto l1486; if (!yymatchChar(ctx, '*')) goto l1486; + l1487:; + { int yypos1488= ctx->pos, yythunkpos1488= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1488; if (!yymatchChar(ctx, '*')) goto l1488; goto l1487; + l1488:; ctx->pos= yypos1488; ctx->thunkpos= yythunkpos1488; + } goto l1485; + l1486:; ctx->pos= yypos1485; ctx->thunkpos= yythunkpos1485; if (!yymatchChar(ctx, '-')) goto l1489; if (!yy_Sp(ctx)) goto l1489; if (!yymatchChar(ctx, '-')) goto l1489; if (!yy_Sp(ctx)) goto l1489; if (!yymatchChar(ctx, '-')) goto l1489; + l1490:; + { int yypos1491= ctx->pos, yythunkpos1491= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1491; if (!yymatchChar(ctx, '-')) goto l1491; goto l1490; + l1491:; ctx->pos= yypos1491; ctx->thunkpos= yythunkpos1491; + } goto l1485; + l1489:; ctx->pos= yypos1485; ctx->thunkpos= yythunkpos1485; if (!yymatchChar(ctx, '_')) goto l1484; if (!yy_Sp(ctx)) goto l1484; if (!yymatchChar(ctx, '_')) goto l1484; if (!yy_Sp(ctx)) goto l1484; if (!yymatchChar(ctx, '_')) goto l1484; + l1492:; + { int yypos1493= ctx->pos, yythunkpos1493= ctx->thunkpos; if (!yy_Sp(ctx)) goto l1493; if (!yymatchChar(ctx, '_')) goto l1493; goto l1492; + l1493:; ctx->pos= yypos1493; ctx->thunkpos= yythunkpos1493; + } + } + l1485:; if (!yy_Sp(ctx)) goto l1484; if (!yy_Newline(ctx)) goto l1484; if (!yy_BlankLine(ctx)) goto l1484; + l1494:; + { int yypos1495= ctx->pos, yythunkpos1495= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1495; goto l1494; + l1495:; ctx->pos= yypos1495; ctx->thunkpos= yythunkpos1495; + } yyDo(ctx, yy_1_HorizontalRule, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "HorizontalRule", ctx->buf+ctx->pos)); + return 1; + l1484:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "HorizontalRule", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Reference(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 3, 0); + yyprintf((stderr, "%s\n", "Reference")); if (!yy_NonindentSpace(ctx)) goto l1496; + { int yypos1497= ctx->pos, yythunkpos1497= ctx->thunkpos; if (!yymatchString(ctx, "[]")) goto l1497; goto l1496; + l1497:; ctx->pos= yypos1497; ctx->thunkpos= yythunkpos1497; + } if (!yy_Label(ctx)) goto l1496; yyDo(ctx, yySet, -3, 0); if (!yymatchChar(ctx, ':')) goto l1496; if (!yy_Spnl(ctx)) goto l1496; if (!yy_RefSrc(ctx)) goto l1496; yyDo(ctx, yySet, -2, 0); if (!yy_RefTitle(ctx)) goto l1496; yyDo(ctx, yySet, -1, 0); if (!yy_BlankLine(ctx)) goto l1496; + l1498:; + { int yypos1499= ctx->pos, yythunkpos1499= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1499; goto l1498; + l1499:; ctx->pos= yypos1499; ctx->thunkpos= yythunkpos1499; + } yyDo(ctx, yy_1_Reference, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Reference", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 3, 0); + return 1; + l1496:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Reference", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Note(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 2, 0); + yyprintf((stderr, "%s\n", "Note")); yyText(ctx, ctx->begin, ctx->end); if (!( extension(EXT_NOTES) )) goto l1500; if (!yy_NonindentSpace(ctx)) goto l1500; if (!yy_RawNoteReference(ctx)) goto l1500; yyDo(ctx, yySet, -2, 0); if (!yymatchChar(ctx, ':')) goto l1500; if (!yy_Sp(ctx)) goto l1500; if (!yy_StartList(ctx)) goto l1500; yyDo(ctx, yySet, -1, 0); if (!yy_RawNoteBlock(ctx)) goto l1500; yyDo(ctx, yy_1_Note, ctx->begin, ctx->end); + l1501:; + { int yypos1502= ctx->pos, yythunkpos1502= ctx->thunkpos; + { int yypos1503= ctx->pos, yythunkpos1503= ctx->thunkpos; if (!yy_Indent(ctx)) goto l1502; ctx->pos= yypos1503; ctx->thunkpos= yythunkpos1503; + } if (!yy_RawNoteBlock(ctx)) goto l1502; yyDo(ctx, yy_2_Note, ctx->begin, ctx->end); goto l1501; + l1502:; ctx->pos= yypos1502; ctx->thunkpos= yythunkpos1502; + } yyDo(ctx, yy_3_Note, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Note", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 2, 0); + return 1; + l1500:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Note", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Verbatim(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "Verbatim")); if (!yy_StartList(ctx)) goto l1504; yyDo(ctx, yySet, -1, 0); if (!yy_VerbatimChunk(ctx)) goto l1504; yyDo(ctx, yy_1_Verbatim, ctx->begin, ctx->end); + l1505:; + { int yypos1506= ctx->pos, yythunkpos1506= ctx->thunkpos; if (!yy_VerbatimChunk(ctx)) goto l1506; yyDo(ctx, yy_1_Verbatim, ctx->begin, ctx->end); goto l1505; + l1506:; ctx->pos= yypos1506; ctx->thunkpos= yythunkpos1506; + } yyDo(ctx, yy_2_Verbatim, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Verbatim", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1504:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Verbatim", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BlockQuote(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "BlockQuote")); if (!yy_BlockQuoteRaw(ctx)) goto l1507; yyDo(ctx, yySet, -1, 0); yyDo(ctx, yy_1_BlockQuote, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "BlockQuote", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1507:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BlockQuote", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BlankLine(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "BlankLine")); if (!yy_Sp(ctx)) goto l1508; if (!yy_Newline(ctx)) goto l1508; + yyprintf((stderr, " ok %s @ %s\n", "BlankLine", ctx->buf+ctx->pos)); + return 1; + l1508:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BlankLine", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Block(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "Block")); + l1510:; + { int yypos1511= ctx->pos, yythunkpos1511= ctx->thunkpos; if (!yy_BlankLine(ctx)) goto l1511; goto l1510; + l1511:; ctx->pos= yypos1511; ctx->thunkpos= yythunkpos1511; + } + { int yypos1512= ctx->pos, yythunkpos1512= ctx->thunkpos; if (!yy_BlockQuote(ctx)) goto l1513; goto l1512; + l1513:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_Verbatim(ctx)) goto l1514; goto l1512; + l1514:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_Note(ctx)) goto l1515; goto l1512; + l1515:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_Reference(ctx)) goto l1516; goto l1512; + l1516:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_HorizontalRule(ctx)) goto l1517; goto l1512; + l1517:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_Heading(ctx)) goto l1518; goto l1512; + l1518:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_OrderedList(ctx)) goto l1519; goto l1512; + l1519:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_BulletList(ctx)) goto l1520; goto l1512; + l1520:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_HtmlBlock(ctx)) goto l1521; goto l1512; + l1521:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_StyleBlock(ctx)) goto l1522; goto l1512; + l1522:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_Para(ctx)) goto l1523; goto l1512; + l1523:; ctx->pos= yypos1512; ctx->thunkpos= yythunkpos1512; if (!yy_Plain(ctx)) goto l1509; + } + l1512:; + yyprintf((stderr, " ok %s @ %s\n", "Block", ctx->buf+ctx->pos)); + return 1; + l1509:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Block", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_StartList(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "StartList")); + { int yypos1525= ctx->pos, yythunkpos1525= ctx->thunkpos; if (!yymatchDot(ctx)) goto l1524; ctx->pos= yypos1525; ctx->thunkpos= yythunkpos1525; + } yyDo(ctx, yy_1_StartList, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "StartList", ctx->buf+ctx->pos)); + return 1; + l1524:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "StartList", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BOM(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "BOM")); if (!yymatchString(ctx, "\357\273\277")) goto l1526; + yyprintf((stderr, " ok %s @ %s\n", "BOM", ctx->buf+ctx->pos)); + return 1; + l1526:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BOM", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_Doc(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; yyDo(ctx, yyPush, 1, 0); + yyprintf((stderr, "%s\n", "Doc")); + { int yypos1528= ctx->pos, yythunkpos1528= ctx->thunkpos; if (!yy_BOM(ctx)) goto l1528; goto l1529; + l1528:; ctx->pos= yypos1528; ctx->thunkpos= yythunkpos1528; + } + l1529:; if (!yy_StartList(ctx)) goto l1527; yyDo(ctx, yySet, -1, 0); + l1530:; + { int yypos1531= ctx->pos, yythunkpos1531= ctx->thunkpos; if (!yy_Block(ctx)) goto l1531; yyDo(ctx, yy_1_Doc, ctx->begin, ctx->end); goto l1530; + l1531:; ctx->pos= yypos1531; ctx->thunkpos= yythunkpos1531; + } yyDo(ctx, yy_2_Doc, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "Doc", ctx->buf+ctx->pos)); yyDo(ctx, yyPop, 1, 0); + return 1; + l1527:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "Doc", ctx->buf+ctx->pos)); + return 0; +} + +#ifndef YY_PART + +typedef int (*yyrule)(yycontext *ctx); + +YY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart) +{ + int yyok; + if (!yyctx->buflen) + { + yyctx->buflen= 1024; + yyctx->buf= (char *)malloc(yyctx->buflen); + yyctx->textlen= 1024; + yyctx->text= (char *)malloc(yyctx->textlen); + yyctx->thunkslen= 32; + yyctx->thunks= (yythunk *)malloc(sizeof(yythunk) * yyctx->thunkslen); + yyctx->valslen= 32; + yyctx->vals= (YYSTYPE *)malloc(sizeof(YYSTYPE) * yyctx->valslen); + yyctx->begin= yyctx->end= yyctx->pos= yyctx->limit= yyctx->thunkpos= 0; + } + yyctx->begin= yyctx->end= yyctx->pos; + yyctx->thunkpos= 0; + yyctx->val= yyctx->vals; + yyok= yystart(yyctx); + if (yyok) yyDone(yyctx); + yyCommit(yyctx); + return yyok; +} + +YY_PARSE(int) YYPARSE(YY_CTX_PARAM) +{ + return YYPARSEFROM(YY_CTX_ARG_ yy_Doc); +} + +#endif + + + + diff --git a/supportlibs/pegmarkdown/markdown_parser.leg b/supportlibs/pegmarkdown/markdown_parser.leg new file mode 100644 index 000000000..cd1fc0b36 --- /dev/null +++ b/supportlibs/pegmarkdown/markdown_parser.leg @@ -0,0 +1,770 @@ +%{ +/********************************************************************** + + markdown_parser.leg - markdown parser in C using a PEG grammar. + (c) 2008 John MacFarlane (jgm at berkeley dot edu). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License or the MIT + license. See LICENSE for details. + + 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. + + ***********************************************************************/ + +#include +#include +#include "markdown_peg.h" +#include "utility_functions.h" + + + +/********************************************************************** + + Definitions for leg parser generator. + YY_INPUT is the function the parser calls to get new input. + We take all new input from (static) charbuf. + + ***********************************************************************/ + + + +# define YYSTYPE element * +#ifdef __DEBUG__ +# define YY_DEBUG 1 +#endif + +#define YY_INPUT(buf, result, max_size) \ +{ \ + int yyc; \ + if (charbuf && *charbuf != '\0') { \ + yyc= *charbuf++; \ + } else { \ + yyc= EOF; \ + } \ + result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ +} + +#define YY_RULE(T) T + + +/********************************************************************** + + PEG grammar and parser actions for markdown syntax. + + ***********************************************************************/ + +%} + +Doc = BOM? a:StartList ( Block { a = cons($$, a); } )* + { parse_result = reverse(a); } + +Block = BlankLine* + ( BlockQuote + | Verbatim + | Note + | Reference + | HorizontalRule + | Heading + | OrderedList + | BulletList + | HtmlBlock + | StyleBlock + | Para + | Plain ) + +Para = NonindentSpace a:Inlines BlankLine+ + { $$ = a; $$->key = PARA; } + +Plain = a:Inlines + { $$ = a; $$->key = PLAIN; } + +AtxInline = !Newline !(Sp? '#'* Sp Newline) Inline + +AtxStart = < ( "######" | "#####" | "####" | "###" | "##" | "#" ) > + { $$ = mk_element(H1 + (strlen(yytext) - 1)); } + +AtxHeading = s:AtxStart Sp? a:StartList ( AtxInline { a = cons($$, a); } )+ (Sp? '#'* Sp)? Newline + { $$ = mk_list(s->key, a); + free(s); } + +SetextHeading = SetextHeading1 | SetextHeading2 + +SetextBottom1 = '='+ Newline + +SetextBottom2 = '-'+ Newline + +SetextHeading1 = &(RawLine SetextBottom1) + a:StartList ( !Endline Inline { a = cons($$, a); } )+ Sp? Newline + SetextBottom1 { $$ = mk_list(H1, a); } + +SetextHeading2 = &(RawLine SetextBottom2) + a:StartList ( !Endline Inline { a = cons($$, a); } )+ Sp? Newline + SetextBottom2 { $$ = mk_list(H2, a); } + +Heading = SetextHeading | AtxHeading + +BlockQuote = a:BlockQuoteRaw + { $$ = mk_element(BLOCKQUOTE); + $$->children = a; + } + +BlockQuoteRaw = a:StartList + (( '>' ' '? Line { a = cons($$, a); } ) + ( !'>' !BlankLine Line { a = cons($$, a); } )* + ( BlankLine { a = cons(mk_str("\n"), a); } )* + )+ + { $$ = mk_str_from_list(a, true); + $$->key = RAW; + } + +NonblankIndentedLine = !BlankLine IndentedLine + +VerbatimChunk = a:StartList + ( BlankLine { a = cons(mk_str("\n"), a); } )* + ( NonblankIndentedLine { a = cons($$, a); } )+ + { $$ = mk_str_from_list(a, false); } + +Verbatim = a:StartList ( VerbatimChunk { a = cons($$, a); } )+ + { $$ = mk_str_from_list(a, false); + $$->key = VERBATIM; } + +HorizontalRule = NonindentSpace + ( '*' Sp '*' Sp '*' (Sp '*')* + | '-' Sp '-' Sp '-' (Sp '-')* + | '_' Sp '_' Sp '_' (Sp '_')*) + Sp Newline BlankLine+ + { $$ = mk_element(HRULE); } + +Bullet = !HorizontalRule NonindentSpace ('+' | '*' | '-') Spacechar+ + +BulletList = &Bullet (ListTight | ListLoose) + { $$->key = BULLETLIST; } + +ListTight = a:StartList + ( ListItemTight { a = cons($$, a); } )+ + BlankLine* !(Bullet | Enumerator) + { $$ = mk_list(LIST, a); } + +ListLoose = a:StartList + ( b:ListItem BlankLine* + { element *li; + li = b->children; + li->contents.str = realloc(li->contents.str, strlen(li->contents.str) + 3); + strcat(li->contents.str, "\n\n"); /* In loose list, \n\n added to end of each element */ + a = cons(b, a); + } )+ + { $$ = mk_list(LIST, a); } + +ListItem = ( Bullet | Enumerator ) + a:StartList + ListBlock { a = cons($$, a); } + ( ListContinuationBlock { a = cons($$, a); } )* + { element *raw; + raw = mk_str_from_list(a, false); + raw->key = RAW; + $$ = mk_element(LISTITEM); + $$->children = raw; + } + +ListItemTight = + ( Bullet | Enumerator ) + a:StartList + ListBlock { a = cons($$, a); } + ( !BlankLine + ListContinuationBlock { a = cons($$, a); } )* + !ListContinuationBlock + { element *raw; + raw = mk_str_from_list(a, false); + raw->key = RAW; + $$ = mk_element(LISTITEM); + $$->children = raw; + } + +ListBlock = a:StartList + !BlankLine Line { a = cons($$, a); } + ( ListBlockLine { a = cons($$, a); } )* + { $$ = mk_str_from_list(a, false); } + +ListContinuationBlock = a:StartList + ( < BlankLine* > + { if (strlen(yytext) == 0) + a = cons(mk_str("\001"), a); /* block separator */ + else + a = cons(mk_str(yytext), a); } ) + ( Indent ListBlock { a = cons($$, a); } )+ + { $$ = mk_str_from_list(a, false); } + +Enumerator = NonindentSpace [0-9]+ '.' Spacechar+ + +OrderedList = &Enumerator (ListTight | ListLoose) + { $$->key = ORDEREDLIST; } + +ListBlockLine = !BlankLine + !( Indent? (Bullet | Enumerator) ) + !HorizontalRule + OptionallyIndentedLine + +# Parsers for different kinds of block-level HTML content. +# This is repetitive due to constraints of PEG grammar. + +HtmlBlockOpenAddress = '<' Spnl ("address" | "ADDRESS") Spnl HtmlAttribute* '>' +HtmlBlockCloseAddress = '<' Spnl '/' ("address" | "ADDRESS") Spnl '>' +HtmlBlockAddress = HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress + +HtmlBlockOpenBlockquote = '<' Spnl ("blockquote" | "BLOCKQUOTE") Spnl HtmlAttribute* '>' +HtmlBlockCloseBlockquote = '<' Spnl '/' ("blockquote" | "BLOCKQUOTE") Spnl '>' +HtmlBlockBlockquote = HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote + +HtmlBlockOpenCenter = '<' Spnl ("center" | "CENTER") Spnl HtmlAttribute* '>' +HtmlBlockCloseCenter = '<' Spnl '/' ("center" | "CENTER") Spnl '>' +HtmlBlockCenter = HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter + +HtmlBlockOpenDir = '<' Spnl ("dir" | "DIR") Spnl HtmlAttribute* '>' +HtmlBlockCloseDir = '<' Spnl '/' ("dir" | "DIR") Spnl '>' +HtmlBlockDir = HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir + +HtmlBlockOpenDiv = '<' Spnl ("div" | "DIV") Spnl HtmlAttribute* '>' +HtmlBlockCloseDiv = '<' Spnl '/' ("div" | "DIV") Spnl '>' +HtmlBlockDiv = HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv + +HtmlBlockOpenDl = '<' Spnl ("dl" | "DL") Spnl HtmlAttribute* '>' +HtmlBlockCloseDl = '<' Spnl '/' ("dl" | "DL") Spnl '>' +HtmlBlockDl = HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl + +HtmlBlockOpenFieldset = '<' Spnl ("fieldset" | "FIELDSET") Spnl HtmlAttribute* '>' +HtmlBlockCloseFieldset = '<' Spnl '/' ("fieldset" | "FIELDSET") Spnl '>' +HtmlBlockFieldset = HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset + +HtmlBlockOpenForm = '<' Spnl ("form" | "FORM") Spnl HtmlAttribute* '>' +HtmlBlockCloseForm = '<' Spnl '/' ("form" | "FORM") Spnl '>' +HtmlBlockForm = HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm + +HtmlBlockOpenH1 = '<' Spnl ("h1" | "H1") Spnl HtmlAttribute* '>' +HtmlBlockCloseH1 = '<' Spnl '/' ("h1" | "H1") Spnl '>' +HtmlBlockH1 = HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1 + +HtmlBlockOpenH2 = '<' Spnl ("h2" | "H2") Spnl HtmlAttribute* '>' +HtmlBlockCloseH2 = '<' Spnl '/' ("h2" | "H2") Spnl '>' +HtmlBlockH2 = HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2 + +HtmlBlockOpenH3 = '<' Spnl ("h3" | "H3") Spnl HtmlAttribute* '>' +HtmlBlockCloseH3 = '<' Spnl '/' ("h3" | "H3") Spnl '>' +HtmlBlockH3 = HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3 + +HtmlBlockOpenH4 = '<' Spnl ("h4" | "H4") Spnl HtmlAttribute* '>' +HtmlBlockCloseH4 = '<' Spnl '/' ("h4" | "H4") Spnl '>' +HtmlBlockH4 = HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4 + +HtmlBlockOpenH5 = '<' Spnl ("h5" | "H5") Spnl HtmlAttribute* '>' +HtmlBlockCloseH5 = '<' Spnl '/' ("h5" | "H5") Spnl '>' +HtmlBlockH5 = HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5 + +HtmlBlockOpenH6 = '<' Spnl ("h6" | "H6") Spnl HtmlAttribute* '>' +HtmlBlockCloseH6 = '<' Spnl '/' ("h6" | "H6") Spnl '>' +HtmlBlockH6 = HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6 + +HtmlBlockOpenMenu = '<' Spnl ("menu" | "MENU") Spnl HtmlAttribute* '>' +HtmlBlockCloseMenu = '<' Spnl '/' ("menu" | "MENU") Spnl '>' +HtmlBlockMenu = HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu + +HtmlBlockOpenNoframes = '<' Spnl ("noframes" | "NOFRAMES") Spnl HtmlAttribute* '>' +HtmlBlockCloseNoframes = '<' Spnl '/' ("noframes" | "NOFRAMES") Spnl '>' +HtmlBlockNoframes = HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes + +HtmlBlockOpenNoscript = '<' Spnl ("noscript" | "NOSCRIPT") Spnl HtmlAttribute* '>' +HtmlBlockCloseNoscript = '<' Spnl '/' ("noscript" | "NOSCRIPT") Spnl '>' +HtmlBlockNoscript = HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript + +HtmlBlockOpenOl = '<' Spnl ("ol" | "OL") Spnl HtmlAttribute* '>' +HtmlBlockCloseOl = '<' Spnl '/' ("ol" | "OL") Spnl '>' +HtmlBlockOl = HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl + +HtmlBlockOpenP = '<' Spnl ("p" | "P") Spnl HtmlAttribute* '>' +HtmlBlockCloseP = '<' Spnl '/' ("p" | "P") Spnl '>' +HtmlBlockP = HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP + +HtmlBlockOpenPre = '<' Spnl ("pre" | "PRE") Spnl HtmlAttribute* '>' +HtmlBlockClosePre = '<' Spnl '/' ("pre" | "PRE") Spnl '>' +HtmlBlockPre = HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre + +HtmlBlockOpenTable = '<' Spnl ("table" | "TABLE") Spnl HtmlAttribute* '>' +HtmlBlockCloseTable = '<' Spnl '/' ("table" | "TABLE") Spnl '>' +HtmlBlockTable = HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable + +HtmlBlockOpenUl = '<' Spnl ("ul" | "UL") Spnl HtmlAttribute* '>' +HtmlBlockCloseUl = '<' Spnl '/' ("ul" | "UL") Spnl '>' +HtmlBlockUl = HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl + +HtmlBlockOpenDd = '<' Spnl ("dd" | "DD") Spnl HtmlAttribute* '>' +HtmlBlockCloseDd = '<' Spnl '/' ("dd" | "DD") Spnl '>' +HtmlBlockDd = HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd + +HtmlBlockOpenDt = '<' Spnl ("dt" | "DT") Spnl HtmlAttribute* '>' +HtmlBlockCloseDt = '<' Spnl '/' ("dt" | "DT") Spnl '>' +HtmlBlockDt = HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt + +HtmlBlockOpenFrameset = '<' Spnl ("frameset" | "FRAMESET") Spnl HtmlAttribute* '>' +HtmlBlockCloseFrameset = '<' Spnl '/' ("frameset" | "FRAMESET") Spnl '>' +HtmlBlockFrameset = HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset + +HtmlBlockOpenLi = '<' Spnl ("li" | "LI") Spnl HtmlAttribute* '>' +HtmlBlockCloseLi = '<' Spnl '/' ("li" | "LI") Spnl '>' +HtmlBlockLi = HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi + +HtmlBlockOpenTbody = '<' Spnl ("tbody" | "TBODY") Spnl HtmlAttribute* '>' +HtmlBlockCloseTbody = '<' Spnl '/' ("tbody" | "TBODY") Spnl '>' +HtmlBlockTbody = HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody + +HtmlBlockOpenTd = '<' Spnl ("td" | "TD") Spnl HtmlAttribute* '>' +HtmlBlockCloseTd = '<' Spnl '/' ("td" | "TD") Spnl '>' +HtmlBlockTd = HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd + +HtmlBlockOpenTfoot = '<' Spnl ("tfoot" | "TFOOT") Spnl HtmlAttribute* '>' +HtmlBlockCloseTfoot = '<' Spnl '/' ("tfoot" | "TFOOT") Spnl '>' +HtmlBlockTfoot = HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot + +HtmlBlockOpenTh = '<' Spnl ("th" | "TH") Spnl HtmlAttribute* '>' +HtmlBlockCloseTh = '<' Spnl '/' ("th" | "TH") Spnl '>' +HtmlBlockTh = HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh + +HtmlBlockOpenThead = '<' Spnl ("thead" | "THEAD") Spnl HtmlAttribute* '>' +HtmlBlockCloseThead = '<' Spnl '/' ("thead" | "THEAD") Spnl '>' +HtmlBlockThead = HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead + +HtmlBlockOpenTr = '<' Spnl ("tr" | "TR") Spnl HtmlAttribute* '>' +HtmlBlockCloseTr = '<' Spnl '/' ("tr" | "TR") Spnl '>' +HtmlBlockTr = HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr + +HtmlBlockOpenScript = '<' Spnl ("script" | "SCRIPT") Spnl HtmlAttribute* '>' +HtmlBlockCloseScript = '<' Spnl '/' ("script" | "SCRIPT") Spnl '>' +HtmlBlockScript = HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript + + +HtmlBlockInTags = HtmlBlockAddress + | HtmlBlockBlockquote + | HtmlBlockCenter + | HtmlBlockDir + | HtmlBlockDiv + | HtmlBlockDl + | HtmlBlockFieldset + | HtmlBlockForm + | HtmlBlockH1 + | HtmlBlockH2 + | HtmlBlockH3 + | HtmlBlockH4 + | HtmlBlockH5 + | HtmlBlockH6 + | HtmlBlockMenu + | HtmlBlockNoframes + | HtmlBlockNoscript + | HtmlBlockOl + | HtmlBlockP + | HtmlBlockPre + | HtmlBlockTable + | HtmlBlockUl + | HtmlBlockDd + | HtmlBlockDt + | HtmlBlockFrameset + | HtmlBlockLi + | HtmlBlockTbody + | HtmlBlockTd + | HtmlBlockTfoot + | HtmlBlockTh + | HtmlBlockThead + | HtmlBlockTr + | HtmlBlockScript + +HtmlBlock = < ( HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing ) > + BlankLine+ + { if (extension(EXT_FILTER_HTML)) { + $$ = mk_list(LIST, NULL); + } else { + $$ = mk_str(yytext); + $$->key = HTMLBLOCK; + } + } + +HtmlBlockSelfClosing = '<' Spnl HtmlBlockType Spnl HtmlAttribute* '/' Spnl '>' + +HtmlBlockType = "address" | "blockquote" | "center" | "dir" | "div" | "dl" | "fieldset" | "form" | "h1" | "h2" | "h3" | + "h4" | "h5" | "h6" | "hr" | "isindex" | "menu" | "noframes" | "noscript" | "ol" | "p" | "pre" | "table" | + "ul" | "dd" | "dt" | "frameset" | "li" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "script" | + "ADDRESS" | "BLOCKQUOTE" | "CENTER" | "DIR" | "DIV" | "DL" | "FIELDSET" | "FORM" | "H1" | "H2" | "H3" | + "H4" | "H5" | "H6" | "HR" | "ISINDEX" | "MENU" | "NOFRAMES" | "NOSCRIPT" | "OL" | "P" | "PRE" | "TABLE" | + "UL" | "DD" | "DT" | "FRAMESET" | "LI" | "TBODY" | "TD" | "TFOOT" | "TH" | "THEAD" | "TR" | "SCRIPT" + +StyleOpen = '<' Spnl ("style" | "STYLE") Spnl HtmlAttribute* '>' +StyleClose = '<' Spnl '/' ("style" | "STYLE") Spnl '>' +InStyleTags = StyleOpen (!StyleClose .)* StyleClose +StyleBlock = < InStyleTags > + BlankLine* + { if (extension(EXT_FILTER_STYLES)) { + $$ = mk_list(LIST, NULL); + } else { + $$ = mk_str(yytext); + $$->key = HTMLBLOCK; + } + } + +Inlines = a:StartList ( !Endline Inline { a = cons($$, a); } + | c:Endline &Inline { a = cons(c, a); } )+ Endline? + { $$ = mk_list(LIST, a); } + +Inline = Str + | Endline + | UlOrStarLine + | Space + | Strong + | Emph + | Image + | Link + | NoteReference + | InlineNote + | Code + | RawHtml + | Entity + | EscapedChar + | Smart + | Symbol + +Space = Spacechar+ + { $$ = mk_str(" "); + $$->key = SPACE; } + +Str = a:StartList < NormalChar+ > { a = cons(mk_str(yytext), a); } + ( StrChunk { a = cons($$, a); } )* + { if (a->next == NULL) { $$ = a; } else { $$ = mk_list(LIST, a); } } + +StrChunk = < (NormalChar | '_'+ &Alphanumeric)+ > { $$ = mk_str(yytext); } | + AposChunk + +AposChunk = &{ extension(EXT_SMART) } '\'' &Alphanumeric + { $$ = mk_element(APOSTROPHE); } + +EscapedChar = '\\' !Newline < [-\\`|*_{}[\]()#+.!><] > + { $$ = mk_str(yytext); } + +Entity = ( HexEntity | DecEntity | CharEntity ) + { $$ = mk_str(yytext); $$->key = HTML; } + +Endline = LineBreak | TerminalEndline | NormalEndline + +NormalEndline = Sp Newline !BlankLine !'>' !AtxStart + !(Line ('='+ | '-'+) Newline) + { $$ = mk_str("\n"); + $$->key = SPACE; } + +TerminalEndline = Sp Newline Eof + { $$ = NULL; } + +LineBreak = " " NormalEndline + { $$ = mk_element(LINEBREAK); } + +Symbol = < SpecialChar > + { $$ = mk_str(yytext); } + +# This keeps the parser from getting bogged down on long strings of '*' or '_', +# or strings of '*' or '_' with space on each side: +UlOrStarLine = (UlLine | StarLine) { $$ = mk_str(yytext); } +StarLine = < "****" '*'* > | < Spacechar '*'+ &Spacechar > +UlLine = < "____" '_'* > | < Spacechar '_'+ &Spacechar > + +Emph = EmphStar | EmphUl + +Whitespace = Spacechar | Newline + +EmphStar = '*' !Whitespace + a:StartList + ( !'*' b:Inline { a = cons(b, a); } + | b:StrongStar { a = cons(b, a); } + )+ + '*' + { $$ = mk_list(EMPH, a); } + +EmphUl = '_' !Whitespace + a:StartList + ( !'_' b:Inline { a = cons(b, a); } + | b:StrongUl { a = cons(b, a); } + )+ + '_' + { $$ = mk_list(EMPH, a); } + +Strong = StrongStar | StrongUl + +StrongStar = "**" !Whitespace + a:StartList + ( !"**" b:Inline { a = cons(b, a); })+ + "**" + { $$ = mk_list(STRONG, a); } + +StrongUl = "__" !Whitespace + a:StartList + ( !"__" b:Inline { a = cons(b, a); })+ + "__" + { $$ = mk_list(STRONG, a); } + +Image = '!' ( ExplicitLink | ReferenceLink ) + { if ($$->key == LINK) { + $$->key = IMAGE; + } else { + element *result; + result = $$; + $$->children = cons(mk_str("!"), result->children); + } } + +Link = ExplicitLink | ReferenceLink | AutoLink + +ReferenceLink = ReferenceLinkDouble | ReferenceLinkSingle + +ReferenceLinkDouble = a:Label < Spnl > !"[]" b:Label + { link match; + if (find_reference(&match, b->children)) { + $$ = mk_link(a->children, match.url, match.title); + free(a); + free_element_list(b); + } else { + element *result; + result = mk_element(LIST); + result->children = cons(mk_str("["), cons(a, cons(mk_str("]"), cons(mk_str(yytext), + cons(mk_str("["), cons(b, mk_str("]"))))))); + $$ = result; + } + } + +ReferenceLinkSingle = a:Label < (Spnl "[]")? > + { link match; + if (find_reference(&match, a->children)) { + $$ = mk_link(a->children, match.url, match.title); + free(a); + } + else { + element *result; + result = mk_element(LIST); + result->children = cons(mk_str("["), cons(a, cons(mk_str("]"), mk_str(yytext)))); + $$ = result; + } + } + +ExplicitLink = l:Label '(' Sp s:Source Spnl t:Title Sp ')' + { $$ = mk_link(l->children, s->contents.str, t->contents.str); + free_element(s); + free_element(t); + free(l); } + +Source = ( '<' < SourceContents > '>' | < SourceContents > ) + { $$ = mk_str(yytext); } + +SourceContents = ( ( !'(' !')' !'>' Nonspacechar )+ | '(' SourceContents ')')* + +Title = ( TitleSingle | TitleDouble | < "" > ) + { $$ = mk_str(yytext); } + +TitleSingle = '\'' < ( !( '\'' Sp ( ')' | Newline ) ) . )* > '\'' + +TitleDouble = '"' < ( !( '"' Sp ( ')' | Newline ) ) . )* > '"' + +AutoLink = AutoLinkUrl | AutoLinkEmail + +AutoLinkUrl = '<' < [A-Za-z]+ "://" ( !Newline !'>' . )+ > '>' + { $$ = mk_link(mk_str(yytext), yytext, ""); } + +AutoLinkEmail = '<' ( "mailto:" )? < [-A-Za-z0-9+_./!%~$]+ '@' ( !Newline !'>' . )+ > '>' + { char *mailto = malloc(strlen(yytext) + 8); + sprintf(mailto, "mailto:%s", yytext); + $$ = mk_link(mk_str(yytext), mailto, ""); + free(mailto); + } + +Reference = NonindentSpace !"[]" l:Label ':' Spnl s:RefSrc t:RefTitle BlankLine+ + { $$ = mk_link(l->children, s->contents.str, t->contents.str); + free_element(s); + free_element(t); + free(l); + $$->key = REFERENCE; } + +Label = '[' ( !'^' &{ extension(EXT_NOTES) } | &. &{ !extension(EXT_NOTES) } ) + a:StartList + ( !']' Inline { a = cons($$, a); } )* + ']' + { $$ = mk_list(LIST, a); } + +RefSrc = < Nonspacechar+ > + { $$ = mk_str(yytext); + $$->key = HTML; } + +RefTitle = ( RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle ) + { $$ = mk_str(yytext); } + +EmptyTitle = < "" > + +RefTitleSingle = Spnl '\'' < ( !( '\'' Sp Newline | Newline ) . )* > '\'' + +RefTitleDouble = Spnl '"' < ( !('"' Sp Newline | Newline) . )* > '"' + +RefTitleParens = Spnl '(' < ( !(')' Sp Newline | Newline) . )* > ')' + +References = a:StartList + ( b:Reference { a = cons(b, a); } | SkipBlock )* + { references = reverse(a); } + +Ticks1 = "`" !'`' +Ticks2 = "``" !'`' +Ticks3 = "```" !'`' +Ticks4 = "````" !'`' +Ticks5 = "`````" !'`' + +Code = ( Ticks1 Sp < ( ( !'`' Nonspacechar )+ | !Ticks1 '`'+ | !( Sp Ticks1 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks1 + | Ticks2 Sp < ( ( !'`' Nonspacechar )+ | !Ticks2 '`'+ | !( Sp Ticks2 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks2 + | Ticks3 Sp < ( ( !'`' Nonspacechar )+ | !Ticks3 '`'+ | !( Sp Ticks3 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks3 + | Ticks4 Sp < ( ( !'`' Nonspacechar )+ | !Ticks4 '`'+ | !( Sp Ticks4 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks4 + | Ticks5 Sp < ( ( !'`' Nonspacechar )+ | !Ticks5 '`'+ | !( Sp Ticks5 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks5 + ) + { $$ = mk_str(yytext); $$->key = CODE; } + +RawHtml = < (HtmlComment | HtmlBlockScript | HtmlTag) > + { if (extension(EXT_FILTER_HTML)) { + $$ = mk_list(LIST, NULL); + } else { + $$ = mk_str(yytext); + $$->key = HTML; + } + } + +BlankLine = Sp Newline + +Quoted = '"' (!'"' .)* '"' | '\'' (!'\'' .)* '\'' +HtmlAttribute = (AlphanumericAscii | '-')+ Spnl ('=' Spnl (Quoted | (!'>' Nonspacechar)+))? Spnl +HtmlComment = "" .)* "-->" +HtmlTag = '<' Spnl '/'? AlphanumericAscii+ Spnl HtmlAttribute* '/'? Spnl '>' +Eof = !. +Spacechar = ' ' | '\t' +Nonspacechar = !Spacechar !Newline . +Newline = '\n' | '\r' '\n'? +Sp = Spacechar* +Spnl = Sp (Newline Sp)? +SpecialChar = '*' | '_' | '`' | '&' | '[' | ']' | '(' | ')' | '<' | '!' | '#' | '\\' | '\'' | '"' | ExtendedSpecialChar +NormalChar = !( SpecialChar | Spacechar | Newline ) . +Alphanumeric = [0-9A-Za-z] | '\200' | '\201' | '\202' | '\203' | '\204' | '\205' | '\206' | '\207' | '\210' | '\211' | '\212' | '\213' | '\214' | '\215' | '\216' | '\217' | '\220' | '\221' | '\222' | '\223' | '\224' | '\225' | '\226' | '\227' | '\230' | '\231' | '\232' | '\233' | '\234' | '\235' | '\236' | '\237' | '\240' | '\241' | '\242' | '\243' | '\244' | '\245' | '\246' | '\247' | '\250' | '\251' | '\252' | '\253' | '\254' | '\255' | '\256' | '\257' | '\260' | '\261' | '\262' | '\263' | '\264' | '\265' | '\266' | '\267' | '\270' | '\271' | '\272' | '\273' | '\274' | '\275' | '\276' | '\277' | '\300' | '\301' | '\302' | '\303' | '\304' | '\305' | '\306' | '\307' | '\310' | '\311' | '\312' | '\313' | '\314' | '\315' | '\316' | '\317' | '\320' | '\321' | '\322' | '\323' | '\324' | '\325' | '\326' | '\327' | '\330' | '\331' | '\332' | '\333' | '\334' | '\335' | '\336' | '\337' | '\340' | '\341' | '\342' | '\343' | '\344' | '\345' | '\346' | '\347' | '\350' | '\351' | '\352' | '\353' | '\354' | '\355' | '\356' | '\357' | '\360' | '\361' | '\362' | '\363' | '\364' | '\365' | '\366' | '\367' | '\370' | '\371' | '\372' | '\373' | '\374' | '\375' | '\376' | '\377' +AlphanumericAscii = [A-Za-z0-9] +Digit = [0-9] +BOM = "\357\273\277" + +HexEntity = < '&' '#' [Xx] [0-9a-fA-F]+ ';' > +DecEntity = < '&' '#' [0-9]+ > ';' > +CharEntity = < '&' [A-Za-z0-9]+ ';' > + +NonindentSpace = " " | " " | " " | "" +Indent = "\t" | " " +IndentedLine = Indent Line +OptionallyIndentedLine = Indent? Line + +# StartList starts a list data structure that can be added to with cons: +StartList = &. + { $$ = NULL; } + +Line = RawLine + { $$ = mk_str(yytext); } +RawLine = ( < (!'\r' !'\n' .)* Newline > | < .+ > Eof ) + +SkipBlock = HtmlBlock + | ( !'#' !SetextBottom1 !SetextBottom2 !BlankLine RawLine )+ BlankLine* + | BlankLine+ + | RawLine + +# Syntax extensions + +ExtendedSpecialChar = &{ extension(EXT_SMART) } ('.' | '-' | '\'' | '"') + | &{ extension(EXT_NOTES) } ( '^' ) + +Smart = &{ extension(EXT_SMART) } + ( Ellipsis | Dash | SingleQuoted | DoubleQuoted | Apostrophe ) + +Apostrophe = '\'' + { $$ = mk_element(APOSTROPHE); } + +Ellipsis = ("..." | ". . .") + { $$ = mk_element(ELLIPSIS); } + +Dash = EmDash | EnDash + +EnDash = '-' &Digit + { $$ = mk_element(ENDASH); } + +EmDash = ("---" | "--") + { $$ = mk_element(EMDASH); } + +SingleQuoteStart = '\'' !(Spacechar | Newline) + +SingleQuoteEnd = '\'' !Alphanumeric + +SingleQuoted = SingleQuoteStart + a:StartList + ( !SingleQuoteEnd b:Inline { a = cons(b, a); } )+ + SingleQuoteEnd + { $$ = mk_list(SINGLEQUOTED, a); } + +DoubleQuoteStart = '"' + +DoubleQuoteEnd = '"' + +DoubleQuoted = DoubleQuoteStart + a:StartList + ( !DoubleQuoteEnd b:Inline { a = cons(b, a); } )+ + DoubleQuoteEnd + { $$ = mk_list(DOUBLEQUOTED, a); } + +NoteReference = &{ extension(EXT_NOTES) } + ref:RawNoteReference + { element *match; + if (find_note(&match, ref->contents.str)) { + $$ = mk_element(NOTE); + assert(match->children != NULL); + $$->children = match->children; + $$->contents.str = 0; + } else { + char *s; + s = malloc(strlen(ref->contents.str) + 4); + sprintf(s, "[^%s]", ref->contents.str); + $$ = mk_str(s); + free(s); + } + } + +RawNoteReference = "[^" < ( !Newline !']' . )+ > ']' + { $$ = mk_str(yytext); } + +Note = &{ extension(EXT_NOTES) } + NonindentSpace ref:RawNoteReference ':' Sp + a:StartList + ( RawNoteBlock { a = cons($$, a); } ) + ( &Indent RawNoteBlock { a = cons($$, a); } )* + { $$ = mk_list(NOTE, a); + $$->contents.str = strdup(ref->contents.str); + } + +InlineNote = &{ extension(EXT_NOTES) } + "^[" + a:StartList + ( !']' Inline { a = cons($$, a); } )+ + ']' + { $$ = mk_list(NOTE, a); + $$->contents.str = 0; } + +Notes = a:StartList + ( b:Note { a = cons(b, a); } | SkipBlock )* + { notes = reverse(a); } + +RawNoteBlock = a:StartList + ( !BlankLine OptionallyIndentedLine { a = cons($$, a); } )+ + ( < BlankLine* > { a = cons(mk_str(yytext), a); } ) + { $$ = mk_str_from_list(a, true); + $$->key = RAW; + } + +%% + + diff --git a/supportlibs/pegmarkdown/markdown_peg.h b/supportlibs/pegmarkdown/markdown_peg.h new file mode 100644 index 000000000..c78d7e2cb --- /dev/null +++ b/supportlibs/pegmarkdown/markdown_peg.h @@ -0,0 +1,72 @@ +/* markdown_peg.h */ +#ifndef MARKDOWN_PEG_H +#define MARKDOWN_PEG_H + +#include "markdown_lib.h" +#include + +/* Information (label, URL and title) for a link. */ +struct Link { + struct Element *label; + char *url; + char *title; +}; + +typedef struct Link link; + +/* Union for contents of an Element (string, list, or link). */ +union Contents { + char *str; + struct Link *link; +}; + +/* Types of semantic values returned by parsers. */ +enum keys { LIST, /* A generic list of values. For ordered and bullet lists, see below. */ + RAW, /* Raw markdown to be processed further */ + SPACE, + LINEBREAK, + ELLIPSIS, + EMDASH, + ENDASH, + APOSTROPHE, + SINGLEQUOTED, + DOUBLEQUOTED, + STR, + LINK, + IMAGE, + CODE, + HTML, + EMPH, + STRONG, + PLAIN, + PARA, + LISTITEM, + BULLETLIST, + ORDEREDLIST, + H1, H2, H3, H4, H5, H6, /* Code assumes that these are in order. */ + BLOCKQUOTE, + VERBATIM, + HTMLBLOCK, + HRULE, + REFERENCE, + NOTE + }; + +/* Semantic value of a parsing action. */ +struct Element { + int key; + union Contents contents; + struct Element *children; + struct Element *next; +}; + +typedef struct Element element; + +element * parse_references(char *string, int extensions); +element * parse_notes(char *string, int extensions, element *reference_list); +element * parse_markdown(char *string, int extensions, element *reference_list, element *note_list); +void free_element_list(element * elt); +void free_element(element *elt); +void print_element_list(GString *out, element *elt, int format, int exts); + +#endif diff --git a/supportlibs/pegmarkdown/odf.c b/supportlibs/pegmarkdown/odf.c new file mode 100644 index 000000000..46265f20a --- /dev/null +++ b/supportlibs/pegmarkdown/odf.c @@ -0,0 +1,181 @@ +/********************************************************************** + + odf.c - Utility routines to enable ODF support in peg-multimarkdown. + (c) 2011 Fletcher T. Penney (http://fletcherpenney.net/). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License or the MIT + license. See LICENSE for details. + + 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. + + ***********************************************************************/ + +#include "odf.h" + + +void print_odf_header(GString *out){ + + /* Insert required XML header */ + g_string_append_printf(out, +"\n" \ +"\n"); + + /* Font Declarations */ + g_string_append_printf(out, "\n" \ + " \n" \ + "\n"); + + /* Append basic style information */ + g_string_append_printf(out, "\n" \ + "\n" \ + " \n" \ + " \n" \ + "\n" \ + " \n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + " \n" \ + "\n" \ + "\n"); + + /* Automatic style information */ + g_string_append_printf(out, "" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + " \n" \ + "\n" \ + "\n" \ + " \n" \ + "\n"); +} + +void print_odf_footer(GString *out) { + g_string_append_printf(out, "\n\n"); +} + diff --git a/supportlibs/pegmarkdown/odf.h b/supportlibs/pegmarkdown/odf.h new file mode 100644 index 000000000..d5bdc8860 --- /dev/null +++ b/supportlibs/pegmarkdown/odf.h @@ -0,0 +1,11 @@ +#ifndef ODF_H +#define ODF_H + +#include +#include +#include + +void print_odf_header(GString *out); +void print_odf_footer(GString *out); +#endif + diff --git a/supportlibs/pegmarkdown/parsing_functions.c b/supportlibs/pegmarkdown/parsing_functions.c new file mode 100644 index 000000000..81fd9e26f --- /dev/null +++ b/supportlibs/pegmarkdown/parsing_functions.c @@ -0,0 +1,117 @@ +/* parsing_functions.c - Functions for parsing markdown and + * freeing element lists. */ + +/* These yy_* functions come from markdown_parser.c which is + * generated from markdown_parser.leg + * */ +typedef int (*yyrule)(); + +extern int yyparse(); +extern int yyparsefrom(yyrule); +extern int yy_References(); +extern int yy_Notes(); +extern int yy_Doc(); + +#include "utility_functions.h" +#include "parsing_functions.h" +#include "markdown_peg.h" + +static void free_element_contents(element elt); + +/* free_element_list - free list of elements recursively */ +void free_element_list(element * elt) { + element * next = NULL; + while (elt != NULL) { + next = elt->next; + free_element_contents(*elt); + if (elt->children != NULL) { + free_element_list(elt->children); + elt->children = NULL; + } + free(elt); + elt = next; + } +} + +/* free_element_contents - free element contents depending on type */ +static void free_element_contents(element elt) { + switch (elt.key) { + case STR: + case SPACE: + case RAW: + case HTMLBLOCK: + case HTML: + case VERBATIM: + case CODE: + case NOTE: + free(elt.contents.str); + elt.contents.str = NULL; + break; + case LINK: + case IMAGE: + case REFERENCE: + free(elt.contents.link->url); + elt.contents.link->url = NULL; + free(elt.contents.link->title); + elt.contents.link->title = NULL; + free_element_list(elt.contents.link->label); + free(elt.contents.link); + elt.contents.link = NULL; + break; + default: + ; + } +} + +/* free_element - free element and contents */ +void free_element(element *elt) { + free_element_contents(*elt); + free(elt); +} + +element * parse_references(char *string, int extensions) { + + char *oldcharbuf; + syntax_extensions = extensions; + + oldcharbuf = charbuf; + charbuf = string; + yyparsefrom(yy_References); /* first pass, just to collect references */ + charbuf = oldcharbuf; + + return references; +} + +element * parse_notes(char *string, int extensions, element *reference_list) { + + char *oldcharbuf; + notes = NULL; + syntax_extensions = extensions; + + if (extension(EXT_NOTES)) { + references = reference_list; + oldcharbuf = charbuf; + charbuf = string; + yyparsefrom(yy_Notes); /* second pass for notes */ + charbuf = oldcharbuf; + } + + return notes; +} + +element * parse_markdown(char *string, int extensions, element *reference_list, element *note_list) { + + char *oldcharbuf; + syntax_extensions = extensions; + references = reference_list; + notes = note_list; + + oldcharbuf = charbuf; + charbuf = string; + + yyparsefrom(yy_Doc); + + charbuf = oldcharbuf; /* restore charbuf to original value */ + return parse_result; + +} diff --git a/supportlibs/pegmarkdown/parsing_functions.h b/supportlibs/pegmarkdown/parsing_functions.h new file mode 100644 index 000000000..d7b7ff426 --- /dev/null +++ b/supportlibs/pegmarkdown/parsing_functions.h @@ -0,0 +1,17 @@ +#ifndef PARSING_FUNCTIONS_H +#define PARSING_FUNCTIONS_H +/* parsing_functions.c - Functions for parsing markdown and + * freeing element lists. */ + +#include "markdown_peg.h" + +/* free_element_list - free list of elements recursively */ +void free_element_list(element * elt); +/* free_element - free element and contents */ +void free_element(element *elt); + +element * parse_references(char *string, int extensions); +element * parse_notes(char *string, int extensions, element *reference_list); +element * parse_markdown(char *string, int extensions, element *reference_list, element *note_list); + +#endif diff --git a/supportlibs/pegmarkdown/peg-0.1.9/Makefile b/supportlibs/pegmarkdown/peg-0.1.9/Makefile new file mode 100644 index 000000000..c10fbda83 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/Makefile @@ -0,0 +1,65 @@ +CFLAGS = -g -Wall $(OFLAGS) $(XFLAGS) +OFLAGS = -O3 -DNDEBUG +#OFLAGS = -pg + +OBJS = tree.o compile.o + +all : peg leg + +peg : peg.o $(OBJS) + $(CC) $(CFLAGS) -o $@-new peg.o $(OBJS) + mv $@-new $@ + +leg : leg.o $(OBJS) + $(CC) $(CFLAGS) -o $@-new leg.o $(OBJS) + mv $@-new $@ + +ROOT = +PREFIX = /usr/local +BINDIR = $(ROOT)$(PREFIX)/bin + +install : $(BINDIR)/peg $(BINDIR)/leg + +$(BINDIR)/% : % + cp -p $< $@ + strip $@ + +uninstall : .FORCE + rm -f $(BINDIR)/peg + rm -f $(BINDIR)/leg + +peg.o : peg.c peg.peg-c + +%.peg-c : %.peg compile.c + ./peg -o $@ $< + +leg.o : leg.c + +leg.c : leg.leg compile.c + ./leg -o $@ $< + +check : check-peg check-leg + +check-peg : peg .FORCE + ./peg < peg.peg > peg.out + diff peg.peg-c peg.out + rm peg.out + +check-leg : leg .FORCE + ./leg < leg.leg > leg.out + diff leg.c leg.out + rm leg.out + +test examples : .FORCE + $(SHELL) -ec '(cd examples; $(MAKE))' + +clean : .FORCE + rm -f *~ *.o *.peg.[cd] *.leg.[cd] + $(SHELL) -ec '(cd examples; $(MAKE) $@)' + +spotless : clean .FORCE + rm -f peg + rm -f leg + $(SHELL) -ec '(cd examples; $(MAKE) $@)' + +.FORCE : diff --git a/supportlibs/pegmarkdown/peg-0.1.9/compile.c b/supportlibs/pegmarkdown/peg-0.1.9/compile.c new file mode 100644 index 000000000..74506b762 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/compile.c @@ -0,0 +1,717 @@ +/* Copyright (c) 2007, 2012 by Ian Piumarta + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the 'Software'), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, provided that the above copyright notice(s) and this + * permission notice appear in all copies of the Software. Acknowledgement + * of the use of this Software in supporting documentation would be + * appreciated but is not required. + * + * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK. + * + * Last edited: 2012-04-29 16:09:36 by piumarta on emilia + */ + +#include +#include +#include +#include + +#include "version.h" +#include "tree.h" + +static int yyl(void) +{ + static int prev= 0; + return ++prev; +} + +static void charClassSet (unsigned char bits[], int c) { bits[c >> 3] |= (1 << (c & 7)); } +static void charClassClear(unsigned char bits[], int c) { bits[c >> 3] &= ~(1 << (c & 7)); } + +typedef void (*setter)(unsigned char bits[], int c); + +static inline int oigit(int c) { return '0' <= c && c <= '7'; } + +static int cnext(unsigned char **ccp) +{ + unsigned char *cclass= *ccp; + int c= *cclass++; + if (c) + { + if ('\\' == c && *cclass) + { + switch (c= *cclass++) + { + case 'a': c= '\a'; break; /* bel */ + case 'b': c= '\b'; break; /* bs */ + case 'e': c= '\e'; break; /* esc */ + case 'f': c= '\f'; break; /* ff */ + case 'n': c= '\n'; break; /* nl */ + case 'r': c= '\r'; break; /* cr */ + case 't': c= '\t'; break; /* ht */ + case 'v': c= '\v'; break; /* vt */ + default: + if (oigit(c)) + { + c -= '0'; + if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0'; + if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0'; + } + break; + } + } + *ccp= cclass; + } + return c; +} + +static char *makeCharClass(unsigned char *cclass) +{ + unsigned char bits[32]; + setter set; + int c, prev= -1; + static char string[256]; + char *ptr; + + if ('^' == *cclass) + { + memset(bits, 255, 32); + set= charClassClear; + ++cclass; + } + else + { + memset(bits, 0, 32); + set= charClassSet; + } + + while (*cclass) + { + if ('-' == *cclass && cclass[1] && prev >= 0) + { + ++cclass; + for (c= cnext(&cclass); prev <= c; ++prev) + set(bits, prev); + prev= -1; + } + else + { + c= cnext(&cclass); + set(bits, prev= c); + } + } + + ptr= string; + for (c= 0; c < 32; ++c) + ptr += sprintf(ptr, "\\%03o", bits[c]); + + return string; +} + +static void begin(void) { fprintf(output, "\n {"); } +static void end(void) { fprintf(output, "\n }"); } +static void label(int n) { fprintf(output, "\n l%d:;\t", n); } +static void jump(int n) { fprintf(output, " goto l%d;", n); } +static void save(int n) { fprintf(output, " int yypos%d= ctx->pos, yythunkpos%d= ctx->thunkpos;", n, n); } +static void restore(int n) { fprintf(output, " ctx->pos= yypos%d; ctx->thunkpos= yythunkpos%d;", n, n); } + +static void Node_compile_c_ko(Node *node, int ko) +{ + assert(node); + switch (node->type) + { + case Rule: + fprintf(stderr, "\ninternal error #1 (%s)\n", node->rule.name); + exit(1); + break; + + case Dot: + fprintf(output, " if (!yymatchDot(ctx)) goto l%d;", ko); + break; + + case Name: + fprintf(output, " if (!yy_%s(ctx)) goto l%d;", node->name.rule->rule.name, ko); + if (node->name.variable) + fprintf(output, " yyDo(ctx, yySet, %d, 0);", node->name.variable->variable.offset); + break; + + case Character: + case String: + { + int len= strlen(node->string.value); + if (1 == len) + { + if ('\'' == node->string.value[0]) + fprintf(output, " if (!yymatchChar(ctx, '\\'')) goto l%d;", ko); + else + fprintf(output, " if (!yymatchChar(ctx, '%s')) goto l%d;", node->string.value, ko); + } + else + if (2 == len && '\\' == node->string.value[0]) + fprintf(output, " if (!yymatchChar(ctx, '%s')) goto l%d;", node->string.value, ko); + else + fprintf(output, " if (!yymatchString(ctx, \"%s\")) goto l%d;", node->string.value, ko); + } + break; + + case Class: + fprintf(output, " if (!yymatchClass(ctx, (unsigned char *)\"%s\")) goto l%d;", makeCharClass(node->cclass.value), ko); + break; + + case Action: + fprintf(output, " yyDo(ctx, yy%s, ctx->begin, ctx->end);", node->action.name); + break; + + case Predicate: + fprintf(output, " yyText(ctx, ctx->begin, ctx->end); if (!(%s)) goto l%d;", node->action.text, ko); + break; + + case Alternate: + { + int ok= yyl(); + begin(); + save(ok); + for (node= node->alternate.first; node; node= node->alternate.next) + if (node->alternate.next) + { + int next= yyl(); + Node_compile_c_ko(node, next); + jump(ok); + label(next); + restore(ok); + } + else + Node_compile_c_ko(node, ko); + end(); + label(ok); + } + break; + + case Sequence: + for (node= node->sequence.first; node; node= node->sequence.next) + Node_compile_c_ko(node, ko); + break; + + case PeekFor: + { + int ok= yyl(); + begin(); + save(ok); + Node_compile_c_ko(node->peekFor.element, ko); + restore(ok); + end(); + } + break; + + case PeekNot: + { + int ok= yyl(); + begin(); + save(ok); + Node_compile_c_ko(node->peekFor.element, ok); + jump(ko); + label(ok); + restore(ok); + end(); + } + break; + + case Query: + { + int qko= yyl(), qok= yyl(); + begin(); + save(qko); + Node_compile_c_ko(node->query.element, qko); + jump(qok); + label(qko); + restore(qko); + end(); + label(qok); + } + break; + + case Star: + { + int again= yyl(), out= yyl(); + label(again); + begin(); + save(out); + Node_compile_c_ko(node->star.element, out); + jump(again); + label(out); + restore(out); + end(); + } + break; + + case Plus: + { + int again= yyl(), out= yyl(); + Node_compile_c_ko(node->plus.element, ko); + label(again); + begin(); + save(out); + Node_compile_c_ko(node->plus.element, out); + jump(again); + label(out); + restore(out); + end(); + } + break; + + default: + fprintf(stderr, "\nNode_compile_c_ko: illegal node type %d\n", node->type); + exit(1); + } +} + + +static int countVariables(Node *node) +{ + int count= 0; + while (node) + { + ++count; + node= node->variable.next; + } + return count; +} + +static void defineVariables(Node *node) +{ + int count= 0; + while (node) + { + fprintf(output, "#define %s ctx->val[%d]\n", node->variable.name, --count); + node->variable.offset= count; + node= node->variable.next; + } + fprintf(output, "#define yy ctx->yy\n"); + fprintf(output, "#define yypos ctx->pos\n"); + fprintf(output, "#define yythunkpos ctx->thunkpos\n"); +} + +static void undefineVariables(Node *node) +{ + fprintf(output, "#undef yythunkpos\n"); + fprintf(output, "#undef yypos\n"); + fprintf(output, "#undef yy\n"); + while (node) + { + fprintf(output, "#undef %s\n", node->variable.name); + node= node->variable.next; + } +} + + +static void Rule_compile_c2(Node *node) +{ + assert(node); + assert(Rule == node->type); + + if (!node->rule.expression) + fprintf(stderr, "rule '%s' used but not defined\n", node->rule.name); + else + { + int ko= yyl(), safe; + + if ((!(RuleUsed & node->rule.flags)) && (node != start)) + fprintf(stderr, "rule '%s' defined but not used\n", node->rule.name); + + safe= ((Query == node->rule.expression->type) || (Star == node->rule.expression->type)); + + fprintf(output, "\nYY_RULE(int) yy_%s(yycontext *ctx)\n{", node->rule.name); + if (!safe) save(0); + if (node->rule.variables) + fprintf(output, " yyDo(ctx, yyPush, %d, 0);", countVariables(node->rule.variables)); + fprintf(output, "\n yyprintf((stderr, \"%%s\\n\", \"%s\"));", node->rule.name); + Node_compile_c_ko(node->rule.expression, ko); + fprintf(output, "\n yyprintf((stderr, \" ok %%s @ %%s\\n\", \"%s\", ctx->buf+ctx->pos));", node->rule.name); + if (node->rule.variables) + fprintf(output, " yyDo(ctx, yyPop, %d, 0);", countVariables(node->rule.variables)); + fprintf(output, "\n return 1;"); + if (!safe) + { + label(ko); + restore(0); + fprintf(output, "\n yyprintf((stderr, \" fail %%s @ %%s\\n\", \"%s\", ctx->buf+ctx->pos));", node->rule.name); + fprintf(output, "\n return 0;"); + } + fprintf(output, "\n}"); + } + + if (node->rule.next) + Rule_compile_c2(node->rule.next); +} + +static char *header= "\ +#include \n\ +#include \n\ +#include \n\ +"; + +static char *preamble= "\ +#ifndef YY_LOCAL\n\ +#define YY_LOCAL(T) static T\n\ +#endif\n\ +#ifndef YY_ACTION\n\ +#define YY_ACTION(T) static T\n\ +#endif\n\ +#ifndef YY_RULE\n\ +#define YY_RULE(T) static T\n\ +#endif\n\ +#ifndef YY_PARSE\n\ +#define YY_PARSE(T) T\n\ +#endif\n\ +#ifndef YYPARSE\n\ +#define YYPARSE yyparse\n\ +#endif\n\ +#ifndef YYPARSEFROM\n\ +#define YYPARSEFROM yyparsefrom\n\ +#endif\n\ +#ifndef YY_INPUT\n\ +#define YY_INPUT(buf, result, max_size) \\\n\ + { \\\n\ + int yyc= getchar(); \\\n\ + result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \\\n\ + yyprintf((stderr, \"<%c>\", yyc)); \\\n\ + }\n\ +#endif\n\ +#ifndef YY_BEGIN\n\ +#define YY_BEGIN ( ctx->begin= ctx->pos, 1)\n\ +#endif\n\ +#ifndef YY_END\n\ +#define YY_END ( ctx->end= ctx->pos, 1)\n\ +#endif\n\ +#ifdef YY_DEBUG\n\ +# define yyprintf(args) fprintf args\n\ +#else\n\ +# define yyprintf(args)\n\ +#endif\n\ +#ifndef YYSTYPE\n\ +#define YYSTYPE int\n\ +#endif\n\ +\n\ +#ifndef YY_PART\n\ +\n\ +typedef struct _yycontext yycontext;\n\ +typedef void (*yyaction)(yycontext *ctx, char *yytext, int yyleng);\n\ +typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk;\n\ +\n\ +struct _yycontext {\n\ + char *buf;\n\ + int buflen;\n\ + int pos;\n\ + int limit;\n\ + char *text;\n\ + int textlen;\n\ + int begin;\n\ + int end;\n\ + int textmax;\n\ + yythunk *thunks;\n\ + int thunkslen;\n\ + int thunkpos;\n\ + YYSTYPE yy;\n\ + YYSTYPE *val;\n\ + YYSTYPE *vals;\n\ + int valslen;\n\ +#ifdef YY_CTX_MEMBERS\n\ + YY_CTX_MEMBERS\n\ +#endif\n\ +};\n\ +\n\ +#ifdef YY_CTX_LOCAL\n\ +#define YY_CTX_PARAM_ yycontext *yyctx,\n\ +#define YY_CTX_PARAM yycontext *yyctx\n\ +#define YY_CTX_ARG_ yyctx,\n\ +#define YY_CTX_ARG yyctx\n\ +#else\n\ +#define YY_CTX_PARAM_\n\ +#define YY_CTX_PARAM\n\ +#define YY_CTX_ARG_\n\ +#define YY_CTX_ARG\n\ +yycontext yyctx0;\n\ +yycontext *yyctx= &yyctx0;\n\ +#endif\n\ +\n\ +YY_LOCAL(int) yyrefill(yycontext *ctx)\n\ +{\n\ + int yyn;\n\ + while (ctx->buflen - ctx->pos < 512)\n\ + {\n\ + ctx->buflen *= 2;\n\ + ctx->buf= (char *)realloc(ctx->buf, ctx->buflen);\n\ + }\n\ + YY_INPUT((ctx->buf + ctx->pos), yyn, (ctx->buflen - ctx->pos));\n\ + if (!yyn) return 0;\n\ + ctx->limit += yyn;\n\ + return 1;\n\ +}\n\ +\n\ +YY_LOCAL(int) yymatchDot(yycontext *ctx)\n\ +{\n\ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\ + ++ctx->pos;\n\ + return 1;\n\ +}\n\ +\n\ +YY_LOCAL(int) yymatchChar(yycontext *ctx, int c)\n\ +{\n\ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\ + if ((unsigned char)ctx->buf[ctx->pos] == c)\n\ + {\n\ + ++ctx->pos;\n\ + yyprintf((stderr, \" ok yymatchChar(ctx, %c) @ %s\\n\", c, ctx->buf+ctx->pos));\n\ + return 1;\n\ + }\n\ + yyprintf((stderr, \" fail yymatchChar(ctx, %c) @ %s\\n\", c, ctx->buf+ctx->pos));\n\ + return 0;\n\ +}\n\ +\n\ +YY_LOCAL(int) yymatchString(yycontext *ctx, char *s)\n\ +{\n\ + int yysav= ctx->pos;\n\ + while (*s)\n\ + {\n\ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\ + if (ctx->buf[ctx->pos] != *s)\n\ + {\n\ + ctx->pos= yysav;\n\ + return 0;\n\ + }\n\ + ++s;\n\ + ++ctx->pos;\n\ + }\n\ + return 1;\n\ +}\n\ +\n\ +YY_LOCAL(int) yymatchClass(yycontext *ctx, unsigned char *bits)\n\ +{\n\ + int c;\n\ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\ + c= (unsigned char)ctx->buf[ctx->pos];\n\ + if (bits[c >> 3] & (1 << (c & 7)))\n\ + {\n\ + ++ctx->pos;\n\ + yyprintf((stderr, \" ok yymatchClass @ %s\\n\", ctx->buf+ctx->pos));\n\ + return 1;\n\ + }\n\ + yyprintf((stderr, \" fail yymatchClass @ %s\\n\", ctx->buf+ctx->pos));\n\ + return 0;\n\ +}\n\ +\n\ +YY_LOCAL(void) yyDo(yycontext *ctx, yyaction action, int begin, int end)\n\ +{\n\ + while (ctx->thunkpos >= ctx->thunkslen)\n\ + {\n\ + ctx->thunkslen *= 2;\n\ + ctx->thunks= (yythunk *)realloc(ctx->thunks, sizeof(yythunk) * ctx->thunkslen);\n\ + }\n\ + ctx->thunks[ctx->thunkpos].begin= begin;\n\ + ctx->thunks[ctx->thunkpos].end= end;\n\ + ctx->thunks[ctx->thunkpos].action= action;\n\ + ++ctx->thunkpos;\n\ +}\n\ +\n\ +YY_LOCAL(int) yyText(yycontext *ctx, int begin, int end)\n\ +{\n\ + int yyleng= end - begin;\n\ + if (yyleng <= 0)\n\ + yyleng= 0;\n\ + else\n\ + {\n\ + while (ctx->textlen < (yyleng + 1))\n\ + {\n\ + ctx->textlen *= 2;\n\ + ctx->text= (char *)realloc(ctx->text, ctx->textlen);\n\ + }\n\ + memcpy(ctx->text, ctx->buf + begin, yyleng);\n\ + }\n\ + ctx->text[yyleng]= '\\0';\n\ + return yyleng;\n\ +}\n\ +\n\ +YY_LOCAL(void) yyDone(yycontext *ctx)\n\ +{\n\ + int pos;\n\ + for (pos= 0; pos < ctx->thunkpos; ++pos)\n\ + {\n\ + yythunk *thunk= &ctx->thunks[pos];\n\ + int yyleng= thunk->end ? yyText(ctx, thunk->begin, thunk->end) : thunk->begin;\n\ + yyprintf((stderr, \"DO [%d] %p %s\\n\", pos, thunk->action, ctx->text));\n\ + thunk->action(ctx, ctx->text, yyleng);\n\ + }\n\ + ctx->thunkpos= 0;\n\ +}\n\ +\n\ +YY_LOCAL(void) yyCommit(yycontext *ctx)\n\ +{\n\ + if ((ctx->limit -= ctx->pos))\n\ + {\n\ + memmove(ctx->buf, ctx->buf + ctx->pos, ctx->limit);\n\ + }\n\ + ctx->begin -= ctx->pos;\n\ + ctx->end -= ctx->pos;\n\ + ctx->pos= ctx->thunkpos= 0;\n\ +}\n\ +\n\ +YY_LOCAL(int) yyAccept(yycontext *ctx, int tp0)\n\ +{\n\ + if (tp0)\n\ + {\n\ + fprintf(stderr, \"accept denied at %d\\n\", tp0);\n\ + return 0;\n\ + }\n\ + else\n\ + {\n\ + yyDone(ctx);\n\ + yyCommit(ctx);\n\ + }\n\ + return 1;\n\ +}\n\ +\n\ +YY_LOCAL(void) yyPush(yycontext *ctx, char *text, int count) { ctx->val += count; }\n\ +YY_LOCAL(void) yyPop(yycontext *ctx, char *text, int count) { ctx->val -= count; }\n\ +YY_LOCAL(void) yySet(yycontext *ctx, char *text, int count) { ctx->val[count]= ctx->yy; }\n\ +\n\ +#endif /* YY_PART */\n\ +\n\ +#define YYACCEPT yyAccept(ctx, yythunkpos0)\n\ +\n\ +"; + +static char *footer= "\n\ +\n\ +#ifndef YY_PART\n\ +\n\ +typedef int (*yyrule)(yycontext *ctx);\n\ +\n\ +YY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart)\n\ +{\n\ + int yyok;\n\ + if (!yyctx->buflen)\n\ + {\n\ + yyctx->buflen= 1024;\n\ + yyctx->buf= (char *)malloc(yyctx->buflen);\n\ + yyctx->textlen= 1024;\n\ + yyctx->text= (char *)malloc(yyctx->textlen);\n\ + yyctx->thunkslen= 32;\n\ + yyctx->thunks= (yythunk *)malloc(sizeof(yythunk) * yyctx->thunkslen);\n\ + yyctx->valslen= 32;\n\ + yyctx->vals= (YYSTYPE *)malloc(sizeof(YYSTYPE) * yyctx->valslen);\n\ + yyctx->begin= yyctx->end= yyctx->pos= yyctx->limit= yyctx->thunkpos= 0;\n\ + }\n\ + yyctx->begin= yyctx->end= yyctx->pos;\n\ + yyctx->thunkpos= 0;\n\ + yyctx->val= yyctx->vals;\n\ + yyok= yystart(yyctx);\n\ + if (yyok) yyDone(yyctx);\n\ + yyCommit(yyctx);\n\ + return yyok;\n\ +}\n\ +\n\ +YY_PARSE(int) YYPARSE(YY_CTX_PARAM)\n\ +{\n\ + return YYPARSEFROM(YY_CTX_ARG_ yy_%s);\n\ +}\n\ +\n\ +#endif\n\ +"; + +void Rule_compile_c_header(void) +{ + fprintf(output, "/* A recursive-descent parser generated by peg %d.%d.%d */\n", PEG_MAJOR, PEG_MINOR, PEG_LEVEL); + fprintf(output, "\n"); + fprintf(output, "%s", header); + fprintf(output, "#define YYRULECOUNT %d\n", ruleCount); +} + +int consumesInput(Node *node) +{ + if (!node) return 0; + + switch (node->type) + { + case Rule: + { + int result= 0; + if (RuleReached & node->rule.flags) + fprintf(stderr, "possible infinite left recursion in rule '%s'\n", node->rule.name); + else + { + node->rule.flags |= RuleReached; + result= consumesInput(node->rule.expression); + node->rule.flags &= ~RuleReached; + } + return result; + } + break; + + case Dot: return 1; + case Name: return consumesInput(node->name.rule); + case Character: + case String: return strlen(node->string.value) > 0; + case Class: return 1; + case Action: return 0; + case Predicate: return 0; + + case Alternate: + { + Node *n; + for (n= node->alternate.first; n; n= n->alternate.next) + if (!consumesInput(n)) + return 0; + } + return 1; + + case Sequence: + { + Node *n; + for (n= node->alternate.first; n; n= n->alternate.next) + if (consumesInput(n)) + return 1; + } + return 0; + + case PeekFor: return 0; + case PeekNot: return 0; + case Query: return 0; + case Star: return 0; + case Plus: return consumesInput(node->plus.element); + + default: + fprintf(stderr, "\nconsumesInput: illegal node type %d\n", node->type); + exit(1); + } + return 0; +} + + +void Rule_compile_c(Node *node) +{ + Node *n; + + for (n= rules; n; n= n->rule.next) + consumesInput(n); + + fprintf(output, "%s", preamble); + for (n= node; n; n= n->rule.next) + fprintf(output, "YY_RULE(int) yy_%s(yycontext *ctx); /* %d */\n", n->rule.name, n->rule.id); + fprintf(output, "\n"); + for (n= actions; n; n= n->action.list) + { + fprintf(output, "YY_ACTION(void) yy%s(yycontext *ctx, char *yytext, int yyleng)\n{\n", n->action.name); + defineVariables(n->action.rule->rule.variables); + fprintf(output, " yyprintf((stderr, \"do yy%s\\n\"));\n", n->action.name); + fprintf(output, " %s;\n", n->action.text); + undefineVariables(n->action.rule->rule.variables); + fprintf(output, "}\n"); + } + Rule_compile_c2(node); + fprintf(output, footer, start->rule.name); +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/Makefile b/supportlibs/pegmarkdown/peg-0.1.9/examples/Makefile new file mode 100644 index 000000000..30d3cc8f8 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/Makefile @@ -0,0 +1,88 @@ +EXAMPLES = test rule accept wc dc dcv calc basic localctx + +CFLAGS = -g -O3 + +DIFF = diff +TEE = cat > + +all : $(EXAMPLES) + +test : .FORCE + ../peg -o test.peg.c test.peg + $(CC) $(CFLAGS) -o test test.c + echo 'ab.ac.ad.ae.afg.afh.afg.afh.afi.afj.' | ./$@ | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +rule : .FORCE + ../peg -o rule.peg.c rule.peg + $(CC) $(CFLAGS) -o rule rule.c + echo 'abcbcdabcbcdabcbcdabcbcd' | ./$@ | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +accept : .FORCE + ../peg -o accept.peg.c accept.peg + $(CC) $(CFLAGS) -o accept accept.c + echo 'abcbcdabcbcdabcbcdabcbcd' | ./$@ | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +wc : .FORCE + ../leg -o wc.leg.c wc.leg + $(CC) $(CFLAGS) -o wc wc.leg.c + cat wc.leg | ./$@ | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +dc : .FORCE + ../peg -o dc.peg.c dc.peg + $(CC) $(CFLAGS) -o dc dc.c + echo ' 2 *3 *(3+ 4) ' | ./dc | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +dcv : .FORCE + ../peg -o dcv.peg.c dcv.peg + $(CC) $(CFLAGS) -o dcv dcv.c + echo 'a = 6; b = 7; a * b' | ./dcv | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +calc : .FORCE + ../leg -o calc.leg.c calc.leg + $(CC) $(CFLAGS) -o calc calc.leg.c + echo 'a = 6; b = 7; a * b' | ./calc | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +basic : .FORCE + ../leg -o basic.leg.c basic.leg + $(CC) $(CFLAGS) -o basic basic.leg.c + ( echo 'load "test"'; echo "run" ) | ./basic | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +localctx : .FORCE + ../peg -o test.peg.c test.peg + $(CC) $(CFLAGS) -o localctx localctx.c + echo 'ab.ac.ad.ae.afg.afh.afg.afh.afi.afj.' | ./$@ | $(TEE) $@.out + $(DIFF) $@.ref $@.out + rm -f $@.out + @echo + +clean : .FORCE + rm -f *~ *.o *.[pl]eg.[cd] $(EXAMPLES) + rm -rf *.dSYM + +spotless : clean + +.FORCE : diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.c new file mode 100644 index 000000000..781e3b11d --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.c @@ -0,0 +1,11 @@ +#include +#include + +#include "accept.peg.c" + +int main() +{ + while (yyparse()); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.peg b/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.peg new file mode 100644 index 000000000..9b28e4040 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.peg @@ -0,0 +1,8 @@ +start <- abcd+ + +abcd <- 'a' { printf("A %d\n", yypos); } bc { printf("ABC %d\n", yypos); } &{YYACCEPT} + / 'b' { printf("B %d\n", yypos); } cd { printf("BCD %d\n", yypos); } &{YYACCEPT} + +bc <- 'b' { printf("B %d\n", yypos); } 'c' { printf("C %d\n", yypos); } + +cd <- 'c' { printf("C %d\n", yypos); } 'd' { printf("D %d\n", yypos); } diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.ref new file mode 100644 index 000000000..789f52830 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/accept.ref @@ -0,0 +1,32 @@ +A 3 +B 3 +C 3 +ABC 3 +B 3 +C 3 +D 3 +BCD 3 +A 3 +B 3 +C 3 +ABC 3 +B 3 +C 3 +D 3 +BCD 3 +A 3 +B 3 +C 3 +ABC 3 +B 3 +C 3 +D 3 +BCD 3 +A 3 +B 3 +C 3 +ABC 3 +B 3 +C 3 +D 3 +BCD 3 diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/basic.leg b/supportlibs/pegmarkdown/peg-0.1.9/examples/basic.leg new file mode 100644 index 000000000..ed38a8d71 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/basic.leg @@ -0,0 +1,361 @@ +# A 'syntax-directed interpreter' (all execution is a side-effect of parsing). +# Inspired by Dennis Allison's original Tiny BASIC grammar, circa 1975. +# +# Copyright (c) 2007 by Ian Piumarta +# All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the 'Software'), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, provided that the above copyright notice(s) and this +# permission notice appear in all copies of the Software. Acknowledgement +# of the use of this Software in supporting documentation would be +# appreciated but is not required. +# +# THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK. +# +# Last edited: 2012-04-29 15:14:06 by piumarta on emilia + +%{ +# include + + typedef struct line line; + + struct line + { + int number; + int length; + char *text; + }; + + line *lines= 0; + int numLines= 0; + int pc= -1, epc= -1; + int batch= 0; + + int nextline(char *buf, int max); + +# define min(x, y) ((x) < (y) ? (x) : (y)) + +# define YY_INPUT(buf, result, max_size) \ + { \ + if ((pc >= 0) && (pc < numLines)) \ + { \ + line *linep= lines+pc++; \ + result= min(max_size, linep->length); \ + memcpy(buf, linep->text, result); \ + } \ + else \ + result= nextline(buf, max_size); \ + } + + union value { + int number; + char *string; + int (*binop)(int lhs, int rhs); + }; + +# define YYSTYPE union value + + int variables[26]; + + void accept(int number, char *line); + + void save(char *name); + void load(char *name); + void type(char *name); + + int lessThan(int lhs, int rhs) { return lhs < rhs; } + int lessEqual(int lhs, int rhs) { return lhs <= rhs; } + int notEqual(int lhs, int rhs) { return lhs != rhs; } + int equalTo(int lhs, int rhs) { return lhs == rhs; } + int greaterEqual(int lhs, int rhs) { return lhs >= rhs; } + int greaterThan(int lhs, int rhs) { return lhs > rhs; } + + int input(void); + + int stack[1024], sp= 0; + + char *help; + + void error(char *fmt, ...); + int findLine(int n, int create); +%} + +line = - s:statement CR +| - n:number < ( !CR . )* CR > { accept(n.number, yytext); } +| - CR +| - < ( !CR . )* CR > { epc= pc; error("syntax error"); } +| - !. { exit(0); } + +statement = 'print'- expr-list +| 'if'- e1:expression r:relop e2:expression { if (!r.binop(e1.number, e2.number)) yythunkpos= 0; } + 'then'- statement +| 'goto'- e:expression { epc= pc; if ((pc= findLine(e.number, 0)) < 0) error("no such line"); } +| 'input'- var-list +| 'let'- v:var EQUAL e:expression { variables[v.number]= e.number; } +| 'gosub'- e:expression { epc= pc; if (sp < 1024) stack[sp++]= pc, pc= findLine(e.number, 0); else error("too many gosubs"); + if (pc < 0) error("no such line"); } +| 'return'- { epc= pc; if ((pc= sp ? stack[--sp] : -1) < 0) error("no gosub"); } +| 'clear'- { while (numLines) accept(lines->number, "\n"); } +| 'list'- { int i; for (i= 0; i < numLines; ++i) printf("%5d %s", lines[i].number, lines[i].text); } +| 'run'- s:string { load(s.string); pc= 0; } +| 'run'- { pc= 0; } +| 'end'- { pc= -1; if (batch) exit(0); } +| 'rem'- ( !CR . )* +| ('bye'|'quit'|'exit')- { exit(0); } +| 'save'- s:string { save(s.string); } +| 'load'- s:string { load(s.string); } +| 'type'- s:string { type(s.string); } +| 'dir'- { system("ls *.bas"); } +| 'help'- { fprintf(stderr, "%s", help); } + +expr-list = ( e:string { printf("%s", e.string); } + | e:expression { printf("%d", e.number); } + )? ( COMMA ( e:string { printf("%s", e.string); } + | e:expression { printf("%d", e.number); } + ) + )* ( COMMA + | !COMMA { printf("\n"); } + ) + +var-list = v:var { variables[v.number]= input(); } + ( COMMA v:var { variables[v.number]= input(); } + )* + +expression = ( PLUS? l:term + | MINUS l:term { l.number = -l.number } + ) ( PLUS r:term { l.number += r.number } + | MINUS r:term { l.number -= r.number } + )* { $$.number = l.number } + +term = l:factor ( STAR r:factor { l.number *= r.number } + | SLASH r:factor { l.number /= r.number } + )* { $$.number = l.number } + +factor = v:var { $$.number = variables[v.number] } +| n:number +| OPEN expression CLOSE + +var = < [a-z] > - { $$.number = yytext[0] - 'a' } + +number = < digit+ > - { $$.number = atoi(yytext); } + +digit = [0-9] + +string = '"' < [^\"]* > '"' - { $$.string = yytext; } + +relop = '<=' - { $$.binop= lessEqual; } +| '<>' - { $$.binop= notEqual; } +| '<' - { $$.binop= lessThan; } +| '>=' - { $$.binop= greaterEqual; } +| '>' - { $$.binop= greaterThan; } +| '=' - { $$.binop= equalTo; } + +EQUAL = '=' - CLOSE = ')' - OPEN = '(' - +SLASH = '/' - STAR = '*' - MINUS = '-' - +PLUS = '+' - COMMA = ',' - + +- = [ \t]* + +CR = '\n' | '\r' | '\r\n' + +%% + +#include +#include + +char *help= + "print | [, | ...] [,]\n" + "if <|<=|<>|=|>=|> then \n" + "input [, ...] let = \n" + "goto gosub \n" + "end return\n" + "list clear\n" + "run [\"filename\"] rem \n" + "dir type \"filename\"\n" + "save \"filename\" load \"filename\"\n" + "bye|quit|exit help\n" + ; + +void error(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (epc > 0) + fprintf(stderr, "\nline %d: %s", lines[epc-1].number, lines[epc-1].text); + else + fprintf(stderr, "\n"); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + epc= pc= -1; +} + +#ifdef USE_READLINE +# include +# include +#endif + +int nextline(char *buf, int max) +{ + pc= -1; + if (batch) exit(0); + if (isatty(fileno(stdin))) + { +# ifdef USE_READLINE + char *line= readline(">"); + if (line) + { + int len= strlen(line); + if (len >= max) len= max - 1; + strncpy(buf, line, len); + (buf)[len]= '\n'; + add_history(line); + free(line); + return len + 1; + } + else + { + printf("\n"); + return 0; + } +# endif + putchar('>'); + fflush(stdout); + } + return fgets(buf, max, stdin) ? strlen(buf) : 0; +} + +int maxLines= 0; + +int findLine(int n, int create) +{ + int lo= 0, hi= numLines - 1; + while (lo <= hi) + { + int mid= (lo + hi) / 2, lno= lines[mid].number; + if (lno > n) + hi= mid - 1; + else if (lno < n) + lo= mid + 1; + else + return mid; + } + if (create) + { + if (numLines == maxLines) + { + maxLines *= 2; + lines= realloc(lines, sizeof(line) * maxLines); + } + if (lo < numLines) + memmove(lines + lo + 1, lines + lo, sizeof(line) * (numLines - lo)); + ++numLines; + lines[lo].number= n; + lines[lo].text= 0; + return lo; + } + return -1; +} + +void accept(int n, char *s) +{ + if (s[0] < 32) /* delete */ + { + int lno= findLine(n, 0); + if (lno >= 0) + { + if (lno < numLines - 1) + memmove(lines + lno, lines + lno + 1, sizeof(line) * (numLines - lno - 1)); + --numLines; + } + } + else /* insert */ + { + int lno= findLine(n, 1); + if (lines[lno].text) free(lines[lno].text); + lines[lno].length= strlen(s); + lines[lno].text= strdup(s); + } +} + +char *extend(char *name) +{ + static char path[1024]; + int len= strlen(name); + sprintf(path, "%s%s", name, (((len > 4) && !strcasecmp(".bas", name + len - 4)) ? "" : ".bas")); + return path; +} + +void save(char *name) +{ + FILE *f= fopen(name= extend(name), "w"); + if (!f) + perror(name); + else + { + int i; + for (i= 0; i < numLines; ++i) + fprintf(f, "%d %s", lines[i].number, lines[i].text); + fclose(f); + } +} + +void load(char *name) +{ + FILE *f= fopen(name= extend(name), "r"); + if (!f) + perror(name); + else + { + int lineNumber; + char lineText[1024]; + while ((1 == fscanf(f, " %d ", &lineNumber)) && fgets(lineText, sizeof(lineText), f)) + accept(lineNumber, lineText); + fclose(f); + } +} + +void type(char *name) +{ + FILE *f= fopen(name= extend(name), "r"); + if (!f) + perror(name); + else + { + int c, d; + while ((c= getc(f)) >= 0) + putchar(d= c); + fclose(f); + if ('\n' != d && '\r' != d) putchar('\n'); + } +} + +int input(void) +{ + char line[32]; + fgets(line, sizeof(line), stdin); + return atoi(line); +} + +int main(int argc, char **argv) +{ + lines= malloc(sizeof(line) * (maxLines= 32)); + numLines= 0; + + if (argc > 1) + { + batch= 1; + while (argc-- > 1) + load(*++argv); + pc= 0; + } + + while (!feof(stdin)) + yyparse(); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/basic.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/basic.ref new file mode 100644 index 000000000..90d916c89 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/basic.ref @@ -0,0 +1,10 @@ + 1 + 2 4 + 3 6 9 + 4 8 12 16 + 5 10 15 20 25 + 6 12 18 24 30 36 + 7 14 21 28 35 42 49 + 8 16 24 32 40 48 56 64 + 9 18 27 36 45 54 63 72 81 + 10 20 30 40 50 60 70 80 90 100 diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/bench.bas b/supportlibs/pegmarkdown/peg-0.1.9/examples/bench.bas new file mode 100644 index 000000000..ffdbd44ff --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/bench.bas @@ -0,0 +1,8 @@ +100 let n=100000 +120 let m=0 +110 let s=0 +130 let m=m+1 +140 let s=s+m +150 if m +int vars[26]; +%} + +Stmt = - e:Expr EOL { printf("%d\n", e); } + | ( !EOL . )* EOL { printf("error\n"); } + +Expr = i:ID ASSIGN s:Sum { $$= vars[i]= s; } + | s:Sum { $$= s; } + +Sum = l:Product + ( PLUS r:Product { l += r; } + | MINUS r:Product { l -= r; } + )* { $$= l; } + +Product = l:Value + ( TIMES r:Value { l *= r; } + | DIVIDE r:Value { l /= r; } + )* { $$= l; } + +Value = i:NUMBER { $$= atoi(yytext); } + | i:ID !ASSIGN { $$= vars[i]; } + | OPEN i:Expr CLOSE { $$= i; } + +NUMBER = < [0-9]+ > - { $$= atoi(yytext); } +ID = < [a-z] > - { $$= yytext[0] - 'a'; } +ASSIGN = '=' - +PLUS = '+' - +MINUS = '-' - +TIMES = '*' - +DIVIDE = '/' - +OPEN = '(' - +CLOSE = ')' - + +- = [ \t]* +EOL = '\n' | '\r\n' | '\r' | ';' + +%% + +int main() +{ + while (yyparse()); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/calc.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/calc.ref new file mode 100644 index 000000000..dbd7d59ec --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/calc.ref @@ -0,0 +1,3 @@ +6 +7 +42 diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.c new file mode 100644 index 000000000..32bf1a54a --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.c @@ -0,0 +1,17 @@ +#include +#include + +int stack[1024]; +int stackp= -1; + +int push(int n) { return stack[++stackp]= n; } +int pop(void) { return stack[stackp--]; } + +#include "dc.peg.c" + +int main() +{ + while (yyparse()); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.peg b/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.peg new file mode 100644 index 000000000..75dcb6719 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.peg @@ -0,0 +1,27 @@ +# Grammar + +Expr <- SPACE Sum EOL { printf("%d\n", pop()); } + / (!EOL .)* EOL { printf("error\n"); } + +Sum <- Product ( PLUS Product { int r= pop(), l= pop(); push(l + r); } + / MINUS Product { int r= pop(), l= pop(); push(l - r); } + )* + +Product <- Value ( TIMES Value { int r= pop(), l= pop(); push(l * r); } + / DIVIDE Value { int r= pop(), l= pop(); push(l / r); } + )* + +Value <- NUMBER { push(atoi(yytext)); } + / OPEN Sum CLOSE + +# Lexemes + +NUMBER <- < [0-9]+ > SPACE +PLUS <- '+' SPACE +MINUS <- '-' SPACE +TIMES <- '*' SPACE +DIVIDE <- '/' SPACE +OPEN <- '(' SPACE +CLOSE <- ')' SPACE +SPACE <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.ref new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/dc.ref @@ -0,0 +1 @@ +42 diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.c new file mode 100644 index 000000000..0c5c46d85 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.c @@ -0,0 +1,20 @@ +#include +#include + +int stack[1024]; +int stackp= -1; +int var= 0; +int vars[26]; + +int push(int n) { return stack[++stackp]= n; } +int pop(void) { return stack[stackp--]; } +int top(void) { return stack[stackp]; } + +#include "dcv.peg.c" + +int main() +{ + while (yyparse()); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.peg b/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.peg new file mode 100644 index 000000000..2ae3a8cb0 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.peg @@ -0,0 +1,34 @@ +# Grammar + +Stmt <- SPACE Expr EOL { printf("%d\n", pop()); } + / (!EOL .)* EOL { printf("error\n"); } + +Expr <- ID { var= yytext[0] } ASSIGN Sum { vars[var - 'a']= top(); } + / Sum + +Sum <- Product ( PLUS Product { int r= pop(), l= pop(); push(l + r); } + / MINUS Product { int r= pop(), l= pop(); push(l - r); } + )* + +Product <- Value ( TIMES Value { int r= pop(), l= pop(); push(l * r); } + / DIVIDE Value { int r= pop(), l= pop(); push(l / r); } + )* + +Value <- NUMBER { push(atoi(yytext)); } + / < ID > !ASSIGN { push(vars[yytext[0] - 'a']); } + / OPEN Expr CLOSE + +# Lexemes + +NUMBER <- < [0-9]+ > SPACE +ID <- < [a-z] > SPACE +ASSIGN <- '=' SPACE +PLUS <- '+' SPACE +MINUS <- '-' SPACE +TIMES <- '*' SPACE +DIVIDE <- '/' SPACE +OPEN <- '(' SPACE +CLOSE <- ')' SPACE + +SPACE <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.ref new file mode 100644 index 000000000..dbd7d59ec --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/dcv.ref @@ -0,0 +1,3 @@ +6 +7 +42 diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/fibonacci.bas b/supportlibs/pegmarkdown/peg-0.1.9/examples/fibonacci.bas new file mode 100644 index 000000000..1872bd3b2 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/fibonacci.bas @@ -0,0 +1,17 @@ +100 let n=32 +110 gosub 200 +120 print "fibonacci(",n,") = ", m +130 end + +200 let c=n +210 let b=1 +220 if c<2 then goto 400 +230 let c=c-1 +240 let a=1 +300 let c=c-1 +310 let d=a+b +320 let a=b +330 let b=d+1 +340 if c<>0 then goto 300 +400 let m=b +410 return diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/left.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/left.c new file mode 100644 index 000000000..ac8cd0bd8 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/left.c @@ -0,0 +1,17 @@ +#include + +#define YY_INPUT(buf, result, max) \ +{ \ + int c= getchar(); \ + result= (EOF == c) ? 0 : (*(buf)= c, 1); \ + if (EOF != c) printf("<%c>\n", c); \ +} + +#include "left.peg.c" + +int main() +{ + printf(yyparse() ? "success\n" : "failure\n"); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/left.peg b/supportlibs/pegmarkdown/peg-0.1.9/examples/left.peg new file mode 100644 index 000000000..f282227d5 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/left.peg @@ -0,0 +1,3 @@ +# Grammar + +S <- (S 'a' / 'a') !'a' diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/localctx.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/localctx.c new file mode 100644 index 000000000..837ebc884 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/localctx.c @@ -0,0 +1,13 @@ +#include + +#define YY_CTX_LOCAL + +#include "test.peg.c" + +int main() +{ + yycontext ctx; + memset(&ctx, 0, sizeof(yycontext)); + while (yyparse(&ctx)); + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/localctx.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/localctx.ref new file mode 100644 index 000000000..2d181091a --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/localctx.ref @@ -0,0 +1,10 @@ +a1 ab1 . +a2 ac2 . +a3 ad3 . +a3 ae3 . +a4 af4 afg4 . +a4 af5 afh5 . +a4 af4 afg4 . +a4 af5 afh5 . +af6 afi6 a6 . +af6 af7 afj7 a6 . diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.c new file mode 100644 index 000000000..15eb0c64b --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.c @@ -0,0 +1,11 @@ +#include +#include + +#include "rule.peg.c" + +int main() +{ + while (yyparse()); + + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.peg b/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.peg new file mode 100644 index 000000000..60a32faa1 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.peg @@ -0,0 +1,8 @@ +start <- abcd+ + +abcd <- 'a' { printf("A %d\n", yypos); } bc { printf("ABC %d\n", yypos); } + / 'b' { printf("B %d\n", yypos); } cd { printf("BCD %d\n", yypos); } + +bc <- 'b' { printf("B %d\n", yypos); } 'c' { printf("C %d\n", yypos); } + +cd <- 'c' { printf("C %d\n", yypos); } 'd' { printf("D %d\n", yypos); } diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.ref new file mode 100644 index 000000000..4249ebec5 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/rule.ref @@ -0,0 +1,32 @@ +A 24 +B 24 +C 24 +ABC 24 +B 24 +C 24 +D 24 +BCD 24 +A 24 +B 24 +C 24 +ABC 24 +B 24 +C 24 +D 24 +BCD 24 +A 24 +B 24 +C 24 +ABC 24 +B 24 +C 24 +D 24 +BCD 24 +A 24 +B 24 +C 24 +ABC 24 +B 24 +C 24 +D 24 +BCD 24 diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/test.bas b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.bas new file mode 100644 index 000000000..8a96e1070 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.bas @@ -0,0 +1,12 @@ +10 let i=1 +20 gosub 100 +30 let i=i+1 +40 if i<=10 then goto 20 +50 end + +100 let j=1 +110 print " ", i*j, +120 let j=j+1 +130 if j<=i then goto 110 +140 print +150 return diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/test.c b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.c new file mode 100644 index 000000000..0403422c3 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.c @@ -0,0 +1,8 @@ +#include +#include "test.peg.c" + +int main() +{ + while (yyparse()); + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/test.peg b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.peg new file mode 100644 index 000000000..716d52372 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.peg @@ -0,0 +1,13 @@ +start <- body '.' { printf(".\n"); } + +body <- 'a' { printf("a1 "); } 'b' { printf("ab1 "); } + + / 'a' { printf("a2 "); } 'c' { printf("ac2 "); } + + / 'a' { printf("a3 "); } ( 'd' { printf("ad3 "); } / 'e' { printf("ae3 "); } ) + + / 'a' { printf("a4 "); } ( 'f' { printf("af4 "); } 'g' { printf("afg4 "); } + / 'f' { printf("af5 "); } 'h' { printf("afh5 "); } ) + + / 'a' { printf("a6 "); } ( 'f' &{ printf("af6 ") } 'i' &{ printf("afi6 ") } + / 'f' &{ printf("af7 ") } 'j' &{ printf("afj7 ") } ) diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/test.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.ref new file mode 100644 index 000000000..2d181091a --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/test.ref @@ -0,0 +1,10 @@ +a1 ab1 . +a2 ac2 . +a3 ad3 . +a3 ae3 . +a4 af4 afg4 . +a4 af5 afh5 . +a4 af4 afg4 . +a4 af5 afh5 . +af6 afi6 a6 . +af6 af7 afj7 a6 . diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/username.leg b/supportlibs/pegmarkdown/peg-0.1.9/examples/username.leg new file mode 100644 index 000000000..2170052aa --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/username.leg @@ -0,0 +1,14 @@ +%{ +#include +%} + +start = "username" { printf("%s", getlogin()); } +| < . > { putchar(yytext[0]); } + +%% + +int main() +{ + while (yyparse()); + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/wc.leg b/supportlibs/pegmarkdown/peg-0.1.9/examples/wc.leg new file mode 100644 index 000000000..59199c89f --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/wc.leg @@ -0,0 +1,22 @@ +%{ +#include +int lines= 0, words= 0, chars= 0; +%} + +start = (line | word | char) + +line = < (( '\n' '\r'* ) | ( '\r' '\n'* )) > { lines++; chars += yyleng; } +word = < [a-zA-Z]+ > { words++; chars += yyleng; printf("<%s>\n", yytext); } +char = . { chars++; } + +%% + +int main() +{ + while (yyparse()) + ; + printf("%d lines\n", lines); + printf("%d chars\n", chars); + printf("%d words\n", words); + return 0; +} diff --git a/supportlibs/pegmarkdown/peg-0.1.9/examples/wc.ref b/supportlibs/pegmarkdown/peg-0.1.9/examples/wc.ref new file mode 100644 index 000000000..083a46e64 --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/examples/wc.ref @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +22 lines +425 chars +52 words diff --git a/supportlibs/pegmarkdown/peg-0.1.9/leg.c b/supportlibs/pegmarkdown/peg-0.1.9/leg.c new file mode 100644 index 000000000..91b696d1e --- /dev/null +++ b/supportlibs/pegmarkdown/peg-0.1.9/leg.c @@ -0,0 +1,1209 @@ +/* A recursive-descent parser generated by peg 0.1.9 */ + +#include +#include +#include +#define YYRULECOUNT 36 + +# include "tree.h" +# include "version.h" + +# include +# include +# include +# include +# include +# include + + typedef struct Header Header; + + struct Header { + char *text; + Header *next; + }; + + FILE *input= 0; + + int verboseFlag= 0; + + static int lineNumber= 0; + static char *fileName= 0; + static char *trailer= 0; + static Header *headers= 0; + + void makeHeader(char *text); + void makeTrailer(char *text); + + void yyerror(char *message); + +# define YY_INPUT(buf, result, max) \ + { \ + int c= getc(input); \ + if ('\n' == c || '\r' == c) ++lineNumber; \ + result= (EOF == c) ? 0 : (*(buf)= c, 1); \ + } + +# define YY_LOCAL(T) static T +# define YY_RULE(T) static T + +#ifndef YY_LOCAL +#define YY_LOCAL(T) static T +#endif +#ifndef YY_ACTION +#define YY_ACTION(T) static T +#endif +#ifndef YY_RULE +#define YY_RULE(T) static T +#endif +#ifndef YY_PARSE +#define YY_PARSE(T) T +#endif +#ifndef YYPARSE +#define YYPARSE yyparse +#endif +#ifndef YYPARSEFROM +#define YYPARSEFROM yyparsefrom +#endif +#ifndef YY_INPUT +#define YY_INPUT(buf, result, max_size) \ + { \ + int yyc= getchar(); \ + result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ + yyprintf((stderr, "<%c>", yyc)); \ + } +#endif +#ifndef YY_BEGIN +#define YY_BEGIN ( ctx->begin= ctx->pos, 1) +#endif +#ifndef YY_END +#define YY_END ( ctx->end= ctx->pos, 1) +#endif +#ifdef YY_DEBUG +# define yyprintf(args) fprintf args +#else +# define yyprintf(args) +#endif +#ifndef YYSTYPE +#define YYSTYPE int +#endif + +#ifndef YY_PART + +typedef struct _yycontext yycontext; +typedef void (*yyaction)(yycontext *ctx, char *yytext, int yyleng); +typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk; + +struct _yycontext { + char *buf; + int buflen; + int pos; + int limit; + char *text; + int textlen; + int begin; + int end; + int textmax; + yythunk *thunks; + int thunkslen; + int thunkpos; + YYSTYPE yy; + YYSTYPE *val; + YYSTYPE *vals; + int valslen; +#ifdef YY_CTX_MEMBERS + YY_CTX_MEMBERS +#endif +}; + +#ifdef YY_CTX_LOCAL +#define YY_CTX_PARAM_ yycontext *yyctx, +#define YY_CTX_PARAM yycontext *yyctx +#define YY_CTX_ARG_ yyctx, +#define YY_CTX_ARG yyctx +#else +#define YY_CTX_PARAM_ +#define YY_CTX_PARAM +#define YY_CTX_ARG_ +#define YY_CTX_ARG +yycontext yyctx0; +yycontext *yyctx= &yyctx0; +#endif + +YY_LOCAL(int) yyrefill(yycontext *ctx) +{ + int yyn; + while (ctx->buflen - ctx->pos < 512) + { + ctx->buflen *= 2; + ctx->buf= (char *)realloc(ctx->buf, ctx->buflen); + } + YY_INPUT((ctx->buf + ctx->pos), yyn, (ctx->buflen - ctx->pos)); + if (!yyn) return 0; + ctx->limit += yyn; + return 1; +} + +YY_LOCAL(int) yymatchDot(yycontext *ctx) +{ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + ++ctx->pos; + return 1; +} + +YY_LOCAL(int) yymatchChar(yycontext *ctx, int c) +{ + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + if ((unsigned char)ctx->buf[ctx->pos] == c) + { + ++ctx->pos; + yyprintf((stderr, " ok yymatchChar(ctx, %c) @ %s\n", c, ctx->buf+ctx->pos)); + return 1; + } + yyprintf((stderr, " fail yymatchChar(ctx, %c) @ %s\n", c, ctx->buf+ctx->pos)); + return 0; +} + +YY_LOCAL(int) yymatchString(yycontext *ctx, char *s) +{ + int yysav= ctx->pos; + while (*s) + { + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + if (ctx->buf[ctx->pos] != *s) + { + ctx->pos= yysav; + return 0; + } + ++s; + ++ctx->pos; + } + return 1; +} + +YY_LOCAL(int) yymatchClass(yycontext *ctx, unsigned char *bits) +{ + int c; + if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0; + c= (unsigned char)ctx->buf[ctx->pos]; + if (bits[c >> 3] & (1 << (c & 7))) + { + ++ctx->pos; + yyprintf((stderr, " ok yymatchClass @ %s\n", ctx->buf+ctx->pos)); + return 1; + } + yyprintf((stderr, " fail yymatchClass @ %s\n", ctx->buf+ctx->pos)); + return 0; +} + +YY_LOCAL(void) yyDo(yycontext *ctx, yyaction action, int begin, int end) +{ + while (ctx->thunkpos >= ctx->thunkslen) + { + ctx->thunkslen *= 2; + ctx->thunks= (yythunk *)realloc(ctx->thunks, sizeof(yythunk) * ctx->thunkslen); + } + ctx->thunks[ctx->thunkpos].begin= begin; + ctx->thunks[ctx->thunkpos].end= end; + ctx->thunks[ctx->thunkpos].action= action; + ++ctx->thunkpos; +} + +YY_LOCAL(int) yyText(yycontext *ctx, int begin, int end) +{ + int yyleng= end - begin; + if (yyleng <= 0) + yyleng= 0; + else + { + while (ctx->textlen < (yyleng + 1)) + { + ctx->textlen *= 2; + ctx->text= (char *)realloc(ctx->text, ctx->textlen); + } + memcpy(ctx->text, ctx->buf + begin, yyleng); + } + ctx->text[yyleng]= '\0'; + return yyleng; +} + +YY_LOCAL(void) yyDone(yycontext *ctx) +{ + int pos; + for (pos= 0; pos < ctx->thunkpos; ++pos) + { + yythunk *thunk= &ctx->thunks[pos]; + int yyleng= thunk->end ? yyText(ctx, thunk->begin, thunk->end) : thunk->begin; + yyprintf((stderr, "DO [%d] %p %s\n", pos, thunk->action, ctx->text)); + thunk->action(ctx, ctx->text, yyleng); + } + ctx->thunkpos= 0; +} + +YY_LOCAL(void) yyCommit(yycontext *ctx) +{ + if ((ctx->limit -= ctx->pos)) + { + memmove(ctx->buf, ctx->buf + ctx->pos, ctx->limit); + } + ctx->begin -= ctx->pos; + ctx->end -= ctx->pos; + ctx->pos= ctx->thunkpos= 0; +} + +YY_LOCAL(int) yyAccept(yycontext *ctx, int tp0) +{ + if (tp0) + { + fprintf(stderr, "accept denied at %d\n", tp0); + return 0; + } + else + { + yyDone(ctx); + yyCommit(ctx); + } + return 1; +} + +YY_LOCAL(void) yyPush(yycontext *ctx, char *text, int count) { ctx->val += count; } +YY_LOCAL(void) yyPop(yycontext *ctx, char *text, int count) { ctx->val -= count; } +YY_LOCAL(void) yySet(yycontext *ctx, char *text, int count) { ctx->val[count]= ctx->yy; } + +#endif /* YY_PART */ + +#define YYACCEPT yyAccept(ctx, yythunkpos0) + +YY_RULE(int) yy_end_of_line(yycontext *ctx); /* 36 */ +YY_RULE(int) yy_comment(yycontext *ctx); /* 35 */ +YY_RULE(int) yy_space(yycontext *ctx); /* 34 */ +YY_RULE(int) yy_braces(yycontext *ctx); /* 33 */ +YY_RULE(int) yy_range(yycontext *ctx); /* 32 */ +YY_RULE(int) yy_char(yycontext *ctx); /* 31 */ +YY_RULE(int) yy_END(yycontext *ctx); /* 30 */ +YY_RULE(int) yy_BEGIN(yycontext *ctx); /* 29 */ +YY_RULE(int) yy_DOT(yycontext *ctx); /* 28 */ +YY_RULE(int) yy_class(yycontext *ctx); /* 27 */ +YY_RULE(int) yy_literal(yycontext *ctx); /* 26 */ +YY_RULE(int) yy_CLOSE(yycontext *ctx); /* 25 */ +YY_RULE(int) yy_OPEN(yycontext *ctx); /* 24 */ +YY_RULE(int) yy_COLON(yycontext *ctx); /* 23 */ +YY_RULE(int) yy_PLUS(yycontext *ctx); /* 22 */ +YY_RULE(int) yy_STAR(yycontext *ctx); /* 21 */ +YY_RULE(int) yy_QUESTION(yycontext *ctx); /* 20 */ +YY_RULE(int) yy_primary(yycontext *ctx); /* 19 */ +YY_RULE(int) yy_NOT(yycontext *ctx); /* 18 */ +YY_RULE(int) yy_suffix(yycontext *ctx); /* 17 */ +YY_RULE(int) yy_action(yycontext *ctx); /* 16 */ +YY_RULE(int) yy_AND(yycontext *ctx); /* 15 */ +YY_RULE(int) yy_prefix(yycontext *ctx); /* 14 */ +YY_RULE(int) yy_BAR(yycontext *ctx); /* 13 */ +YY_RULE(int) yy_sequence(yycontext *ctx); /* 12 */ +YY_RULE(int) yy_SEMICOLON(yycontext *ctx); /* 11 */ +YY_RULE(int) yy_expression(yycontext *ctx); /* 10 */ +YY_RULE(int) yy_EQUAL(yycontext *ctx); /* 9 */ +YY_RULE(int) yy_identifier(yycontext *ctx); /* 8 */ +YY_RULE(int) yy_RPERCENT(yycontext *ctx); /* 7 */ +YY_RULE(int) yy_end_of_file(yycontext *ctx); /* 6 */ +YY_RULE(int) yy_trailer(yycontext *ctx); /* 5 */ +YY_RULE(int) yy_definition(yycontext *ctx); /* 4 */ +YY_RULE(int) yy_declaration(yycontext *ctx); /* 3 */ +YY_RULE(int) yy__(yycontext *ctx); /* 2 */ +YY_RULE(int) yy_grammar(yycontext *ctx); /* 1 */ + +YY_ACTION(void) yy_9_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_9_primary\n")); + push(makePredicate("YY_END")); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_8_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_8_primary\n")); + push(makePredicate("YY_BEGIN")); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_7_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_7_primary\n")); + push(makeAction(yytext)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_6_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_6_primary\n")); + push(makeDot()); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_5_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_5_primary\n")); + push(makeClass(yytext)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_4_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_4_primary\n")); + push(makeString(yytext)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_3_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_primary\n")); + push(makeName(findRule(yytext))); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_primary\n")); + Node *name= makeName(findRule(yytext)); name->name.variable= pop(); push(name); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_primary(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_primary\n")); + push(makeVariable(yytext)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_3_suffix(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_suffix\n")); + push(makePlus (pop())); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_suffix(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_suffix\n")); + push(makeStar (pop())); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_suffix(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_suffix\n")); + push(makeQuery(pop())); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_3_prefix(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_3_prefix\n")); + push(makePeekNot(pop())); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_prefix(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_prefix\n")); + push(makePeekFor(pop())); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_prefix(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_prefix\n")); + push(makePredicate(yytext)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_sequence(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_sequence\n")); + Node *f= pop(); push(Sequence_append(pop(), f)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_expression(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_expression\n")); + Node *f= pop(); push(Alternate_append(pop(), f)); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_2_definition(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_2_definition\n")); + Node *e= pop(); Rule_setExpression(pop(), e); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_definition(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_definition\n")); + if (push(beginRule(findRule(yytext)))->rule.expression) + fprintf(stderr, "rule '%s' redefined\n", yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_trailer(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_trailer\n")); + makeTrailer(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} +YY_ACTION(void) yy_1_declaration(yycontext *ctx, char *yytext, int yyleng) +{ +#define yy ctx->yy +#define yypos ctx->pos +#define yythunkpos ctx->thunkpos + yyprintf((stderr, "do yy_1_declaration\n")); + makeHeader(yytext); ; +#undef yythunkpos +#undef yypos +#undef yy +} + +YY_RULE(int) yy_end_of_line(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "end_of_line")); + { int yypos2= ctx->pos, yythunkpos2= ctx->thunkpos; if (!yymatchString(ctx, "\r\n")) goto l3; goto l2; + l3:; ctx->pos= yypos2; ctx->thunkpos= yythunkpos2; if (!yymatchChar(ctx, '\n')) goto l4; goto l2; + l4:; ctx->pos= yypos2; ctx->thunkpos= yythunkpos2; if (!yymatchChar(ctx, '\r')) goto l1; + } + l2:; + yyprintf((stderr, " ok %s @ %s\n", "end_of_line", ctx->buf+ctx->pos)); + return 1; + l1:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "end_of_line", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_comment(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "comment")); if (!yymatchChar(ctx, '#')) goto l5; + l6:; + { int yypos7= ctx->pos, yythunkpos7= ctx->thunkpos; + { int yypos8= ctx->pos, yythunkpos8= ctx->thunkpos; if (!yy_end_of_line(ctx)) goto l8; goto l7; + l8:; ctx->pos= yypos8; ctx->thunkpos= yythunkpos8; + } if (!yymatchDot(ctx)) goto l7; goto l6; + l7:; ctx->pos= yypos7; ctx->thunkpos= yythunkpos7; + } if (!yy_end_of_line(ctx)) goto l5; + yyprintf((stderr, " ok %s @ %s\n", "comment", ctx->buf+ctx->pos)); + return 1; + l5:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "comment", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_space(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "space")); + { int yypos10= ctx->pos, yythunkpos10= ctx->thunkpos; if (!yymatchChar(ctx, ' ')) goto l11; goto l10; + l11:; ctx->pos= yypos10; ctx->thunkpos= yythunkpos10; if (!yymatchChar(ctx, '\t')) goto l12; goto l10; + l12:; ctx->pos= yypos10; ctx->thunkpos= yythunkpos10; if (!yy_end_of_line(ctx)) goto l9; + } + l10:; + yyprintf((stderr, " ok %s @ %s\n", "space", ctx->buf+ctx->pos)); + return 1; + l9:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "space", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_braces(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "braces")); + { int yypos14= ctx->pos, yythunkpos14= ctx->thunkpos; if (!yymatchChar(ctx, '{')) goto l15; + l16:; + { int yypos17= ctx->pos, yythunkpos17= ctx->thunkpos; if (!yy_braces(ctx)) goto l17; goto l16; + l17:; ctx->pos= yypos17; ctx->thunkpos= yythunkpos17; + } if (!yymatchChar(ctx, '}')) goto l15; goto l14; + l15:; ctx->pos= yypos14; ctx->thunkpos= yythunkpos14; + { int yypos18= ctx->pos, yythunkpos18= ctx->thunkpos; if (!yymatchChar(ctx, '}')) goto l18; goto l13; + l18:; ctx->pos= yypos18; ctx->thunkpos= yythunkpos18; + } if (!yymatchDot(ctx)) goto l13; + } + l14:; + yyprintf((stderr, " ok %s @ %s\n", "braces", ctx->buf+ctx->pos)); + return 1; + l13:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "braces", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_range(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "range")); + { int yypos20= ctx->pos, yythunkpos20= ctx->thunkpos; if (!yy_char(ctx)) goto l21; if (!yymatchChar(ctx, '-')) goto l21; if (!yy_char(ctx)) goto l21; goto l20; + l21:; ctx->pos= yypos20; ctx->thunkpos= yythunkpos20; if (!yy_char(ctx)) goto l19; + } + l20:; + yyprintf((stderr, " ok %s @ %s\n", "range", ctx->buf+ctx->pos)); + return 1; + l19:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "range", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_char(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "char")); + { int yypos23= ctx->pos, yythunkpos23= ctx->thunkpos; if (!yymatchChar(ctx, '\\')) goto l24; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\204\040\000\000\000\000\000\070\146\100\124\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l24; goto l23; + l24:; ctx->pos= yypos23; ctx->thunkpos= yythunkpos23; if (!yymatchChar(ctx, '\\')) goto l25; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l25; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l25; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l25; goto l23; + l25:; ctx->pos= yypos23; ctx->thunkpos= yythunkpos23; if (!yymatchChar(ctx, '\\')) goto l26; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l26; + { int yypos27= ctx->pos, yythunkpos27= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l27; goto l28; + l27:; ctx->pos= yypos27; ctx->thunkpos= yythunkpos27; + } + l28:; goto l23; + l26:; ctx->pos= yypos23; ctx->thunkpos= yythunkpos23; + { int yypos29= ctx->pos, yythunkpos29= ctx->thunkpos; if (!yymatchChar(ctx, '\\')) goto l29; goto l22; + l29:; ctx->pos= yypos29; ctx->thunkpos= yythunkpos29; + } if (!yymatchDot(ctx)) goto l22; + } + l23:; + yyprintf((stderr, " ok %s @ %s\n", "char", ctx->buf+ctx->pos)); + return 1; + l22:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "char", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_END(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "END")); if (!yymatchChar(ctx, '>')) goto l30; if (!yy__(ctx)) goto l30; + yyprintf((stderr, " ok %s @ %s\n", "END", ctx->buf+ctx->pos)); + return 1; + l30:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "END", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BEGIN(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "BEGIN")); if (!yymatchChar(ctx, '<')) goto l31; if (!yy__(ctx)) goto l31; + yyprintf((stderr, " ok %s @ %s\n", "BEGIN", ctx->buf+ctx->pos)); + return 1; + l31:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BEGIN", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_DOT(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "DOT")); if (!yymatchChar(ctx, '.')) goto l32; if (!yy__(ctx)) goto l32; + yyprintf((stderr, " ok %s @ %s\n", "DOT", ctx->buf+ctx->pos)); + return 1; + l32:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "DOT", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_class(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "class")); if (!yymatchChar(ctx, '[')) goto l33; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l33; + l34:; + { int yypos35= ctx->pos, yythunkpos35= ctx->thunkpos; + { int yypos36= ctx->pos, yythunkpos36= ctx->thunkpos; if (!yymatchChar(ctx, ']')) goto l36; goto l35; + l36:; ctx->pos= yypos36; ctx->thunkpos= yythunkpos36; + } if (!yy_range(ctx)) goto l35; goto l34; + l35:; ctx->pos= yypos35; ctx->thunkpos= yythunkpos35; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l33; if (!yymatchChar(ctx, ']')) goto l33; if (!yy__(ctx)) goto l33; + yyprintf((stderr, " ok %s @ %s\n", "class", ctx->buf+ctx->pos)); + return 1; + l33:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "class", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_literal(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "literal")); + { int yypos38= ctx->pos, yythunkpos38= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l39; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l39; + l40:; + { int yypos41= ctx->pos, yythunkpos41= ctx->thunkpos; + { int yypos42= ctx->pos, yythunkpos42= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l42; goto l41; + l42:; ctx->pos= yypos42; ctx->thunkpos= yythunkpos42; + } if (!yy_char(ctx)) goto l41; goto l40; + l41:; ctx->pos= yypos41; ctx->thunkpos= yythunkpos41; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l39; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l39; if (!yy__(ctx)) goto l39; goto l38; + l39:; ctx->pos= yypos38; ctx->thunkpos= yythunkpos38; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l37; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l37; + l43:; + { int yypos44= ctx->pos, yythunkpos44= ctx->thunkpos; + { int yypos45= ctx->pos, yythunkpos45= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l45; goto l44; + l45:; ctx->pos= yypos45; ctx->thunkpos= yythunkpos45; + } if (!yy_char(ctx)) goto l44; goto l43; + l44:; ctx->pos= yypos44; ctx->thunkpos= yythunkpos44; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l37; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l37; if (!yy__(ctx)) goto l37; + } + l38:; + yyprintf((stderr, " ok %s @ %s\n", "literal", ctx->buf+ctx->pos)); + return 1; + l37:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "literal", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_CLOSE(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "CLOSE")); if (!yymatchChar(ctx, ')')) goto l46; if (!yy__(ctx)) goto l46; + yyprintf((stderr, " ok %s @ %s\n", "CLOSE", ctx->buf+ctx->pos)); + return 1; + l46:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "CLOSE", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_OPEN(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "OPEN")); if (!yymatchChar(ctx, '(')) goto l47; if (!yy__(ctx)) goto l47; + yyprintf((stderr, " ok %s @ %s\n", "OPEN", ctx->buf+ctx->pos)); + return 1; + l47:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "OPEN", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_COLON(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "COLON")); if (!yymatchChar(ctx, ':')) goto l48; if (!yy__(ctx)) goto l48; + yyprintf((stderr, " ok %s @ %s\n", "COLON", ctx->buf+ctx->pos)); + return 1; + l48:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "COLON", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_PLUS(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "PLUS")); if (!yymatchChar(ctx, '+')) goto l49; if (!yy__(ctx)) goto l49; + yyprintf((stderr, " ok %s @ %s\n", "PLUS", ctx->buf+ctx->pos)); + return 1; + l49:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "PLUS", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_STAR(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "STAR")); if (!yymatchChar(ctx, '*')) goto l50; if (!yy__(ctx)) goto l50; + yyprintf((stderr, " ok %s @ %s\n", "STAR", ctx->buf+ctx->pos)); + return 1; + l50:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "STAR", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_QUESTION(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "QUESTION")); if (!yymatchChar(ctx, '?')) goto l51; if (!yy__(ctx)) goto l51; + yyprintf((stderr, " ok %s @ %s\n", "QUESTION", ctx->buf+ctx->pos)); + return 1; + l51:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "QUESTION", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_primary(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "primary")); + { int yypos53= ctx->pos, yythunkpos53= ctx->thunkpos; if (!yy_identifier(ctx)) goto l54; yyDo(ctx, yy_1_primary, ctx->begin, ctx->end); if (!yy_COLON(ctx)) goto l54; if (!yy_identifier(ctx)) goto l54; + { int yypos55= ctx->pos, yythunkpos55= ctx->thunkpos; if (!yy_EQUAL(ctx)) goto l55; goto l54; + l55:; ctx->pos= yypos55; ctx->thunkpos= yythunkpos55; + } yyDo(ctx, yy_2_primary, ctx->begin, ctx->end); goto l53; + l54:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_identifier(ctx)) goto l56; + { int yypos57= ctx->pos, yythunkpos57= ctx->thunkpos; if (!yy_EQUAL(ctx)) goto l57; goto l56; + l57:; ctx->pos= yypos57; ctx->thunkpos= yythunkpos57; + } yyDo(ctx, yy_3_primary, ctx->begin, ctx->end); goto l53; + l56:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_OPEN(ctx)) goto l58; if (!yy_expression(ctx)) goto l58; if (!yy_CLOSE(ctx)) goto l58; goto l53; + l58:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_literal(ctx)) goto l59; yyDo(ctx, yy_4_primary, ctx->begin, ctx->end); goto l53; + l59:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_class(ctx)) goto l60; yyDo(ctx, yy_5_primary, ctx->begin, ctx->end); goto l53; + l60:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_DOT(ctx)) goto l61; yyDo(ctx, yy_6_primary, ctx->begin, ctx->end); goto l53; + l61:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_action(ctx)) goto l62; yyDo(ctx, yy_7_primary, ctx->begin, ctx->end); goto l53; + l62:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_BEGIN(ctx)) goto l63; yyDo(ctx, yy_8_primary, ctx->begin, ctx->end); goto l53; + l63:; ctx->pos= yypos53; ctx->thunkpos= yythunkpos53; if (!yy_END(ctx)) goto l52; yyDo(ctx, yy_9_primary, ctx->begin, ctx->end); + } + l53:; + yyprintf((stderr, " ok %s @ %s\n", "primary", ctx->buf+ctx->pos)); + return 1; + l52:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "primary", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_NOT(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "NOT")); if (!yymatchChar(ctx, '!')) goto l64; if (!yy__(ctx)) goto l64; + yyprintf((stderr, " ok %s @ %s\n", "NOT", ctx->buf+ctx->pos)); + return 1; + l64:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "NOT", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_suffix(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "suffix")); if (!yy_primary(ctx)) goto l65; + { int yypos66= ctx->pos, yythunkpos66= ctx->thunkpos; + { int yypos68= ctx->pos, yythunkpos68= ctx->thunkpos; if (!yy_QUESTION(ctx)) goto l69; yyDo(ctx, yy_1_suffix, ctx->begin, ctx->end); goto l68; + l69:; ctx->pos= yypos68; ctx->thunkpos= yythunkpos68; if (!yy_STAR(ctx)) goto l70; yyDo(ctx, yy_2_suffix, ctx->begin, ctx->end); goto l68; + l70:; ctx->pos= yypos68; ctx->thunkpos= yythunkpos68; if (!yy_PLUS(ctx)) goto l66; yyDo(ctx, yy_3_suffix, ctx->begin, ctx->end); + } + l68:; goto l67; + l66:; ctx->pos= yypos66; ctx->thunkpos= yythunkpos66; + } + l67:; + yyprintf((stderr, " ok %s @ %s\n", "suffix", ctx->buf+ctx->pos)); + return 1; + l65:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "suffix", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_action(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "action")); if (!yymatchChar(ctx, '{')) goto l71; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l71; + l72:; + { int yypos73= ctx->pos, yythunkpos73= ctx->thunkpos; if (!yy_braces(ctx)) goto l73; goto l72; + l73:; ctx->pos= yypos73; ctx->thunkpos= yythunkpos73; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l71; if (!yymatchChar(ctx, '}')) goto l71; if (!yy__(ctx)) goto l71; + yyprintf((stderr, " ok %s @ %s\n", "action", ctx->buf+ctx->pos)); + return 1; + l71:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "action", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_AND(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "AND")); if (!yymatchChar(ctx, '&')) goto l74; if (!yy__(ctx)) goto l74; + yyprintf((stderr, " ok %s @ %s\n", "AND", ctx->buf+ctx->pos)); + return 1; + l74:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "AND", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_prefix(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "prefix")); + { int yypos76= ctx->pos, yythunkpos76= ctx->thunkpos; if (!yy_AND(ctx)) goto l77; if (!yy_action(ctx)) goto l77; yyDo(ctx, yy_1_prefix, ctx->begin, ctx->end); goto l76; + l77:; ctx->pos= yypos76; ctx->thunkpos= yythunkpos76; if (!yy_AND(ctx)) goto l78; if (!yy_suffix(ctx)) goto l78; yyDo(ctx, yy_2_prefix, ctx->begin, ctx->end); goto l76; + l78:; ctx->pos= yypos76; ctx->thunkpos= yythunkpos76; if (!yy_NOT(ctx)) goto l79; if (!yy_suffix(ctx)) goto l79; yyDo(ctx, yy_3_prefix, ctx->begin, ctx->end); goto l76; + l79:; ctx->pos= yypos76; ctx->thunkpos= yythunkpos76; if (!yy_suffix(ctx)) goto l75; + } + l76:; + yyprintf((stderr, " ok %s @ %s\n", "prefix", ctx->buf+ctx->pos)); + return 1; + l75:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "prefix", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_BAR(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "BAR")); if (!yymatchChar(ctx, '|')) goto l80; if (!yy__(ctx)) goto l80; + yyprintf((stderr, " ok %s @ %s\n", "BAR", ctx->buf+ctx->pos)); + return 1; + l80:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "BAR", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_sequence(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "sequence")); if (!yy_prefix(ctx)) goto l81; + l82:; + { int yypos83= ctx->pos, yythunkpos83= ctx->thunkpos; if (!yy_prefix(ctx)) goto l83; yyDo(ctx, yy_1_sequence, ctx->begin, ctx->end); goto l82; + l83:; ctx->pos= yypos83; ctx->thunkpos= yythunkpos83; + } + yyprintf((stderr, " ok %s @ %s\n", "sequence", ctx->buf+ctx->pos)); + return 1; + l81:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "sequence", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_SEMICOLON(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "SEMICOLON")); if (!yymatchChar(ctx, ';')) goto l84; if (!yy__(ctx)) goto l84; + yyprintf((stderr, " ok %s @ %s\n", "SEMICOLON", ctx->buf+ctx->pos)); + return 1; + l84:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "SEMICOLON", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_expression(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "expression")); if (!yy_sequence(ctx)) goto l85; + l86:; + { int yypos87= ctx->pos, yythunkpos87= ctx->thunkpos; if (!yy_BAR(ctx)) goto l87; if (!yy_sequence(ctx)) goto l87; yyDo(ctx, yy_1_expression, ctx->begin, ctx->end); goto l86; + l87:; ctx->pos= yypos87; ctx->thunkpos= yythunkpos87; + } + yyprintf((stderr, " ok %s @ %s\n", "expression", ctx->buf+ctx->pos)); + return 1; + l85:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "expression", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_EQUAL(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "EQUAL")); if (!yymatchChar(ctx, '=')) goto l88; if (!yy__(ctx)) goto l88; + yyprintf((stderr, " ok %s @ %s\n", "EQUAL", ctx->buf+ctx->pos)); + return 1; + l88:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "EQUAL", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_identifier(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "identifier")); yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l89; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\040\000\000\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l89; + l90:; + { int yypos91= ctx->pos, yythunkpos91= ctx->thunkpos; if (!yymatchClass(ctx, (unsigned char *)"\000\000\000\000\000\040\377\003\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l91; goto l90; + l91:; ctx->pos= yypos91; ctx->thunkpos= yythunkpos91; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l89; if (!yy__(ctx)) goto l89; + yyprintf((stderr, " ok %s @ %s\n", "identifier", ctx->buf+ctx->pos)); + return 1; + l89:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "identifier", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_RPERCENT(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "RPERCENT")); if (!yymatchString(ctx, "%}")) goto l92; if (!yy__(ctx)) goto l92; + yyprintf((stderr, " ok %s @ %s\n", "RPERCENT", ctx->buf+ctx->pos)); + return 1; + l92:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "RPERCENT", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_end_of_file(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "end_of_file")); + { int yypos94= ctx->pos, yythunkpos94= ctx->thunkpos; if (!yymatchDot(ctx)) goto l94; goto l93; + l94:; ctx->pos= yypos94; ctx->thunkpos= yythunkpos94; + } + yyprintf((stderr, " ok %s @ %s\n", "end_of_file", ctx->buf+ctx->pos)); + return 1; + l93:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "end_of_file", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_trailer(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "trailer")); if (!yymatchString(ctx, "%%")) goto l95; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l95; + l96:; + { int yypos97= ctx->pos, yythunkpos97= ctx->thunkpos; if (!yymatchDot(ctx)) goto l97; goto l96; + l97:; ctx->pos= yypos97; ctx->thunkpos= yythunkpos97; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l95; yyDo(ctx, yy_1_trailer, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "trailer", ctx->buf+ctx->pos)); + return 1; + l95:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "trailer", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_definition(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "definition")); if (!yy_identifier(ctx)) goto l98; yyDo(ctx, yy_1_definition, ctx->begin, ctx->end); if (!yy_EQUAL(ctx)) goto l98; if (!yy_expression(ctx)) goto l98; yyDo(ctx, yy_2_definition, ctx->begin, ctx->end); + { int yypos99= ctx->pos, yythunkpos99= ctx->thunkpos; if (!yy_SEMICOLON(ctx)) goto l99; goto l100; + l99:; ctx->pos= yypos99; ctx->thunkpos= yythunkpos99; + } + l100:; + yyprintf((stderr, " ok %s @ %s\n", "definition", ctx->buf+ctx->pos)); + return 1; + l98:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "definition", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy_declaration(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "declaration")); if (!yymatchString(ctx, "%{")) goto l101; yyText(ctx, ctx->begin, ctx->end); if (!(YY_BEGIN)) goto l101; + l102:; + { int yypos103= ctx->pos, yythunkpos103= ctx->thunkpos; + { int yypos104= ctx->pos, yythunkpos104= ctx->thunkpos; if (!yymatchString(ctx, "%}")) goto l104; goto l103; + l104:; ctx->pos= yypos104; ctx->thunkpos= yythunkpos104; + } if (!yymatchDot(ctx)) goto l103; goto l102; + l103:; ctx->pos= yypos103; ctx->thunkpos= yythunkpos103; + } yyText(ctx, ctx->begin, ctx->end); if (!(YY_END)) goto l101; if (!yy_RPERCENT(ctx)) goto l101; yyDo(ctx, yy_1_declaration, ctx->begin, ctx->end); + yyprintf((stderr, " ok %s @ %s\n", "declaration", ctx->buf+ctx->pos)); + return 1; + l101:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "declaration", ctx->buf+ctx->pos)); + return 0; +} +YY_RULE(int) yy__(yycontext *ctx) +{ + yyprintf((stderr, "%s\n", "_")); + l106:; + { int yypos107= ctx->pos, yythunkpos107= ctx->thunkpos; + { int yypos108= ctx->pos, yythunkpos108= ctx->thunkpos; if (!yy_space(ctx)) goto l109; goto l108; + l109:; ctx->pos= yypos108; ctx->thunkpos= yythunkpos108; if (!yy_comment(ctx)) goto l107; + } + l108:; goto l106; + l107:; ctx->pos= yypos107; ctx->thunkpos= yythunkpos107; + } + yyprintf((stderr, " ok %s @ %s\n", "_", ctx->buf+ctx->pos)); + return 1; +} +YY_RULE(int) yy_grammar(yycontext *ctx) +{ int yypos0= ctx->pos, yythunkpos0= ctx->thunkpos; + yyprintf((stderr, "%s\n", "grammar")); if (!yy__(ctx)) goto l110; + { int yypos113= ctx->pos, yythunkpos113= ctx->thunkpos; if (!yy_declaration(ctx)) goto l114; goto l113; + l114:; ctx->pos= yypos113; ctx->thunkpos= yythunkpos113; if (!yy_definition(ctx)) goto l110; + } + l113:; + l111:; + { int yypos112= ctx->pos, yythunkpos112= ctx->thunkpos; + { int yypos115= ctx->pos, yythunkpos115= ctx->thunkpos; if (!yy_declaration(ctx)) goto l116; goto l115; + l116:; ctx->pos= yypos115; ctx->thunkpos= yythunkpos115; if (!yy_definition(ctx)) goto l112; + } + l115:; goto l111; + l112:; ctx->pos= yypos112; ctx->thunkpos= yythunkpos112; + } + { int yypos117= ctx->pos, yythunkpos117= ctx->thunkpos; if (!yy_trailer(ctx)) goto l117; goto l118; + l117:; ctx->pos= yypos117; ctx->thunkpos= yythunkpos117; + } + l118:; if (!yy_end_of_file(ctx)) goto l110; + yyprintf((stderr, " ok %s @ %s\n", "grammar", ctx->buf+ctx->pos)); + return 1; + l110:; ctx->pos= yypos0; ctx->thunkpos= yythunkpos0; + yyprintf((stderr, " fail %s @ %s\n", "grammar", ctx->buf+ctx->pos)); + return 0; +} + +#ifndef YY_PART + +typedef int (*yyrule)(yycontext *ctx); + +YY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart) +{ + int yyok; + if (!yyctx->buflen) + { + yyctx->buflen= 1024; + yyctx->buf= (char *)malloc(yyctx->buflen); + yyctx->textlen= 1024; + yyctx->text= (char *)malloc(yyctx->textlen); + yyctx->thunkslen= 32; + yyctx->thunks= (yythunk *)malloc(sizeof(yythunk) * yyctx->thunkslen); + yyctx->valslen= 32; + yyctx->vals= (YYSTYPE *)malloc(sizeof(YYSTYPE) * yyctx->valslen); + yyctx->begin= yyctx->end= yyctx->pos= yyctx->limit= yyctx->thunkpos= 0; + } + yyctx->begin= yyctx->end= yyctx->pos; + yyctx->thunkpos= 0; + yyctx->val= yyctx->vals; + yyok= yystart(yyctx); + if (yyok) yyDone(yyctx); + yyCommit(yyctx); + return yyok; +} + +YY_PARSE(int) YYPARSE(YY_CTX_PARAM) +{ + return YYPARSEFROM(YY_CTX_ARG_ yy_grammar); +} + +#endif + + +void yyerror(char *message) +{ + fprintf(stderr, "%s:%d: %s", fileName, lineNumber, message); + if (yyctx->text[0]) fprintf(stderr, " near token '%s'", yyctx->text); + if (yyctx->pos < yyctx->limit || !feof(input)) + { + yyctx->buf[yyctx->limit]= '\0'; + fprintf(stderr, " before text \""); + while (yyctx->pos < yyctx->limit) + { + if ('\n' == yyctx->buf[yyctx->pos] || '\r' == yyctx->buf[yyctx->pos]) break; + fputc(yyctx->buf[yyctx->pos++], stderr); + } + if (yyctx->pos == yyctx->limit) + { + int c; + while (EOF != (c= fgetc(input)) && '\n' != c && '\r' != c) + fputc(c, stderr); + } + fputc('\"', stderr); + } + fprintf(stderr, "\n"); + exit(1); +} + +void makeHeader(char *text) +{ + Header *header= (Header *)malloc(sizeof(Header)); + header->text= strdup(text); + header->next= headers; + headers= header; +} + +void makeTrailer(char *text) +{ + trailer= strdup(text); +} + +static void version(char *name) +{ + printf("%s version %d.%d.%d\n", name, PEG_MAJOR, PEG_MINOR, PEG_LEVEL); +} + +static void usage(char *name) +{ + version(name); + fprintf(stderr, "usage: %s [