rendered paste body// nasza-klasa.pl mutual friend finder// Written by Leszek Godlewski#include <stdio.h>#include <stdlib.h>#include <string.h>#include <curl/curl.h>// friends list request flags#define FLF_UID (1 << 0)#define FLF_FIRST_NAME (1 << 1)#define FLF_LAST_NAME (1 << 2)#define FLF_AVATAR (1 << 3)#define FLF_FRIENDS_COUNT (1 << 4)#define FLF_LOCATION (1 << 5) // city#define FLF_MSGC_STATUS (1 << 6) // messaging centre status#define FLF_MSGC_STATUS_DESC (1 << 7) // messaging centre status description string#define FLF_UNKNOWN (1 << 8) // unknown flag#define FLF_ARTIFICIALITY (1 << 9) // whether or not the person in the account is a fictitious one or a real onetypedef unsigned char bool_t;#define btrue 1#define bfalse 0CURL *easyhandle = NULL;char *response = NULL;int responseSize = 0;void printHelp(char *argv0) { printf("Compares the friend lists of 2 given users and returns mutual friends.\n" "\n" "Usage: %s <username> <password> <UID1> <UID2>\n" " username - your nasza-klasa.pl username/e-mail address\n" " password - your nasza-klasa.pl password\n" " UID1 - the UID of the first person\n" " UID2 - the UID of the second person\n", argv0);}size_t writeDocument(void *buf, size_t size, size_t nmemb, void *p) { int bytes = size * nmemb; char *target; if (!response) { responseSize = bytes + 1; response = malloc(responseSize); target = response; } else { response = realloc(response, responseSize + bytes); target = response + responseSize - 1; responseSize += bytes; } memcpy(target, buf, bytes); response[responseSize - 1] = 0; // ensure a trailing 0 return bytes;}struct curl_slist *headers = NULL;void initCurl(void) { curl_global_init(CURL_GLOBAL_WIN32); easyhandle = curl_easy_init(); curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, writeDocument); curl_easy_setopt(easyhandle, CURLOPT_COOKIEFILE, "dummyfile"); curl_easy_setopt(easyhandle, CURLOPT_FOLLOWLOCATION, 1);#if 0 // debugging curl_easy_setopt(easyhandle, CURLOPT_VERBOSE, 1);#endif // the server requires a user agent headers = curl_slist_append(headers, "User-Agent: nasza-klasa.pl mutual friend finder"); curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);}bool_t login(char *l, char *p) { char postdata[1024], *el, *ep; int retval; el = curl_easy_escape(easyhandle, l, strlen(l)); ep = curl_easy_escape(easyhandle, p, strlen(p)); snprintf(postdata, sizeof(postdata), "login=%s&password=%s", el, ep); curl_free(el); curl_free(ep); curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, postdata); curl_easy_setopt(easyhandle, CURLOPT_URL, "http://nasza-klasa.pl/login"); retval = curl_easy_perform(easyhandle); curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, ""); if (strstr(response, "Nieprawid\305\202owa nazwa u\305\274ytkownika lub has\305\202o.")) retval = bfalse; else retval = (retval == 0); free(response); response = NULL; responseSize = 0; return retval;}#define CLIENT_VERSION 135 // version of the nasza-klasa.pl software we're identifying as#define MAX_NAME_LENGTH 100 // limit present in the nasza-klasa.pl website's source codetypedef struct { int uid; char fname[MAX_NAME_LENGTH]; char lname[MAX_NAME_LENGTH]; bool_t mutual;} contact_t;contact_t *contacts = NULL;int numContacts = 0;bool_t getContactLists(char *u1, char *u2) { char url[1024]; char *r1 = NULL, *r2 = NULL; char *in, *out; int retval, i, j, n; snprintf(url, sizeof(url), "http://nasza-klasa.pl/friends_list/%s/%d/%d", u1, FLF_UID | FLF_FIRST_NAME | FLF_LAST_NAME, CLIENT_VERSION); curl_easy_setopt(easyhandle, CURLOPT_URL, url); retval = curl_easy_perform(easyhandle); if (retval != 0) { if (response) { free(response); response = NULL; } return bfalse; } r1 = response; response = NULL; responseSize = 0; // we don't need as much info from the other person, fetch the UIDs only snprintf(url, sizeof(url), "http://nasza-klasa.pl/friends_list/%s/%d/%d", u2, FLF_UID, CLIENT_VERSION); curl_easy_setopt(easyhandle, CURLOPT_URL, url); retval = curl_easy_perform(easyhandle); if (retval != 0) { if (response) { free(response); response = NULL; } if (r1) free(r1); return bfalse; } r2 = response; response = NULL; responseSize = 0; // parse the first contact list // get the friends count and allocate memory in = strstr(r1 + 3, "\"FRIENDS_COUNT\":"); if (!in) { if (response) { free(response); response = NULL; } if (r1) free(r1); if (r2) free(r2); return bfalse; } in += 16; out = url; // reuse the variable while (*in < '0' || *in > '9') in++; while (*in >= '0' && *in <= '9') *out++ = *in++; *out = 0; numContacts = atoi(url); contacts = malloc(numContacts * sizeof(*contacts)); memset(contacts, 0, numContacts * sizeof(*contacts)); // get the UIDs in = strstr(r1 + 3, "\"UID\":"); if (!in) { if (response) { free(response); response = NULL; } if (r1) free(r1); if (r2) free(r2); free(contacts); return bfalse; } in += 6; while (*in != '[') in++; for (i = 0; i < numContacts; i++) { out = url; while (*in < '0' || *in > '9') in++; while (*in >= '0' && *in <= '9') *out++ = *in++; *out = 0; contacts[i].uid = atoi(url); } // get the first names in = strstr(r1 + 3, "\"FIRST_NAME\":"); if (!in) { if (response) { free(response); response = NULL; } if (r1) free(r1); if (r2) free(r2); free(contacts); return bfalse; } in += 13; while (*in != '[') in++; for (i = 0; i < numContacts; i++) { out = url; while (*in != '\"') in++; in++; while (*in != '\"') *out++ = *in++; in++; *out = 0; strncpy(contacts[i].fname, url, sizeof(contacts->fname)); } // get the last names in = strstr(r1 + 3, "\"LAST_NAME\":"); if (!in) { if (response) { free(response); response = NULL; } if (r1) free(r1); if (r2) free(r2); free(contacts); return bfalse; } in += 12; while (*in != '[') in++; for (i = 0; i < numContacts; i++) { out = url; while (*in != '\"') in++; in++; while (*in != '\"') *out++ = *in++; in++; *out = 0; strncpy(contacts[i].lname, url, sizeof(contacts->lname)); } // parse the second contact list // get the friends count in = strstr(r2 + 3, "\"FRIENDS_COUNT\":"); if (!in) { if (response) { free(response); response = NULL; } if (r1) free(r1); if (r2) free(r2); return bfalse; } in += 16; out = url; // reuse the variable while (*in < '0' || *in > '9') in++; while (*in >= '0' && *in <= '9') *out++ = *in++; *out = 0; retval = atoi(url); // reuse the variable // get the UIDs in = strstr(r2 + 3, "\"UID\":"); if (!in) { if (response) { free(response); response = NULL; } if (r1) free(r1); if (r2) free(r2); free(contacts); return bfalse; } in += 6; while (*in != '[') in++; for (i = 0; i < retval; i++) { out = url; while (*in < '0' || *in > '9') in++; while (*in >= '0' && *in <= '9') *out++ = *in++; *out = 0; n = atoi(url); for (j = 0; j < numContacts; j++) { if (contacts[j].uid == n) { contacts[j].mutual = btrue; break; } } } free(r1); free(r2); return btrue;}void logout(void) { curl_easy_setopt(easyhandle, CURLOPT_URL, "http://nasza-klasa.pl/logout?l=1"); curl_easy_perform(easyhandle);}void cleanupCurl(void) { curl_slist_free_all(headers); curl_easy_cleanup(easyhandle); curl_global_cleanup();}void printMutualFriends(void) { int i; for (i = 0; i < numContacts; i++) { if (!contacts[i].mutual) continue; printf("%s %s (http://nasza-klasa.pl/profile/%d)\n", contacts[i].fname, contacts[i].lname, contacts[i].uid); }}int main(int argc, char *argv[]) { printf("nasza-klasa.pl mutual friend finder\n" "Written by Leszek Godlewski\n" "This program is free software under the WTFPL license.\n" "\n" ); if (argc != 5) { printHelp(argv[0]); exit(0); } initCurl(); printf("Logging in...\n"); if (!login(argv[1], argv[2])) { printf("Logging in failed. Check your login details and internet connection.\n"); exit(0); } printf("Downloading and processing contact lists...\n"); if (!getContactLists(argv[3], argv[4])) { printf("Retrieving contact lists failed. Check your internet connection.\n"); exit(0); } printf("Logging out...\n"); logout(); cleanupCurl(); printf("Mutual friends are:\n"); printMutualFriends(); free(contacts); return 0;}