#!/usr/bin/perl

# TenFourFoxBox 1.0
# Copyright 2015-2017 Cameron Kaiser
# Portions copyright 2007-2011 Mozilla Labs
# Pashua copyright 2015 Carsten Bluem
# All rights reserved

# Modified for use with InterWebPPC by wicknix 2022

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

$returncode = 1;
$FOXBOX_VERSION="0.1";

$pwd = $0;
$pwd =~ s#/?foxbox$##;
$pwd =~ s#/?script$##;
$pwd =~ s#/?maker.pl$##;
$pwd ||= ".";

# InterWebPPC must be installed.
$path = "/Applications/InterWebPPC.app"; # fallback
chomp($machine = `/usr/bin/machine`);
$path = "/Applications/InterWebPPC-G3.app";
$path = "/Applications/InterWebPPC-G4.app" if ($machine eq 'ppc7450');
$path = "/Applications/InterWebPPC-G5.app" if ($machine eq 'ppc970');
$path = "/Applications/TenFourFoxBoxRunner.app" if (-x
	"/Applications/TenFourFoxBoxRunner.app/Contents/MacOS/firefox");

	if (! -d $path || ! -x "$path/Contents/MacOS/interwebppc") {
		if (-x "/Applications/InterWebPPC.app/Contents/MacOS/interwebppc") {
			$path = "/Applications/InterWebPPC.app";
		} else {
			&dialogue("Couldn't find $path!");
		}
	}
	
# Load and cache icon.
if (open(K, "$pwd/foxbox.icns") || open(K, "$pwd/../Resources/foxbox.icns")) {
	$/ = undef;
	$icns = scalar(<K>);
	close(K);
} else {
	warn "Couldn't load and cache foxbox icon. Apps will use the default icon.\n";
}

#warn "@ARGV";

if($ARGV[0] ne '-cli') {

ARGY: while(scalar(@ARGV)) {
# THIS DOESN'T WORK YET.
# If something was dropped on us, try to retrieve its data.
	$x = shift(@ARGV);
	if (-d $x) {
		&dialogue("That app doesn't appear to be a foxbox.")
			if (! -r "$x/Contents/Resources/foxbox/application.ini");
		open(K, "$x/Contents/Resources/foxbox/application.ini");
		$ok = 0;
		while(<K>) {
			chomp;
			if (/\[InTheBox\]/) {
				$ok = 1;
				next;
			}
			next if (!$ok);
			($key, $value) = split(/\=/, $_, 2);
			$$key = $value;
		}
		close(K);
		&dialogue("The foxbox settings appear corrupted in this app.")
			if (!$ok || !defined($appname) || !defined($url) || !defined($title) || !defined($width) || !defined($height));
		$upgrading = "[return][return](Previous settings loaded from $appname.)";
		last ARGY;
	}
}

# Launch interface.
# First, find Pashua.
$pashua = (-x "$pwd/Pashua.app/Contents/MacOS/Pashua") ? "$pwd/Pashua.app/Contents/MacOS/Pashua"
		: (-x "$pwd/../MacOS/Pashua") ? "$pwd/../MacOS/Pashua"
		: (-x "$pwd/Pashua") ? "$pwd/Pashua"
		: undef;
die("Pashua not found in $pwd") if (!defined($pashua));

open(K, ">/tmp/xulmaker.$$") || die("temp file failure");
$appname ||= "/Applications/InTheBox.app";
$url ||= "https://www.duckduckgo.com/";
$title ||= "DuckDuckGo";
$width ||= "1024";
$height ||= "738";
$persist ||= 0;
$formfill ||= 0;
$cloak ||= 0;
print K <<"EOF";

*.title=InTheBox

img.type=image
img.path=$pwd/../Resources/foxboxapp.icns
img.x=0
img.y=360
img.border=1
img.tooltip=Too bad if you think this icon sucks. :)

txt.type=text
txt.x=150
txt.y=390
txt.text=InTheBox builds application boxes  unique single-site web browsers you can tailor for your favourite websites.[return][return]Powered by InterWebPPC.$upgrading
txt.tooltip=InTheBox applications you build with InterWebPPC can go anywhere you have InterWebPPC installed.

