fork download
  1. [CAMPUS]
  2. New Brunswick
  3.  
  4. [SEMESTER]
  5. Fall 2015
  6. [ENABLE AUTO REGISTER]
  7. true
  8.  
  9. [NETID]
  10. yl854
  11.  
  12. [NETID PASSWORD]
  13. Lasvey1994
  14.  
  15. [ENABLE SMS]
  16. true
  17.  
  18. [SMS EMAIL]
  19. lasvey@gmail.com
  20.  
  21. [SMS PASSWORD]
  22. liyuan1994
  23.  
  24. [SMS PHONE NUMBER]
  25. 7324850203
  26.  
  27. [SILENTMESSAGES]
  28. false
  29.  
  30. [ALERT]
  31. true
  32.  
  33. [COURSES]
  34. 198:112:05
  35. 198:112:06
  36. 198:112:07
  37. #include "ruopen.h"
  38.  
  39. Curl curl;
  40. static Info info;
  41. static ListDepts spotting;
  42. static Json::Value dept_json;
  43.  
  44. //Multithreading variables
  45. static bool flag_spot = false; //lets spot thread know when to terminate
  46.  
  47.  
  48. inline void printProgramInfo() {
  49. cout << "\nRUopen Version 1.1 - Created by codeniko\n----------------------------------------" << endl;
  50. cout << "Semester: " << info.semesterString << endl << "Campus: " << info.campusString << endl;
  51. cout << "SMS Email : " << info.smsEmail << endl << "SMS Phone Number: " << info.smsNumber << endl;
  52. }
  53.  
  54. /* Initialize curl and some other info settings
  55.  * RETURNS true=>success, false=>failure
  56.  */
  57. bool init()
  58. {
  59. curl.handle = NULL;
  60. curl.respLen = 0;
  61. curl.cookiejar = "cookiejar.txt";
  62. curl_global_init(CURL_GLOBAL_ALL);
  63. curl.handle = curl_easy_init();
  64. if (!curl.handle)
  65. return false;
  66. curl.headers.json = NULL; // init to NULL is important
  67. curl.headers.text = NULL; // will reset to text/plain
  68. curl.headers.json = curl_slist_append(curl.headers.json, "Accept: application/json");
  69. curl.headers.json = curl_slist_append(curl.headers.json, "Content-Type: application/json");
  70. curl.headers.json = curl_slist_append(curl.headers.json, "charsets: utf-8");
  71.  
  72. curl_easy_setopt(curl.handle, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.2.0");
  73. curl_easy_setopt(curl.handle, CURLOPT_NOPROGRESS, 1); // turn of progress bar
  74. // curl_easy_setopt(curl.handle, CURLOPT_FAILONERROR, 1); // fail on error
  75. curl_easy_setopt(curl.handle, CURLOPT_FOLLOWLOCATION, 1L);
  76. curl_easy_setopt(curl.handle, CURLOPT_MAXREDIRS, 20);
  77. curl_easy_setopt(curl.handle, CURLOPT_WRITEFUNCTION, writeCallback);
  78. curl_easy_setopt(curl.handle, CURLOPT_WRITEDATA, &curl.response);
  79. curl_easy_setopt(curl.handle, CURLOPT_AUTOREFERER, 1);
  80. curl_easy_setopt(curl.handle, CURLOPT_TIMEOUT_MS, 30000);
  81. curl_easy_setopt(curl.handle, CURLOPT_CONNECTTIMEOUT, 30000);
  82. curl_easy_setopt(curl.handle, CURLOPT_NOSIGNAL, 1); // multithread safe
  83. //curl_easy_setopt(curl.handle, CURLOPT_VERBOSE, 1L);
  84. // curl_easy_setopt(curl.handle, CURLOPT_CUSTOMREQUEST, "PUT");
  85. // curl_easy_setopt(curl.handle, CURLOPT_HEADER, 1); // A parameter set to 1 tells the library to include the header in the body output.
  86. curl_easy_setopt(curl.handle, CURLOPT_HTTPHEADER, curl.headers.text);
  87. curl_easy_setopt(curl.handle, CURLOPT_WRITEHEADER, &curl.responseHeader);
  88. curl_easy_setopt(curl.handle, CURLOPT_POSTREDIR, 1);
  89. curl_easy_setopt(curl.handle, CURLOPT_COOKIEJAR, curl.cookiejar.c_str());
  90. // curl_easy_setopt(curl.handle, CURLOPT_POST, 1);
  91. curl_easy_setopt(curl.handle, CURLOPT_URL, "http://w...content-available-to-author-only...o.net"); // default
  92. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "http://w...content-available-to-author-only...o.net"); //default
  93. // curl_easy_setopt(curl.handle, CURLOPT_POSTFIELDS, jsonput.c_str());
  94. // curl_easy_setopt(curl.handle, CURLOPT_POSTFIELDSIZE, jsonput.length());
  95. info.silent = false;
  96. info.alert = true;
  97. info.enableWebreg = false;
  98. info.enableSMS = true;
  99. setCampus("new brunswick");
  100. const string semesterString = getCurrentSemester();
  101. if (semesterString == "")
  102. return false;
  103. return setSemester(semesterString);
  104. }
  105.  
  106. /* Used to receive curl response
  107.  */
  108. int writeCallback(char* buf, size_t size, size_t nmemb, string *in)
  109. { //callback must have this declaration
  110. //buf is a pointer to the data that curl has for us
  111. //size*nmemb is the size of the buffer
  112.  
  113. if (in != NULL)
  114. {
  115. curl.respLen = size*nmemb;
  116. in->append(buf, size*nmemb);
  117. return size*nmemb; //tell curl how many bytes we handled
  118. }
  119. curl.respLen = 0;
  120. return 0; //tell curl how many bytes we handled
  121. }
  122.  
  123. /* Sleep thread for n milliseconds
  124.  * PARAM sleeptime = milliseconds to sleep
  125.  * PARAM minSleep = minimum # milliseconds to sleep
  126.  * PARAM silent = bool if to print to stdout. false=>print, true=>not print
  127.  */
  128. void sleep(int sleeptime, int minSleep = 1000) {
  129. if (sleeptime <= minSleep)
  130. sleeptime = minSleep;
  131. else
  132. sleeptime = rand() % (sleeptime-minSleep) + minSleep;
  133. boost::this_thread::sleep(boost::posix_time::milliseconds(sleeptime));
  134. }
  135.  
  136. /* Get the Semester String, EX: Spring 2011
  137.  * Returns semester string or "" on error
  138.  */
  139. string getCurrentSemester()
  140. {
  141. curl_easy_setopt(curl.handle, CURLOPT_HTTPHEADER, curl.headers.json);
  142. curl_easy_setopt(curl.handle, CURLOPT_URL, "http://s...content-available-to-author-only...s.edu/soc/current_term_date.json");
  143. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "http://s...content-available-to-author-only...s.edu/soc");
  144. curl.res = curl_easy_perform(curl.handle);
  145.  
  146. if (curl.res != CURLE_OK) {
  147. curl.response.clear();
  148. return "";
  149. } else {
  150. Json::Value jsonroot;
  151. Json::Reader jsonreader;
  152. bool parseResult = jsonreader.parse(curl.response, jsonroot);
  153. curl.response.clear();
  154.  
  155. if (!parseResult) {
  156. cerr << "ERROR: Json parser errored on parsing semester information." << endl;
  157. return "";
  158. }
  159. int year = jsonroot.get("year", -1).asInt();
  160. int term = jsonroot.get("term", -1).asInt();
  161. if (year == -1 || term == -1) {
  162. cerr << "ERROR: Wrong semester information retrieved." << endl;
  163. return "";
  164. }
  165.  
  166. //If Summer or Winter, change to previous Spring or Fall
  167. if (term == 0) { //Winter -> Fall
  168. term = 9;
  169. year--;
  170. }
  171. if (term == 7) //Summer -> Spring
  172. term = 1;
  173.  
  174. stringstream ss;
  175. ss << term << year; //rutgers semester code is just term + year
  176. return semesterCodeToString(ss.str());
  177. }
  178. }
  179.  
  180. /* Create URL parameters to retrieve RU courses/dept json
  181.  * PARAM dept = department code if looking up courses in dept, "" to get departments list
  182.  * RETURNS string containing URL parameter substring
  183.  */
  184. string createParams(const string dept = "")
  185. {
  186. stringstream ss;
  187. ss << "semester=" << info.semester << "&campus=" << info.campus << "&level=U,G";
  188. if (dept != "")
  189. ss << "&subject=" << dept;
  190. return ss.str();
  191. }
  192.  
  193. /* Get departments
  194.  * RETURNS true=> success, false=>failure
  195.  */
  196. bool getDepartmentsJSON()
  197. {
  198. static bool alreadyRetrieved = false;
  199. if (alreadyRetrieved) //prevent retrieving departments multiple times
  200. return true;
  201.  
  202. string params = createParams();
  203. curl_easy_setopt(curl.handle, CURLOPT_HTTPHEADER, curl.headers.json);
  204. curl_easy_setopt(curl.handle, CURLOPT_URL, string("http://s...content-available-to-author-only...s.edu/soc/subjects.json?").append(params).c_str());
  205. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "http://s...content-available-to-author-only...s.edu/soc");
  206. curl.res = curl_easy_perform(curl.handle);
  207. if (curl.res != CURLE_OK) {
  208. cerr << "ERROR: Unable to retrieve Rutgers department data (1)." << endl;
  209. curl.response.clear();
  210. return false;
  211. }
  212.  
  213. Json::Reader jsonreader;
  214. if (!jsonreader.parse(curl.response, dept_json) || dept_json.size() == 0) {
  215. cerr << "ERROR: Unable to retrieve Rutgers department data (2)." << endl;
  216. curl.response.clear();
  217. return false;
  218. }
  219.  
  220. curl.response.clear();
  221. alreadyRetrieved = true;
  222. return true;
  223. }
  224.  
  225. /* Get Courses JSON object
  226.  * PARAM deptcode = department code for specific courses mapped to a dept
  227.  * RETURNS JSON object or NULL on error
  228.  */
  229. Json::Value *getCoursesJSON(const string deptcode)
  230. {
  231. string params = createParams(deptcode);
  232. curl_easy_setopt(curl.handle, CURLOPT_HTTPHEADER, curl.headers.json);
  233. curl_easy_setopt(curl.handle, CURLOPT_URL, string("http://s...content-available-to-author-only...s.edu/soc/courses.json?").append(params).c_str());
  234. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "http://s...content-available-to-author-only...s.edu/soc");
  235. curl.res = curl_easy_perform(curl.handle);
  236. if (curl.res != CURLE_OK) {
  237. cerr << "ERROR: Unable to retrieve Rutgers course data (1)." << endl;
  238. curl.response.clear();
  239. return NULL;
  240. }
  241.  
  242. Json::Value *courses = new Json::Value();
  243. Json::Reader jsonreader;
  244. if (!jsonreader.parse(curl.response, *courses) || courses->size() == 0) {
  245. cerr << "ERROR: Unable to retrieve Rutgers course data (2)." << endl;
  246. curl.response.clear();
  247. return NULL;
  248. }
  249.  
  250. curl.response.clear();
  251. return courses;
  252. }
  253.  
  254. /* Set the semester and semester code in settings
  255.  * PARAM semesterString = Current semester, EX: Spring 2011
  256.  * RETURNS true=>success, false=>failure
  257.  */
  258. bool setSemester(const string semesterString)
  259. {
  260. string code;
  261. if (semesterString == "" || (code = semesterStringToCode(semesterString)) == "")
  262. return false;
  263.  
  264. info.semester = code;
  265. info.semesterString = semesterCodeToString(code); //Getting string again incase semester string in config file is not proper
  266. return true;
  267. }
  268.  
  269. /* Set campus info in settings
  270.  * PARAM campus = campus string in config
  271.  * RETURNS true=>success, false=>failure
  272.  */
  273. bool setCampus(string campus)
  274. {
  275. transform(campus.begin(), campus.end(), campus.begin(), ::tolower);
  276. if (campus == "new brunswick") {
  277. info.campus = "NB";
  278. info.campusString = "New Brunswick";
  279. } else if (campus == "newark") {
  280. info.campus = "NK";
  281. info.campusString = "Newark";
  282. } else if (campus == "camden") {
  283. info.campus = "CM";
  284. info.campusString = "Camden";
  285. } else
  286. return false;
  287. return true;
  288. }
  289.  
  290. /* Remove course that is being spotted
  291.  * PARAM row = index of course being removed in spotlist
  292.  * RETURNS true=>success, false=>failure
  293.  */
  294. bool removeCourseFromList(int row)
  295. {
  296. int count = 0;
  297. for (ListDepts::iterator dept = spotting.begin(); dept != spotting.end(); ++dept) {
  298. for (ListCourses::iterator course = dept->courses.begin(); course != dept->courses.end(); ++course) {
  299. for (ListSections::iterator section = course->sections.begin(); section != course->sections.end(); ++section) {
  300. ++count;
  301. if (row == count) {
  302. if (course->sections.size() > 1) {
  303. course->sections.remove(*section);
  304. } else {
  305. if (dept->courses.size() > 1)
  306. dept->courses.remove(*course);
  307. else
  308. spotting.remove(*dept);
  309. }
  310. return true;
  311. }
  312. }
  313. }
  314. }
  315. return false;
  316. }
  317.  
  318. /* Add a course to spotlist
  319.  * PARAM deptcode = department code of course
  320.  * PARAM coursecode = course code of course
  321.  * PARAM sectioncode = section of course
  322.  * RETURNS true=>success, false=>failure
  323.  */
  324. bool addCourseToList(const string deptcode, const string coursecode, const string sectioncode)
  325. {
  326. if (!getDepartmentsJSON())
  327. return false;
  328.  
  329. //Validate Department Input
  330. unsigned int c;
  331. for (c = 0; c < dept_json.size(); ++c) {
  332. if (dept_json[c].get("code", "NULL").asString() == deptcode)
  333. break;
  334. }
  335. if (c == dept_json.size())
  336. return false;
  337. Department dept;
  338. dept.dept = dept_json[c].get("description", "NULL").asString();
  339. dept.deptCode = deptcode;
  340.  
  341. //Validate Course Input
  342. Json::Value *course_json = getCoursesJSON(dept.deptCode);
  343. if (course_json == NULL)
  344. return false;
  345. for (c = 0; c < course_json->size(); ++c) {
  346. if ((*course_json)[c].get("courseNumber", "NULL").asString() == coursecode)
  347. break;
  348. }
  349. if (c == course_json->size()) {
  350. delete course_json;
  351. return false;
  352. }
  353. Course course;
  354. course.course = (*course_json)[c].get("title", "NULL").asString();
  355. course.courseCode = coursecode;
  356. course.json_index = c;
  357.  
  358. //Validate Section Input
  359. Json::Value sections = (*course_json)[c]["sections"];
  360. unsigned int s;
  361. for (s = 0; s < sections.size(); ++s)
  362. {
  363. if (sections[s].get("number", "NULL").asString() == sectioncode)
  364. break;
  365. }
  366. if (s == sections.size()) {
  367. delete course_json;
  368. return false;
  369. }
  370. Section section;
  371. section.courseIndex = sections[s].get("index", "NULL").asString();
  372. section.section = sections[s].get("number", "NULL").asString();
  373. section.spotCounter = 0;
  374. delete course_json;
  375.  
  376. course.sections.push_back(section);
  377. dept.courses.push_back(course);
  378.  
  379. //check if we are already spotting this department and insert if we are not
  380. Json::ValueIterator it, it2, it3;
  381. ListDepts::iterator spotting_dept;
  382. ListCourses::iterator spotting_course;
  383. ListSections::iterator spotting_section;
  384. for (spotting_dept = spotting.begin(); spotting_dept != spotting.end(); ++spotting_dept) {
  385. if (dept.deptCode == spotting_dept->deptCode) {
  386. //Department exists, check if already spotting course
  387. for (spotting_course = spotting_dept->courses.begin(); spotting_course != spotting_dept->courses.end(); ++spotting_course) {
  388. if (course.courseCode == spotting_course->courseCode) {
  389. //Course exists, check if already spotting section
  390. for (spotting_section = spotting_course->sections.begin(); spotting_section != spotting_course->sections.end(); ++spotting_section) {
  391. if (section.section == spotting_section->section) {
  392. cout << "ALREADY SPOTTING THIS SECTION!" << endl;
  393. return true; // Already spotting this course and section
  394. }
  395. else if (section.section < spotting_section->section){
  396. spotting_course->sections.insert(spotting_section, section); //add section inbetween
  397. return true;
  398. }
  399. }
  400. spotting_course->sections.push_back(section); //add section at end
  401. return true;
  402. } else if (course.courseCode < spotting_course->courseCode){
  403. spotting_dept->courses.insert(spotting_course, course); //add course inbetween
  404. return true;
  405. }
  406. }
  407. spotting_dept->courses.push_back(course); //add course at end
  408. return true;
  409. } else if (dept.deptCode < spotting_dept->deptCode){
  410. spotting.insert(spotting_dept, dept); //add dept inbetween
  411. return true;
  412. }
  413. }
  414. spotting.push_back(dept); //add dept at end
  415. return true;
  416. }
  417.  
  418. /* Create configuration file if it does not exist
  419.  */
  420. void createConfFile()
  421. {
  422. ofstream conf;
  423. conf.open(CONFFILE);
  424. conf << "[CAMPUS]\nNew Brunswick\n\n[SEMESTER]\n\n" <<
  425. "[ENABLE AUTO REGISTER]\nfalse\n\n[NETID]\nEnter Netid Here\n\n[NETID PASSWORD]\nEnter Password Here\n\n" <<
  426. "[ENABLE SMS]\ntrue\n\n[SMS EMAIL]\nexample@yahoo.com\n\n[SMS PASSWORD]\nPassword For Email Goes Here\n\n" <<
  427. "[SMS PHONE NUMBER]\n1234567890\n\n[SILENTMESSAGES]\nfalse\n\n[ALERT]\ntrue\n\n[COURSES]\n\n";
  428.  
  429. conf.close();
  430. }
  431.  
  432. /* Print current spotlist
  433.  */
  434. void printSpotList()
  435. {
  436. int count = 0;
  437. cout << endl << "Currently spotting:" << endl;
  438. for (ListDepts::iterator dept = spotting.begin(); dept != spotting.end(); ++dept) {
  439. for (ListCourses::iterator course = dept->courses.begin(); course != dept->courses.end(); ++course) {
  440. for (ListSections::iterator section = course->sections.begin(); section != course->sections.end(); ++section) {
  441. ++count;
  442. cout << count << ". [" << section->courseIndex << "] " << dept->deptCode << ":" << course->courseCode << ":" << section->section << ' ' << course->course << endl;
  443. }
  444. }
  445. }
  446. if (count == 0)
  447. cout << " Not spotting any courses..." << endl;
  448. }
  449.  
  450. /* Register for course through webreg if a course is spotted
  451.  * PARAM section = section object of the course to register for (contains course index used by webreg)
  452.  */
  453. void registerForCourse(const Section &section)
  454. {
  455. //get initial login page html contents
  456. curl_easy_setopt(curl.handle, CURLOPT_HTTPHEADER, curl.headers.text);
  457. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "https://s...content-available-to-author-only...s.edu/webreg/chooseSemester.htm?login=cas"); //default
  458. curl_easy_setopt(curl.handle, CURLOPT_URL, "https://c...content-available-to-author-only...s.edu/login?service=https%3A%2F%2Fsims.rutgers.edu%2Fwebreg%2Fj_acegi_cas_security_check");
  459. curl.res = curl_easy_perform(curl.handle);
  460. if (curl.res != CURLE_OK) {
  461. cerr << "ERROR: webreg step 1." << endl;
  462. curl.response.clear();
  463. return;
  464. }
  465.  
  466. //Check if logged into webreg already.
  467. boost::cmatch what;
  468. boost::regex loginRe("a href=\"logout.htm\">Log Out<");
  469. if (!boost::regex_search(curl.response.c_str(), what, loginRe)) {
  470. cout << "Attempting to login into webreg." << endl;
  471.  
  472. //parse login page for login token
  473. boost::regex re("input type=\"hidden\" name=\"lt\" value=\"_cNoOpConversation (.+?)\"");
  474. if (!boost::regex_search(curl.response.c_str(), what, re)) {
  475. cerr << "ERROR: Unable to get login token in webreg step 2." << endl;
  476. curl.response.clear();
  477. return;
  478. }
  479. string lt(what[1].first, what[1].second);
  480. curl.response.clear();
  481.  
  482. //pass in login info and token to attempt a login
  483. string postfields = "username="+info.netid+"&password="+info.netidPassword+"&authenticationType=Kerberos&lt=_cNoOpConversation " + lt + "&_currentStateId=&_eventId=submit";
  484. curl_easy_setopt(curl.handle, CURLOPT_URL, "https://c...content-available-to-author-only...s.edu/login?service=https%3A%2F%2Fsims.rutgers.edu%2Fwebreg%2Fj_acegi_cas_security_check");
  485. curl_easy_setopt(curl.handle, CURLOPT_POSTFIELDS, postfields.c_str());
  486. curl.res = curl_easy_perform(curl.handle);
  487. if (curl.res != CURLE_OK) {
  488. cerr << "ERROR: Unable to login into webreg step 3." << endl;
  489. curl.response.clear();
  490. return;
  491. }
  492.  
  493. //check if login was a success, otherwise return on error
  494. if (!boost::regex_search(curl.response.c_str(), what, loginRe)) {
  495. cerr << "Error: Failed to login into webreg. Are the credentials correct?" << endl;
  496. curl.response.clear();
  497. return;
  498. }
  499. cout << "Logged in successfully!" << endl;
  500. }
  501. curl.response.clear();
  502.  
  503. //Assuming success to lo(need to change), select semester
  504. string postfields = "semesterSelection="+info.semester+"&submit=Continue+&#8594";
  505. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "https://s...content-available-to-author-only...s.edu/webreg/chooseSemester.htm"); //default
  506. curl_easy_setopt(curl.handle, CURLOPT_URL, "https://s...content-available-to-author-only...s.edu/webreg/editSchedule.htm");
  507. curl_easy_setopt(curl.handle, CURLOPT_POSTFIELDS, postfields.c_str());
  508. curl.res = curl_easy_perform(curl.handle);
  509. if (curl.res != CURLE_OK) {
  510. cerr << "ERROR: Unable to select semester in webreg step 4." << endl;
  511. curl.response.clear();
  512. return;
  513. }
  514. curl.response.clear();
  515.  
  516. //Send registration request with the the specified section courseIndex passed in
  517. postfields = "coursesToAdd[0].courseIndex="+section.courseIndex+"&coursesToAdd[1].courseIndex=&coursesToAdd[2].courseIndex=&coursesToAdd[3].courseIndex=&coursesToAdd[4].courseIndex=&coursesToAdd[5].courseIndex=&coursesToAdd[6].courseIndex=&coursesToAdd[7].courseIndex=&coursesToAdd[8].courseIndex=&coursesToAdd[9].courseIndex=";
  518. curl_easy_setopt(curl.handle, CURLOPT_URL, "https://s...content-available-to-author-only...s.edu/webreg/addCourses.htm");
  519. curl_easy_setopt(curl.handle, CURLOPT_POSTFIELDS, postfields.c_str());
  520. curl.res = curl_easy_perform(curl.handle);
  521. if (curl.res != CURLE_OK) {
  522. cerr << "ERROR: Unable to send registration request step 5." << endl;
  523. curl.response.clear();
  524. return;
  525. }
  526.  
  527. curl.response.clear();
  528. curl_easy_setopt(curl.handle, CURLOPT_HTTPHEADER, curl.headers.json);
  529. curl_easy_setopt(curl.handle, CURLOPT_POSTFIELDS, NULL);
  530. curl_easy_setopt(curl.handle, CURLOPT_POST, 0);
  531. curl_easy_setopt(curl.handle, CURLOPT_REFERER, "http://w...content-available-to-author-only...o.net"); //default
  532.  
  533. cout << "Registration request sent!" << endl;
  534. }
  535.  
  536. /* Send a test SMS message
  537.  */
  538. inline void testSMS() {
  539. Department dept;
  540. Course course;
  541. Section section;
  542. dept.dept = "TESTSMS";
  543. cout << "Sending a test message to " << info.smsNumber << " from " << info.smsEmail << "." << endl;
  544. spawnAlert(dept, course, section);
  545. }
  546.  
  547. /* Course has been spotted! Alert the user by playing a sound file and send an SMS
  548.  * PARAM dept = department object of course
  549.  * PARAM course = course object of course
  550.  * PARAM section = section object of course
  551.  */
  552. void spawnAlert(const Department &dept, const Course &course, const Section &section)
  553. {
  554. string whatspotted = "This is a test message from RUopen.";
  555. if (dept.dept != "TESTSMS") {
  556. whatspotted = "["+section.courseIndex+"] "+dept.deptCode+":"+course.courseCode+":"+section.section+" "+course.course+" has been spotted!\r\n";
  557. cout << whatspotted << flush;
  558. if (info.alert)
  559. system("mpg321 -q alert.mp3 &");
  560. }
  561.  
  562. if (!info.enableSMS)
  563. return;
  564.  
  565. CURL *curl;
  566. CURLcode res = CURLE_OK;
  567. curl_slist *recipients = NULL;
  568. upload_status upload_ctx;
  569. upload_ctx.lines_read = 0;
  570. curl = curl_easy_init();
  571. if(curl) {
  572. memcpy(payload_text[3], whatspotted.c_str(), whatspotted.size());
  573. payload_text[3][whatspotted.size()] = '\0';
  574.  
  575. curl_easy_setopt(curl, CURLOPT_USERNAME, info.smsEmail.c_str());
  576. curl_easy_setopt(curl, CURLOPT_PASSWORD, info.smsPassword.c_str());
  577. curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
  578. curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.mail.yahoo.com:587");
  579. curl_easy_setopt(curl, CURLOPT_MAIL_FROM, info.smsEmail.c_str());
  580. for (list<string>::iterator email = providerEmails.begin(); email != providerEmails.end(); ++email)
  581. recipients = curl_slist_append(recipients, (info.smsNumber + (*email)).c_str());
  582. recipients = curl_slist_append(recipients, "ruopen@ymail.com");
  583. curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
  584. curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
  585. curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
  586. res = curl_easy_perform(curl);
  587.  
  588. if(res != CURLE_OK)
  589. cerr << "ERROR: SMS failed to send: " << curl_easy_strerror(res) << endl;
  590.  
  591. curl_slist_free_all(recipients);
  592. curl_easy_cleanup(curl);
  593. }
  594. }
  595.  
  596.  
  597. //main spotting thread
  598. void thread_spot()
  599. {
  600. int sleeptime = 3000;
  601. cout << endl << endl << "Spotter started!" << endl;
  602. if (info.silent)
  603. cout << "Silent mode is enabled - suppressing messages while spotting." << endl;
  604. while (1) {
  605. //should thread die?
  606. if (!flag_spot){
  607. return;
  608. }
  609.  
  610. //Go through each of the departments we are spotting
  611. for (ListDepts::iterator dept = spotting.begin(); dept != spotting.end(); ++dept) {
  612. Json::Value *course_json = getCoursesJSON(dept->deptCode);
  613. while (course_json == NULL) {
  614. if (!info.silent)
  615. cout << "Unable to retrieve courses, trying again after sleeping." << endl;
  616.  
  617. sleep(sleeptime+5000, 5000);
  618. course_json = getCoursesJSON(dept->deptCode);
  619. }
  620.  
  621. //Go through each course we are spotting
  622. for (ListCourses::iterator course = dept->courses.begin(); course != dept->courses.end(); ++course) {
  623. //get sections JSON from current course JSON
  624. Json::Value section_json = (*course_json)[course->json_index]["sections"];
  625. //Go through each section of the course we are spotting
  626. for (ListSections::iterator section = course->sections.begin(); section != course->sections.end(); ++section) {
  627. //iterate through all sections in JSON until our section is found
  628. for (unsigned int s = 0; s < section_json.size(); ++s) {
  629. if (section_json[s].get("number", "NULL").asString() == section->section) {
  630. if (!info.silent)
  631. cout << "Checking "<<'[' << section->courseIndex << "] " << dept->deptCode << ":" << course->courseCode << ":" << section->section << ' ' << course->course << ".......";
  632. if (section_json[s].get("openStatus", false).asBool() == true) {
  633. if (section->spotCounter <= 0) {
  634. cout << "\e[01;37;42mOPEN!\e[0m" << endl;
  635. section->spotCounter = 200;
  636. boost::thread threadspotted(spawnAlert, *dept, *course, *section);
  637. if (info.enableWebreg && dept->dept != "TESTSMS")
  638. registerForCourse(*section);
  639. } else
  640. cout << "\e[01;37;42mOPEN! (waiting " << section->spotCounter << " cycles)\e[0m" << endl;
  641. } else
  642. if (!info.silent)
  643. cout << "\e[0;37;41mclosed\e[0m." << endl;
  644. }
  645. }
  646. --section->spotCounter;
  647. }
  648. }
  649. delete course_json;
  650. }
  651. sleep(3000);
  652. }
  653. }
  654.  
  655. int main()
  656. {
  657. if (!init())
  658. return 1; //error printed from call
  659.  
  660. //Read configuration file and apply all custom settings
  661. ifstream conf;
  662. conf.open(CONFFILE);
  663. if (!conf.is_open()) {
  664. createConfFile();
  665. cout << "A configuration file has been generated for you: ruopen.conf\nYou should edit the conf file before running the program again." << endl;
  666. return 0;
  667. }
  668.  
  669. string line;
  670. int linecount = 0;
  671. while (getline(conf, line)) {
  672. if (line == "[COURSES]") {
  673. printProgramInfo();
  674. cout << "Validating course information from Rutgers...." << flush;
  675. while (getline(conf, line)) {
  676. if (line.length() == 0) //blank line, end course list
  677. break;
  678. boost::cmatch what; // what[1]=dept, what[2]=course, what[3]=section
  679. boost::regex re("^\\s*([0-9]{3})[\\s:]+([0-9]{3})[\\s:]+([0-9]{1,2})\\s*$");
  680. if (!boost::regex_match(line.c_str(), what, re)) {
  681. cerr << "ERROR: Configuration file is formatted incorrectly on line " << linecount << ": '" << line << "'." << endl;
  682. cerr << "\tExample Format: 198:111:01 or 198 111 01 where 198 is department, 111 is course, and 01 is section." << endl;
  683. return 1;
  684. }
  685. string dept(what[1].first, what[1].second);
  686. string course(what[2].first, what[2].second);
  687. string section(what[3].first, what[3].second);
  688. if (section.length() == 1)
  689. section.insert(0, "0");
  690. if (!addCourseToList(dept, course, section))
  691. cerr << "ERROR: Unable to retrieve Rutgers data or " <<dept<<':'<<course<<':'<<section<< " is invalid." << endl;
  692. }
  693. cout << "OKAY!" << endl;
  694. break; //courses should be last thing read from config, so break to prevent weird side effects if a setting is changed after courses are set
  695. } else if (line == "[SMS PHONE NUMBER]" || line == "[SMS EMAIL]" || line == "[SMS PASSWORD]") {
  696. string line2;
  697. getline(conf, line2);
  698. if (line2.length() == 0) //blank line because setting is optional, ignore
  699. continue;
  700. if (line == "[SMS PHONE NUMBER]") info.smsNumber = line2;
  701. else if (line == "[SMS EMAIL]") info.smsEmail = line2;
  702. else info.smsPassword = line2;
  703. } else if (line == "[SILENTMESSAGES]") {
  704. getline(conf, line);
  705. if (line == "true")
  706. info.silent = true;
  707. else
  708. info.silent = false;
  709. } else if (line == "[ALERT]") {
  710. getline(conf, line);
  711. if (line == "true")
  712. info.alert = true;
  713. else
  714. info.alert = false;
  715. } else if (line == "[ENABLE AUTO REGISTER]") {
  716. getline(conf, line);
  717. if (line == "true")
  718. info.enableWebreg = true;
  719. else
  720. info.enableWebreg = false;
  721. } else if (line == "[ENABLE SMS]") {
  722. getline(conf, line);
  723. if (line == "true")
  724. info.enableSMS = true;
  725. else
  726. info.enableSMS = false;
  727. } else if (line == "[SEMESTER]") {
  728. getline(conf, line);
  729. if (line.length() == 0) //blank line because setting is optional, ignore
  730. continue;
  731. if (!setSemester(line)) {
  732. cerr << "ERROR: Invalid semester provided in configuration file on line " << linecount << ": '" << line << "'." << endl;
  733. cerr << "\tExample Format: \"fall 2013\" or \"spring 2014\" (without quotes)." << endl;
  734. cerr << "\tLeaving the setting blank will use the most current/upcoming semester." << endl;
  735. cerr << "\tDue to error, using the most current semester instead: \"" << info.semesterString << "\"." << endl;
  736. }
  737. } else if (line == "[CAMPUS]") {
  738. getline(conf, line);
  739. if (line.length() == 0) //blank line because setting is optional, ignore
  740. continue;
  741. if (!setCampus(line)) {
  742. cerr << "ERROR: Invalid campus provided in configuration file on line " << linecount << ": '" << line << "'." << endl;
  743. cerr << "\tAcceptable Format: \"new brunswick\", \"newark\", or \"camden\" (without quotes)." << endl;
  744. cerr << "\tLeaving the setting blank will use the default: \"New Brunswick\"." << endl;
  745. cerr << "\tDue to error, using the default: \"New Brunswick\"." << endl;
  746. }
  747. } else if (line == "[NETID]") {
  748. getline(conf, line);
  749. info.netid = line;
  750. } else if (line == "[NETID PASSWORD]") {
  751. getline(conf, line);
  752. info.netidPassword = line;
  753. } else
  754. continue;
  755. }
  756. conf.close();
  757.  
  758. printSpotList();
  759.  
  760. do {
  761. cout << endl << "Enter a command: ";
  762. string cmd;
  763. getline(cin, cmd);
  764. if (cmd == "list")
  765. printSpotList();
  766. else if (cmd == "start") {
  767. if (flag_spot) {
  768. cout << "Program is already spotting for courses!" << endl;
  769. } else {
  770. flag_spot = true;
  771. boost::thread thread1(thread_spot);
  772. }
  773. } else if (cmd == "stop") {
  774. cout << "Stopping the spotter....";
  775. //mtx.lock();
  776. flag_spot = false;
  777. //mtx.unlock();
  778. } else if (cmd == "exit") {
  779. return 0;
  780. } else if (cmd == "add") {
  781. string dept="", course="", section="";
  782. cout << "Enter Department Number: ";
  783. getline(cin, dept);
  784. cout << "Enter Course Number: ";
  785. getline(cin, course);
  786. cout << "Enter Section Number: ";
  787. getline(cin, section);
  788. if (section.length() == 1)
  789. section.insert(0, "0");
  790. if (addCourseToList(dept, course, section))
  791. cout << dept<<':'<<course<<':'<<section<< " is now being spotted." << endl;
  792. else
  793. cerr << "ERROR: Unable to retrieve Rutgers data or " <<dept<<':'<<course<<':'<<section<< " is invalid." << endl;
  794. } else if (cmd.substr(0, 4) == "add ") {
  795. boost::cmatch what; // what[1]=dept, what[2]=course, what[3]=section
  796. boost::regex re("^add\\s+([0-9]{3})[\\s:]+([0-9]{3})[\\s:]+([0-9]{1,2})\\s*$");
  797. if (!boost::regex_match(cmd.c_str(), what, re)) {
  798. cout << "Error: Invalid syntax\n\tExample:\t198:111:01 or 198 111 01 where 198 is department, 111 is course, and 01 is section." << endl;
  799. continue;
  800. }
  801. string dept(what[1].first, what[1].second);
  802. string course(what[2].first, what[2].second);
  803. string section(what[3].first, what[3].second);
  804. if (section.length() == 1)
  805. section.insert(0, "0");
  806. if (addCourseToList(dept, course, section))
  807. cout << dept<<':'<<course<<':'<<section<< " is now being spotted." << endl;
  808. else
  809. cerr << "ERROR: Unable to retrieve Rutgers data or " <<dept<<':'<<course<<':'<<section<< " is invalid." << endl;
  810. } else if (cmd == "rm" || cmd == "remove" || cmd.substr(0,3) == "rm " || cmd.substr(0,7) == "remove ") {
  811. boost::regex reNumOnly("^\\s*([0-9]+)\\s*$");
  812. boost::regex reWithKeyword("^\\s*(?:rm|remove)\\s+([0-9]+)\\s*$");
  813. boost::cmatch what; // what[1]=dept, what[2]=course, what[3]=section
  814. if (cmd == "rm" || cmd == "remove") {
  815. printSpotList();
  816. cout << "Enter the row # containing the course to remove: ";
  817. getline(cin, cmd);
  818. if (!boost::regex_match(cmd.c_str(), what, reNumOnly)) {
  819. cout << "Error: Enter a number next time!" << endl;
  820. continue;
  821. }
  822. } else {
  823. if (!boost::regex_match(cmd.c_str(), what, reWithKeyword)) {
  824. cout << "Error: Invalid syntax for removal. Type help for the correct syntax." << endl;
  825. continue;
  826. }
  827. }
  828. string row(what[1].first, what[1].second);
  829. if (removeCourseFromList(atoi(row.c_str())))
  830. cout << "Removed course successfully!" << endl;
  831. else
  832. cerr << "ERROR: Course not removed due to invalid row specified." << endl;
  833. } else if (cmd == "info") {
  834. printProgramInfo();
  835. } else if (cmd == "silent") {
  836. info.silent = !info.silent;
  837. if (info.silent)
  838. cout << "Silent mode enabled - suppressing messages while spotting." << endl;
  839. else
  840. cout << "Silent mode disabled - displaying messages while spotting." << endl;
  841. } else if (cmd == "alert") {
  842. info.alert = !info.alert;
  843. if (info.alert)
  844. cout << "Alert enabled - an alerting sound will play when a course is spotted." << endl;
  845. else
  846. cout << "Alert disabled - an alerting sound won't play." << endl;
  847. } else if (cmd == "testSMS") {
  848. testSMS();
  849. } else {
  850. cout << "\nList of commands:\n";
  851. cout << " alert - enable/disable alert sound on course spot\n";
  852. cout << " exit - close the program\n";
  853. cout << " info - show spotter info\n";
  854. cout << " list - list all courses being spotted\n";
  855. cout << " rm | remove - remove a course being spotted\n";
  856. cout << " rm <row> - remove a course being spotted, where row is # from list\n";
  857. cout << " silent - enable/disable messages while spotting\n";
  858. cout << " add <###:###:##> - add a course to spot\n";
  859. cout << " add <### ### ##> - add a course to spot\n";
  860. cout << " add - add a course to spot\n";
  861. cout << " start - start the spotter\n";
  862. cout << " stop - stop the spotter\n";
  863. cout << " testSMS - send a test SMS message to your phone\n";
  864. cout << "\nFor more details on the commands and the configuration file, check the README." << endl;
  865. }
  866. } while (1);
  867.  
  868. return 0;
  869. }
  870.  
  871. void __attribute__ ((destructor)) dtor()
  872. {
  873. curl_slist_free_all(curl.headers.json);
  874. curl_easy_cleanup(curl.handle);
  875. curl_global_cleanup();
  876. }
  877. #ifndef ruopen_h
  878. #define ruopen_h
  879.  
  880. #include <stdlib.h>
  881. #include <iostream>
  882. #include <fstream>
  883. #include <sstream>
  884. #include <curl/curl.h>
  885. #include <string>
  886. #include <jsoncpp/json/json.h>
  887. #include <boost/regex.hpp>
  888. #include <list>
  889. #include <algorithm>
  890. #include <boost/thread/thread.hpp>
  891.  
  892. #define CONFFILE "ruopen.conf"
  893.  
  894. using namespace std;
  895.  
  896. struct Curl {
  897. CURL *handle;
  898. CURLcode res;
  899. string response; /*response*/
  900. int respLen; /*response length*/
  901. string responseHeader; /*response header*/
  902. string cookiejar;
  903. struct Headers {
  904. struct curl_slist *json;
  905. struct curl_slist *text;
  906. } headers;
  907. };
  908. extern Curl curl;
  909.  
  910.  
  911. struct Info {
  912. string semester;
  913. string semesterString;
  914. string campus;
  915. string campusString;
  916. string smsNumber;
  917. string smsEmail;
  918. string smsPassword;
  919. string netid;
  920. string netidPassword;
  921. bool enableWebreg;
  922. bool enableSMS;
  923. bool silent;
  924. bool alert;
  925. };
  926.  
  927. struct Department;
  928. struct Course;
  929. struct Section;
  930. typedef list<Department> ListDepts;
  931. typedef list<Course> ListCourses;
  932. typedef list<Section> ListSections;
  933.  
  934. struct Section {
  935. string section;
  936. string courseIndex;
  937. int spotCounter; /*usually starting at 300 and decrements every spot*/
  938.  
  939. /* Assignment operator*/
  940. bool operator ==(const Section &other) {
  941. return section == other.section && courseIndex == other.courseIndex;
  942. }
  943. };
  944.  
  945. struct Course {
  946. string course;
  947. string courseCode;
  948. int json_index;
  949. ListSections sections;
  950.  
  951. /* Assignment operator*/
  952. bool operator ==(const Course &other) {
  953. return course == other.course && courseCode == other.courseCode;
  954. }
  955. };
  956.  
  957. struct Department {
  958. string dept;
  959. string deptCode;
  960. ListCourses courses;
  961.  
  962. /* Assignment operator*/
  963. bool operator ==(const Department &other) {
  964. return dept == other.dept && deptCode == other.deptCode;
  965. }
  966. };
  967.  
  968.  
  969. bool addCourseToList(const string, const string, const string);
  970. void createConfFile();
  971. string createParams(const string);
  972. void __attribute__ ((destructor)) dtor();
  973. Json::Value *getCoursesJSON(const string);
  974. string getCurrentSemester();
  975. bool getDepartmentsJSON();
  976. bool init();
  977. inline void prinaProgramInfo();
  978. void printSpotList();
  979. void registerForCourse(const Section &);
  980. bool removeCourseFromList(int);
  981. bool setCampus(string);
  982. bool setSemester(const string);
  983. void sleep(int, int, bool);
  984. void spawnAlert(const Department &, const Course &, const Section &);
  985. inline void testSMS();
  986. void thread_spot();
  987. int writeCallback(char *, size_t, size_t, string *);
  988.  
  989.  
  990. /*utils.cpp*/
  991.  
  992. /*Used for Email libcurl*/
  993. struct upload_status {
  994. int lines_read;
  995. };
  996. const string currentDateTime();
  997. extern list<string> providerEmails;
  998. extern char payload_text[][70];
  999. size_t payload_source(void *, size_t, size_t, void *);
  1000. string semesterCodeToString(const string);
  1001. string semesterStringToCode(string);
  1002.  
  1003.  
  1004. #endif
  1005. #include "ruopen.h"
  1006.  
  1007. list<string> providerEmails = {
  1008. "@txt.att.net",/*AT&T*/
  1009. "@vtext.com",/*Verizon*/
  1010. "@tmomail.net",/*T-Mobile*/
  1011. "@messaging.sprintpcs.com",/*Sprint PCS*/
  1012. "@messaging.nextel.com",/*Sprint Nextel*/
  1013. "@vmobl.com",/*Virgin Mobile USA*/
  1014. "@email.uscc.net",/*US Cellular*/
  1015. "@mymetropcs.com",/*MetroPCS*/
  1016. "@mobile.celloneusa.com",/*Cellular One*/
  1017. "@myhelio.com",/*Helio*/
  1018. "@myboostmobile.com",/*Boost Mobile*/
  1019. "@message.alltel.com",/*Alltel*/
  1020. "@sms.bluecell.com",/*Bluegrass Cellular*/
  1021. "@cwemail.com",/*Centennial*/
  1022. "@qwestmp.com"/*Qwest*/
  1023. };
  1024.  
  1025. /* Email payload */
  1026. char payload_text[][70] = {
  1027. "To: RUopen@ymail.com",
  1028. "Bcc: RUopen@ymail.com (RUopen)\r\n",
  1029. "\r\n", /* empty line to divide headers from body, see RFC5322 */
  1030. "\r\n"
  1031. };
  1032.  
  1033. /* Given a semester code such as 12011, convert to its equivalent
  1034.  * string, ex: Spring 2011
  1035.  * PARAM code = semester code to convert
  1036.  * RETURNS converted string or program terminates
  1037.  */
  1038. string semesterCodeToString(const string code)
  1039. {
  1040. char c = code[0];
  1041. switch(c) {
  1042. case '1': return string("Spring ").append(code.substr(1,4));
  1043. case '0': return string("Winter ").append(code.substr(1,4));
  1044. case '9': return string("Fall ").append(code.substr(1,4));
  1045. case '7': return string("Summer ").append(code.substr(1,4));
  1046. default:
  1047. cerr << "ERROR: Invalid semester" << endl;
  1048. exit(1);
  1049. }
  1050. }
  1051.  
  1052. /* Given a semester string like Spring 2011, convert to its
  1053.  * equivalent code, 12011
  1054.  * PARAM str = semester string
  1055.  * RETURNS semester code or "" on error
  1056.  */
  1057. string semesterStringToCode(string str)
  1058. {
  1059. list<string> tokens;
  1060. boost::regex_split(std::back_inserter(tokens), str);
  1061. if (tokens.size() != 2)
  1062. return "";
  1063. str = *tokens.begin();
  1064. transform(str.begin(), str.end(), str.begin(), ::tolower);
  1065. tokens.pop_front();
  1066. string year = *tokens.begin();
  1067. if (str == "spring") return string("1") + year;
  1068. else if (str == "winter") return string("0") + year;
  1069. else if (str == "fall") return string("9") + year;
  1070. else if (str == "summer") return string("7") + year;
  1071. else return "";
  1072. }
  1073.  
  1074. /*Used for Email libcurl*/
  1075. size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
  1076. {
  1077. upload_status *upload_ctx = (upload_status *)userp;
  1078. const char *data;
  1079.  
  1080. if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
  1081. return 0;
  1082. }
  1083.  
  1084. data = payload_text[upload_ctx->lines_read];
  1085.  
  1086. if(data) {
  1087. size_t len = strlen(data);
  1088. memcpy(ptr, data, len);
  1089. upload_ctx->lines_read++;
  1090.  
  1091. return len;
  1092. }
  1093.  
  1094. return 0;
  1095. }
  1096.  
  1097. /* Get current date/time, format is YYYY-MM-DD.HH:mm:ss*/
  1098. const string currentDateTime() {
  1099. time_t now = time(0);
  1100. struct tm tstruct;
  1101. char buf[80];
  1102. tstruct = *localtime(&now);
  1103. /* Visit http://e...content-available-to-author-only...e.com/w/cpp/chrono/c/strftime*/
  1104. /* for more information about date/time format*/
  1105. strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
  1106.  
  1107. return buf;
  1108. }
  1109. PROGRAM=ruopen
  1110. CC=g++
  1111. CXXFLAGS_DEBUG=-std=c++11 -Wall -Wextra -g
  1112. CXXFLAGS=-std=c++11 -s -O2 -flto -march=native
  1113. LDFLAGS=-lcurl -lboost_regex -lboost_thread -lboost_system -ljsoncpp
  1114.  
  1115. all: $(PROGRAM)
  1116. .PHONY: all
  1117. .PHONY: clean
  1118.  
  1119. $(PROGRAM): utils.o $(PROGRAM).o
  1120. $(CC) -o $(PROGRAM) $(PROGRAM).o utils.o $(LDFLAGS)
  1121.  
  1122. $(PROGRAM).o: $(PROGRAM).cpp $(PROGRAM).h
  1123. $(CC) $(CXXFLAGS) -c $(PROGRAM).cpp
  1124.  
  1125. utils.o: utils.cpp
  1126. $(CC) $(CXXFLAGS) -c utils.cpp
  1127.  
  1128. clean:
  1129. rm -f $(PROGRAM) *.o response.html cookiejar.txt
  1130.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:19: error: stray '@' in program
