Google Sites Comments

If you use Google Sites (like I do) you know there is no good way to allow guests to leave comments or discuss your pages.  The more popular choice it to use a combination of Google Documents spreadsheet and a form.  This leaves a clunky ugly spreadsheet on the bottom of your page.  Not the best choice.  I am not saying my solution is the best either, but it suits my needs and has a cleaner look. Plus it is free.

If you have access to a server you can run CGI on you can use this set up.  I have a Linux web server running in my home office on normal cable modem.  Not the ideal choice for hosting a web site due to speed and port availability (i.e. port 80 is blocked.) However with the use of a dynamic DNS service it is a satisfactory solution for running the comments CGI script.

Google Sites will allow you to embed an external CGI page into your Sites page by using IFRAME

<iframe name="foo" src="yourserver/cgibin/bar.cgi?read=filename></iframe>

Filename is where you choose what to call the text file that will hold the comments for that page. 

It will look like all other Google Sites Widgets in the editor but will look clean when viewed.

I have attached a modified version of the C code I wrote. 

The key features are:

One compiled program handles all pages.

Automatically creates text files for the comments.

Converts HTTP/URL escape characters to ascii.

Small foot print on the server.

No HTML files to maintain.

Basics:

CGI program takes in the Query String and determines whether and where to write the comments to. If we are going to write a comment, remove the escape codes from the URL string. Write them to the appropriate file.  Display the comment form. Display the comments.

It is really that easy. I used more lines of code than needed doing silly pointer things, but it is pretty basic.  If you want to use it, add your own level of error checking and security as you chose.

Thanks Kyle for some bug finding!

CODE:

 #include <stdio.h>

#include <stdlib.h>

#include <string.h>

void cleaner(char *htmlEncoded);

char hexToAscii(char temp[3]);

main()

{

    char *strg,*temp;

    char delim[] = "/";    

    char txt[] = ".txt";

    char operation[64], cp[1024], fileStrng[64], name[128], comment[1024],timeStmp[26];

    int pos;

    printf("content-type: text/html\n\n"); /*Required for browser*/

    

    strg=getenv("QUERY_STRING"); /* get the vars from the browser formated                                                                          like--- write=pagename&name=username&                                                                            comment=comment (for a submision) */

    

    /* Make sure YOUR page is calling this -- -optional */

    if(getenv("REMOTE_HOST")!="yourforwardingDDNS.com")

        return 0;

    /* set the file name of the comments to the page it is for */

    char filename[64] = "/cgi-bin/comments/";

    strcpy(cp,strg); /* copy Query String */

    temp = strtok(cp,"&"); /*First element of Query String */

    strcpy(cp,temp);

    temp= strtok(cp,"="); /* separate the name from the value i.e. read=mypage                                                     first we get 'read' then the 'mypage' */

    strcpy(operation,temp);

    temp=strtok(NULL,"=");

    strcpy(fileStrng,temp); /*save this for adding a 'hidden' field on the html                                                             form */

    strcpy(cp,temp); /* make a full file name */

    strcat(cp,txt);

    strcat(filename,cp);

    

    

    /* If we are submitting a comment ... */

    if(strcmp(operation,"write")==0)

    {

        strcpy(cp,strg); /* copy Query String */

        temp = strtok(cp,"&"); /*First element of Query String  --- we dont care                                                                 here*/

        temp = strtok(NULL,"&"); /*Second element of Query String this will have                                                                 the 'name=usename' */

        strcpy(name,temp);

        temp = strtok(NULL,"&"); /*Third element of Query String this will have                                                                 'comment=blahblahblah' */

        strcpy(comment,temp);

        temp = strtok(name,"="); /* look at 'name=username' and seperate 'name'                                                                 from 'username' */

        while(temp!=NULL)

        {

            strcpy(name,temp); /* if the user doesnt type in a name this will be                                                             'name' (error check later) else it is their username */

            temp = strtok(NULL,"=");

        }

        temp=name; //Send it off to have the escape codes removed

        cleaner(temp);

        strcpy(name,temp);

        temp = strtok(comment,"="); /* same process as name is used for the                                                                                     comment */

        while(temp!=NULL)

        {

            strcpy(comment,temp);

            temp= strtok(NULL,"=");

        }

        temp=comment;

        cleaner(temp);

        strcpy(comment,temp);

        time_t rawtime; /*load up local time for the date stamp */

        time ( &rawtime );

        if(strcmp(name,"name")==0 || strcmp(comment,"comment")==0) /* error                                                                                     check for blank name or comment */

        {

            printf("<font color=\"red\">You must enter a Name and Comment</font><p>");

        }

        else

        {

            FILE *file = fopen ( filename, "a+" ); /* open the file and append a html                                                                                     table containing the comment line

                                                                                remove the '+' if you dont want it to

                                                                                create the file automatically*/

            if (file != NULL)

            {

                fprintf(file,"%s%s%s%s%s%s%s","<table border=\"0\"><tr><td width=\"25%\">",ctime(&rawtime),"</td><td width=\"15%\">",name,"<td><td width=\"60%\">",comment,"</td><p><hr>");

                fclose (file);

            }

            else

            {

                //printf some error message here about file not loading

            }

        }

        

    }

    

    /* hard coded HTML form to be displayed*/

    printf("<FORM ACTION=\"/cgi-bin/comment.cgi\" method=\"get\">Name:<br><input type=\"HIDDEN\" name=\"write\" value=\"%s\">",fileStrng);

    printf("<input type=\"text\" name=\"name\"><p>Comment:<br><TEXTAREA name=\"comment\" cols=\"40\" rows=\"3\"></TEXTAREA><p><input type=\"submit\" value=\"Submit\"></FORM><p>");

    /* open, read, and display the comments file*/

    FILE *file = fopen ( filename, "r" );

    if ( file != NULL )

    {

        char line [ 128 ];

        while ( fgets ( line, sizeof line, file ) != NULL )

        {

            printf("%s", line);         

        }

        fclose ( file );

    }

    else

    {

        //printf some error message here about file not loading

    }

    

    /* free our pointers for good measure*/

    free(temp);

    free(strg);

}