appname.type=savebrowser
appname.label=Specify the path and application name for the new site's app box.
appname.tooltip=The inthebox application will be created using this folder and application name.
appname.default=$appname
appname.filetype=app
appname.width=480
appname.x=0
appname.y=295

url.type=textfield
url.label=Enter the URL for the site (include http:// or https://).
url.tooltip=When you double click the .app above, the web site you enter here will automatically appear in the app box application when it starts up.
url.default=$url
url.width=480
url.x=0
url.y=240

persist.type=checkbox
persist.label=Allow this app box to keep cookies and other site data after it closes.
persist.tooltip=InTheBoxes default to private browsing and clear cookies when you quit. Check this box to allow them to persist.
persist.x=0
persist.y=210
persist.default=$persist

formfill.type=checkbox
formfill.label=Allow this foxbox to remember form data and autofill form fields.
formfill.tooltip=Check this box to allow form fields to be automatically remembered and filled in (EXCEPT PASSWORDS).
formfill.x=0
formfill.y=190
formfill.default=$formfill

cloak.type=checkbox
cloak.label=Prevent the web site from detecting it's not in a normal browser.
cloak.tooltip=This forces the website to think you are using regular Firefox on an Intel Mac. Only enable if necessary, as the site may try to enable unsupported features.
cloak.x=0
cloak.y=170
cloak.default=$cloak

title.type=textfield
title.label=Enter a brief title to appear on the window.
title.default=$title
title.x=0
title.y=100
title.width=480

width.type=textfield
width.label=Default width of window (you can enlarge it).
width.default=$width
width.x=0
width.y=44

height.type=textfield
height.label=Default height of window.
height.tooltip=Remember to leave enough room for the titlebar (22 pixels) and/or Dock.
height.default=$height
height.x=280
height.y=44

can.type=cancelbutton
can.label=Cancel
can.tooltip=Don't make thi app box (and lament in agony the rest of your days).

dfb.type=defaultbutton
dfb.label=Create
dfb.tooltip=Create the box app with the location, website, settings and application name you specified.

EOF
close(K);
$result = `'$pashua' /tmp/xulmaker.$$`;
unlink("/tmp/xulmaker.$$");
#print $result;
foreach (split/\n/, $result) {
	/^(\w+)=(.*)$/;
	next if (!defined($1));
	exit if ($1 eq 'can' && $2 eq '1');
	$$1=$2;
}
exit if ($dfb ne '1');

} else {
	($cli, $appname, $url, $title, $width, $height, $persist, $formfill, $cloak) = (@ARGV);
}

