Jump to content

Routine for retrieving WebAPI torrents using C++ [code dump]


click

Recommended Posts

This is a routine to retrieve the torrent list from the WebAPI using C++. It was thrown together with CSimpleSocket, Json++ and this base64 library. It is currently being used to poll for torrent updates and post them to our chat server. Any glaring errors would be appreciated (i couldn't make jsonxx cache that object?). Hope it helps someone else get started - i couldn't find any c++ libraries that already had this under control


#define UT_UADDR "127.0.0.1"
#define UT_UPORT 81
#define UT_UUSER "admin"
#define UT_UPASS "admin"

struct Torrent {
string Name;
string Label;
double Progress; /* Range 0...1000*/
};

typedef map<string, Torrent> VTMAP;

// ######################################

///<summary>
/// Escapes some invalid HTTP characters.
///</summary>
void httpEscape(string& sString) {
int iFind;
for(; {
iFind = sString.find("=");
if (iFind == sString.npos) break;
sString.replace(iFind, 1, "%3D");
}
}

///<summary>
/// Performs an HTTP/1.1 GET on the specified sHostname:iPort sPath and blocks until
/// it recieves a result.
///</summary>
string httpGet(char* sHostname, char* sPath, int iPort, char* sUserAndPass) {

// Construct query
string sQuery = format("GET %s HTTP/1.1\nHost: %s:%d", sPath, sHostname, iPort);
if (sUserAndPass) {
sQuery.append("\nAuthorization: Basic ");
sQuery.append(base64_encode((const unsigned char*) sUserAndPass, strlen(sUserAndPass)));
}
sQuery.append("\n\n");

// Connect to address
CActiveSocket* sock = new CActiveSocket();
sock->Initialize();
sock->SetBlocking();
sock->Open((const uint8 *) sHostname, iPort);
if (!(sock->Send((const uint8 *) sQuery.c_str(), sQuery.length()))) {
delete sock;
return "Couldn't send the query!\n";
}

// Wait for the returned token
sock->Receive(16384);
if (!(sock->GetData())) {
delete sock;
return "Couldn't read the replied data!\n";
}

// Copy and return the response
char *cBuff = new char[sock->GetBytesReceived() + 16];
sock->GetBytesReceived();
sock->GetData();
memcpy(cBuff, sock->GetData(), sock->GetBytesReceived());
string sResult;
sResult.assign(cBuff);
delete[] cBuff;

delete sock;
return sResult;
}

///<summary>
/// Communicates with the uTorrent WebUI and returns a list of torrents
/// TODO: When uTorrent 2.1 is released, we might have to use cookie authentication as well
///</summary>
bool retrieveTorrents(VTMAP& vtResult) {

// Retrieve token.html
string sResponse = httpGet(UT_UADDR, "/gui/token.html", UT_UPORT, UT_UUSER ":" UT_UPASS);

// Parse response for token
string sToken = "";
int iPos = sResponse.find("div id='token'");
if (iPos) {
iPos = sResponse.find(">", iPos);
if (iPos) {
int iLast = sResponse.find("</div", iPos++);
sToken.assign(sResponse.substr(iPos, iLast-iPos));
}
}
if (!(sToken.length())) {
printf("Couldn't find a connection token in the response!\n");
return false;
}
httpEscape(sToken);

// Retrieve torrent list as JSON
string sAddress = "/gui/?list=1&token="; sAddress.append(sToken);
sResponse = httpGet(UT_UADDR, (char*)sAddress.c_str(), UT_UPORT, UT_UUSER ":" UT_UPASS);

// Isolate the JSON and load into JSON structure
iPos = sResponse.find("{");
int iEnd = sResponse.find("}");
string sJSON; sJSON.assign(sResponse.substr(iPos, iEnd - iPos + 1));

istringstream iJSON(sJSON);
jsonxx::Object o;
if (!(o.parse(iJSON, o))) {
printf("Failed to parse JSON!\n");
return false;
}

// Extract the individual torrents
if (!(o.has<jsonxx::Array>("torrents"))) {
printf("Malformed JSON response!\n"); return false;
}
vtResult.clear();
for (int i=0,e = o.get<jsonxx::Array>("torrents").size(); i < e; i++) {
Torrent t;
t.Name = o.get<jsonxx::Array>("torrents").get<jsonxx::Array>(i).get<string>(2); // Magic
t.Label = o.get<jsonxx::Array>("torrents").get<jsonxx::Array>(i).get<string>(11);
t.Progress = o.get<jsonxx::Array>("torrents").get<jsonxx::Array>(i).get<double>(4);
vtResult[t.Name] = t;
}

// Tidy up
return true;
}

Link to comment
Share on other sites

  • 2 weeks later...

Hey,

I was just starting my own project (automatic file extractor for freshly downloaded files) and i was wondering how should i communicate with utorrent, when i stumbled upon your code. After changing some code i made it work, so i wanted to thank you for this piece of code!

Once i finish my project that it will be useable, i will post it on sourceforge so you can dl it and laugh at my puny c++ code ;p

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...