General :  K-Meleon Web Browser Forum
General discussion about K-Meleon 
Encrypted storage - items to paste (beta release)
Posted by: JamesD
Date: July 21, 2009 10:42PM

I have a system for entering, and saving IDs, passwords, and email addresses. This is not a traditional password manager. That is already available. This is to hold items that you might wish to paste into a form which is not included on your password manager.

The system requirements for this macro are as follows:
K-Meleon version 1.5.3 or higher. [ uses iniwrite() and iniread() ]
KMListBox [ http://www.perigee.net/~jmd8421r/KMListBox.7z ]
MySecret.exe encryption program. [ http://www.di-mgt.com.au/mysecret.html ]
Mark307's util.dll. [ I cannot remember the link ]

I used the util.dll version 0.0.9 but I can no longer find the link. I hope someone can provide.

Directions on where to place files are in the top of the Secure_Paste kmm file.

Secur_Paste.kmm

#  K-Meleon Macros (http://kmeleon.sourceforge.net/wiki/index.php?id=MacroLanguage)
#  
# ---------- Secur_Paste.kmm
# ---------- K-Meleon Macro Language secure items for pasting into forms --------
#
# Dependencies        : main.kmm  K-Meleon ver 1.5.3 or higher 
# Resources (1)       : KMListBox at http://www.perigee.net/~jmd8421r/KMListBox.7z
#                     : extract files to UserMacro folder
# Resources (2)       : MySecret.exe at http://www.di-mgt.com.au/mysecret.html
#                     : put file in K-Meleon root\Tools folder
# Resources (3)       : utils.dll in K-Meleon root\kplugins folder
#                     :
# Preferences         : k-meleon_securpaste_mpw
# Version             :  0.8   2009-07-20
# --------------------------------------------------------------------------------

_Secur_Paste_Paste{
$_SP_Item = $ARG;
$_SP_Item = substr($_SP_Item,2);
setclipboard($_SP_Item);
id(ID_EDIT_PASTE) ;
setclipboard("");
}

_Secur_Paste_ListBox{
$_SP_Box_Value_1 = _("id / passcode") ;
$_SP_Box_Value_2 = _("email address") ;
pluginmsg(utils, "exec", "\"".$_SP_ListBox_Path."\\KMListBox.exe\" \"".$_SP_Box_Value_1."\" \"".$_SP_Box_Value_2."\"", 29000);
#exec("\"".$_SP_ListBox_Path."\\KMListBox.exe\" \"".$_SP_Box_Value_1."\" \"".$_SP_Box_Value_2."\"");
#alert( _("Do not click this OK until listbox choice is done.") , _("Waiting for ListBox") , INFO );
$_SP_Reg_Value = readreg("HKCU","software\\KMELEON\\kmlistbox");
}

_Secur_Paste_Add{
menugrayed=getpref( BOOL , "k-meleon_securpaste_mpw" )==false;
$_SP_NewKeyNum = $_SP_keycnt + 1;
macros(_Secur_Paste_ListBox);
if ($_SP_Reg_Value == "id / passcode" ) { &_Secur_Paste_Add2;}
if ($_SP_Reg_Value == "email address" ) { &_Secur_Paste_Add2A;}
if ($_SP_Reg_Value == "cancel" ) { 
	alert("Cancel chosen - process terminated", "Return from listbox", INFO);
	}
}

_Secur_Paste_Add2{
$_SP_NewName=prompt("Enter the Name here", "Name " .$_SP_NewKeyNum);
$_SP_NewID=prompt("Enter the ID for ".$_SP_NewName, "ID ".$_SP_NewKeyNum);
$_SP_NewPasscode=prompt("Enter the Passcode for ".$_SP_NewID, "Passcode ". $_SP_NewKeyNum);
$_SPtext1 = "New key number  ". $_SP_NewKeyNum ."\n" ;
$_SPtext2 = "New name . . .   ". $_SP_NewName ."\n" ;
$_SPtext3 = "New ID . . . . .    ". $_SP_NewID ."\n" ;
$_SPtext4 = "New passcode     ". $_SP_NewPasscode ;
$_SP_Results=confirm($_SPtext1.$_SPtext2.$_SPtext3.$_SPtext4, "Confirm New Values CORRECT?", YESNO, QUESTION);   
&_Secur_Paste_Add3 ;
}

_Secur_Paste_Add3 { 
if ($_SP_Results==NO ) { 
	$_SP_Result2 = confirm("Do you wish re-enter the information", "Retry entry or Cancel", RETRYCANCEL, QUESTION);  
	if ($_SP_Result2=="RETRY") { 
		if ($_SP_Reg_Value == "id / passcode" ) { 
			&_Secur_Paste_Add2 ;
			} else { 
			&_Secur_Paste_Add2A ;
			} 
		} else { 
		alert("Add set # ".$_SP_NewKeyNum. " cancelled", "ADD CANCELED", INFO);
		}	
	} else { 
		if ($_SP_Reg_Value == "id / passcode" ) { 
			&_Secur_Paste_WriteNew ;
			} else { 
			&_Secur_Paste_WriteNewA ; 
			} 
	}
}


_Secur_Paste_Add2A{
$_SP_NewName=prompt("Enter the Name here", "Name " .$_SP_NewKeyNum);
$_SP_NewAddress=prompt("Enter the email address for ".$_SP_NewName, "ID ".$_SP_NewKeyNum);
$_SPtext1 = "New key number    ". $_SP_NewKeyNum ."\n" ;
$_SPtext2 = "New name . . . . .   ". $_SP_NewName ."\n" ;
$_SPtext3 = "New email address ". $_SP_NewAddress  ;
$_SP_Results=confirm($_SPtext1.$_SPtext2.$_SPtext3, "Confirm New Values CORRECT?", YESNO, QUESTION);   
&_Secur_Paste_Add3 ;
}

_Secur_Paste_WriteNew{
if (getpref( BOOL , "k-meleon_securpaste_mpw" )==true) {
if ( readfile($_Secur_Encrypt_Path) != "") {
	macros(_Secur_Paste_Decrypt); 
	}
# if overwrite, then clear menu before write to file
if ($_SP_Replace == "true") {&_Secur_Paste_ClearListMenu; } 
# rewrite the count
if ($_SP_Replace == "false") {
	iniwrite("sets","count",$_SP_NewKeyNum,$_SP_Path);
	if (iniread("sets","maxcount","",$_SP_Path) < $_SP_NewKeyNum) {
		iniwrite("sets","maxcount",$_SP_NewKeyNum,$_SP_Path);
		}
	}
# write the section, key=[type,name,id,passcode] and value=["id",NewName,NewID,NewPasscode]
iniwrite($_SP_NewKeyNum,"type","id",$_SP_Path);
iniwrite($_SP_NewKeyNum,"name",$_SP_NewName,$_SP_Path);
iniwrite($_SP_NewKeyNum,"id",$_SP_NewID,$_SP_Path);
iniwrite($_SP_NewKeyNum,"passcode",$_SP_NewPasscode,$_SP_Path);
&_Secur_Paste_ModMenuI;
}
}

_Secur_Paste_WriteNewA{
if (getpref( BOOL , "k-meleon_securpaste_mpw" )==true) {
macros(_Secur_Paste_Decrypt);
# if overwrite, then clear menu before write to file
if ($_SP_Replace == "true") {&_Secur_Paste_ClearListMenu; } 
# rewrite the count
if ($_SP_Replace == "false") {
	iniwrite("sets","count",$_SP_NewKeyNum,$_SP_Path); }
	if (iniread("sets","maxcount","",$_SP_Path) < $_SP_NewKeyNum) {
		iniwrite("sets","maxcount",$_SP_NewKeyNum,$_SP_Path);
		}
# write the section, key=[type,name,address] and value=["email",NewName,NewAddress]
iniwrite($_SP_NewKeyNum,"type","email",$_SP_Path);
iniwrite($_SP_NewKeyNum,"name",$_SP_NewName,$_SP_Path);
iniwrite($_SP_NewKeyNum,"address",$_SP_NewAddress,$_SP_Path);
&_Secur_Paste_ModMenuI;
}
}

_Secur_Paste_Overwrite{
menugrayed=getpref( BOOL , "k-meleon_securpaste_mpw" )==false;
$_SP_OW = prompt("Enter the number of the set to overwrite", "Overwrite set");
## decrypt the file
macros(_Secur_Paste_Decrypt);
$_SP_OWVName = iniread($_SP_OW,"name","",$_SP_Path);
$_SP_OWVType = iniread($_SP_OW,"type","",$_SP_Path);
## encrypt the file
macros(_Secur_Paste_Encrypt);
$_SPtext1 = "Replace this number    ". $_SP_OW ."\n" ;
$_SPtext2 = "Current name . . . .    ". $_SP_OWVName ."\n" ;
$_SPtext3 = "Current type . . . .      ". $_SP_OWVType  ;
$_SP_Results=confirm($_SPtext1.$_SPtext2.$_SPtext3, "Confirm this set to replace", YESNO, QUESTION);   
if ($_SP_Results=="NO" ) {
	$_SP_Result2 = confirm("Do you wish re-enter the information", "Retry entry or Cancel", RETRYCANCEL, QUESTION);  
	if ($_SP_Result2=="RETRY") { 
		&_Secur_Paste_Overwrite;
		} else {
		alert("Overwrite set # ".$_SP_OW. " cancelled", "OVERWRITE CANCELED", INFO);
		} 
	} else {
		# set some values so Add2, and Add2A can be used for overwrite
		$_SP_NewKeyNum = $_SP_OW;
		$_SP_Replace = "true";		
		if ($_SP_OWVType == "id" ) {
			$_SP_Reg_Value = "id / passcode" ;		
			&_Secur_Paste_Add2 ;
			} else {
			$_SP_Reg_Value = "email address" ;			
			&_Secur_Paste_Add2A ;
			} 	
	}
}

_Secur_Paste_ClearListMenu{
macros(_Secur_Paste_Decrypt);
statusbar("Clearing Secure Paste List Menu");
# write empty string to all set menu items - before write to ini file
$_SP_keycnt = iniread("sets","count","",$_SP_Path);
$_SP_Key = 0 ;
while ($_SP_Key < $_SP_keycnt) {
	$_SP_Type = iniread($_SP_Key+1,"type","",$_SP_Path);
	if ($_SP_Type == "id" ) {
		$_SP_Name = iniread($_SP_Key+1,"name","",$_SP_Path);
		$_SP_ID = iniread($_SP_Key+1,"id","",$_SP_Path);
		$_SP_Passcode = iniread($_SP_Key+1,"passcode","",$_SP_Path);
		setmenu($_SP_Popm,macro,$_SP_Key+1."  ".$_SP_Name." - ID","");
		setmenu($_SP_Popm,macro,$_SP_Key+1."  ".$_SP_Name." - Passcode","");			
		}
	if ($_SP_Type == "email" ) {
		$_SP_Name = iniread($_SP_Key+1,"name","",$_SP_Path);
		$_SP_Address = iniread($_SP_Key+1,"address","",$_SP_Path);
		setmenu($_SP_Popm,macro,$_SP_Key+1."  ".$_SP_Name." - Address","");		
		}					
	$_SP_Key = $_SP_Key + 1 ;
	}
rebuildmenu($_SP_Popm);
}

_Secur_Paste_Reduce{
menugrayed=getpref( BOOL , "k-meleon_securpaste_mpw" )==false;
if (getpref( BOOL , "k-meleon_securpaste_mpw" )==true) {
$_SP_DS = prompt("Enter the number of the set to delete", "Delete set");
macros(_Secur_Paste_Decrypt);
$_SP_DSVName = iniread($_SP_DS,"name","",$_SP_Path);
$_SP_DSVType = iniread($_SP_DS,"type","",$_SP_Path);
macros(_Secur_Paste_Encrypt);
$_SPtext1 = "Delete this set          ". $_SP_DS ."\n" ;
$_SPtext2 = "Current name . . .    ". $_SP_DSVName ."\n" ;
$_SPtext3 = "Current type . . .      ". $_SP_DSVType  ;
$_SP_Results=confirm($_SPtext1.$_SPtext2.$_SPtext3, "Confirm this set to delete", YESNO, QUESTION);   
if ($_SP_Results=="NO" ) {
	$_SP_Result2 = confirm("Do you wish re-enter the information", "Retry entry or Cancel", RETRYCANCEL, QUESTION);  
	if ($_SP_Result2=="RETRY") { 
		&_Secur_Paste_Reduce;
		} else { 
		alert("Delete set # ".$_SP_DS. " cancelled", "DELETE CANCELED", INFO);}
	} else { &_Secur_Paste_Reduce2; }
}
}
		
_Secur_Paste_Reduce2 {
&_Secur_Paste_ClearListMenu;
while (	$_SP_DS < 	$_SP_keycnt) {
if ($_SP_DSVType == "id" ) {
	# clear values for id and passcode
	iniwrite($_SP_DS,"id","",$_SP_Path);
	iniwrite($_SP_DS,"passcode","",$_SP_Path);
	&_Secur_Paste_ReduceRH ; # read next higher
	&_Secur_Paste_ReduceWL1; # write high to low
	} else { 
	# clear value for address
	iniwrite($_SP_DS,"address","",$_SP_Path);
	&_Secur_Paste_ReduceRH ; # read next higher
	&_Secur_Paste_ReduceWL1; # write high to low 
	} 
$_SP_DS = $_SP_DS + 1;	
} 
##  write empty strings to highest section 
iniwrite($_SP_keycnt,"type","",$_SP_Path);
iniwrite($_SP_keycnt,"name","",$_SP_Path);
iniwrite($_SP_keycnt,"id","",$_SP_Path);
iniwrite($_SP_keycnt,"passcode","",$_SP_Path);
iniwrite($_SP_keycnt,"address","",$_SP_Path);
##  rewrite count to indicate one less section
iniwrite("sets","count",$_SP_keycnt-1,$_SP_Path);
# Value remains after delete because iniread is reading cached info in registry
$_Value = iniread("","","","");
## rebuild the listmenu
&_Secur_Paste_ModMenuI ; 	
}

_Secur_Paste_ReduceRH {
# read name and type values for next higher section
$_SP_DSName = iniread($_SP_DS+1,"name","",$_SP_Path);
$_SP_DSVType = iniread($_SP_DS+1,"type","",$_SP_Path);
# if 'id' read id and passcode else read address
if ($_SP_DSVType == "id" ) {
	$_SP_DSVId = iniread($_SP_DS+1,"id","",$_SP_Path);
	$_SP_DSVPscd = iniread($_SP_DS+1,"passcode","",$_SP_Path);			
	} else { $_SP_DSVAdd = iniread($_SP_DS+1,"address","",$_SP_Path);}		
}

_Secur_Paste_ReduceWL1 {
# write section +1 keys and values to current section
if ($_SP_DSVType == "id" ) {
	iniwrite($_SP_DS,"type","id",$_SP_Path);
	iniwrite($_SP_DS,"name",$_SP_DSName,$_SP_Path);
	iniwrite($_SP_DS,"id",$_SP_DSVId,$_SP_Path);
	iniwrite($_SP_DS,"passcode",$_SP_DSVPscd,$_SP_Path);
} else {
	iniwrite($_SP_DS,"type","email",$_SP_Path);
	iniwrite($_SP_DS,"name",$_SP_DSName,$_SP_Path);
	iniwrite($_SP_DS,"address",$_SP_DSVAdd,$_SP_Path);
}
}

_Secur_Paste_MPassWord {
menuchecked=getpref( BOOL , "k-meleon_securpaste_mpw" )==true;
if (getpref( BOOL , "k-meleon_securpaste_mpw" )==true) {
	macros(_Secur_Paste_MPassDel);
	} else {
	macros(_Secur_Paste_MPassSet);
	}
}

_Secur_Paste_MPassDel{
setpref( BOOL , "k-meleon_securpaste_mpw", false );
&_Secur_Paste_ClearListMenu ;
macros(_Secur_Paste_Encrypt);
# retain password until all del password ops have completed
$_SP_MPW = "";
}

_Secur_Paste_MPassSet{	
# prompt for proposed master password
$_SPtext1 = "The master password is in memory only. \n" ;
$_SPtext2 = "It is not recoverable. \n" ;
$_SPtext3 = "It will be entered in the open so that \n" ;
$_SPtext4 = "you may verify your keystrokes." ;
alert($_SPtext1.$_SPtext2.$_SPtext3.$_SPtext4, "Master Password Notice", INFO);
$_SP_MPWP = prompt("Enter a master password for encryption", "Master Password (case sensitive)", "at least 7 characters");
$_SP_MPW = $_SP_MPWP;
setpref( BOOL , "k-meleon_securpaste_mpw", true );
macros(_Secur_Paste_Decrypt);
&_Secur_Paste_ModMenuI ;
}

_Secur_Paste_Encrypt {
$_SP_ini_Exist = getfolder(UserMacroFolder)."\\Secur_Paste.ini" ;
if (pluginmsgex(utils, "exist", $_SP_ini_Exist, STRING) == true ) {
	statusbar("Encrypting data file");
	$_file_input="Secur_Paste.ini";
	$_file_output="Secur_Paste.ecm";
	$_Secur_Input_Path=" \"".getfolder(UserMacroFolder)."\\".$_file_input."\"";
	$_Secur_output_path=" \"".getfolder(UserMacroFolder)."\\".$_file_output."\"";
	$_SP_SwitchM1 = "-e -n -p "; # a space required between -p and the passphrase
	$_SP_SwitchM2 = $_SP_MPW;  # must have quotes if includes spaces
	$_SP_SwitchM3 = $_Secur_Input_Path." ".$_Secur_output_path;
	$_SP_SwitchM  = $_SP_SwitchM1."\"".$_SP_SwitchM2."\"".$_SP_SwitchM3 ;
	##  Run MySecret and allow 9 seconds for process to complete
	pluginmsg(utils, "exec", $_MySecret_path.$_SP_SwitchM, 9000);
	# Wait 4 seconds for all disk writes to finish
	pluginmsg(utils, "sleep", 4000);
	# wipe old Secur_Paste.ini
	$_SP_wcnt = iniread("sets","maxcount","",$_SP_Path);
	$_SP_Key = 0 ; $_SP_IKey = 0 ;
	while ($_SP_Key < $_SP_wcnt) {
		while ($_SP_IKey < 5) {
			iniwrite($_SP_Key+1,"type","XXXX",$_SP_Path);
			iniwrite($_SP_Key+1,"name","XXXXXXXXXXXXXXXXXXXXX",$_SP_Path);
			iniwrite($_SP_Key+1,"id","XXXXXXXXXXXXXXXXXXXXX",$_SP_Path);
			iniwrite($_SP_Key+1,"passcode","XXXXXXXXXXXXXXXXXXXXX",$_SP_Path);
			iniwrite($_SP_Key+1,"address","XXXXXXXXXXXXXXXXXXXXX",$_SP_Path);
			iniwrite($_SP_Key+1,"type","oooo",$_SP_Path);
			iniwrite($_SP_Key+1,"name","ooooooooooooooooooooo",$_SP_Path);
			iniwrite($_SP_Key+1,"id","ooooooooooooooooooooo",$_SP_Path);
			iniwrite($_SP_Key+1,"passcode","ooooooooooooooooooooo",$_SP_Path);
			iniwrite($_SP_Key+1,"address","ooooooooooooooooooooo",$_SP_Path);
			$_SP_IKey = $_SP_IKey + 1 ;
		}
		$_SP_IKey = 0 ; 
		$_SP_Key = $_SP_Key + 1 ;
	}
	# erase the old Secur_Paste.ini
	$platform = pluginmsgex(utils, "GetOSVer", "Platform", STRING);
	if ($platform == 2) {
		exec("cmd /c ERASE \"".$_SP_Path."\"");
		} else {
		exec("command /c ERASE \"".$_SP_Path."\"");
		}
	statusbar("");
} else { alert("Secur_Paste.ini does not exist", "Correct if first use", EXCLAIM); }
}

_Secur_Paste_Decrypt{
$_SP_ecm_Exist = getfolder(UserMacroFolder)."\\Secur_Paste.ecm" ;
if (pluginmsgex(utils, "exist", $_SP_ecm_Exist, STRING) == true ) {
	statusbar("Decrypting data file");
	$_file_output="Secur_Paste.ini";
	$_file_input="Secur_Paste.ecm";
	$_input_path=" \"".getfolder(UserMacroFolder)."\\".$_file_input."\"";
	$_output_path=" \"".getfolder(UserMacroFolder)."\\".$_file_output."\"";
	$_SP_SwitchM1 = "-d -n -p "; # a space required between -p and the passphrase
	$_SP_SwitchM2 = $_SP_MPW;  # must have quotes if includes spaces
	$_SP_SwitchM3 = $_input_path." ".$_output_path;
	$_SP_SwitchM  = $_SP_SwitchM1."\"".$_SP_SwitchM2."\"".$_SP_SwitchM3 ;
	pluginmsg(utils, "exec", $_MySecret_path.$_SP_SwitchM, 8000);
	pluginmsg(utils, "sleep", 2000);
	statusbar("");
} else { alert("Secur_Paste.ecm does not exist", "Correct if first use", EXCLAIM); }
}

_Secur_Paste_ModMenu{
$_SP_Popm = "Secure Paste";
setmenu("&Tools",popup,$_SP_Popm,Misc);
setmenu($_SP_Popm,macro,"Add new set","_Secur_Paste_Add");
setmenu($_SP_Popm,macro,"Overwrite set #","_Secur_Paste_Overwrite");
setmenu($_SP_Popm,macro,"Delete set #","_Secur_Paste_Reduce");
setmenu($_SP_Popm,macro,"Master Password","_Secur_Paste_MPassWord");
setmenu($_SP_Popm,separator,5);	
&_Secur_Paste_ModMenuI;
}

_Secur_Paste_ModMenuI{
if (getpref( BOOL , "k-meleon_securpaste_mpw" )==true) {
statusbar("Writing Secure Paste List Menu");
$_SP_keycnt = iniread("sets","count","",$_SP_Path);
$_SP_Key = 0 ;

while ($_SP_Key < $_SP_keycnt) {
	$_SP_Type = iniread($_SP_Key+1,"type","",$_SP_Path);
	if ($_SP_Type == "id" ) {
		$_SP_Name = iniread($_SP_Key+1,"name","",$_SP_Path);
		$_SP_ID = iniread($_SP_Key+1,"id","",$_SP_Path);
		$_SP_Passcode = iniread($_SP_Key+1,"passcode","",$_SP_Path);
		setmenu($_SP_Popm,macro,$_SP_Key+1."  ".$_SP_Name." - ID","_Secur_Paste_Paste(".$_SP_Key+1." ".$_SP_ID.")"); 
		setmenu($_SP_Popm,macro,$_SP_Key+1."  ".$_SP_Name." - Passcode","_Secur_Paste_Paste(".$_SP_Key+1." ".$_SP_Passcode.")"); 
		}
	if ($_SP_Type == "email" ) {
		$_SP_Name = iniread($_SP_Key+1,"name","",$_SP_Path);
		$_SP_Address = iniread($_SP_Key+1,"address","",$_SP_Path);
		setmenu($_SP_Popm,macro,$_SP_Key+1."  ".$_SP_Name." - Address","_Secur_Paste_Paste(".$_SP_Key+1." ".$_SP_Address.")"); 
		}
	$_SP_Replace = "false" ;
	$_SP_Key = $_SP_Key + 1 ;
}
	rebuildmenu($_SP_Popm);
	macros(_Secur_Paste_Encrypt);
}
}

_Secur_Paste_Get_Path{
$_SP_Path= getfolder(UserMacroFolder)."\\Secur_Paste.ini";
$_Secur_Encrypt_Path= getfolder(UserMacroFolder)."\\Secur_Paste.ecm";
$_SP_ListBox_Path= getfolder(UserMacroFolder)."\\KMListBox" ;
$_MySecret_path="\"".getfolder(RootFolder)."\\Tools\\MySecret.exe\" ";
## Other OnInit items
$_SP_MPW = "";
setpref( BOOL , "k-meleon_securpaste_mpw", false );
$_SP_keycnt = 0;
$_SP_Replace = "false";
$_SP_DelPass = "false";
}

# = = = = = = = = = = = = = = = = = = = = = = = = = = = 
$OnInit=$OnInit."_Secur_Paste_Get_Path;";
$OnStartup=$OnStartup."_Secur_Paste_ModMenu;";
$macroModules=$macroModules."Secur_Paste;";


Options: ReplyQuote
Re: Encrypted storage - items to paste (beta release)
Posted by: desga2
Date: July 21, 2009 11:05PM

Link to mark307's website.
Direct link to download utils-0.0.9.zip

Great job JamesD, thanks!

K-Meleon in Spanish



Edited 1 time(s). Last edit at 07/21/2009 11:07PM by desga2.

Options: ReplyQuote
Re: Encrypted storage - items to paste (beta release)
Posted by: JamesD
Date: July 22, 2009 12:11AM

@ desga2

Thanks for the link to Mark307's site.

Options: ReplyQuote


K-Meleon forum is powered by Phorum.