($appname =~ m#(^|/)([^/]+).app$#) && ($gappname = $2);
&dialogue("Unable to parse application name $appname.") if (!length($gappname) || $appname !~ /\.app$/);
&dialogue("Nonsense URL $url.") if ($url !~ m#^[a-z0-9]+://.+$# || $url =~ /['"]/);
$MKDIR = "/bin/mkdir";
$RM = "/bin/rm";
$CP = "/usr/bin/cp";

# If it exists, don't overwrite something that's obviously not a foxbox.
if (-d $appname) {
	if (! -r "$appname/Contents/Resources/foxbox/application.ini") {
		&dialogue("Refusing to overwrite non-box app $appname.");
		exit; # paranoia
	}
}
system("$RM -rf '$appname'");
mkdir("$appname") || &dialogue("Unable to create $appname: $!\n");
chdir("$appname");

system("$MKDIR -p Contents/MacOS");

&file("Contents/Info.plist", <<"EOF");
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>CFBundleDevelopmentRegion</key>
        <string>English</string>
        <key>CFBundleExecutable</key>
        <string>foxbox</string>
        <key>CFBundleGetInfoString</key>
        <string>Built by InTheBox $FOXBOX_VERSION (C)2017 Cameron Kaiser and 2022 wicknix</string>
        <key>CFBundleName</key>
        <string>Foxbox</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleLongVersionString</key>
        <string>$FOXBOX_VERSION</string>
        <key>CFBundleShortVersionString</key>
        <string>$FOXBOX_VERSION</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleIdentifier</key>
        <string>com.floodgap.foxbox.$gappname</string>
        <key>CFBundleVersion</key>
        <string>$FOXBOX_VERSION</string>
        <key>CFBundleIconFile</key>
        <string>foxbox.icns</string>
        <key>NSPrincipalClass</key>
        <string>NSApplication</string>
        <key>NSHumanReadableCopyright</key>
        <string>Built by InTheBox $FOXBOX_VERSION (C)2017 Cameron Kaiser and 2022 wicknix</string>
</dict>
</plist>
EOF

&file("Contents/MacOS/foxbox", <<'EOF');
#!/usr/bin/perl

$file = $0;
$file =~ s#/MacOS/foxbox##;
$path = "/Applications/InterWebPPC.app"; # fallback
chomp($machine = `/usr/bin/machine`);
$path = "/Applications/InterWebPPC-G3.app";
$path = "/Applications/InterWebPPC-G4.app" if ($machine eq 'ppc7450');
$path = "/Applications/InterWebPPC-G5.app" if ($machine eq 'ppc970');
$path = "/Applications/TenFourFoxBoxRunner.app" if (-x
	"/Applications/TenFourFoxBoxRunner.app/Contents/MacOS/firefox");

	if (! -d $path || ! -x "$path/Contents/MacOS/interwebppc") {
		if (-x "/Applications/InterWebPPC.app/Contents/MacOS/interwebppc") {
			$path = "/Applications/InterWebPPC.app";
		} else {
			&dialogue("Couldn't find $path!");
		}
	}

exec("\"$path/Contents/MacOS/interwebppc\" -app \"$file/Resources/foxbox/application.ini\"");
&dialogue("Failed to execute: $!\n");
sub dialogue {
	open(O, "|/usr/bin/osascript") || (print "Can't open osascript; $!\n", exit);
	print O <<"EOG";
tell application "Dock"
	activate
	display dialog "@_" buttons ("OK") default button "OK"
	set answername to button returned of the result
end tell
EOG
	close(O);
	exit;
}

EOF
chmod(0755, "Contents/MacOS/foxbox") || &dialogue("Unable to set foxbox perms: $!\n");

system("$MKDIR -p Contents/Resources/foxbox/components");
system("$MKDIR -p Contents/Resources/foxbox/chrome/content");
system("$MKDIR -p Contents/Resources/foxbox/defaults/preferences");
system("$MKDIR -p Contents/Resources/foxbox/chrome/skin/standard");
system("$MKDIR -p Contents/Resources/foxbox/chrome/locale/en-US/brand");

&file("Contents/Resources/foxbox/application.ini", <<"EOF");
[App]
Version=$FOXBOX_VERSION
Vendor=InTheBox
Name=$gappname
BuildID=1
ID=${gappname}\@InTheBox
[Gecko]
MinVersion=38.3
MaxVersion=100.0
[InTheBox]
appname=$appname
url=$url
title=$title
width=$width
height=$height
persist=$persist
formfill=$formfill
cloak=$cloak
EOF

$persist = ($persist) ? "" : 'pref("browser.privatebrowsing.autostart", true);';
$formfill = ($formfill) ? 'pref("browser.formfill.enable", true);' : "";
$cloak = ($cloak) ? 'pref("general.useragent.override", "Mozilla/5.0 (Android 7.0; Mobile; rv:52.0) Gecko/52 Firefox/52.0");' : "";

&file("Contents/Resources/foxbox/defaults/preferences/prefs.js", <<"EOF");
pref("toolkit.defaultChromeURI", "chrome://foxbox/content/foxbox.xul");

pref("layout.spellcheckDefault", 0);

pref("browser.dom.window.dump.enabled", true);
pref("javascript.options.showInConsole", true);

pref("browser.chromeURL", "chrome://foxbox/content/foxbox.xul");
pref("tenfourfox.mp3.enabled", true);

pref("browser.download.useDownloadDir", true);
pref("browser.download.folderList", 0);
pref("browser.download.manager.showAlertOnComplete", true);
pref("browser.download.manager.showAlertInterval", 2000);
pref("browser.download.manager.retention", 2);
pref("browser.download.manager.showWhenStarting", true);
pref("browser.download.manager.useWindow", true);
pref("browser.download.manager.closeWhenDone", true);
pref("browser.download.manager.openDelay", 0);
pref("browser.download.manager.focusWhenStarting", false);
pref("browser.download.manager.flashCount", 2);

pref("dom.webnotifications.enabled", true);
pref("notification.prompt.testing", true);

pref("app.update.enabled", false);
$formfill
pref("browser.formfill.saveHttpsForms", true);
pref("browser.formfill.agedWeight", 2);
pref("browser.formfill.boundaryWeight", 25);
pref("browser.formfill.bucketSize", 1);
pref("browser.formfill.debug", false);
pref("browser.formfill.expire_days", 180);
pref("browser.formfill.maxTimeGroupings", 25);
pref("browser.formfill.prefixWeight", 5);
pref("browser.formfill.timeGroupingSize", 604800);
$persist
$cloak

EOF
&file("Contents/Resources/foxbox.icns", $icns) if (length($icns));
&file("Contents/Resources/foxbox/chrome.manifest", <<'EOF');
manifest components/components.manifest
manifest chrome/chrome.manifest
EOF
&file("Contents/Resources/foxbox/chrome/chrome.manifest", <<'EOF');
content foxbox content/
locale	foxbox en-US	locale/en-US/
skin	foxbox standard/1.0 skin/standard/
locale	branding en-US	locale/en-US/brand/
EOF
&file("Contents/Resources/foxbox/components/components.manifest", <<'EOF');
component {fff440b3-fae2-45c1-bf03-3b5a2e432271} TrivialMozAppsRegistry.js
contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432271}

EOF
&file("Contents/Resources/foxbox/components/TrivialMozAppsRegistry.js", <<'EOF');
// navigator.mozApps trivial implementation (avoids bug 1094714)
// Use a different CID so we can mask it.

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

function TrivialMozAppsRegistry() {
}
TrivialMozAppsRegistry.prototype = {
  classID : Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432271}"),
  QueryInterface : XPCOMUtils.generateQI(
    [Components.interfaces.nsISupportsWeakReference,
     Components.interfaces.nsISupports,
     Components.interfaces.nsIObserver,
     Components.interfaces.nsIDOMGlobalPropertyInitializer]),
  classInfo : XPCOMUtils.generateCI({
    classID : Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432271}"),
    contractID : "@mozilla.org/webapps;1",
    classDescription : "Phony mozApps",
    interfaces : [Components.interfaces.nsISupportsWeakReference,
                  Components.interfaces.nsISupports,
                  Components.interfaces.nsIObserver,
                  Components.interfaces.nsIDOMGlobalPropertyInitializer],
    flags : Components.interfaces.nsIClassInfo.SINGLETON
  }),
  
  // mozIDOMApplicationRegistry
  install : function(aURL, aParams) { },
  installPackage : function(aURL, aParams) { },
  getSelf : function() { },
  getInstalled: function() { },
  checkInstalled : function(aManifestURL) { },
  get mgmt() { return null },
  
  // Language pack API (not currently supported)
  getAdditionalLanguages : function() { },
  getLocalizationResource : function(aLanguage, aVersion, aPath, aType) { },
  
  // nsIDOMGlobalPropertyInitializer
  init : function(aWindow) { }
};

