This is main.c in view mode; [Download] [Up]
/*
* WWW document access counter
*
* RCS:
* $Revision: 2.3 $
* $Date: 1996/05/03 02:20:22 $
*
* Security:
* Unclassified
*
* Description:
* main routine for WWW homepage access counter
*
* Input Parameters:
* type identifier description
*
* N/A
*
* Output Parameters:
* type identifier description
*
* N/A
*
* Return Values:
* value description
*
* Side Effects:
* None
*
* Limitations and Comments:
* None
*
* Development History:
* who when why
* muquit@semcor.com 10-Apr-95 first cut
* muquit@semcor.com 06-07-95 release 1.2
* muquit@semcor.com 07-13-95 release 1.3
*/
#define __Main__
#include "cdebug.h"
#include "combine.h"
#include "count.h"
#ifdef SYS_WIN32
#include "configNT.h"
#else
#include "config.h"
#endif
static char *ImagePrefix[]=
{
"zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine",
};
void main (argc, argv)
int
argc;
char
**argv;
{
int
rc = 0;
unsigned int
ignore_site=False;
register int
i;
char
*browser_type,
*remote_ip,
*query_string;
int
n;
int
counter_length;
int
left_pad;
char
filename[MaxTextLength];
char
tmpbuf[MaxTextLength];
char
digitbuf[MaxTextLength];
int
fd;
char
format[10],
buf[50];
int
count,
counter;
int
tagdigit;
int
MaxDigits=10;
DigitInfo
digit_info;
FrameInfo
frame_info;
unsigned int
use_st;
int
min_dig1,
min_dig2;
int
mon_dig1,
mon_dig2,
day_dig1,
day_dig2,
year_dig1,
year_dig2;
char
hour[10],
min[10],
ampm[10];
int
display_what;
unsigned int
untrusted_browser=False;
#ifdef ACCESS_AUTH
char
*rem_refh;
#endif
/*
**---------initialize globals------Starts---
*/
for (i=0; i < MaxSites; i++)
{
GrefererHost[i] = (char *) NULL;
GignoreSite[i] = (char *) NULL;
}
Grhost=0;
Gsite=0;
Gdebug=False;
Gauto_file_creation=0;
Gstrict_mode=1;
GrgbMappingIsError=1;
/*
**---------initialize globals------Ends---
*/
count=1;
*hour='\0';
*min='\0';
*ampm='\0';
*format='\0';
*buf='\0';
*filename = '\0';
*digitbuf='\0';
*tmpbuf = '\0';
counter = 0;
tagdigit=9;
left_pad=MaxDigits;
use_st=False;
display_what=SHOW_COUNTER;
remote_ip=(char *) NULL;
/*
** parse command line, this is only used for testing at commandline
** no command line flag is allowed in the web page while calling
** the program
*/
for (i=1; i < argc; i++)
{
if (!strncmp(argv[i],"-debug",(int)strlen("-debug")))
{
Gdebug=True;
break;
}
}
Debug2("[%s] Count %s: --Debug--",GetTime(),Version);
#ifdef TEST_RRR
/*************REMOVE****************/
env_test=getenv("PATH_INFO");
if (env_test == (char *) NULL)
{
(void) strcpy(tmpbuf,"PATH_INFO is NULL");
}
else
{
(void) sprintf(tmpbuf,"PATH_INFO is=%s\n",env_test);
}
Warning(tmpbuf);
env_test=getenv("PATH_TRANSLATED");
if (env_test == (char *) NULL)
{
(void) strcpy(tmpbuf,"PATH_TRANSLATED is NULL");
}
else
{
(void) sprintf(tmpbuf,"PATH_TRANSLATED=%s\n",env_test);
}
Warning(tmpbuf);
/*************REMOVE****************/
#endif
rc=CheckDirs();
if (rc == 1)
{
*tmpbuf='\0';
(void) sprintf(tmpbuf,"ConfigDir,DigitDir,DataDir,LogDir must differ");
Warning(tmpbuf);
PrintHeader();
StringImage(tmpbuf);
exit(1);
}
/*
** parse the authorization list
*/
rc = ParseConfig ();
switch (rc)
{
case ConfigOpenFailed:
{
*tmpbuf='\0';
(void) sprintf (tmpbuf,
"Faliled to open configuration file: \"%s/%s\"",
ConfigDir,ConfigFile);
Warning (tmpbuf);
PrintHeader ();
StringImage (tmpbuf);
exit(1);
break;
}
case NoAutofcBlock:
{
*tmpbuf='\0';
(void) sprintf (tmpbuf,
"No auto file creation block in conf file: \"%s/%s\"",
ConfigDir,ConfigFile);
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
break;
}
case NoStrictBlock:
{
*tmpbuf='\0';
(void) sprintf (tmpbuf,
"No Strict mode block in conf file: \"%s/%s\"",
ConfigDir,ConfigFile);
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
break;
}
case NoIgnoreHostsBlock:
{
*tmpbuf='\0';
(void) sprintf (tmpbuf,
"No IgnoreHosts Block in the configuration file: \"%s/%s\"",
ConfigDir,ConfigFile);
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
}
case NoRefhBlock:
{
*tmpbuf='\0';
(void) sprintf(tmpbuf,"Compiled with -DACCESS_AUTH,but no such block in configuration file!");
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
}
case UnpexpectedEof:
{
*tmpbuf='\0';
(void) sprintf (tmpbuf,
"Unexpected EOF in configuration file: \"%s/%s\"",
ConfigDir,ConfigFile);
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
}
} /* switch (rc) */
Debug2("Gsite: %d",Gsite,0);
Debug2("Gauto_file_creation= %d",Gauto_file_creation,0);
Debug2("Gstrict_mode= %d",Gstrict_mode,0);
#ifdef ACCESS_AUTH
/*
** check if the referer is a remote host or not. refere should
** be the local host.
*/
rem_refh = (char *) getenv("HTTP_REFERER");
if (rem_refh != (char *) NULL)
{
char
http_ref[1024],
Rhost[1024];
*http_ref = '\0';
*Rhost = '\0';
/*
** this will be same as your host when accessed from your
** page. if the host is anything else, it is an unauthorized
** access. handle it.
*/
*tmpbuf='\0';
(void) strcpy (http_ref, rem_refh);
GetRemoteReferer(http_ref, Rhost);
/*
(void) sprintf(tmpbuf,"http_ref=%s",http_ref);
Warning(tmpbuf);
*/
Debug2("Grhost= %d",Grhost,0);
Debug2("Rhost= %s",Rhost,0);
if (*Rhost != '\0')
{
if (Grhost > 0)
{
for (i=0; i < Grhost; i++)
{
rc=mystrcasecmp(Rhost,GrefererHost[i]);
if (rc == 0)
break;
}
}
if (rc != 0)
{
*tmpbuf='\0';
(void) sprintf(tmpbuf,
"Host: \"%s\" is not in the auth block of the conf file",Rhost);
Warning(tmpbuf);
PrintHeader();
StringImage(tmpbuf);
exit(1);
}
}
}
#endif /* ACCESS_AUTH */
/*
** get the user name from query string
*/
query_string = (char *) getenv("QUERY_STRING");
if (query_string == (char *) NULL)
{
*tmpbuf='\0';
(void) sprintf(tmpbuf,"%s","Empty QUERY_STRING!");
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
}
rc=ParseQueryString(query_string,&digit_info,&frame_info);
Debug2("\n",0,0);
Debug2("Parsed QUERY_STRING",0,0);
Debug2(" ft=%d",frame_info.width,0);
Debug4(" rgb=%d,%d,%d", frame_info.matte_color.red,
frame_info.matte_color.green, frame_info.matte_color.blue,0);
Debug2(" tr=%d",digit_info.alpha,0);
Debug4(" trgb=%d,%d,%d",digit_info.alpha_red,
digit_info.alpha_green,digit_info.alpha_blue,0);
Debug2(" replace_color=%d",digit_info.replace_color,0);
Debug4(" srgb=%d,%d,%d",
digit_info.opaque_red,
digit_info.opaque_green,
digit_info.opaque_blue,
0);
Debug4(" prgb=%d,%d,%d",
digit_info.pen_red,
digit_info.pen_green,
digit_info.pen_blue,
0);
Debug2(" maxdigits=%d",digit_info.maxdigits,0);
Debug2(" wxh [ignored,exists for compatibity] =%dx%d",
digit_info.width, digit_info.height);
Debug2(" md=%d", digit_info.maxdigits,0);
Debug2(" pad=%d", digit_info.leftpad,0);
Debug2(" ddhead=%s",digit_info.ddhead,0);
Debug2(" st=%d",digit_info.st,0);
Debug2(" sh=%d", digit_info.show,0);
Debug2(" df=%s",digit_info.datafile,0);
Debug2(" lit=%s",digit_info.literal,0);
Debug2(" incr=%d",digit_info.increment_counter,0);
Debug2(" negate=%d",digit_info.negate,0);
Debug2(" rotate=%d",digit_info.rotate,0);
Debug2(" degrees=%d",digit_info.rotate_degrees,0);
Debug2(" timezone=%s",digit_info.time_z,0);
Debug2(" timeformat=%d",digit_info.time_format,0);
Debug2(" istrip=%d",digit_info.use_strip,0);
Debug2(" image=%s", digit_info.gif_file,0);
Debug2(" parsed QS--\n",0,0);
if (rc)
{
Debug2("rc from from ParseQueryString()=%d",rc,0);
exit(1);
}
if (digit_info.leftpad == True)
{
MaxDigits=digit_info.maxdigits;
if ((MaxDigits < 5) || (MaxDigits > 10))
{
Warning("Maxdigits (md) must be >= 5 and <= 10");
PrintHeader ();
StringImage("Maxdigits (md) must be >= 5 and <= 10");
exit(1);
}
}
/*
** now find out what we'r trying to display
*/
display_what=digit_info.display_type;
if (display_what == SHOW_COUNTER)
{
if (checkfilename (digit_info.datafile) != 0)
{
*tmpbuf='\0';
(void) sprintf(tmpbuf,"Illegal datafile path!");
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
}
}
/*
** get frameinfo
*/
if (frame_info.width > 1)
digit_info.Frame=True;
else
digit_info.Frame=False;
/*
** get the IP address of the connected machine to check if we need
** to increment the counter
*/
if (display_what == SHOW_COUNTER)
{
remote_ip = (char *) getenv("REMOTE_ADDR");
if (remote_ip == (char *) NULL)
{
/*
** put a dummy here
*/
remote_ip = "dummy_ip";
}
else
{
for (i=0; i < Gsite; i++)
{
ignore_site=CheckRemoteIP(remote_ip,GignoreSite[i]);
if (ignore_site == True)
{
Debug2("Not counting IP: %s",remote_ip,0);
Debug2("GignoreSite[%d]:%s",i,GignoreSite[i]);
break;
}
}
}
}
/*
** initialize Limit array
*/
if (display_what == SHOW_COUNTER)
{
Debug2("Maxdigits=%d",MaxDigits,0);
}
#ifdef ACCESS_AUTH
if (Gstrict_mode == 1)
{
if (rem_refh == (char *) NULL)
{
untrusted_browser=True;
/*
** no HTTP_REFERER env variable found.
** display a literal string. this will make sure that even if
** someone with a broken browser tries to access the counter
** remotely, will not mess up the datafile. of course we'll
** miss some counts. because anyone accesses the page with a
** broken browser like this will see a literal string
*/
(void) strcpy(digit_info.literal,"888888");
/*
if (remote_ip != (char *) NULL)
{
(void) sprintf(tmpbuf,"No HTTP_REFERER supplied from %s",
remote_ip);
Warning(tmpbuf);
}
*/
/*
** try to get the browser name, it will give us a good
** feedback.
*/
browser_type=(char *) getenv("HTTP_USER_AGENT");
if (browser_type != (char *) NULL)
{
if (remote_ip != (char *) NULL)
{
*tmpbuf='\0';
(void) sprintf(tmpbuf,"Untrusted browser %s",browser_type);
Warning(tmpbuf);
}
}
}
} /* Gstrict_mode == 1 */
#endif
switch (display_what)
{
case SHOW_CLOCK: /* act as a clock*/
{
time_t
daytime,
tm;
struct tm
*Tm=(struct tm *) NULL;
long
diff; /* in seconds */
if (untrusted_browser == False)
{
tm=time(NULL);
if (*digit_info.time_z != '\0')
{
/*
** no more TZ, 03/26/96
*/
diff=checkTimezone(digit_info.time_z);
Tm=gmtime(&tm);
#ifdef HAVE_MKTIME
daytime=mktime(Tm);
#else
daytime=netMktime(Tm);
#endif
daytime += diff;
Tm=localtime(&daytime);
}
else
{
Debug2("No timezone",0,0);
Tm=localtime(&tm);
}
if (digit_info.time_format == 12)
{
if ((Tm)->tm_hour < 12)
(void) strcpy(ampm,"A");
else
(void) strcpy(ampm,"P");
if ((Tm)->tm_hour > 12)
(Tm)->tm_hour = (Tm)->tm_hour-12;
if ((Tm)->tm_hour == 0)
(Tm)->tm_hour=12;
}
/*
** take off strftime(), 1/13/95, muquit
*/
(void) sprintf(hour,"%d",(Tm)->tm_hour);
/*
** I like to keep leading zeros for minutes
*/
min_dig1=(Tm->tm_min - (Tm->tm_min % 10)) / 10;
min_dig2=Tm->tm_min % 10;
(void) sprintf(min,"%d%d",min_dig1,min_dig2);
(void) sprintf(buf,"%s:%s%s",hour,min,ampm);
}
else
{
(void) strcpy(buf,"888888");
}
Debug2(" time buf= %s",buf,0);
*digitbuf='\0';
(void) strcpy(digitbuf,buf);
WriteCounterImage(digitbuf, &digit_info,&frame_info);
/*
** we will not be here
*/
exit(0);
break;
}
case SHOW_DATE:
{
time_t
daytime,
tm;
struct tm
*Tm;
long
diff; /* in seconds */
if (untrusted_browser == False)
{
tm=time(NULL);
if (*digit_info.time_z != '\0')
{
/*
** no more TZ, 03/26/96
*/
diff=checkTimezone(digit_info.time_z);
Tm=gmtime(&tm);
#ifdef HAVE_MKTIME
daytime=mktime(Tm);
#else
daytime=netMktime(Tm);
#endif
daytime += diff;
Tm=localtime(&daytime);
}
else
{
Tm=localtime(&tm);
}
Tm->tm_mon++;
Debug2(" Inside SHOW_DATE",0,0);
/*
** padding, saw in xdaliclock
*/
mon_dig1=(Tm->tm_mon-(Tm->tm_mon % 10)) / 10;
mon_dig2=Tm->tm_mon % 10;
day_dig1=(Tm->tm_mday-(Tm->tm_mday % 10)) / 10;
day_dig2=Tm->tm_mday % 10;
year_dig1=(Tm->tm_year-(Tm->tm_year % 10)) / 10;
year_dig2=Tm->tm_year % 10;
switch (digit_info.date_format)
{
case DATE_MMDDYY:
default:
{
(void) sprintf(buf,"%d%d-%d%d-%d%d",
mon_dig1,mon_dig2,day_dig1,day_dig2,year_dig1,year_dig2);
break;
}
case DATE_DDMMYY:
{
(void) sprintf(buf,"%d%d-%d%d-%d%d",
day_dig1,day_dig2,mon_dig1,mon_dig2,year_dig1,year_dig2);
break;
}
case DATE_YYMMDD:
{
(void) sprintf(buf,"%d%d-%d%d-%d%d",
year_dig1,year_dig2,mon_dig1,mon_dig2,day_dig1,day_dig2);
break;
}
case DATE_YYDDMM:
{
(void) sprintf(buf,"%d%d-%d%d-%d%d",
year_dig1,year_dig2,day_dig1,day_dig2,mon_dig1,mon_dig2);
break;
}
case DATE_MMYYDD:
{
(void) sprintf(buf,"%d%d-%d%d-%d%d",
mon_dig1,mon_dig2,year_dig1,year_dig2,day_dig1,day_dig2);
break;
}
case DATE_DDYYMM:
{
(void) sprintf(buf,"%d%d-%d%d-%d%d",
day_dig1,day_dig2,year_dig1,year_dig2,mon_dig1,mon_dig2);
break;
}
}
Debug2(" date buf=%s",buf,0);
}
else
{
(void) strcpy(buf,"888888");
}
(void) strcpy(digitbuf,buf);
WriteCounterImage (digitbuf, &digit_info,&frame_info);
/*
** we won't be here
*/
break;
}
case SHOW_GIF_FILE:
{
if (*digit_info.gif_file == '\0')
{
PrintHeader();
StringImage("No GIF file specified to dispaly");
exit(1);
}
(void) sprintf(digitbuf,"%s/%s/%s",
DigitDir,digit_info.ddhead,digit_info.gif_file);
WriteCounterImage(digitbuf,&digit_info,&frame_info);
/*
** we won't be here
*/
break;
}
case SHOW_COUNTER:
default:
{
if (digit_info.comma == True)
digit_info.leftpad=False;
if ((int) strlen(digit_info.literal) > 0)
{
/*
** only copy 10 digits, otherwise we take the risk
** of buffer overflow
*/
if (strlen(digit_info.literal) > 10)
(void) strncpy(buf, digit_info.literal,10);
else
{
(void) strcpy(buf, digit_info.literal);
}
if (digit_info.comma == True)
(void) sprintf(buf,"%d",atoi(buf));
digit_info.leftpad=False;
}
else if (mystrcasecmp(digit_info.datafile,DfForRandom) == 0)
{
srand(time(NULL)); /* Seed number generator */
counter = rand(); /* My psychic prediction of counter value */
/*
** we do not want to overflow buffer
*/
Debug2("random number=%d",counter,0);
*tmpbuf='\0';
(void) sprintf(tmpbuf,"%d",counter);
if (strlen(tmpbuf) > 10)
(void) strncpy(buf,tmpbuf,10);
else
(void) strcpy(buf,tmpbuf);
Debug2("random number after bound checning=%s",buf,0);
digit_info.leftpad=False;
}
else
{
(void) strcpy(filename, DataDir);
(void) strcat(filename, "/");
(void) strcat (filename, digit_info.datafile);
/*
** check if the counter file exists or not
*/
if (Gauto_file_creation == 0)
{
if (CheckFile (filename) != 0)
{
*tmpbuf='\0';
(void) sprintf (tmpbuf,
"Counter datafile \"%s\" must be created first!", filename);
Warning(tmpbuf);
PrintHeader ();
StringImage (tmpbuf);
exit(1);
}
}
else
{
if (CheckFile (filename) != 0)
use_st=True;
}
#ifdef SYS_WIN32
fd=sopen(filename,_O_RDWR | _O_CREAT, _SH_DENYWR, _S_IREAD |_S_IWRITE);
#else
fd = open (filename, O_RDWR | O_CREAT,0644);
#endif
if (fd < 0)
{
*tmpbuf='\0';
if (Gauto_file_creation == 1)
{
if (CheckFile (filename) != 0)
(void) sprintf(tmpbuf,
"Could not create data file: \"%s\"",filename);
else
(void) sprintf (tmpbuf,
"Could not write to counter file: \"%s\"", filename);
}
else
(void) sprintf (tmpbuf,
"Could not write to counter file: \"%s\"", filename);
Warning(tmpbuf);
PrintHeader ();
StringImage(tmpbuf);
exit(1);
}
#ifdef SYS_UNIX
SetLock(fd);
#endif
/*
** try to read from the file
*/
lseek(fd,0L,0);
/* n = read(fd, buf, MaxDigits);*/
n = read(fd, buf, 10);
if (n > 0)
{
/*
** check if the datafile is edited,
** NULL terminate at first non-digit
*/
for (i=0; i < n; i++)
{
if (!isdigit(buf[i]))
{
buf[i]='\0';
break;
}
}
if (i == n)
buf[n]='\0';
Debug2("In buffer=%s",buf,0);
if (*buf == '\0')
counter=0;
else
counter = atoi(buf);
if (counter < 0)
{
/*
** possibly we reached the limit, the digit didn't fit
** in an int
*/
PrintHeader();
StringImage("The digit did not fit in a signed int!");
exit(1);
}
*buf='\0';
(void) sprintf(buf,"%d",counter);
Debug2(" before increment=%d",counter,0);
if (counter == 0)
counter_length = 1;
else
{
if (digit_info.increment_counter == True)
counter++;
(void) sprintf(buf, "%d", counter);
counter_length = (int) strlen(buf);
}
Debug2(" after increment=%d",counter,0);
if (ignore_site == False)
{
lseek(fd,0L,0);
(void) write(fd, buf, (int)strlen(buf));
(void) close (fd); /*unlocks as well */
}
}
else
{
if (use_st == True)
{
counter=digit_info.st;
Debug2("counter=%d",counter,0);
}
Debug2(" n < 0",0,0);
Debug2(" before increment=%d",counter,0);
if ( digit_info.increment_counter==True )
counter++;
(void) sprintf(buf, "%d", counter);
Debug2(" after increment=%d",counter,0);
lseek(fd,0L,0);
write (fd, buf, (int) strlen(buf));
(void) close (fd);
}
#ifdef SYS_UNIX
UnsetLock(fd);
#endif
}
counter_length = (int) strlen(buf);
if (digit_info.show == False)
{
Image
*image;
image=CreateBaseImage(1,1,0,0,0,DirectClass);
if (image == (Image *) NULL)
{
PrintHeader();
StringImage("Failed to create 1x1 GIF image");
exit(1);
}
AlphaImage(image,0,0,0);
PrintHeader();
(void) WriteGIFImage (image, (char *)NULL);
DestroyAnyImageStruct (&image);
exit(0);
}
if (digit_info.leftpad == False) /* no left padding */
{
(void) strcpy(digitbuf,buf);
WriteCounterImage(digitbuf,&digit_info,&frame_info);
/*
** we will not be here, we'll exit from LoadDigits()
*/
}
else
{
if (counter_length < MaxDigits)
left_pad = MaxDigits - counter_length;
else
left_pad=0;
Debug2(" MaxDigits=%d",MaxDigits,0);
Debug2(" left_pad=%d",left_pad,0);
if ((left_pad < MaxDigits) && (left_pad != 0))
{
(void) strcpy(digitbuf,"0");
for (i=1; i < left_pad; i++)
{
(void) sprintf(digitbuf,"%s0",digitbuf);
}
(void) sprintf(digitbuf,"%s%s",digitbuf,buf);
WriteCounterImage(digitbuf,&digit_info,&frame_info);
/*
** we will not be here
*/
}
else /* MaxDigits*/
{
Debug2(" We are in MaxDigits=%d",MaxDigits,0);
(void) strcpy(digitbuf,buf);
WriteCounterImage(digitbuf,&digit_info,&frame_info);
/*
** we won't be here
*/
}
}
exit(0);
} /* case SHOW_COUNTER*/
}
}
/*
* checkfilename:
* - check to see if a path was specified - return 1 if so, 0 otherwise
* it might not be foolproof, but I can't come up with
* any other ways to specify paths.
* by carsten@group.com (07/27/95)
* ..\filename was not getting ignored on NT
* reported by asolberg@pa.net>
* fixed: 04/19/96
*/
int checkfilename(str)
char
*str;
{
while (*str)
{
if ((*str == '/') ||
(*str == '\\') ||
(*str == ':') ||
(*str == '~'))
return 1;
str ++;
}
return 0;
}
/*
** check if the counter file exists
*/
int CheckFile (filename)
char
*filename;
{
int
rc=0;
rc = access (filename, F_OK);
return rc;
}
/*
** something went wrong..write the built in GIF image to stdout
*/
void SendErrorImage (bits, length)
unsigned char
*bits;
int
length;
{
register unsigned char
*p;
register int
i;
p = bits;
for (i=0; i < length; i++)
{
(void) fputc((char) *p, stdout);
(void) fflush (stdout);
p++;
}
}
void PrintHeader ()
{
if (Gdebug == False)
{
(void) fprintf (stdout,
"Content-type: image/gif%c%c",LF,LF);
(void) fflush (stdout);
}
return;
}
void WriteCounterImage(digitbuf,digit_info,frame_info)
char
*digitbuf;
DigitInfo
*digit_info;
FrameInfo
*frame_info;
{
Image
*image;
if (digit_info->display_type == SHOW_GIF_FILE)
{
Debug2("Displaying GIF file=\"%s\"",digitbuf,0);
image=ReadImage(digitbuf);
}
else
{
image=CombineImages(digitbuf,digit_info);
}
if (image != (Image *) NULL)
{
MogrifyImage(&image,digit_info,frame_info);
PrintHeader();
(void) WriteGIFImage (image, (char *)NULL);
}
else
{
PrintHeader();
StringImage("Failed! Check DigitDir in config.h or dd in QUERY_STRING");
}
exit(1);
}
Image *CombineImages(digitbuf,digit_info)
char
*digitbuf;
DigitInfo
*digit_info;
{
register char
*p;
char
tmpbuf[MaxTextLength];
int
rc=0;
unsigned int
bwidth,
bheight,
gbW,
gbH,
base_width,
base_height;
Image
*strip_image,
*sub_image,
*base_image;
int
nsegment,
segment;
int
*seg_array=(int *) NULL;
RectangleInfo
rinfo;
int
n;
int
i;
char
*token;
segment=0;
bwidth=0;
bheight=0;
gbW=0;
gbH=0;
base_width=0;
base_height=0;
strip_image=(Image *) NULL;
/*
** if comma is requesed, commaize (my new invented word!) the
** digit. also it's meaningness to left pad while commizing,
** therefore, don't left pad with zeros as well
*/
if ((digit_info->display_type == (unsigned int) SHOW_COUNTER) &&
(digit_info->comma == True))
{
Commaize(digitbuf);
Debug2("after commaze=%s",digitbuf,0);
}
/*
** if image strip is not used, we'll handle it as usual
*/
if (digit_info->use_strip == False)
{
for (p=digitbuf; *p != '\0'; p++)
{
*tmpbuf='\0';
if(isdigit(*p))
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,ImagePrefix[(int)*p-'0']);
else
{
if (*p == ':')
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"colon");
else if ((*p == 'A') || (*p == 'a'))
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"am");
else if ((*p == 'P') || (*p == 'p'))
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"pm");
else if (*p == ',')
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"comma");
else
if (*p == '-')
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"dash");
}
rc=GetGIFsize(tmpbuf,&gbW,&gbH);
if (rc)
{
PrintHeader();
StringImage("Unable to determine digit image size!");
exit(1);
}
bwidth += gbW;
if (gbH > bheight)
bheight=gbH;
}
}
else
{
/*
** strip is in use. First of all, we will determine the with of the
** base image. The segments in the strip may be of varaible widths,
** we'll handle it
*/
(void) sprintf(tmpbuf,"%s/%s/strip.gif",DigitDir,digit_info->ddhead);
strip_image=ReadImage(tmpbuf);
if (strip_image == (Image *) NULL)
{
PrintHeader();
StringImage("Unable to read strip image!");
exit(1);
}
if (strip_image->comments != (char *) NULL)
{
rc=sscanf(strip_image->comments,"%d",&nsegment);
Debug2("segments=%d rc=%d",nsegment,rc);
if (rc != 1)
{
PrintHeader();
StringImage("No string segment info found in GIF comment ext.!");
exit(1);
}
seg_array=(int *) malloc((nsegment+2)*sizeof(int));
if (seg_array == (int *) NULL)
{
PrintHeader();
StringImage("Memory Allocation Failed for seg_array!");
exit(1);
}
p=strip_image->comments;
i=0;
while ((token=mystrtok(p,":")) != (char *) NULL)
{
p=(char *) NULL;
if (token != (char *) NULL)
seg_array[i]=atoi(token);
i++;
}
/*
** the info about strip in the comment extension of the GIF image
** does not match. we'll abort
** btw, if the strip is created with my mkstrip program, the info
** should be correct. possibly someone is using a strip made by
** some other program. Tough luck!
*/
if (i != (nsegment+2))
{
PrintHeader();
StringImage("Strip info mismatch in GIF comment ext.!");
exit(1);
}
for (p=digitbuf; *p != '\0'; p++)
{
if (isdigit(*p))
{
n=(*p-'0');
bwidth += (seg_array[n+2]-seg_array[n+1]);
}
else
{
if (*p == ':')
{
rinfo.x=seg_array[11];
bwidth += (seg_array[12]-seg_array[11]);
}
if ((*p == 'A') || (*p == 'a'))
{
rinfo.x=seg_array[12];
bwidth += (seg_array[13]-seg_array[12]);
}
if ((*p == 'P') || (*p == 'p'))
{
rinfo.x=seg_array[13];
bwidth += (seg_array[14]-seg_array[13]);
}
if (*p == ',')
{
rinfo.x=seg_array[14];
bwidth += (seg_array[15]-seg_array[14]);
}
if (*p == '-')
{
rinfo.x=seg_array[15];
bwidth += (seg_array[16]-seg_array[15]);
}
}
}
bheight=strip_image->rows;
}
else
{
PrintHeader();
StringImage("No info about strip found in GIF comment ext.!");
exit(1);
}
}
base_image= CreateBaseImage (bwidth,bheight,0,0,0,DirectClass);
if (base_image == (Image *) NULL)
{
PrintHeader();
StringImage("Unable to create base image!");
exit(1);
}
if (digit_info->use_strip == False)
{
for (p=digitbuf; *p != '\0'; p++)
{
*tmpbuf='\0';
if(isdigit(*p))
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,ImagePrefix[(int)*p-'0']);
else
{
if (*p == ':')
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"colon");
if ((*p == 'A') || (*p == 'a'))
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"am");
if ((*p == 'P') || (*p == 'p'))
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"pm");
if (*p == ',')
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"comma");
if (*p == '-')
(void) sprintf(tmpbuf,"%s/%s/%s.gif",
DigitDir,digit_info->ddhead,"dash");
}
sub_image=ReadImage(tmpbuf);
if (sub_image != (Image *) NULL)
{
FlattenImage(base_image,sub_image,ReplaceCompositeOp,
base_width,0);
base_width += sub_image->columns;
DestroyAnyImageStruct(&sub_image);
}
else
{
PrintHeader();
StringImage(" FAILED to combine digit images!");
exit(1);
}
}
}
else
{
rinfo.y=0;
rinfo.width=15;
rinfo.height=strip_image->rows;
for (p=digitbuf; *p != '\0'; p++)
{
*tmpbuf='\0';
if (isdigit(*p))
{
n=(*p-'0');
rinfo.x=seg_array[n+1];
rinfo.width=seg_array[n+2]-seg_array[n+1];
}
else
{
if (*p == ':')
{
rinfo.x=seg_array[11];
rinfo.width=seg_array[12]-seg_array[11];
}
if ((*p == 'A') || (*p == 'a'))
{
rinfo.x=seg_array[12];
rinfo.width=seg_array[13]-seg_array[12];
}
if ((*p == 'P') || (*p == 'p'))
{
rinfo.x=seg_array[13];
rinfo.width=seg_array[14]-seg_array[13];
}
if (*p == ',')
{
rinfo.x=seg_array[14];
rinfo.width=seg_array[15]-seg_array[14];
}
if (*p == '-')
{
rinfo.x=seg_array[15];
rinfo.width=seg_array[16]-seg_array[15];
}
}
sub_image=CropImage(strip_image,&rinfo);
if (sub_image != (Image *) NULL)
{
FlattenImage(base_image,sub_image,ReplaceCompositeOp, base_width,0);
base_width += sub_image->columns;
DestroyAnyImageStruct(&sub_image);
}
else
{
PrintHeader();
StringImage("Failed to extract image from strip!");
exit(1);
}
}
}
return(base_image);
}
/*
** buf is modified
*/
void Commaize(buf)
char
*buf;
{
char
tmpbuf[100];
register char
*p,
*q;
int
m=0;
int
i=-1;
*tmpbuf='\0';
if (*buf != '\0')
{
m=0;
m=m+strlen(buf)/3;
if (strlen(buf)%3 == 0)
m--;
p=buf+strlen(buf)-1;
tmpbuf[strlen(buf)+m]='\0';
q=tmpbuf+strlen(buf)+m-1;
while (1)
{
if (p < buf)
break;
if (++i == 3)
i=0, *q-- = ',';
*q-- = *p--;
}
(void) strcpy(buf,tmpbuf);
}
}
/*
** mogrify image if needed
*/
void MogrifyImage(image,digit_info,frame_info)
Image
**image;
DigitInfo
*digit_info;
FrameInfo
*frame_info;
{
Image
*framed_image,
*rotated_image;
if (*image != (Image *) NULL)
{
if (digit_info->negate == True)
NegateImage(*image);
if (digit_info->Frame == True)
{
RGB
color,
matte_color;
matte_color.red=frame_info->matte_color.red;
matte_color.green=frame_info->matte_color.green;
matte_color.blue=frame_info->matte_color.blue;
frame_info->height=frame_info->width;
frame_info->outer_bevel=(frame_info->width >> 2)+1;
frame_info->inner_bevel=frame_info->outer_bevel;
frame_info->x=frame_info->width;
frame_info->y=frame_info->height;
frame_info->width=(*image)->columns+(frame_info->width << 1);
frame_info->height=(*image)->rows+(frame_info->height << 1);
frame_info->matte_color=matte_color;
XModulate(&color,matte_color.red,matte_color.green,
matte_color.blue, HighlightModulate);
frame_info->highlight_color.red=color.red;
frame_info->highlight_color.green=color.green;
frame_info->highlight_color.blue=color.blue;
XModulate(&color,matte_color.red,matte_color.green,
matte_color.blue, ShadowModulate);
frame_info->shadow_color.red=color.red;
frame_info->shadow_color.green=color.green;
frame_info->shadow_color.green=color.green;
framed_image=FrameImage(*image,frame_info);
if (framed_image != (Image *) NULL)
{
DestroyAnyImageStruct (image);
framed_image->class=DirectClass;
*image=framed_image;
}
}
(*image)->comments = (char *) malloc (1024*sizeof(char));
if ((*image)->comments != (char *) NULL)
{
(void) sprintf((*image)->comments,"\n%s %s \n%s %s\n%s %s\n",
"Count.cgi", Version, "By", Author, "URL:", Url);
}
if (digit_info->replace_color == True)
{
OpaqueImage(*image,
digit_info->opaque_red,
digit_info->opaque_green,
digit_info->opaque_blue,
digit_info->pen_red,
digit_info->pen_green,
digit_info->pen_blue);
}
if (digit_info->alpha == True)
{
AlphaImage(*image,digit_info->alpha_red,digit_info->alpha_green,
digit_info->alpha_blue);
}
if (digit_info->rotate == True)
{
rotated_image=RotateImage(*image,digit_info->rotate_degrees);
if (rotated_image != (Image *) NULL)
{
DestroyAnyImageStruct (image);
*image=rotated_image;
}
else
{
(void) fprintf (stderr," Could not rotate %d degrees\n",
digit_info->rotate_degrees);
}
}
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.