Create your own webshop

Creating a webshop is easy. With some HTML code using the FORM formule, you can set up a really fine webshop that is safe, secure and easy to maintain. But sometimes you just want that little bit extra. And then you need to buy or make your own version of a webshop. Here is a simple webshop based upon PayPal buttons and PayPal shopping carts: https://www.vedt.nl/longshine/shop.html .

Buying a webshop is easy yet can be very expensive. Many webshop formulas are for hire. Others can be bought but only at a price. And not a modest one. Please visit fruttenboel/shop/index.html to read all about webshops that I know of.

Shopper, version 0.2

Below is the source code for shopper, version 0.2. It works stable and reliable. It doesn't do much yet, apart from outputing its data to screen. As mentioned in other sections, I now use the full web browser screen as a big TTY.

MODULE shopper;

(*	Webshop CGI executable; copyleft 2009 jan@vedt.nl

  ver	does						   date
 -----	--------------------------------------------	-----------
  0.1	run errorfree on the local server		12 Jun 2009
  0.2	GetData and Process added (Init stripped)	13 Jun 2009
								*)


IMPORT	CGI, InOut, NumConv, Strings;


VAR	ok		: BOOLEAN;


PROCEDURE  Process (str   : Strings.String);

VAR	ch		: CHAR;
	i, j		: CARDINAL;
	name, val, hex	: Strings.String;

BEGIN
   i := 0;
   REPEAT
      j := 0;					(*  Get new Name/Value pair	*)
      LOOP
	 ch := str [i];
	 INC (i);
	 IF  ch = '='  THEN  EXIT  END;			(*  EXIT strategy	*)
	 name [j] := ch;
	 INC (j)
      END;
      name [j] := 0C;					(*  varName extracted	*)
      j := 0;
      LOOP
	 ch := str [i];
	 INC (i);
	 IF  (ch = '&') OR (ch = 0C)  THEN		(*  Exit strategy	*)
	    EXIT
	 ELSIF  ch = '+'  THEN
	    ch := ' '
	 ELSIF  ch = '%'  THEN
	    hex [0] := str [i];
	    hex [1] := str [i+1];
	    hex [2] := 0C;				(*  Create HEX string	*)
	    INC (i, 2);
	    ch := CGI.ConvertHex (hex)		(*  Have it converted to ASCII	*)
	 END;
	 val [j] := ch;
	 INC (j)
      END;
      val [j] := 0C;					(*  value extracted	*)
      IF  CGI.StoreVar (name) = FALSE  THEN
	 InOut.WriteString ("CGI variable already defined; aborting.");
	 InOut.WriteLn;
	 HALT
      END;
      CGI.thisVar^.value := val		(*  store name and value in linked list	*)
   UNTIL  ch = 0C;
END  Process;


PROCEDURE  GetData;

VAR	value		: Strings.String;
	ch		: CHAR;
	i, j		: CARDINAL;
	ok		: BOOLEAN;

BEGIN
   IF  Strings.StrEq (value, "GET")  THEN
      IF  CGI.EnvVar ("QUERY_STRING", value) = FALSE  THEN
	 InOut.WriteString ("No 'query string' despite method is GET; aborting.");
	 InOut.WriteLn;
	 HALT
      END;
      Process (value)
   ELSIF  Strings.StrEq (value, "POST")  THEN
      IF  CGI.EnvVar ("CONTENT_LENGTH", value) = FALSE  THEN
	 InOut.WriteString ("No 'content length' despite method is POST; aborting.");
	 InOut.WriteLn;
	 HALT
      END;
      NumConv.Str2Num (i, 10, value, ok);
      IF  NOT ok  THEN
	 InOut.WriteString ("Invalid token in 'content length' (");
	 InOut.WriteString (value);
	 InOut.WriteString ("); aborting.");
	 InOut.WriteLn;
	 HALT
      END;
      j := 0;
      WHILE  i > 0  DO
	 InOut.Read (ch);	(* Read from StdIn	*)
	 DEC (i);
	 value [j] := ch;
	 INC (j)
      END;
      value [j] := 0C;
      Process (value);
   ELSE
      InOut.WriteString ("Request method is neither GET nor POST; aborting.");
      InOut.WriteLn;
      HALT
   END;
END  GetData;


PROCEDURE  GetInfo;

VAR	value		: Strings.String;

BEGIN
   IF  CGI.EnvVar ("HTTP_REFERER", value) = FALSE  THEN
      InOut.WriteString ("No http referer specified; suspicious; aborting.");
      InOut.WriteLn;
      HALT
   END;
   IF  CGI.StoreVar ("http_referer") = FALSE  THEN
      InOut.WriteString ("Could not create http_referer entry; aborting.");
      InOut.WriteLn;
      HALT
   END;
   CGI.thisVar^.value := value;
   IF  CGI.EnvVar ("REMOTE_ADDR", value) = FALSE  THEN
      InOut.WriteString ("No remote address specified; suspicious; aborting.");
      InOut.WriteLn;
      HALT
   END;
   IF  CGI.StoreVar ("remote_address") = FALSE  THEN
      InOut.WriteString ("Could not create remote_address entry; aborting.");
      InOut.WriteLn;
      HALT
   END;
   CGI.thisVar^.value := value;
   IF  Strings.StrEq (value, "127.0.0.1") = FALSE  THEN
      IF  CGI.EnvVar ("REMOTE_HOST", value) = FALSE  THEN
	 InOut.WriteString ("No remote host specified; suspicious; aborting.");
	 InOut.WriteLn;
	 HALT
      END;
      IF  CGI.StoreVar ("remote_host") = FALSE  THEN
	 InOut.WriteString ("Could not create remote_host entry; aborting.");
	 InOut.WriteLn;
	 HALT
      END;
      CGI.thisVar^.value := value
   END
END  GetInfo;


PROCEDURE  Init;

VAR	value		: Strings.String;

BEGIN
   CGI.SetMimeType (CGI.text);
   IF  CGI.EnvVar ("REQUEST_METHOD", value) = FALSE  THEN
      InOut.WriteString ("Request method not defined; aborting.");
      InOut.WriteLn;
      HALT
   END;
END Init;


BEGIN
   Init;
   GetData;
   GetInfo;
   CGI.ShowList;				(*  Call debugging routine	*)
   InOut.WriteBf
END shopper.
   
This source does: And that's about it for the time being.

Compiling and installing

Compiling is easy of course. This is Mocka (Modula-2) so the IDE will do all for you. The difficult part is that the shopper executable must be installed in /var/www/cgi-bin by 'root'. Then refer to it in the FORM definition section of your webshop. And that's it.

Page created on 13 June 2009 and