// XPCOM HO!
var components = [ TrivialMozAppsRegistry ];
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

EOF
&file("Contents/Resources/foxbox/chrome/skin/standard/about.css", <<'EOF');
/* global skin ------------------------------------------------------------- */
@import url(chrome://global/skin/);

/* dialog skin ------------------------------------------------------------- */
#about {
  -moz-appearance: dialog;
}

#brandName {
  font-weight: bold; font-size: 3.0em;
}

#useragent {
  margin: 11px 20px 0px 13px;
  color: #000000;
  padding: 1px 0px 0px 3px;
  background-color: -moz-Dialog;
  -moz-appearance: textfield-multiline;
  overflow: hidden;
  border: 1px solid;
}

.version {
  font-weight: bold;
}

.cozy {
  margin-top: 0px;
  margin-bottom: 0px;
}
EOF
&file("Contents/Resources/foxbox/chrome/locale/en-US/brand/brand.dtd", <<"EOF");
<!ENTITY  brandShortName  "InTheBox">
<!ENTITY  brandFullName   "InTheBox">

<!-- required for download dialog (unknownContentType.xul) -->

<!ENTITY  intro2.label                 "You have chosen to open">
<!ENTITY  from.label                  "from:">
<!ENTITY  actionQuestion.label        "What should &brandShortName; do with this file?">

<!ENTITY  openWith.label              "Open with">
<!ENTITY  openWith.accesskey          "o">
<!ENTITY  other.label                 "Other...">

<!ENTITY  saveFile.label                  "Save File">
<!ENTITY  saveFile.accesskey              "s">

<!ENTITY  rememberChoice.label        "Do this automatically for files like this from now on.">
<!ENTITY  rememberChoice.accesskey    "a">

<!ENTITY  settingsChangePreferences.label        "Settings can be changed in &brandShortName;'s Preferences.">
<!ENTITY  settingsChangeOptions.label     "Settings can be changed in &brandShortName;'s Options.">

<!ENTITY  whichIs.label              "which is a:">

<!ENTITY  chooseHandlerMac.label      "Choose...">
<!ENTITY  chooseHandlerMac.accesskey  "C">

<!ENTITY  unknownPromptText.label     "Would you like to save this file?">
EOF
&file("Contents/Resources/foxbox/chrome/locale/en-US/brand/brand.properties", <<"EOF");
brandShortName=InTheBox
brandFullName=InTheBox
EOF

$dialog_width = 24*length($gappname);
$dialog_width = 400 if ($dialog_width < 400);
&file("Contents/Resources/foxbox/chrome/content/about.xul", <<"EOF");
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://foxbox/skin/about.css" type="text/css"?>
<dialog id="about" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
	title="About TenFourFoxBox" buttons="accept" width="$dialog_width" height="300"
	onload="getAppInfo()">
    
  <script type="application/x-javascript">
  <![CDATA[
function getAppInfo() 
{
  var appInfo = Components.classes["\@mozilla.org/xre/app-info;1"]
                          .getService(Components.interfaces.nsIXULAppInfo);

  var name = document.getElementById("brandName");
  name.value = appInfo.name;
  
  var version = document.getElementById("vversion");
  version.value = "powered by InterWebPPC/" + appInfo.version;

  var userAgent = document.getElementById("useragent");
  userAgent.value = navigator.userAgent;
}  
  ]]>
  </script>

  <vbox flex="1">
  	<label id="brandName"/>
    <label class="version cozy" id="vversion"/>
    <label value=""/>
    <label class="cozy" value="Copyright &#169; 2015-2017 Cameron Kaiser and 2022 wicknix."/>
    <label class="cozy" value="Copyright &#169; 2010-2017 Contributors to TenFourFox."/>
    <label class="cozy" value="Copyright &#169; 2007-2011 Mozilla Labs."/>
    <label class="cozy" value="All rights reserved."/>
    <textbox id="useragent" multiline="true" readonly="true" flex="1"/>
  </vbox>
</dialog>

EOF

if (length($formfill)) {
	# No sense instantiating the overhead if we're not going to use it.
	$f1 = '<panel id="popup_autocomplete" type="autocomplete" noautofocus="true" />';
	$f2 = 'autocompletepopup="popup_autocomplete" ';
} else {
	$f1 = '';
	$f2 = '';
}
&file("Contents/Resources/foxbox/chrome/content/foxbox.xul", <<"EOF");
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<window
     id="main"
     title="InTheBox: $title"
     width="$width" height="$height" 
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
     persist="width,height,screenX,screenY,sizemode"
     onload="nLoad();">