void cleaner(char *htmlEncoded)

{

    int pos, pos2,term;

    char tmp[4],input,hold[1024];

    int first, second, final;

    

    term = strlen(htmlEncoded);   

    for(pos=0;pos<strlen(htmlEncoded);pos++)  //step char by char through                                                                                                         the string

    {

        input=htmlEncoded[pos];  //grab one char at a time

        

        if (input=='+')  //remove + replace with spaces

            input=' ';

        if (input=='%') //escape code starts with % then hex --- %34 = "

        {

            strncpy(tmp,htmlEncoded+pos,3); //grab the %HH

            input=hexToAscii(tmp);  //convert string HH to int then to char

            pos+=2; //advance two more spaces to eliminate the HH

            if(input==13)   // Special case - CR and LF -- HTML has no use for CRLF                                                         replace it with <BR>   13=CR 10=LF

            {

                hold[pos2]='<';

                pos2++;

                hold[pos2]='B';

                pos2++;

                hold[pos2]='R';

                pos2++;

                input='>';

            }

            if(input==10)

                input=' ';

        }

        

        hold[pos2]=input; //write the char to a temp string

        pos2++;

    }

   

    hold[term]='\0';

    strcpy(htmlEncoded,hold);

}

    

char hexToAscii(char *tmp) //convert string of two HEX values to INT then to                                                                 a CHAR

{

    int first,second,final;

    

    char ascii;

    

    first = tmp[1]; //first value %H0  - getting the H

    first-=48;  //the char '0' is equal to 48 decimal, subtract 48 from the int                                         value of the char '0' you get decimal 0

    if(first>9) //if the value is higher than 9 it was not a number to start, but a                                     letter A-F

        first-=7; // A is 65, 65-48=17 subtract 7 more and A = 10 the right hex value in dec

    

    second = tmp[2];  

    second-=48;

    if(second>9)

        second-=7;

    final = (first * 16)+second; //first * 16 makes the hex values a byte rather                                                                     than two nibbles

    

    ascii=final;

    return ascii;

}