1 /* babel_story_functions.c babel top-level operations for story files
\r
2 * (c) 2006 By L. Ross Raszewski
\r
4 * This code is freely usable for all purposes.
\r
6 * This work is licensed under the Creative Commons Attribution2.5 License.
\r
7 * To view a copy of this license, visit
\r
8 * http://creativecommons.org/licenses/by/2.5/ or send a letter to
\r
10 * 543 Howard Street, 5th Floor,
\r
11 * San Francisco, California, 94105, USA.
\r
13 * This file depends upon babel_handler.c, babel.h, and misc.c
\r
21 #ifndef THREE_LETTER_EXTENSIONS
\r
22 #define IFICTION_EXT ".iFiction"
\r
24 #define IFICTION_EXT ".ifi"
\r
26 void *my_malloc(int32, char *);
\r
28 void babel_story_ifid()
\r
30 char buffer[TREATY_MINIMUM_EXTENT];
\r
33 i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);
\r
34 ep=strtok(buffer, ",");
\r
37 printf("IFID: %s\n",ep);
\r
38 ep=strtok(NULL,",");
\r
41 fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");
\r
46 void babel_story_format()
\r
49 b=babel_get_format();
\r
50 if (!b) b="unknown";
\r
51 if (!babel_get_authoritative())
\r
52 printf("Format: %s (non-authoritative)\n",b);
\r
53 else printf("Format: %s\n",b);
\r
56 static void deep_babel_ifiction(char stopped)
\r
58 char buffer[TREATY_MINIMUM_EXTENT];
\r
66 i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);
\r
67 if (i==0 && !babel_md5_ifid(buffer, TREATY_MINIMUM_EXTENT))
\r
69 fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");
\r
74 ep=strtok(buffer, ",");
\r
77 i=babel_treaty(GET_STORY_FILE_METADATA_EXTENT_SEL,NULL,0);
\r
80 if (stopped) printf("No iFiction record for %s\n",buffer);
\r
83 md=(char *)my_malloc(i,"Metadata buffer");
\r
84 if (babel_treaty(GET_STORY_FILE_METADATA_SEL,md,i)<0)
\r
86 fprintf(stderr,"A serious error occurred while retrieving metadata.\n");
\r
92 char epb[TREATY_MINIMUM_EXTENT+9];
\r
96 strcat(epb, IFICTION_EXT);
\r
102 if (!f || fputs(md,f)==EOF)
\r
103 fprintf(stderr,"A serious error occurred writing to disk.\n");
\r
104 else if (stopped!=2) printf("Extracted %s\n",epb);
\r
106 if (stopped) break;
\r
107 ep=strtok(NULL,",");
\r
112 void babel_story_ifiction()
\r
114 deep_babel_ifiction(1);
\r
116 static char *get_jpeg_dim(void *img, int32 extent)
\r
118 unsigned char *dp=(unsigned char *) img;
\r
119 unsigned char *ep=dp+extent;
\r
120 static char buffer[256];
\r
121 unsigned int t1, t2, w, h;
\r
126 if (t1!=0xff || t2!=0xD8 )
\r
128 return "(invalid)";
\r
133 if (dp>ep) return "(invalid)";
\r
134 for(t1=*(dp++);t1!=0xff;t1=*(dp++)) if (dp>ep) return "(invalid)";
\r
135 do { t1=*(dp++); if (dp>ep) return "(invalid 4)";} while (t1 == 0xff);
\r
137 if ((t1 & 0xF0) == 0xC0 && !(t1==0xC4 || t1==0xC8 || t1==0xCC))
\r
140 if (dp>ep) return "(invalid)";
\r
142 if (dp>ep) return "(invalid)";
\r
144 if (dp>ep) return "(invalid)";
\r
146 if (dp>ep) return "(invalid)";
\r
148 sprintf(buffer, "(%dx%d)",w,h);
\r
151 else if (t1==0xD8 || t1==0xD9)
\r
156 if (dp>ep) return "(invalid)";
\r
158 if (dp>ep) return "(invalid)";
\r
162 if (dp>ep) return "(invalid)";
\r
165 return "(invalid)";
\r
168 static int32 read_int(unsigned char *mem)
\r
174 return i1 | (i2<<8) | (i3<<16) | (i4<<24);
\r
178 static char *get_png_dim(void *img, int32 extent)
\r
180 unsigned char *dp=(unsigned char *)img;
\r
181 static char buffer[256];
\r
184 !(dp[0]==137 && dp[1]==80 && dp[2]==78 && dp[3]==71 &&
\r
185 dp[4]==13 && dp[5] == 10 && dp[6] == 26 && dp[7]==10)||
\r
186 !(dp[12]=='I' && dp[13]=='H' && dp[14]=='D' && dp[15]=='R'))
\r
187 return "(invalid)";
\r
190 sprintf(buffer,"(%dx%d)",w,h);
\r
193 static char *get_image_dim(void *img, int32 extent, int fmt)
\r
195 if (fmt==JPEG_COVER_FORMAT) return get_jpeg_dim(img,extent);
\r
196 else if (fmt==PNG_COVER_FORMAT) return get_png_dim(img, extent);
\r
197 return "(unknown)";
\r
200 static void deep_babel_cover(char stopped)
\r
202 char buffer[TREATY_MINIMUM_EXTENT];
\r
209 i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);
\r
211 if (babel_md5_ifid(buffer, TREATY_MINIMUM_EXTENT))
\r
212 printf("IFID: %s\n",buffer);
\r
215 fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");
\r
220 ep=strtok(buffer, ",");
\r
221 i=babel_treaty(GET_STORY_FILE_COVER_EXTENT_SEL,NULL,0);
\r
222 j=babel_treaty(GET_STORY_FILE_COVER_FORMAT_SEL,NULL,0);
\r
226 if (stopped) printf("No cover art for %s\n",buffer);
\r
229 if (j==PNG_COVER_FORMAT) ext=".png";
\r
230 else if (j==JPEG_COVER_FORMAT) ext=".jpg";
\r
231 md=my_malloc(i,"Image buffer");
\r
232 if (babel_treaty(GET_STORY_FILE_COVER_SEL,md,i)<0)
\r
234 fprintf(stderr,"A serious error occurred while retrieving cover art.\n");
\r
238 dim=get_image_dim(md,i,j);
\r
241 char epb[TREATY_MINIMUM_EXTENT+9];
\r
246 if (!f || fwrite(md,1,i,f)==EOF)
\r
247 fprintf(stderr,"A serious error occurred writing to disk.\n");
\r
248 else printf("Extracted %s %s\n",epb, dim);
\r
250 if (stopped) break;
\r
251 ep=strtok(NULL,",");
\r
256 void babel_story_cover()
\r
258 deep_babel_cover(1);
\r
261 void babel_story_fish()
\r
263 deep_babel_ifiction(0);
\r
264 deep_babel_cover(0);
\r
267 static char *get_biblio(void)
\r
271 char *bib="No bibliographic data";
\r
272 char *bibb; char *bibe;
\r
274 static char buffer[TREATY_MINIMUM_EXTENT];
\r
276 i=babel_treaty(GET_STORY_FILE_METADATA_EXTENT_SEL,NULL,0);
\r
277 if (i<=0) return bib;
\r
279 md=(char *) my_malloc(i,"Metadata buffer");
\r
280 if (babel_treaty(GET_STORY_FILE_METADATA_SEL,md,i)<0) return bib;
\r
282 bibb=strstr(md,"<bibliographic>");
\r
283 if (!bibb) { free(md); return bib; }
\r
284 bibe=strstr(bibb,"</bibliographic>");
\r
286 t=strstr(bibb,"<title>");
\r
290 bibe=strstr(t,"</title>");
\r
295 for(i=0;t[i];i++) if (t[i]<0x20 || t[i]>0x7e) t[i]='_';
\r
296 sprintf(buffer, "\"%s\" ",t);
\r
299 else strcpy(buffer,"<no title found> ");
\r
301 t=strstr(bibb,"<author>");
\r
305 bibe=strstr(t,"</author>");
\r
310 for(i=0;t[i];i++) if (t[i]<0x20 || t[i]>0x7e) t[i]='_';
\r
311 strcat(buffer, "by ");
\r
315 else strcat(buffer, "<no author found>");
\r
321 void babel_story_identify()
\r
324 char *b, *cf, *dim;
\r
325 char buffer[TREATY_MINIMUM_EXTENT];
\r
327 printf("%s\n",get_biblio());
\r
328 babel_story_ifid();
\r
329 b=babel_get_format();
\r
330 if (!b) b="unknown";
\r
331 l=babel_get_length() / 1024;
\r
334 i=babel_treaty(GET_STORY_FILE_COVER_EXTENT_SEL,NULL,0);
\r
335 j=babel_treaty(GET_STORY_FILE_COVER_FORMAT_SEL,NULL,0);
\r
343 char *md=my_malloc(i,"Image buffer");
\r
344 if (babel_treaty(GET_STORY_FILE_COVER_SEL,md,i)<0)
\r
350 dim=get_image_dim(md,i,j)+1;
\r
351 dim[strlen(dim)-1]=0;
\r
352 if (j==JPEG_COVER_FORMAT) cf="jpeg";
\r
353 else if (j==PNG_COVER_FORMAT) cf="png";
\r
354 else cf="unknown format";
\r
355 sprintf(buffer,"cover %s %s",dim,cf);
\r
359 printf("%s, %dk, %s\n",b, l,cf);
\r
362 void babel_story_meta()
\r
364 deep_babel_ifiction(2);
\r
367 void babel_story_story()
\r
373 char buffer[TREATY_MINIMUM_EXTENT+20];
\r
374 j=babel_get_story_length();
\r
375 p=babel_get_story_file();
\r
378 fprintf(stderr,"A serious error occurred while retrieving the story file.\n");
\r
382 i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);
\r
383 if (i==0 && !babel_md5_ifid(buffer, TREATY_MINIMUM_EXTENT))
\r
385 fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");
\r
388 ep=strchr(buffer, ',');
\r
389 if (!ep) ep=buffer+strlen(buffer);
\r
391 babel_treaty(GET_STORY_FILE_EXTENSION_SEL,ep,19);
\r
392 f=fopen(buffer,"wb");
\r
393 if (!f || !fwrite(p,1,j,f))
\r
395 fprintf(stderr,"A serious error occurred writing to disk.\n");
\r
399 printf("Extracted %s\n",buffer);
\r
405 void babel_story_unblorb()
\r
407 deep_babel_ifiction(1);
\r
408 deep_babel_cover(1);
\r
409 babel_story_story();
\r