$f1
	<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
	<script type="application/javascript" src="chrome://global/content/printUtils.js"/>
	<script type="application/javascript">
	<![CDATA[
// Much of this was borrowed wholesale with minor changes from Webrunner.
// Appropriate credit to mfinkle and bsmedberg at MoCo, et al.

var listener = null;
var myBrowser = null;
var currentNode = null;

// nsIXULBrowserWindow implementation to display link destinations in the status bar.
var gXULBrowserWindow = {
  QueryInterface: function(aIID) {
    if (aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
        aIID.equals(Components.interfaces.nsISupports))
     return this;

    throw Components.results.NS_NOINTERFACE;
  },

  setJSStatus: function() { },
  setJSDefaultStatus: function() { },

  setOverLink: function(aStatusText, aLink) {
    var statusbar = document.getElementById("status");
    statusbar.label = aStatusText;
  }
};

// nsIWebProgressListener implementation to monitor activity in the browser.
function WebProgressListener() {
}
WebProgressListener.prototype = {
  _requestsStarted: 0,
  _requestsFinished: 0,

  QueryInterface: function(iid) {
    if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
        iid.equals(Components.interfaces.nsISupportsWeakReference) ||
        iid.equals(Components.interfaces.nsISupports))
      return this;
    
    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  // This method is called to indicate state changes.
  onStateChange: function(webProgress, request, stateFlags, status) {
    const WPL = Components.interfaces.nsIWebProgressListener;

    var progress = document.getElementById("progress");

    if (stateFlags & WPL.STATE_IS_REQUEST) {
      if (stateFlags & WPL.STATE_START) {
        this._requestsStarted++;
      } else if (stateFlags & WPL.STATE_STOP) {
        this._requestsFinished++;
      }
      if (this._requestsStarted > 1) {
        var value = (100 * this._requestsFinished) / this._requestsStarted;
        progress.setAttribute("mode", "determined");
        progress.setAttribute("value", value + "%");
      }
    }

    if (stateFlags & WPL.STATE_IS_NETWORK) {
      if (stateFlags & WPL.STATE_START) {
        progress.setAttribute("style", "");
      } else if (stateFlags & WPL.STATE_STOP) {
        progress.setAttribute("style", "display: none");
        this.onStatusChange(webProgress, request, 0, "Done");
        this._requestsStarted = this._requestsFinished = 0;
      }
    }
  },

  // This method is called to indicate progress changes for the currently
  // loading page.
  onProgressChange: function(webProgress, request, curSelf, maxSelf,
                             curTotal, maxTotal) {
    if (this._requestsStarted == 1) {
      var progress = document.getElementById("progress");
      if (maxSelf == -1) {
        progress.setAttribute("mode", "undetermined");
      } else {
        progress.setAttribute("mode", "determined");
        progress.setAttribute("value", ((100 * curSelf) / maxSelf) + "%");
      }
    }
  },

  // This method is called to indicate a change to the current location.
  onLocationChange: function(webProgress, request, locationURI, flags) {
	// nothing yet
  },

  // This method is called to indicate a status changes for the currently
  // loading page.  The message is already formatted for display.
  onStatusChange: function(webProgress, request, status, message) {
    var status = document.getElementById("status");
    status.setAttribute("label", message);
  },

  // This method is called when the security state of the browser changes.
  onSecurityChange: function(webProgress, request, state) {
    const WPL = Components.interfaces.nsIWebProgressListener;

    var sec = document.getElementById("security");

    if (state & WPL.STATE_IS_INSECURE) {
      sec.setAttribute("style", "display: none");
    } else {
      var level = "unknown";
      if (state & WPL.STATE_IS_SECURE) {
        if (state & WPL.STATE_SECURE_HIGH)
          level = "high";
        else if (state & WPL.STATE_SECURE_MED)
          level = "medium";
        else if (state & WPL.STATE_SECURE_LOW)
          level = "low";
      } 
      sec.setAttribute("label", "Security: " + level);
      sec.setAttribute("style", "");
    }
  }
};

function nLoad() {
	listener = new WebProgressListener();
	getBrowser().addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);

	var browserContext = document.getElementById("main-popup");
	browserContext.addEventListener("popupshowing", popupShowing, false);
	document.getElementById("edit-menu").addEventListener("popupshowing", popupShowing, false);

  // hookup the browser window callbacks
  window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
        .getInterface(Components.interfaces.nsIWebNavigation)
        .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
        .treeOwner
        .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
        .getInterface(Components.interfaces.nsIXULWindow)
        .XULBrowserWindow = gXULBrowserWindow;

	nHome();
}
function getBrowser() {
	if (!myBrowser)
		myBrowser = document.getElementById("browser");
	return myBrowser;
}
function nStop() { getBrowser().stop(); }
function nHome() { getBrowser().goHome(); }
function nBack() { getBrowser().goBack(); }
function nReload() { getBrowser().reload(); }
function nForward() { getBrowser().goForward(); }
function nQuit() {
	var appStartup = Components.classes['\@mozilla.org/toolkit/app-startup;1'].
		getService(Components.interfaces.nsIAppStartup);
	appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit);
}
function nAbout() {
	window.openDialog("chrome://foxbox/content/about.xul", "about", "centerscreen,modal");
}
function nCopyURL() {
    var clipboard = Components.classes["\@mozilla.org/widget/clipboardhelper;1"].
                    getService(Components.interfaces.nsIClipboardHelper);
    clipboard.copyString(getBrowser().currentURI.spec, document);
}
function nCopyLink() {
	if (!currentNode || !currentNode.href) return; // hmmm
    var clipboard = Components.classes["\@mozilla.org/widget/clipboardhelper;1"].
                    getService(Components.interfaces.nsIClipboardHelper);
	clipboard.copyString(currentNode.href, document);
}

