Skip to content

Instantly share code, notes, and snippets.

@adammw
Created March 11, 2011 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adammw/865856 to your computer and use it in GitHub Desktop.
Save adammw/865856 to your computer and use it in GitHub Desktop.
search from the command line
/*
* main.c
*
* Created on: 11/03/2011
* Author: adam
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "cJSON.h"
#define USER_AGENT "ConsoleSearch/1.0 (like GoogleCL/1.0)"
#define REFERER "Console-based Google Search Client"
#define USE_ANSI 1
#if USE_ANSI
#define RESULT_FORMAT "%2i. \x1b[1m%s\x1b[0m\n %s\n <\x1b[4m%s\x1b[0m>\n\n"
#else
#define RESULT_FORMAT "%2i. %s\n %s\n <%s>\n\n"
#endif
struct MemoryStruct {
char *memory;
size_t size;
};
/**
* Callback for cURL to write response into memory
*
* Copied from libcurl example <http://curl.haxx.se/libcurl/c/getinmemory.html>
*/
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) {
/* out of memory! */
fprintf(stderr,"not enough memory (realloc returned NULL)\n");
exit(EXIT_FAILURE);
}
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
char* convertHtmlEntities(char* str) {
size_t length = strlen(str);
size_t i;
char *endchar = malloc(sizeof(char));
long charCode;
if (!endchar) {
fprintf(stderr,"not enough memory");
exit(EXIT_FAILURE);
}
for (i=0;i<length;i++) {
if (*(str+i) == '&' && *(str+i+1) == '#' && *(str+i+2) >= '0' && *(str+i+2) <= '9' && *(str+i+3) >= '0' && *(str+i+3) <= '9' && *(str+i+4) == ';') {
charCode = strtol(str+i+2,&endchar,0);
*(str+i) = charCode;
memmove(str+i+1,str+i+5,length - (i+5) + 1);
} else if (*(str+i) == '&' && *(str+i+1) == 'q' && *(str+i+2) == 'u' && *(str+i+3) == 'o' && *(str+i+4) == 't' && *(str+i+5) == ';') {
*(str+i) = '"';
memmove(str+i+1,str+i+6,length - (i+6) + 1);
}
}
return str;
}
char* convertHtmlTags(char* str) {
size_t length = strlen(str);
char *start = str;
while ((start = strstr(start, "<b>"))) {
memmove(start,start+3, length - 3 + 1);
start = strstr(start, "</b>");
memmove(start,start+4, length - 4 + 1);
if (!*(start+1)) {
break;
} else {
start++;
}
}
return str;
}
int main(int argc, char *argv[])
{
const char baseUrl[] = "https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=";
const int baseUrlLength = strlen(baseUrl);
CURL *curl;
CURLcode res;
cJSON *json;
struct MemoryStruct chunk;
char* searchQuery;
char* searchUrl;
chunk.memory = malloc(1);
chunk.size = 0;
/* Get search query */
if (argc > 1) {
int count;
int searchQueryLength = (argc - 2);
char sepChar[] = "+";
for (count = 1; count < argc; count++) {
searchQueryLength += strlen(argv[count]);
}
searchQuery = malloc(sizeof(char) * searchQueryLength + 1);
if (!searchQuery) {
fprintf(stderr,"not enough memory\n");
return -1;
}
for (count = 1; count < argc; count++) {
strcat(searchQuery, argv[count]);
if (count != (argc-1)) {
strcat(searchQuery, sepChar);
}
}
} else {
searchQuery = malloc(sizeof(char) * 255);
printf("Enter a search query: ");
scanf("%[^\n]s", searchQuery);
}
/* Free memory used by response */
if(chunk.memory)
{
free(chunk.memory);
}
/* Get search url */
searchUrl = malloc(sizeof(char) * (baseUrlLength + strlen(searchQuery) + 1));
if (!searchUrl) {
fprintf(stderr,"not enough memory\n");
return -1;
}
memmove(searchUrl,baseUrl,baseUrlLength);
memmove(searchUrl+baseUrlLength,searchQuery,strlen(searchQuery));
*(searchUrl+baseUrlLength+strlen(searchQuery)) = 0;
/* Initialise cURL */
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (!curl) {
fprintf(stderr,"Error Initalising cURL\n");
return -1;
}
/* Set cURL options */
curl_easy_setopt(curl, CURLOPT_URL, searchUrl);
curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
curl_easy_setopt(curl, CURLOPT_REFERER, REFERER);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
/* Perform cURL request */
res = curl_easy_perform(curl);
if (res != CURLE_OK || (long)chunk.size == 0) {
curl_easy_cleanup(curl);
fprintf(stderr,"Error Performing Request\n");
return -1;
}
/* Clean up */
curl_easy_cleanup(curl);
/* Decode JSON */
json=cJSON_Parse(chunk.memory);
if (!json) {
fprintf(stderr,"Error Parsing JSON\n");
return -1;
}
/* Check response status */
if (cJSON_GetObjectItem(json,"responseStatus")->valueint != 200) {
fprintf(stderr,"Service Error: %s\n", cJSON_GetObjectItem(json,"responseDetails")->valuestring);
return -1;
}
/* Get number of results */
cJSON *data = cJSON_GetObjectItem(json,"responseData");
cJSON *results = cJSON_GetObjectItem(data,"results");
int numResults = cJSON_GetArraySize(results);
/* Print each result */
cJSON *result;
int resultIndex;
for (resultIndex = 0; resultIndex < numResults; resultIndex++) {
result = cJSON_GetArrayItem(results, resultIndex);
printf(RESULT_FORMAT, resultIndex + 1, convertHtmlEntities(cJSON_GetObjectItem(result,"titleNoFormatting")->valuestring), convertHtmlTags(convertHtmlEntities(cJSON_GetObjectItem(result,"content")->valuestring)), cJSON_GetObjectItem(result,"unescapedUrl")->valuestring);
}
/* Free memory used by response */
if(chunk.memory)
{
free(chunk.memory);
}
/*printf("%s",cJSON_Print(json));*/
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment