The UK Online Safety Act needs to be considered. The Online Safety Act explainer.
This idea could allow any content to be posted un-moderated. The server side scripts need validation of who is posting. A separate script to unlock and lock the posts is used to restrict ad-hoc posts. Some validation of the form data is needed. Ad-hoc posts would need to be moderated before publication.
Here is a way of writing simple web applications by using a 'guestbook' server side script and client side JavaScript. There are loads of simple applications that just need a simple sorted list of user's occasional amendments.
This idea modifies the guestbook to return the posts in a format that can be processed by the user's web page. Instead of HTML, download the posts wrapped in a javaScript function gbF().
When your visitor signs this guestbook, the entry is appended to a file of JavaScript , which is downloaded when the page is next loaded by the next viewer.
Some of these pages result from work on automating our sailing club web site. Our sailing club needed some simple but useful applications without too much effort. This was invented as BTInternet offered three pre written CGI scripts, but did not allow user CGI scripts.
If they modified their guestbook script to support this idea, then the site owner could ftp .htm files, and ftp gbookFXXX.js up to the server. Also, I was on a Pay As you Go Dial Up. Editing on line was painful, as I paid for every minute I was connected. Always on Broadband has changed this.
This is also good if you need a simple application where security is not a big issue, and access to the server is constrained by no telnet access and update is via ftp only via dial up. Also, as the web page code is 'open' to a view source, anybody who wants to rip off and improve for private or public use can! For our sailing any member could see how it was done, if interested!
This is also good if you need:-
Note: users can only append data, and cannot delete entries. Spam can be deleted by the person with FTP access.
Using javascript code that you write, the guestbook entries can be sorted, selected and formatted by JavaScript running on the clients browser.
This allows simple applications to be written.
All the demo applications use the same cgi perl script guestbook.pl hosted on my Web server ccgi.dougrice.plus.com.
You could run guestbook.pl ( or ASP / PHP version ) on your own Web server.
You write the custom JavaScript to sort and summarise the data in the guestbook, and the data is also available to validate the guestbook form.
I first used this to implement an online booking diary for our sailing club boats, which members can use. This diagram shows the split of functionality between the Server and the client.
An example
Display the latest Guestbook entries first using the HTML and Javascript code below. You may need to refresh the example page to see latest entry if you use this form.
<!DOCTYPE html> <html><body> <link rel="stylesheet" type="text/css" href="club.css"> <H2>Minimal Form - After use press refresh to pull down new data. </h2> <form name="F1" action="http://ccgi.dougrice.plus.com/cgi-bin/guestbook.pl" method="POST" > name: <input type="text" name="name" value="name" size="20" > email: <input type="text" name="email" value="email" size="20" > <BR> <!-- You can also have fields: userfield1,userfield2,userfield3,userfield4 --> <input type="hidden" name="userfield5" value="USERFEILD5" size="20" ><!-- anti spam --> Please enter any comments:- <BR> <textarea name="comments" rows="2" cols="80"></textarea><BR> <input type="hidden" name="guestbook" size="20" value="XXX" > <input type="hidden" name="nextpage" size="70" value="http://www.dougrice.plus.com/hp/gbbook/example.htm" " > <input type="hidden" name="loadnextpage" size="70" value="loadnextpage" > <input type="submit" name="B1" value="Submit"> </form> <HR> <script> // // Javascript functions to use the guestbook data and include the guestbook data file. // var thisEntry = "", opStr = "" // The function below is called once per guestbook entry. // You write this function to do what you want!! function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ news = ((""+comments).replace( "<","<")).replace( ">",">") updated = new Date( postedOn ).toString()+" by "+name thisEntry = "<HR><B>" + userfield1 + "</B><BR><pre>" + news + "</pre><BR><i>" + updated + "</i>" opStr = thisEntry + opStr } // test call gbF( "Test Call","email","15 Nov 2003","IPaddress","userfield1","userfield2","userfield3","userfield4","Testcomments") </script> <!-- Include remote guestbook and gbF() will be called once per entry.--> <script language = "JavaScript" type = "text/javascript" src = "http://ccgi.dougrice.plus.com/gb/gbookFXXX.js" > </script> <H2>Guestbook data expanded by userdefined gbF() function </h2> <H2> Last Entry</h2> <script> self.document.write( thisEntry ) </script> <H2> Prevous Entries</h2> <script> self.document.write( opStr ) </script> </body></html>
My entry is appended to: http://ccgi.dougrice.plus.com/gb/gbookFXXX.js
I put spam into: http://ccgi.dougrice.plus.com/gb/gbookF_guest_XXX.js
You may need to refresh the example page to see latest entry if you use this form, as the .js file may be cached
Data dump of guestbooks:
Data Dump at www.plus.net
Otherways to look at the data in this guestbook.
Example including update form do view souce to see how it is done.
gb.py and notes for Raspberry Pi and starting on power up
gb.py and notes for Raspberry Pi
Posted Fields used by guestbook scripts:
name =name - name of person signing guestbook email =email - email address of person signing guestbook userfield1 =userfield1 - a string that the application can use userfield2 =userfield2 - a string that the application can use userfield3 =userfield3 - a string that the application can use userfield4 =userfield4 - a string that the application can use userfield5 =uf5 Tue Oct 23 21:47:32 UTC+0100 2007 - anti spam security string set by javascript comments =This is a multi line comment
The fields above are copied into the parameters below, suitably escaped:
function gbF( name, email, postedOn, IPaddress, userfield1, userfield2, userfield3, userfield4, comments) function gbF( "user's name", "user's email", "timestamp postedOn", "users IPaddress", "uf1", "uf2", "uf3", "uf4", " user's comments");
This field is use to select the guestbook to update:
guestbook =XXX - this string is appended to gbookF{guestbook}.js
These fields control the next URL to go to:
nextpage ="http://www.dougrice.plus.com/hp/gbbook/index.htm" - URL of page to go to. loadnextpage=loadnextpage - this is a flag to load the next page
You write gbF() like you write callback functions. What gbF() does is your choice. It can filter the data as required. Use HTML tags and styles to format.
A more complicated format would be to wrap HTML table tags around the data.
function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ self.document.write( "<Tr>"+ "<TD >"+ name+ "</TD>"+ "<TD >"+ email+ "</TD>"+ "<TD >"+ <B>postedOn</B>+ "</TD>"+ "<TD >"+ IPaddress+ "</TD>"+ "<TD >"+ userfield1+ "</TD>"+ "<TD >"+ userfield2+ "</TD>"+ "<TD >"+ userfield3+ "</TD>"+ "<TD >"+ userfield4+ "</TD>"+ "<TD >"+ comments+ "</TD>"+ "</TR>" }
Below is an example of loading JavaScript Objects
var count = 0 var gbA = new Array() function GB( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ var avA = userfield2.split(",") < 4 if ( avA.length < 4 ) { userfield2 = "0,0,0" } this.name = name this.email = email this.postedOn = postedOn this.IPaddress = IPaddress this.userfield1 = userfield1 this.userfield2 = userfield2 this.userfield3 = userfield3 this.userfield4 = userfield4 this.comments = comments return this } function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ gbA[ count ] = new GB( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments) count=count+1; }
And simplified way of storing the data into an Object.
Using JavaScript object format
var gbA = new Array() function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ var r = new Object() r.name = name r.email = email r.postedOn = postedOn r.IPaddress = IPaddress r.userfield1 = userfield1 r.userfield2 = userfield2 r.userfield3 = userfield3 r.userfield4 = userfield4 r.comments = comments r.link = "" //return r // Append this object to an Array gbA[ gbA.length ] = r }
Using JavaScript Objects
var gbA = [] var gbA = new Array() console.log( gbA.length ) function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ gbA[ gbA.length ] = { "name":name, "email":email, "postedOn":postedOn, "IPaddress":IPaddress, "userfield1":userfield1, "userfield2":userfield2, "userfield3":userfield3, "userfield4":userfield4, "comments":comments, "index":gbA.length } } // test call gbF( "Test Call1","email","15 Nov 2003","IPaddress","userfield1","userfield2","userfield3","userfield4","Testcomments") gbF( "Test Call4","email","15 Nov 2003","IPaddress","userfield1","userfield2","userfield3","userfield4","Testcomments") gbF( "Test Call5","email","15 Nov 2003","IPaddress","userfield1","userfield2","userfield3","userfield4","Testcomments") gbF( "Test Call2","email","15 Nov 2003","IPaddress","userfield1","userfield2","userfield3","userfield4","Testcomments") function sortfn( a, b ){ if (a.name > b.name){ return 1 } else { return -1 } } // pass name of sort function gbA.sort( sortfn ) /*
For debugging, it is possible to dump the data.
*/ self.document.write("<H1> dump using JSON.stringify( gbA, null, 2 ) </H1>"); self.document.write("<pre> dump using "+JSON.stringify( gbA, null, 2 )+"</pre>"); /*
For debugging, it is possible to dump the data.
*/ var calls = 0 /* gbA[ index ].name is the same as gbA[ index ][ "name" ] typeof() can be used to find the type of the object. The function below was used dump objects when testing 20 years ago. Now you can use JSON.stringify( gbA, null, 2 ) to dump the data. */ function decend( r, level ){ // dump a JavaScript Object passed to it var opStr = "" for ( var I in r ) { //opStr += level+" "+I+" = "+r[ I ] + " " + typeof( r[ I ] )"\n" if ( typeof( r[ I ] ) == "object" ){ // attempt to limit it running for ever. calls += 1 if ( calls > 250 ) { return opStr + "++++++++++++++ too many objects +++++++++++++++\n" } opStr += level+" "+typeof( r[ I ] )+": "+I+" [ \n" // an attempt to look for looping if( I != "document" ){ opStr += decend( r[ I ], level + " " ) } else { opStr += level + " ... \n" } opStr += level+" ] \n" } else { opStr += level+" "+typeof( r[ I ] )+": "+I+" = "+r[ I ] +"\n" } } return opStr } self.document.write("<H1> decend( gbA, 1 ) </H1>"); self.document.write("<pre>"+decend( gbA, 1 )+"</pre>");
For debugging, it is possible to dump the data.
This web page uses descend() for debugging. Signal boxes
Sailing club booing system:-
A boat booking system - Life Raft system - demo
Notice board - shows future events and those last week:-
Updateable Notice Board - used for 10 years at work
Updateable Notice Board - with update form
Gant Chart:-
Scrap book of code samples:-
This was adopted into a simple fault tracker: Website bug report system
Include data and display using SVG - could be simpler
Plot Solar cell measurements using SVG graphics See: Solar cell measurements
This used the mouse to put pins on the diagram - broken
ePinboard - for Beer festival (Only works in Microsoft IE5 ) - Broken at the moment
A complicated system that was used for notes:- broken
My eScrap Book on www.plus.net
A table that can be created from an upload of CSV data. Each row can also be edited.
Table | Table - allows updates and uploads | Dump of all posts
This was an early try, and is now broken. Roster Display for A Staff Availability / Sports Club Team - broken .
A web site bug tracker! a Website bug report system and fault tracker.
A walk through the basics... Minimal application and code...
This was adopted into a simple fault tracker: Website bug report system
eScrapBook / eWorkingRecords - A User Updateable Sorted lists with history User Updateable Sorted lists. This could be adapted to a loan book, room booking, leave records, Document indexs, Test Spec/ results, Resource Information, Message boards, Fault tracker etc
Christmas Menu Questionnaire, Captured data viewed using eScrapbook
All the formatting is done by JavaScript on your browser. All the applications use the same cgi perl script guestbook.pl hosted on my Web server ccgi.dougrice.plus.com.
There are a few problems that needs attention.
One problem is that JavaScript is cached which means you need to refresh the webpage to see what you have added. Try some cache busting so the URL is not cached.
<script> now = new Date() /* try some cache busting append the time to the URL to make it different, so the URL is not cached. */ self.document.write( '<scr'+'ipt src=http://ccgi.dougrice.plus.com/gb/gbookFXXX.js?'+now.getTime()+' language="JavaScript"> </scr'+'ipt>' ) </script> <script>
conditionally include data if file name ends in .htm . So you do not include the data file if the file name end in .php This way you can toggle file name between .hth and .php.htm for test.
<script> // get extension and see if htm let url = location.href; var extA=url.split("."); var ext = extA[extA.length-1] if ( ext=="htm" ){ now = new Date() /* try some cache busting append the time to the URL to make it different, so the URL is not cached. */ self.document.write( '<scr'+'ipt src=http://ccgi.dougrice.plus.com/gb/gbookFXXX.js?'+now.getTime()+' language="JavaScript"> </scr'+'ipt>' ) } </script> <script>
If the data contains ' or " these need to be escaped and it is really complicated !
Options are:
If the data is wrapped in SQL and JavaScript and these are not escaped correctly, things break.
When the JavaScript or SQL code is executed again this breaks things and can be exploited by hackers.
Different character sets like UTF-8 coding and Latin-1, also called ISO-8859-1 encoding can also break things!
For JavaScript: v JavaScript needs inband ' escaped to \' JavaScript needs inband " escaped to \" // PHP escapes ' to \' using addslashes() but SQL needs ' escaped to '' http://ccgi.dougrice.plus.com/gb/gbookFDemoBookings.js has the date wrapped in gbF() e.g. gbF( // guestbook.pl "name","email","Tue, 2 Jun 2020 06:15:06 UTC+0000","212.56.108.219 | dougrice.plus.com ", "userfield1", "userfield1", "userfield1", "userfield1", "comments" ); If the posted data has " or ' within it, it would break the javaScript parser so convert " to \" Within your code for gbF() you will need to consider that the data may have " within it. For SQL: This would not work! INSERT into GB( comments ) values ( ' Billy's comment ' ); INSERT into GB( comments ) values ( ' a comment ' ); INSERT into GB( comments ) values ( ' Billy''s comment ' ); INSERT into GB( comments ) values ( ' Billy\'s comment ' ); // SQL INSERT values need inband ' escaped to '' // so replace \' with '' // for SQL:- function esc ( $s ) { $ts= str_replace("'","''", $s ); return $ts ; } For PHP // php escapes ' to \' using addslashes() For HTML needs escaping within tags. A Web form does a GET or POST which could write SQL or HTML or JavaScript when responding.
Add data to http://ccgi.dougrice.plus.com/gb/gbookFXXX.js using the simple form.
Here are various ways of displaying and sorting gbookFXXX.js. This is all done by your web browser using javascript.
Remember that you can use IE's view source menu option to view the source.
Guestbook
Guestbook
( code )
Guestbook-last entry first
( code )
Another Guestbook - last entry first
JavaScript - open then do viewsource for code
SQLite schema and insert statements - open then do viewsource for code
MySQL schema and insert statements and PHP scripts - How to interface to a MySQL database using PHP
and gbookFXXX.js
Or variations of the Sorted Guestbooks:
Sorted:
Sorted + update form
( code )
Intelligently Sorted + update form
( code )
Sortable tables - remembering last sort order
Sortable tables - remembering last sort order - All guestbooks ( ~800 entries )
Collated using linked lists:
Collate data by userfield1
( code )
tables of data by userfield1
( code )
or
tables of data by userfield1 + updates
Or a
Calendar showing when the gbookFXXX was updated. It is a calendar showing when people posted an entry in the guest book. ( Use View Source to see code ).
Using the idea, it is possible to include data into other pages to analyse data.
A C program gets data from a scope and saves it in files that can be included into a page to analyse data. The page could reload every few seconds.
Not working inline yet but click on the links below:
Scope - iic : Scope - iic
Scope - RS232 @ 9600 : Scope - RS232 @ 9600
Scope - RS232 @ 9600 : Scope - RS232 @ 9600
Arduino Logger : Arduino Logger info
Arduino Logger : Arduino Logger graph.
A technical overview of the idea...
A walk through the basics...
Minimal application and code...
There are times when multiple updates are required. This did not work very well.
A try at a multiple update form and perl script... This provides multiple sub forms, using data from gbookFmulti.js, which are appended to the gbookFmulti.js using gbook_multi.pl
A minimal multiple update form and perl script... This provides multiple forms.
A try at a multiple update form and perl script... This provides links generated, using data from gbookFmulti.js, you can add sub forms by clicking on hypertext links of by using a dropdown select list.
Another multiple update form... This a page where each item can be edited, and before submit, a list of updated entries can be listed, checked and submitted.
When you submit the data is appended to gbookFmulti.js using gbook_multi.pl
I wrote this essay for the TCN, who gave me a special commendation prize.
IOT: IOT| Simple TCP/IP examples | relayIOTprototype
Use JavaScript to read text and wrap HTML tags around it.
<div id="gifs"> biled0.gif biled1.gif biled2.gif biled3.gif dnld.gif dnlda.gif </div> <script> function showImages(){ if (document.getElementById){ gifs = document.getElementById( "gifs" ).innerHTML /* split the list into an array */ gifsA = gifs.split("\n") var opStr = "" for( var i = 0 ; i < gifsA.length ; i++ ){ opStr += "<br><img src="+gifsA[i]+">" } document.getElementById( "gifs" ).innerHTML=opStr } } showImages()
Use a canvas for a simple graph
function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){ values = userfield1 } // test call gbF( "Test Call1","email","15 Nov 2003","IPaddress","5,20,15,10,12,15,16,2,5,5,8,9,8,20,30,40,50","userfield2","userfield3","userfield4","Testcomments") graph( "myCanvasBar", values ,"bar" ) graph( "myCanvasLine", values ,"line" ) graph( "myCanvasStep", values ,"step" )
do view source to see the code:-