function popupShowing(aEvent) {
  function isHTMLLink(aNode)
  {
    // Be consistent with what nsContextMenu.js does.
    return ((aNode instanceof HTMLAnchorElement && aNode.href) ||
            (aNode instanceof HTMLAreaElement && aNode.href) ||
            aNode instanceof HTMLLinkElement);
  }

  var cut = document.getElementById("cut-menuitem");
  var copy = document.getElementById("copy-menuitem");
  var paste = document.getElementById("paste-menuitem");
  var del = document.getElementById("delete-menuitem");
  var clink = document.getElementById("copylink-menuitem");

  var isContentSelected = !document.commandDispatcher.focusedWindow.getSelection().isCollapsed;

  var target = document.popupNode;
  var isTextField = target instanceof HTMLTextAreaElement;
  var isAnchor = false;
  if (target instanceof HTMLInputElement && (target.type == "text" || target.type == "password"))
    isTextField = true;
  if (!isTextField && !isContentSelected) {
    // Try to see if it's an anchor. This may require walking nodes up.
    var anchorNode = target;
    while (anchorNode && !isAnchor) {
      if (isHTMLLink(anchorNode))
        isAnchor = true;
      else
        anchorNode = anchorNode.parentNode;
    }

    if (isAnchor)
      currentNode = anchorNode;
    else
      currentNode = null;
  }
  var isTextSelectied= (isTextField && target.selectionStart != target.selectionEnd);

  cut.setAttribute("disabled", ((!isTextField || !isTextSelectied) ? "true" : "false"));
  copy.setAttribute("disabled", (((!isTextField || !isTextSelectied) && !isContentSelected) ? "true" : "false"));
  paste.setAttribute("disabled", (!isTextField ? "true" : "false"));
  del.setAttribute("disabled", (!isTextField ? "true" : "false"));
  clink.setAttribute("disabled", (!isAnchor ? "true" : "false"));
}

	]]>
	</script>

	<toolbox>
		<menubar id="menubar">
		<menu id="box-menu" label="Box">
			<menupopup id="nav-popup">
				<menuitem key="key_back" label="Back" oncommand="nBack();"/>
				<menuitem key="key_fwd" label="Forward" oncommand="nForward();"/>
				<menuitem key="key_home" label="Home" oncommand="nHome();"/>
				<menuseparator/>
				<menuitem key="key_stop" label="Stop" oncommand="nStop();"/>
				<menuitem key="key_reload" label="Reload" oncommand="nReload();"/>
				<menuseparator/>
				<menuitem key="key_copyurl" label="Copy Current Location" oncommand="nCopyURL();"/>
      			<menuitem id="print-menuitem" key="key_print" label="Print..." oncommand="PrintUtils.print();"/>
      			<!-- These get moved to the App menu. -->
      			<menuitem id="aboutName" label="About InTheBox" oncommand="nAbout();"/>
        		<menuitem id="menu_mac_services" label="Services"/>
        		<menuitem id="menu_mac_hide_app" label="Hide InTheBox" key="key_hideThisAppCmdMac"/>
        		<menuitem id="menu_mac_hide_others" label="Hide Others" key="key_hideOtherAppsCmdMac"/>
        		<menuitem id="menu_mac_show_all" label="Show All"/>
			</menupopup>
		</menu>
		<menu id="edit-menu" label="Edit">
			<menupopup id="edit-popup">
      <menuitem id="cut-menuitem" label="Cut" key="key_cut" oncommand="goDoCommand('cmd_cut');"/>
      <menuitem id="copy-menuitem" label="Copy" key="key_copy" oncommand="goDoCommand('cmd_copy');"/>
      <menuitem id="paste-menuitem" label="Paste" key="key_paste" oncommand="goDoCommand('cmd_paste');"/>
      <menuitem id="delete-menuitem" label="Delete" key="key_delete" oncommand="goDoCommand('cmd_delete');"/>
      <menuitem id="selectall-menuitem" label="Select All" key="key_selectAll" oncommand="goDoCommand('cmd_selectAll');"/>
			</menupopup>
		</menu>
		</menubar>
	</toolbox>
  <popupset>
    <popup id="main-popup">
      <menuitem id="cut-menuitem" label="Cut" key="key_cut" oncommand="goDoCommand('cmd_cut');"/>
      <menuitem id="copy-menuitem" label="Copy" key="key_copy" oncommand="goDoCommand('cmd_copy');"/>
      <menuitem id="paste-menuitem" label="Paste" key="key_paste" oncommand="goDoCommand('cmd_paste');"/>
      <menuitem id="delete-menuitem" label="Delete" key="key_delete" oncommand="goDoCommand('cmd_delete');"/>
      <menuitem id="selectall-menuitem" label="Select All" key="key_selectAll" oncommand="goDoCommand('cmd_selectAll');"/>
      <menuitem id="copylink-menuitem" label="Copy Link Location" oncommand="nCopyLink();"/>
    </popup>
  </popupset>
  <keyset id="editMenuKeys">
    <key id="key_undo" key="z" modifiers="accel" command="cmd_undo"/>
    <key id="key_redo" key="z" modifiers="accel,shift" command="cmd_redo"/>
    <key id="key_cut" key="x" modifiers="accel" command="cmd_cut"/>
    <key id="key_copy" key="c" modifiers="accel" command="cmd_copy"/>
    <key id="key_paste" key="v" modifiers="accel" command="cmd_paste"/>
    <key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/>
    <key id="key_selectAll" key="a" modifiers="accel" command="cmd_selectAll"/>
  </keyset>
  <commandset id="boxMenuKeys">
  	<command id="cmd_print" oncommand="PrintUtils.print();"/>
  </commandset>
  <keyset id="boxMenuKeys">
  	<key id="key_print" key="p" modifiers="accel" command="cmd_print"/>
  </keyset>
  <keyset id="navMenuKeys">
    <key id="key_back" class="nav" modifiers="accel" keycode="VK_LEFT" oncommand="nBack()"/>
    <key id="key_fwd" class="nav" modifiers="accel" keycode="VK_RIGHT" oncommand="nForward()"/>
    <key id="key_home" class="nav" modifiers="accel" keycode="VK_HOME" oncommand="nHome()"/>
    <key id="key_reload" class="nav" modifiers="accel" key="r" oncommand="nReload()"/>
    <key id="key_stop" class="nav" keycode="VK_ESCAPE" oncommand="nStop()"/>
    <key id="key_copyurl" class="nav" modifiers="shift,accel" key="u" oncommand="nCopyURL()"/>
	<key modifiers="accel" key="W" oncommand="window.close()"/>
  </keyset>
  <keyset id="baseMenuKeyset">
