summaryrefslogtreecommitdiff
path: root/getgbook.c
blob: 1442e8e4e6dd117466205a1d4bcafeb09f85bf1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* See COPYING file for copyright, license and warranty details. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.c"

#define usage "getgbook " VERSION " - a google books downloader\n" \
              "usage: getgbook [-p|-a] bookid\n" \
              "  -p print all available pages\n" \
              "  -a download all available pages\n" \
              "  otherwise, all pages in stdin will be downloaded\n"

#define URLMAX 1024
#define BOOKID_LEN 12

typedef struct {
	int num;
	char url[URLMAX];
	char name[80];
} Page;

char pagecodes[][3] = { "PP", "PR", "PA", "PT", "\0" };

Page *getpagedetail(char *bookid, char *pg)
{
	char url[URLMAX];
	char *buf, *c, *d, m[80], *p;
	Page *page;

	snprintf(url, URLMAX, "/books?id=%s&pg=%s&jscmd=click3", bookid, pg);

	if(!get("books.google.com", url, &buf))
		return NULL;

	snprintf(m, 80, "\"pid\":\"%s\"", pg);
	if(!(c = strstr(buf,m)))
		return NULL;

	page = malloc(sizeof(Page));
	strncpy(page->name, pg, 80);
	page->url[0] = '\0';
	page->num = -1;

	if(!strncmp(c+strlen(m)+1, "\"src\"", 5)) {
		for(p=page->url, d=c+strlen(m)+8; *d && *d != '"'; d++, p++) {
			if(!strncmp(d, "\\u0026", 6)) {
				*p = '&';
				d+=5;
			} else
				*p = *d;
		}
		*p = '\0';
	}

	for(; *d; d++) {
		if(*d == '}') {
			break;
		}
		if(!strncmp(d, "\"order\"", 7)) {
			sscanf(d+8, "%d,", &(page->num));
			break;
		}
	}

	free(buf);
	return page;
}

int main(int argc, char *argv[])
{
	char *bookid, pg[16], buf[1024], n[80], code[3];
	int i, c;
	Page *page;

	if(argc < 2 || argc > 3 ||
	   (argv[1][0]=='-' && ((argv[1][1]!='p' && argv[1][1]!='a') || argc < 3)))
		die(usage);

	bookid = argv[argc-1];

	if(argv[1][0] == '-') {
		strncpy(code, pagecodes[0], 3);
		c = i =0;
		while(++i) {
			snprintf(pg, 16, "%s%d", code, i);
			if(!(page = getpagedetail(bookid, pg))) {
				/* no more pages with that code */
				strncpy(code, pagecodes[++c], 3);
				if(code[0] == '\0') break;
				i=0;
				continue;
			}
			if(!page->url[0]) {
				fprintf(stderr, "%s not available\n", pg);
				free(page);
				continue;
			}
			if(argv[1][1] == 'a') {
				snprintf(n, 80, "%05d.png", page->num);
				gettofile("books.google.com", page->url, n);
				printf("Downloaded page %d\n", page->num);
			} else if(page->num != -1)
				printf("%d\n", page->num);
			free(page);
		}
	} else {
		/* todo: find the page based on its order number, rather than using PA%d */
		while(fgets(buf, 1024, stdin)) {
			sscanf(buf, "%d", &i);
			snprintf(pg, 16, "%s%d", "PA", i);
			if(!(page = getpagedetail(bookid, pg)) || !page->url[0]) {
				fprintf(stderr, "%d failed\n", i);
				free(page);
				continue;
			}
			snprintf(n, 80, "%05d.png", page->num);
			gettofile("books.google.com", page->url, n);
			printf("Downloaded page %d\n", page->num);
			free(page);
		}
	}

	return EXIT_SUCCESS;
}