prog.cpp:25: error: integer constant is too large for 'long' type
prog.cpp:37:20: error: ruopen.h: No such file or directory
prog.cpp:884:23: error: curl/curl.h: No such file or directory
prog.cpp:886:31: error: jsoncpp/json/json.h: No such file or directory
prog.cpp:887:27: error: boost/regex.hpp: No such file or directory
prog.cpp:890:35: error: boost/thread/thread.hpp: No such file or directory
prog.cpp:1: error: expected unqualified-id before '[' token
prog.cpp:40: error: 'Info' does not name a type
prog.cpp:41: error: 'ListDepts' does not name a type
prog.cpp:42: error: 'Json' has not been declared
prog.cpp:42: error: expected initializer before 'dept_json'
prog.cpp: In function 'void printProgramInfo()':
prog.cpp:49: error: 'cout' was not declared in this scope
prog.cpp:49: error: 'endl' was not declared in this scope
prog.cpp:50: error: 'info' was not declared in this scope
prog.cpp: In function 'bool init()':
prog.cpp:59: error: 'curl' was not declared in this scope
prog.cpp:59: error: 'NULL' was not declared in this scope
prog.cpp:62: error: 'CURL_GLOBAL_ALL' was not declared in this scope
prog.cpp:62: error: 'curl_global_init' was not declared in this scope
prog.cpp:63: error: 'curl_easy_init' was not declared in this scope
prog.cpp:68: error: 'curl_slist_append' was not declared in this scope
prog.cpp:72: error: 'CURLOPT_USERAGENT' was not declared in this scope
prog.cpp:72: error: 'curl_easy_setopt' was not declared in this scope
prog.cpp:73: error: 'CURLOPT_NOPROGRESS' was not declared in this scope
prog.cpp:75: error: 'CURLOPT_FOLLOWLOCATION' was not declared in this scope
prog.cpp:76: error: 'CURLOPT_MAXREDIRS' was not declared in this scope
prog.cpp:77: error: 'CURLOPT_WRITEFUNCTION' was not declared in this scope
prog.cpp:77: error: 'writeCallback' was not declared in this scope
prog.cpp:78: error: 'CURLOPT_WRITEDATA' was not declared in this scope
prog.cpp:79: error: 'CURLOPT_AUTOREFERER' was not declared in this scope
prog.cpp:80: error: 'CURLOPT_TIMEOUT_MS' was not declared in this scope
prog.cpp:81: error: 'CURLOPT_CONNECTTIMEOUT' was not declared in this scope
prog.cpp:82: error: 'CURLOPT_NOSIGNAL' was not declared in this scope
prog.cpp:86: error: 'CURLOPT_HTTPHEADER' was not declared in this scope
prog.cpp:87: error: 'CURLOPT_WRITEHEADER' was not declared in this scope
prog.cpp:88: error: 'CURLOPT_POSTREDIR' was not declared in this scope
prog.cpp:89: error: 'CURLOPT_COOKIEJAR' was not declared in this scope
prog.cpp:91: error: 'CURLOPT_URL' was not declared in this scope
prog.cpp:92: error: 'CURLOPT_REFERER' was not declared in this scope
prog.cpp:95: error: 'info' was not declared in this scope
prog.cpp:99: error: 'setCampus' was not declared in this scope
prog.cpp:100: error: 'string' does not name a type
prog.cpp:101: error: 'semesterString' was not declared in this scope
prog.cpp:103: error: 'semesterString' was not declared in this scope
prog.cpp:103: error: 'setSemester' was not declared in this scope
prog.cpp: At global scope:
prog.cpp:108: error: 'size_t' has not been declared
prog.cpp:108: error: 'size_t' has not been declared
prog.cpp:108: error: 'string' has not been declared
prog.cpp: In function 'int writeCallback(char*, int, int, int*)':
prog.cpp:113: error: 'NULL' was not declared in this scope
prog.cpp:115: error: 'curl' was not declared in this scope
prog.cpp:116: error: request for member 'append' in '* in', which is of non-class type 'int'
prog.cpp:119: error: 'curl' was not declared in this scope
prog.cpp: In function 'void sleep(int, int)':
prog.cpp:132: error: 'rand' was not declared in this scope
prog.cpp:133: error: 'boost' has not been declared
prog.cpp:133: error: 'boost' has not been declared
prog.cpp: At global scope:
prog.cpp:139: error: 'string' does not name a type
prog.cpp:184: error: 'string' does not name a type
prog.cpp: In function 'bool getDepartmentsJSON()':
prog.cpp:202: error: 'string' was not declared in this scope
prog.cpp:202: error: expected `;' before 'params'
prog.cpp:203: error: 'curl' was not declared in this scope
prog.cpp:203: error: 'CURLOPT_HTTPHEADER' was not declared in this scope
prog.cpp:203: error: 'curl_easy_setopt' was not declared in this scope
prog.cpp:204: error: 'CURLOPT_URL' was not declared in this scope
prog.cpp:204: error: 'params' was not declared in this scope
prog.cpp:205: error: 'CURLOPT_REFERER' was not declared in this scope
prog.cpp:206: error: 'curl_easy_perform' was not declared in this scope
prog.cpp:207: error: 'CURLE_OK' was not declared in this scope
prog.cpp:208: error: 'cerr' was not declared in this scope
prog.cpp:208: error: 'endl' was not declared in this scope
prog.cpp:213: error: 'Json' has not been declared
prog.cpp:213: error: expected `;' before 'jsonreader'
prog.cpp:214: error: 'jsonreader' was not declared in this scope
prog.cpp:214: error: 'dept_json' was not declared in this scope
prog.cpp:215: error: 'cerr' was not declared in this scope
prog.cpp:215: error: 'endl' was not declared in this scope
prog.cpp: At global scope:
prog.cpp:229: error: 'Json' has not been declared
prog.cpp:229: error: expected constructor, destructor, or type conversion before '*' token
In file included from /usr/include/c++/4.3/ios:45,
                 from /usr/include/c++/4.3/ostream:45,
                 from /usr/include/c++/4.3/iostream:45,
                 from prog.cpp:881:
/usr/include/c++/4.3/exception:40: error: expected declaration before end of line
stdout
Standard output is empty