<!-- These are used to build the Application menu under Cocoa widgets. -->
        <key id="key_hideThisAppCmdMac"
             key="h"
             modifiers="accel"/>
        <key id="key_hideOtherAppsCmdMac"
             modifiers="accel,alt"/>
  </keyset>


        <browser id="browser" type="content-primary" src="" homepage="$url" context="main-popup" ${f2}flex="1"/>
		<statusbar>
			<statusbarpanel id   ="status"
                            label="Loading InTheBox..."
                            crop ="end"
                            flex ="1" />
			<progressmeter id    ="progress"
                           mode  ="determined"
                           value ="0%"
                           style ="display: none" />
			<statusbarpanel id   ="security"
                            label=""
                            style="display: none" />
		</statusbar>
</window>
EOF
$returncode = 0;
&dialogue("Created $gappname successfully!");
exit(0);

sub shell { foreach(split(/\n/, "@_")) { system($_); } }
sub file { ($name, $what)=(@_); open(W,">$name") || &dialogue("Failed to create $name: $!"); print W $what; close(W); }
sub dialogue {
	if ($cli) {
		warn("@_\n");
		exit($returncode);
	}
	open(O, "|/usr/bin/osascript") || (print "Can't open osascript; $!\n", exit);
	print O <<"EOF";
tell application "Dock"
	activate
	display dialog "@_" buttons ("OK") default button "OK"
	set answername to button returned of the result
end tell
EOF
	close(O);
	exit($returncode);
}
