/* CGI for processing El Nino quiz form and returning results */ /* CGI stuff at top from a web tutorial, the rest by me */ /* Adrian Taylor 1997 */ #include #include #include #include char x2c(char *what); void unescape_url(char url[]); char **getcgivars(void); void printAggregates(int marksGot); void printTopOfPage(void); void printBottomOfPage(void); int markEachQuestion(void); void printCorrectAnswer(int theQuestion); int isItCorrect(int questionNumber,char *theAnswer); int contains(char *outerString,char *innerString); /*************/ void main (void) { int marksGot; printTopOfPage(); marksGot=markEachQuestion(); printAggregates(marksGot); printBottomOfPage(); } /*****************************************/ /*** CGI code copied from a web tutorial */ /*****************************************/ char x2c(char *what) { /* This takes a hex number and returns its real character */ char digit; digit = (what[0]>='A' ? ((what[0] & 0xDF )-'A')+10 : (what[0]-'0')); digit *=16; digit += (what[1]>='A'?((what[1] & 0xDF )-'A')+10: (what[1]-'0')); return (digit); } void unescape_url(char url[]) { /* This removes the escape sequences from an URL */ int i,j; for (i=0,j=0;url[j];++i,++j) { if ((url[i] = url[j]) == '%') { url[i]=x2c(&url[j+1]); j+=2; } } url[i]='\0'; } char **getcgivars(void) { /* Returns a list of strings: name1, value1, name2, value2 etc. */ int i; char *request_method; int content_length; char *cgiinput; char **cgivars; char **pairlist; int paircount; char *nvpair; char *eqpos; request_method=getenv("REQUEST_METHOD"); if(!getenv("REQUEST_METHOD") || (!strcmp(request_method, "GET")&& !getenv("QUERY_STRING")) || !getenv("CONTENT_TYPE") || !getenv("CONTENT_LENGTH")) { printf("getcgivars(): Required environment variables have not been set!\n"); exit(1); } if (!strcmp(request_method,"GET")) { /* We are using get method */ cgiinput=strdup(getenv("QUERY_STRING")); } else if (!strcmp(request_method,"POST")) { /* We are using post method */ if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) { printf("getcgivars(): Unsupported Content-Type.\n"); printf("Ctype is %s\n",getenv("CONTENT_TYPE")); exit(1); } if (!(content_length=atoi(getenv("CONTENT_LENGTH")))) { printf("getcgivars(): No content-length was sent with the POST request.\n"); exit(1); } if (!(cgiinput=(char *)malloc(content_length+1))) { printf("getcgivars(): Could not malloc for CGI Input.\n"); exit(1); } if (!fread(cgiinput,content_length,1,stdin)) { printf("getcgivars(): Couldn't read CGI input from stdin.\n"); exit(1); } cgiinput[content_length]='\0'; } else { printf("getcgivars(): unsupported REQUEST_METHOD\n"); exit(1); } /* Change all plusses back to spaces */ for (i=0;cgiinput[i];i++) if (cgiinput[i]=='+') cgiinput[i]=' '; /* Now split on & to extract the name-value pairs into pairlist */ pairlist=(char**)malloc(256*sizeof(char**)); paircount=0; nvpair=strtok(cgiinput,"&"); while (nvpair) { pairlist[paircount++]=strdup(nvpair); if (!(paircount%256)) pairlist=(char**) realloc(pairlist,(paircount+256)*sizeof(char**)); nvpair=strtok(NULL,"&"); } pairlist[paircount]=0; /* Then from the list of pairs extract the names and values */ cgivars=(char**)malloc((paircount*2+1)*sizeof(char**)); for (i=0;i

Total scores

\n\nYou got %d",marksGot); printf(" right, which is %3.1f percent.

", marksGot*10.0); switch (marksGot) { case 0: printf("That's just silly, really, isn't it?"); break; case 1: case 2: case 3: printf("It could be worse."); break; case 4: printf("Well, it's a pass."); break; case 5: printf("Half way!"); break; case 6: printf("If only I could get that in exams..."); break; case 7: printf("A first! Wow!"); break; case 8: printf("You've been revising."); break; case 9: printf("Swot."); break; case 10: printf("That'll be £1000 for tuition, please, Doctor."); break; } printf("

"); } void printTopOfPage(void) { /* Prints the top of the returned page, before any processing occurs */ printf("Content-type: text/html\n\n"); /* That line is necessary to indicate that we are returning HTML */ printf("Marks for El Niño Quiz"); printf("\n\n"); printf("

Marks for quiz

\n\n"); } void printBottomOfPage(void) { printf("
Thank you for taking the quiz.\n\n

Return to main page (on BITS)."); } int markEachQuestion(void) { /* Goes through and marks each individual question */ char **cgivars; char *theAnswer; int currentQuestion,cgiVarQuestion,foundCurrentQuestionResponse; int sumOfMarksSoFar=0,gotItRight,i,j; cgivars=getcgivars(); /* Puts the input variables into a string array of form name1,value1,name2,value2 */ for (currentQuestion=1;currentQuestion<11;currentQuestion++) { foundCurrentQuestionResponse=0; gotItRight=0; printf("\n\n

Question %d

",currentQuestion); for (i=0;cgivars[i];i+=2) { if (sscanf(cgivars[i],"%d",&cgiVarQuestion)) { if (cgiVarQuestion==currentQuestion) { theAnswer=cgivars[i+1]; /* We now have the answer they gave to question currentQuestion */ foundCurrentQuestionResponse++; for (j=0;j\n"); printf("\nCorrect!

\n"); } else { printf("\"icon(418bytes)\"\n"); printf("\nWrong!

\nThe correct answer is: "); printCorrectAnswer(currentQuestion); printf(". "); } printf("You said %s.",theAnswer); printf(" Marks so far: %d.

",sumOfMarksSoFar); printf("
\n"); } } } if (foundCurrentQuestionResponse!=1) printf("Whoops: question %d has %d responses.

",currentQuestion,foundCurrentQuestionResponse); } return sumOfMarksSoFar; } void printCorrectAnswer(int theQuestion) { switch (theQuestion) { case 1: printf("Fred Bloggs"); break; case 2: printf("sort of icky"); break; case 3: printf("acme widgets"); break; case 4: printf("Fred"); break; case 5: printf("Fred's"); break; case 6: printf("None at all"); break; case 7: printf("Wavy"); break; case 8: printf("2004"); break; case 9: printf("it goes all shiny"); break; case 10: printf("Beeblebroxes"); break; } } int isItCorrect(int questionNumber,char *theAnswer) { switch (questionNumber) { case 1: return (contains(theAnswer,"bloggs")); case 2: return (contains(theAnswer,"sort of icky")); case 3: return (contains(theAnswer,"acme widgets")); case 4: return (contains(theAnswer,"fred")); case 5: return (contains(theAnswer,"fred")); case 6: return (contains(theAnswer,"none")); case 7: return (contains(theAnswer,"wavy")); case 8: return (contains(theAnswer,"04")||contains(theAnswer,"2004")); case 9: return (contains(theAnswer,"shiny")||contains(theAnswer,"glossy")); case 10: return (contains(theAnswer,"beeblebroxes")); } } int contains(char *outerString,char *innerString) { if (strstr(outerString,innerString)) return 1; else return 0; }