#!/usr/bin/perl --
#
#  Set up Windows directories for Samba PCs in ~:
#    ~/Windows for configuration data which is accessed direct from the PC
#    # ~/My_Documents was for the user's visible files, accessed directly
#    # ~/.profiles was for the WinXP roaming profile which is copied at login/logout
#    ~/.profiles.V2 for the Win7 roaming profile which is copied at login/logout
#    ~/.profiles.V6 for the Win10 roaming profile which is copied at login/logout
#
#  For the moment the argument is /users/%g/%u/.profiles -- change that later
#  The argument is defined in smb.conf and is "wrong" at Win7 ... but does not matter.
#
#  With a second argument of --setup-only--no-run, only set up (Firefox?) files,
#  as used in /usr/sms/bin/firefox-refresh.
#  (Silly argument name, matching that in /usr/sms/bin/firefox.)


    ( $cmd = $0 ) =~ s!.*/!!;

eval
{

    ( $group, $user ) = $ARGV[0] =~ m!^/users/(.+?)/(.+?)/.profiles$!
	or die "Bad argument $ARGV[0]\n";

    -e "/usr/sms.$_" and $host = $_, last foreach qw( rome bianco newrome newbianco p639 );
    $host or die "Bad host (must be bianco or rome)\n";

    ## Undergrad group names are alpha followed by a single digit,
    ## thus e.g. mc2stuff or gen21 or st5 are NOT undergrads.
    #$is_undergrad = ( ( $host ne 'bianco' ) && ( $group =~ m!^[a-z]+[0-4]$! ) );
    # Undergrad usernames contain a digit: see also siv:/s/SMS/User.pm
    $is_undergrad = ( $user =~ m!\d! );

    # logmsg( "called for $user.$group" );

    umask 077;

    chdir "/users/$group/$user"
	or die "Could not chdir to /users/$group/$user\n";

    ( $group eq 'cap' || $user eq 'conf' || ! -w "/users/$group/$user" ) and exit;


    # Rarely we end up with ".profiles/Local Settings": sign that
    # profile is corrupted, or will be soon? Remove it.
    foreach(
      #'.profiles/Local Settings',
      '.profiles.V2/AppData/Local',
      '.profiles.V2/AppData/LocalLow',
      '.profiles.V6/AppData/Local',
      '.profiles.V6/AppData/LocalLow' )
    {
	if( -e $_ )
	{
	    logmsg( "Removing unwanted /users/$group/$user/$_" );
	    system( "rm", "-rf", $_ );
	}
    }

    # Rarely we end up with ".profiles/prf*.tmp" files (would be
    # NTUSER.DAT but not renamed yet)?
    foreach(
      #glob( ".profiles/prf*.tmp" ),
      #glob( ".profiles/*/prf*.tmp" ),
      glob( ".profiles.V2/prf*.tmp" ),
      glob( ".profiles.V2/*/prf*.tmp" ),
      glob( ".profiles.V6/prf*.tmp" ),
      glob( ".profiles.V6/*/prf*.tmp" ) )
    {
	unlink $_;
	logmsg( "Removed unwanted /users/$group/$user/$_" );
    }

    # Rarely we have ".profiles/ntuser.dat", rename to NTUSER.DAT for
    # uniformity (though at WinXP it seems the "default" is lowercase)
    foreach(
      #'.profiles',
      '.profiles.V2',
      '.profiles.V6' )
    {
	if( -e "$_/ntuser.dat" )
	{
	    if( -e "$_/NTUSER.DAT" )
	    {
		logmsg( "Both ntuser.dat and NTUSER.DAT in /users/$group/$user/$_" );
	    }
	    else
	    {
		logmsg( "Renaming /users/$group/$user/$_/ntuser.dat as NTUSER.DAT" );
		rename "$_/ntuser.dat", "$_/NTUSER.DAT";
	    }
	}
	# Same for "ntuser.dat.LOG". Funny that capitalization...
	if( -e "$_/ntuser.dat.LOG" )
	{
	    if( -e "$_/NTUSER.DAT.LOG" )
	    {
		logmsg( "Both ntuser.dat.LOG and NTUSER.DAT.LOG in /users/$group/$user/$_" );
	    }
	    else
	    {
		logmsg( "Renaming /users/$group/$user/$_/ntuser.dat.LOG as NTUSER.DAT.LOG" );
		rename "$_/ntuser.dat.LOG", "$_/NTUSER.DAT.LOG";
	    }
	}
    }

    # Is this a "good" profile worth saving?
    # Should we (also) check the existence of ntuser.ini?
    foreach(
      #'.profiles',
      '.profiles.V2',
      '.profiles.V6' )
    {
	if( ( -s "$_/NTUSER.DAT") > 256*1024 )
	{
	    if( $cmd =~ m/unset/ )
	    {
		# Only cleanup above, do nothing else for unset-profile at disconnect
	    }
	    elsif( defined($ARGV[1]) and $ARGV[1] eq '--setup-only--no-run' )
	    {
		# Do not save anything but only set up (Firefox?) files, below
	    }
	    else
	    {
		# This is "good", save it
		$MNTUSER = -M _;
		$Msaved = -M "$_-saved.tgz";
		if( $MNTUSER > 0 and $Msaved > 0 and $MNTUSER > $Msaved )
		{
		    #logmsg( "Not saving, /users/$group/$user/$_-saved.tgz newer than NTUSER.DAT" );
		}
		else
		{
		    #logmsg( "Saving to /users/$group/$user/$_-saved.tgz" );
		    # Do not save $_/Desktop: sometime too large. (Should be moved to ~/Windows instead.)
		    # Do not save $_/MyDocuments: sometimes large, and wrongly still in .profiles and .profiles.V2 .
		    # Do not save $_/ApplicationData: often large, and we do not really need.
		    # Names are Documents and AppData for Win7.
		    # Should not we save just NTUSER.DAT and maybe NTUSER.DAT.LOG ?
		    system( "tar zcf $_-saved.tgz --exclude=$_/Desktop --exclude='$_/My Documents' --exclude='$_/Documents' --exclude='$_/Application Data' --exclude='$_/AppData' --exclude='$_/Tracing' --exclude='$_/Dropbox*' $_ >/dev/null 2>/dev/null" );
		}
	    }
	}
	# Otherwise is there a good saved profile?
	elsif( ( -s "$_-saved.tgz" ) > 20*1024 and
	    0 == system( "gunzip -t $_-saved.tgz >/dev/null 2>/dev/null" ) )
	{
	    if( $cmd =~ m/unset/ )
	    {
		# Only cleanup above, do nothing else for unset-profile at disconnect
		logmsg( "Should restore /users/$group/$user/$_-saved.tgz" );
	    }
	    elsif( defined($ARGV[1]) and $ARGV[1] eq '--setup-only--no-run' )
	    {
		# Do not restore anything but only set up (Firefox?) files, below
	    }
	    else
	    {
		# Saved is good, restore it
		logmsg( "Restoring /users/$group/$user/$_-saved.tgz" );
		# Do not pre-remove: we did not save everything in $_ (see above).
		#system( "rm -rf $_" );
		# We used to have ">&- 2>&-" so as not to be bothered by bogus output;
		# but "tar zxf" does not seem to like that, would whinge
		# "gzip: stdout: Bad file descriptor" and fail. Instead use
		# ">/dev/null 2>/dev/null" (though "tar zcf" does not seem to mind).
		system( "tar zxf $_-saved.tgz $_ >/dev/null 2>/dev/null" );
	    }
	}
    }


    # Only cleanup above, do nothing else for unset-profile at disconnect
    $cmd =~ m/unset/ and exit;


    # Unlikely this would ever happen after our restore above...
    #
    #  Avoid problems with empty NTUSER.DAT file (left like that when
    #  logging out with disk quota exceeded): remove so default one
    #  can be created.
    #  With an empty NTUSER.DAT, the user would get the error message
    #
    #    Windows cannot load the locally stored profile. Contact your
    #    network administrator.
    #    DETAIL: the system has attempted to load or restore a file into
    #    the registry, but the specified file is not in a registry file
    #    format.
    #    ...
    #    Windows cannot load the profile and is logging you on with a
    #    temporary profile.
    #    Changes you make to this profile will be lost when you log off.
    #
    #  With a missing NTUSER.DAT, the user's profile is not copied in; at
    #  logout a default NTUSER.DAT and profile are written out; thus any
    #  customizations to the profile are lost.
    #  This also occurs for new users: the seeding of profiles does not
    #  work on first login. See profile-ok.sms below also.
    #
    #  Empty prefs.js files are (silently) picked up later.
    #
    #  Any way of alerting the user (e.g. WinPopup with smbclient)?
    #  Used to do this also when logging out, not only when logging in.
    #  Want to alert anyway? (Users would needlessly ask for backups.)
    foreach(
      #'.profiles/NTUSER.DAT',
      '.profiles.V2/NTUSER.DAT',
      '.profiles.V6/NTUSER.DAT' )
    {
	if( -f $_ and ! -s _ )
	{
	    unlink $_;
	    logmsg( "Removed empty /users/$group/$user/$_" );
	}
    }

    # Bad profiles often have NTUSER.DAT of exactly 256kB. Complain, but
    # not after very first login when we never yet had a good profile.
    foreach(
      #'.profiles',
      '.profiles.V2',
      '.profiles.V6' )
    {
	if( ( -s "$_/NTUSER.DAT") == 256*1024 and
	    ( -s "$_-saved.tgz" ) > 20*1024 )
	{
	    logmsg( "Should remove /users/$group/$user/$_/NTUSER.DAT of 262144 bytes" );
	}
    }


    #  On first login, we must make the .profiles directory.  Paul points out
    #  we also need to create some other directories, as if Windows does so it
    #  will use inappropriate permissions.
    #  2 Nov 2001 (PSz) With Samba 2.2.1a I cannot see a permissions problem,
    #    though we do not use any of
#   restrict acl with mask = yes
#   security mask = 0000
#   directory security mask = 0000
#   force security mode = 0600
#   force directory security mode = 0700
    #    nor even
#   inherit permissions = Yes
    #    in smb.conf, but have only
#   create mask               = 0600
#   directory mask            = 0700
#   force create mode         = 0600
#   force directory mode      = 0700

    #  Still we need to pre-create some directories, as Windows attempts to
    #  write files/dirs without creating the tree above. (In some cases it
    #  tries again and creates the tree, but we do not like samba to whinge.)

#    unless( $is_undergrad )
#    {
#      makedirs_from_path( ".profiles/$_" ) foreach
#	'Start Menu/Programs/Startup/',
#	'Start Menu/Programs/Accessories/System Tools/',
#	'Start Menu/Programs/Accessories/Entertainment/',
#	'Start Menu/Programs/Accessories/Accessibility/',
#	'Favorites/Media/',
#	'Favorites/Links/',
#	'Desktop/',
#	'Application Data/Adobe/Acrobat/WHAPI/',
#	'Application Data/Microsoft/Crypto/RSA/',
#	'Application Data/Microsoft/Excel/XLSTART/',
#	'Application Data/Microsoft/FrontPage/State',
#	'Application Data/Microsoft/Internet Explorer/',
#	'Application Data/Microsoft/Office/Recent/',
#	'Application Data/Microsoft/Protect/',
#	'Application Data/Microsoft/SystemCertificates/My/',
#	'Application Data/Microsoft/Word/STARTUP/',
#	'Application Data/Identities/',
#	'My Documents/My Pictures/';
#    }
    ##### What is it we need for Win7 and .profiles.V2, or Win10 and .profiles.V6 ?

    # Should have
    #   [HKEY_CURRENT_USER\Software\Adobe\Acrobat Reader\11.0\JSPrefs]
    #   "bEnableJS"=dword:00000000
    #   [HKEY_CURRENT_USER\Software\Adobe\Acrobat Reader\11.0\Originals]
    #   "bAllowOpenFile"=dword:00000000
    #   [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Adobe\Acrobat Reader\11.0\TrustManager]
    #   "bEnhancedSecurityStandalone"=dword:00000001
    #   "bEnhancedSecurityInBrowser"=dword:00000001
    #   "bDisableTrustedFolders"=dword:00000001
    #   "bDisableTrustedSites"=dword:00000001
    #   "bDisableOSTrustedSites"=dword:00000001
    #   "iProtectedView"=dword:00000002
    # set in Mike's policies.
    # I see the registry setting for "Enable External Streams", but
    # where is "Allow multimedia operations" (and are they dangerous)?
    # See:
    #   http://rome/u/psz/securepc.html#Acrobatx
    #   /usr/sms/bin/acroreadn
    #   http://www.adobe.com/devnet-docs/acrobatetk/tools/AppSec/index.html
    #   http://www.adobe.com/devnet-docs/acrobatetk/tools/PrefRef/Windows/index.html

    #makedirs_from_path( '.profiles/Application Data/Adobe/Acrobat/7.0/JavaScripts/glob.settings.js/' );

    if( $is_undergrad )
    {
      # Mike will make Word user templates be written there for students
      makedirs_from_path( "Windows/.office/" );
    }

    if( $host eq 'bianco' )
    {
      # Mike want this for admin users
      makedirs_from_path( "Windows/Lotus/Backups/" );
    }


    # No longer needed, surely...
    ##  For proper permissions
    #makedirs_from_path( 'My_Documents/My_Pictures/' );

    if( $host eq 'bianco' )
    {
	# Do we need still?
	#  Set up Admin database reports files
	makedirs_from_path( "My_Documents/db/reports/$_/" )
	    foreach qw( staff );
    }


    foreach(
      #'.profiles/Start Menu/Programs/Startup/desktop.ini',
      #'.profiles/Start Menu/Programs/Startup/Desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Internet Explorer/Quick Launch/User Pinned/TaskBar/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Internet Explorer/Quick Launch/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Libraries/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Recent/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/SendTo/Desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Accessories/Accessibility/Desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Accessories/Desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Accessories/System Tools/Desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Administrative Tools/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Maintenance/Desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/desktop.ini',
      '.profiles.V2/AppData/Roaming/Microsoft/Windows/Start Menu/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Internet Explorer/Quick Launch/User Pinned/TaskBar/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Internet Explorer/Quick Launch/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Libraries/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Recent/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/SendTo/Desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Accessories/Accessibility/Desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Accessories/Desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Accessories/System Tools/Desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Administrative Tools/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Maintenance/Desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/desktop.ini',
      '.profiles.V6/AppData/Roaming/Microsoft/Windows/Start Menu/desktop.ini',
      'Windows/Contacts/desktop.ini',
      'Windows/Desktop/desktop.ini',
      'Windows/Documents/desktop.ini',
      'Windows/Downloads/desktop.ini',
      'Windows/Favorites/desktop.ini',
      'Windows/Links/desktop.ini',
      'Windows/Music/desktop.ini',
      'Windows/Pictures/desktop.ini',
      'Windows/Saved Games/desktop.ini',
      'Windows/Searches/desktop.ini',
      'Windows/Videos/desktop.ini' )
    {
	if( -f $_ )
	{
	    unlink $_;
	    logmsg( "Removed annoying /users/$group/$user/$_" );
	}
    }


    #  Flag so we (i.e. Mike's login scripts) can recognize when
    #  the seeding of the profiles did not work.
    #provide_file( '.profiles/profile-ok.sms', '' );
    # More useful than just an empty flag file:
    # store disk quota info there, so can maybe parse later.
    # May be unable to write contents when over quota...
    #system( "/usr/sms/bin/quota -v >.profiles/profile-ok.sms 2>&1" );
    #system( "cp .profiles/profile-ok.sms .profiles.V2/profile-ok.sms 2>&1" );
    system( "/usr/sms/bin/quota -v >.profiles.V2/profile-ok.sms 2>&1" );
    #system( "/usr/sms/bin/quota -v >.profiles.V6/profile-ok.sms 2>&1" );
    system( "cp .profiles.V2/profile-ok.sms .profiles.V6/profile-ok.sms 2>&1" );


    if( -f '.profiles.V2/NTUSER.DAT' )
    {
	# This is a Win7 user.

	# For new Win7 users, move things from WinXP to new places.
	# Directories ~/Windows/DIR used for Windows7 => previous WinXP objects
	# Noting that Documents may be created before others and we may have
	# already moved those things.
	# For some directories, I do not know where WinXP may have kept similar
	# objects; we just ignore those, could instead comment them out here.
	%W7DIRS = (
		Contacts	=> '.profiles/Contacts/*',
		Desktop		=> '.profiles/Desktop/*',
		Documents	=> 'My_Documents/* .profiles/My?Documents/*',
		Downloads	=> 'My_Documents/Downloads/* .profiles/My?Documents/Downloads/* Windows/Documents/Downloads/*',
		Favorites	=> '.profiles/Favorites/*',
		Links		=> '',
		Music		=> 'My_Documents/My?Music/* .profiles/My?Documents/My?Music/* Windows/Documents/My?Music/*',
		Pictures	=> 'My_Documents/My?Pictures/* .profiles/My?Documents/My?Pictures/* Windows/Documents/My?Pictures/*',
		'Saved Games'	=> '',
		Searches	=> '',
		Videos		=> 'My_Documents/My?Videos/* .profiles/My?Documents/My?Videos/* Windows/Documents/My?Videos/*',
	);
	$W7MISS = '';
	foreach $DIR ( keys( %W7DIRS ) ) {
		$OLD = $W7DIRS{$DIR};
		$DIR or next;
		$OLD or next;
		$DIR = "Windows/$DIR";
		-d "$DIR" or $W7MISS .= " $DIR", next;	# Directory not in place
		-f "$DIR/.from_WinXP" and next;		# Moves done already
		system "( date; echo 'When $DIR contains:'; ls -al $DIR; echo 'doing: mv $OLD $DIR/'; echo; mv -n -v $OLD $DIR/; ) </dev/null >$DIR/.from_WinXP 2>&1";
	}

	$W7MISS and logmsg( "Some directories missing from /users/$group/$user:$W7MISS" );
	# Might be tempted to remove (or not put in place) profile-ok.sms
	# when directories are missing: but if we do not let Windows "live"
	# for a while then those directories never get created...
    }

#    if( -f '.profiles.V6/NTUSER.DAT' )
#    {
#	# This is a Win10 user.
#	# No need to do anything:
#	# - the Win7 places are fine (shared correctly with Win7?)
#	# - no users go from WinXP to Win10 without having been to Win7.
#    }


    #  For Firefox 1.5.X ... 8.0.X

    #  Might do even without installing (Thunderbird also?), see
    #    http://lists.grok.org.uk/pipermail/full-disclosure/2004-November/028772.html
    #  :
    #  >> Can the Firefox settings be controlled centrally?
    #  > ... Download Firefox 1.0.zip, unpack it to R/O share on file server,
    #  > edit JS configuration files in .\defaults\pref and .\greprefs, then
    #  > create a shortcut to firefox.exe on user desktops. To change FF
    #  > settings, edit JS configs again. Voila!

    #  Run  L:\win\sfwinst\DataOnly\FirefoxSetup-3.0.X.exe  and do:
    #    accept licence,
    #    Standard install (or Custom without "Quality Feedback Agent"?)
    #    in C:\Program Files\Mozilla Firefox.
    #  Start firefox (as admin), as that still creates a few things.

    #  User might want to copy his latest bookmarks file e.g.
    #    ~/Windows/.netscape7/bookmarks.html
    #  to
    #    ~/Windows/.firefox/
    #  at any time (but not while firefox is running).

    #  There is some slowness on first use of FF ...
    #  and two tabs at upgrade or version change ...

    # FF3 uses not bookmarks.html but places.sqlite, and does the automatic
    # translation or seeding only if there is no inaccessible bookmarkbackups
    # object. Use urlclassifierkey3.txt as a flag whether we need this.

    # In Jan2024, Firefox no longer works for eseneta or psz, starts but says
    # "Firefox is not responding".
    # Updated Firefox... which then had difficulties with the profiles,
    # trying to create new ones in  .../AppData/Roaming/Mozilla/Firefox/,
    # file installs.ini and changed profiles.ini and new directory in Profiles.
    # Sanity for profiles seems restored with (both):
    #  - Environment variable MOZ_LEGACY_PROFILES=1 set in
    #    Control Panel
    #    System and Security
    #    System
    #    Advanced System Settings
    #    Advanced
    #    Environment Variable
    #    System variables
    #  - Registry setting
    #    HKLM\SOFTWARE\Policies\Mozilla\Firefox\LegacyProfiles=1 (dword)
    # but still, Firefox starts and says "not responding".


    foreach(
      #'.profiles/Application Data/Mozilla/Firefox/profiles.ini',
      '.profiles.V2/AppData/Roaming/Mozilla/Firefox/profiles.ini',
      '.profiles.V6/AppData/Roaming/Mozilla/Firefox/profiles.ini' )
    {
	# Be kind to people who may have changed their profile (Dmitry Badziahin only?)
	$ini = ''; open F, "<$_" and ( $ini = join( '', <F> ), close F ) and $ini =~ m/Path=C:/ and not $ini =~ m/Path=C:[\/\\]+Users[\/\\]+/ and next;
$user eq 'dzmitry' and logmsg( "Skipping dzmitry $_ = $ini"), next;

	provide_file( $_, <<EO );
[General]
StartWithLastProfile=1

[Profile0]
Name=default
IsRelative=0
Path=H:\\Windows\\.firefox

EO
    }

    $FFdir = 'Windows/.firefox';
    $FFprefs = "$FFdir/prefs.js";
    $FFbookmark = "$FFdir/bookmarks.html";
    $FFhomepage = 'http://www.maths.usyd.edu.au/local.html';
    #$FFhomepage= 'http://www.maths.usyd.edu.au/s/classpage' if $is_undergrad;
    # Noting that undergrads or kiosk do not use Windows...
    $FFhomepage	= 'http://www.maths.usyd.edu.au/u/UG/' if $is_undergrad;
    $FFhomepage	= 'http://www.maths.usyd.edu.au/MATH2067/DE/' if $is_undergrad and -f '/usr/sms.host/sbin/myUOS' and `/usr/sms.host/sbin/myUOS` =~ m/MATH2067/;
    $FFhomepage	= 'http://www.maths.usyd.edu.au/u/x0kiosk/loc/kiosk/' if $VAL{ USER } eq 'x0kiosk';

    # Sometimes FF "loses" the prefs file. Is there an older copy
    # (that FF itself regularly saves)?
    # We simply go by size; on 17 Sep 07 all current "active" prefs.js
    # are over 1800 bytes, defaults (as set by us) are 1678 bytes.
    if( ( -s $FFprefs ) < 1500 )
    {
	$FFbak = '';
	$M = 35600;	# Hundred years old
	# Pick out last-modified suitable one
	foreach( glob( "$FFdir/prefs*.js" ) )
	{
	    # Must be named prefs-1.js or prefs-N.js or prefs.js.bak
	    next unless m/\/prefs-\d+\.js$/ or m/\/prefs\.js\.bak$/;
	    # Must exist (but surely ...)
	    next unless -f $_;
	    # Must be suitably sized
	    next unless ( -s _ ) > 1500;
	    # Must be newer than we had already
	    next unless ( -M _ ) < $M;
	    $M = ( -M _ );
	    $FFbak = $_;
	}
	if( $FFbak )
	{
	    logmsg( "Restoring /users/$group/$user/$FFbak" );
	    system( "cp", $FFbak, $FFprefs );
	}
    }

    #  Generate FF preferences (but not bookmarks) based on NS7.

    #  Could check if NS7 settings are newer, and re-create.
    #  Not really needed: we have "static" FF preferences; user can
    #  easily copy his latest bookmarks file.
#    if( -f $FFprefs )
#    {
#	$M = -M _;
#	if( -f $NS7prefs and $M > -M _ )
#	{
#	    # logmsg( "/users/$group/$user/$FFprefs is older than $NS7prefs" );
#	    #  The FF file is older than the NS7 one:
#	    #  is unused yet, the default we gave some time ago?
#	    eval
#	    {
#		opendir D, $FFdir or die "Cannot opendir $FFdir\n";
#		while( $_ = readdir D )
#		{
#		    m/^(\.|\.\.|Cache|Cache\.Trash|XUL.mfl|compreg.dat|compreg.dat.tmp|prefs.js|bookmarks\.html)$/ or
#			die "Unexpected file $_ in $FFdir\n";
#		}
#		closedir D or die "Cannot closedir $FFdir\n";
#	    };
#	    unless( $@ )
#	    {
#		logmsg( "Removing unused /users/$group/$user/$FFprefs ($NS7prefs is newer)" );
#		unlink $FFprefs;
#		#  Test newness of bookmarks?
#		#  Or is it "cheaper" to recreate anyway?
#		unlink $FFbookmark;
#	    }
#	}
#    }

    unless( -f $FFprefs && -s _ )
    {
	setup_VAL();

	##  Tempting to copy NS7 preferences, but do not want to keep
	##  directory settings. Do afresh, from scratch.
#	#  Keep NS7 preferences.
#	#  Some (mail, news etc) lines are not needed/used by FF: strip them out?
#	open F, $NS7prefs and (
#	  $prefs = join( '', <F> ),
#	  close F or die "Cannot close $NS7prefs (to copy to $FFprefs)\n"
#	);
#	$prefs .= <<EO;
#user_pref("app.update.autoUpdateEnabled", false);
#user_pref("extensions.update.autoUpdateEnabled", false);
#EO

	$prefs = <<EO;
# Non-JS comment
user_pref("app.update.auto", false);
user_pref("app.update.autoUpdateEnabled", false);
user_pref("app.update.enabled", false);
//user_pref("app.update.lastUpdateTime.addon-background-update-timer", 1234);
//user_pref("app.update.lastUpdateTime.background-update-timer", 1234);
//user_pref("app.update.lastUpdateTime.blocklist-background-update-timer", 1234);
//user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1234);
// At FF2.0 after an "update" we get an extra tab (with $FFhomepage) even with silent
//user_pref("app.update.silent", true);
user_pref("app.update.url", "");
user_pref("app.update.url.details", "");
user_pref("app.update.url.manual", "");
user_pref("browser.cache.disk.enable", false);
// Using browser.cache.disk.capacity=1 may allow firefox to clean up (when already higher)
user_pref("browser.cache.disk.capacity", 1);
user_pref("browser.cache.offline.enable", false);
user_pref("browser.cache.offline.capacity", 1);
user_pref("browser.download.dir", "C:\\\\Temp");
user_pref("browser.download.folderList", 2);
user_pref("browser.download.manager.closeWhenDone", true);
user_pref("browser.download.manager.retention", 0);
user_pref("browser.download.useDownloadDir", false);
user_pref("browser.formfill.enable", false);
user_pref("browser.link.open_external", 3);
// see http://forums.mozillazine.org/viewtopic.php?t=2495321
// see http://forums.mozillazine.org/viewtopic.php?t=2569439
user_pref("browser.pagethumbnails.capturing_disabled", true);
//user_pref("browser.preferences.lastpanel", 0);
//user_pref("browser.search.selectedEngine", "Google");
user_pref("browser.search.update", false);
// Could avoid annoying 'set as default?' question... but we want to be set
//user_pref("browser.shell.checkDefaultBrowser", false);
// Dialog about "save tabs" when quitting: was default true up until FF3, and may have been called browser.warnOnQuit
//user_pref("browser.showQuitWarning", true);
user_pref("browser.startup.homepage", "$FFhomepage");
user_pref("browser.startup.homepage_override.mstone", "ignore");
user_pref("browser.tabs.loadInBackground", false);
user_pref("browser.tabs.closeButtons", 3);
user_pref("browser.urlbar.hideGoButton", true);
user_pref("dom.disable_window_flip", true);
user_pref("dom.disable_window_move_resize", true);
user_pref("dom.event.contextmenu.enabled", false);
// For PDF.js, see psz email 31 Oct 2016
user_pref("browser.tabs.remote.autostart.2", false);
user_pref("e10s.rollout.cohort", "optedOut");
//user_pref("extensions.e10sBlockedByAddons", true);
//user_pref("extensions.e10sBlocksEnabling", true);
//user_pref("browser.tabs.remote.autostart", false);
//user_pref("extensions.lastAppVersion", "5.0");
user_pref("extensions.update.autoUpdateEnabled", false);
user_pref("extensions.update.enabled", false);
//user_pref("extensions.update.notifyUser", false);
user_pref("extensions.update.url", "");
// FF38 might be slow with Win7, needs proper graphics driver or to DisableHardwareAcceleration (both direct2d and acceleration)?
//user_pref("gfx.direct2d.disabled", true);
//user_pref("layers.acceleration.disabled", true);
// Protect against downloadable fonts: should be solved with http://technet.microsoft.com/security/advisory/2639658 workaround
//user_pref("gfx.downloadable_fonts.enabled", false);
//user_pref("intl.charsetmenu.browser.cache", "ISO-8859-1");
// Disable media autoplay, on a Yterm the video on http://sydney.edu.au would
// saturate the network and make it unresponsive: may not matter on a PC.
user_pref("media.autoplay.enabled", false);
user_pref("network.cookie.lifetimePolicy", 2);
//user_pref("network.cookie.prefsMigrated", true);
user_pref("network.enableIDN", false);
//user_pref("network.image.imageBehavior", 2);
// see http://isc.sans.edu/forums/diary/14089
user_pref("network.http.spdy.enabled", false);
user_pref("network.http.spdy.enabled.v2", false);
// see http://www.mozilla.org/projects/netlib/Link_Prefetching_FAQ.html
user_pref("network.prefetch-next", false);
user_pref("network.proxy.autoconfig_url", "http://siv/proxy.pac");
user_pref("network.proxy.type", 4);
user_pref("print.postscript.paper_size", "A4");
//user_pref("security.OCSP.URL", "");
//user_pref("security.OCSP.signingCA", "Builtin Object Token:IPS CLASE1 root");
user_pref("security.enable_java", false);
// See http://www.mozilla.org/security/announce/2007/mfsa2007-06.html
user_pref("security.enable_ssl2", false);
// Avoid annoyance
user_pref("security.warn_entering_secure", false);
user_pref("security.warn_leaving_secure", false);
user_pref("security.warn_submit_insecure", false);
user_pref("startup.homepage_override_url", "$FFhomepage");
user_pref("signon.rememberSignons", false);
// Avoid slowness, see RT#7982
user_pref("urlclassifier.gethash.timeout_ms", 1);
user_pref("xpinstall.enabled", false);
// See https://bugzilla.mozilla.org/show_bug.cgi?id=370445#c2
user_pref("capability.policy.default.Location.hostname.set", "noAccess");
// See https://bugzilla.mozilla.org/show_bug.cgi?id=370555#c15
user_pref("dom.disable_window_open_feature.location", true);
// See http://isc.sans.edu/diary.html?date=2011-05-11
// or  http://isc.sans.edu/forums/diary/Time+to+disable+WebGL+/10867
user_pref("webgl.disabled", true);
EO

	provide_file( $FFprefs, $prefs );

## Do not bother with bookmarks file: the defaults below are old/obsolete.
#	unless( -f $FFbookmark && -s _ )
#	{
#	    #$bookmark = '';
#	    ##  Use NS7 bookmarks if we can; otherwise use default.
#	    #open F, $NS7bookmark and (
#	    #  $bookmark = join( '', <F> ),
#	    #  close F or die "Cannot close $NS7bookmark (to copy to $FFbookmark)\n"
#	    #);
#	    #$bookmark or $bookmark = <<EO;
#	    $bookmark = <<EO;
#<!DOCTYPE NETSCAPE-Bookmark-file-1>
#<!-- This is an automatically generated file.
#It will be read and overwritten.
#Do Not Edit! -->
#<TITLE>Bookmarks</TITLE>
#<H1>Bookmarks</H1>
#
#<DL><p>
#    <DT><H3 ADD_DATE="$VAL{NOW}" PERSONAL_TOOLBAR_FOLDER="true">Personal Toolbar Folder</H3>
#    <DL><p>
#        <DT><H3 ADD_DATE="$VAL{NOW}">School</H3>
#        <DL><p>
#            <DT><A HREF="http://www.maths.usyd.edu.au/SMSsearch.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">SMSsearch</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/scnews.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">scnews</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/s/sccal" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">calendar</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/s/members" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">scwho</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/Research.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">Research</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/Teaching.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">Teaching</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/w/loc/" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">Administration</A>
#            <DT><A HREF="http://www.maths.usyd.edu.au/loc/comp/alpha/alpha.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">Digital Alpha</A>
#        </DL><p>
#        <DT><H3 ADD_DATE="$VAL{NOW}">Usyd</H3>
#        <DL><p>
#            <DT><A HREF="http://sydney.edu.au/" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">University of Sydney</A>
#            <DT><A HREF="http://search.usyd.edu.au/" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">University of Sydney Search</A>
#            <DT><A HREF="http://intranet.usyd.edu.au/staff/people.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">Electronic Phone Book</A>
#            <DT><A HREF="http://opac.library.usyd.edu.au/screens/opacmenu.html" ADD_DATE="$VAL{NOW}" LAST_VISIT="0" LAST_MODIFIED="0">Library catalogue search</A>
#        </DL><p>
#    </DL><p>
#EO
#
#	    provide_file( $FFbookmark, $bookmark );
#	}

    }

    if( $is_undergrad )
    {
	#  Undergraduates don't need https (except for MyUni) so don't get
	#  certificates. Others may need this ...
	unlink "$FFdir/cert8.db";
    }

    #  Be double-safe even with browser.cache.disk.capacity set to 0
    foreach(
      "$FFdir/Cache",
      "$FFdir/Cache.Trash",
      "$FFdir/OfflineCache",
      "$FFdir/XPC.mfasl",
      "$FFdir/XPC.mfl",
      "$FFdir/XUL.mfasl",
      "$FFdir/XUL.mfl",
      "$FFdir/compreg.dat",
      "$FFdir/compreg.dat.tmp",
      "$FFdir/datareporting",
      "$FFdir/minidumps",
      "$FFdir/saved-telemetry-pings",
      "$FFdir/startupCache",
     #"$FFdir/storage",			# at FF70, prevents Office365 and similar
      "$FFdir/thumbnails",
      "$FFdir/urlclassifier2.sqlite",
     #"$FFdir/urlclassifier3.sqlite",	# FF12 tries and times out and slows down, cannot cope without
    )
    {
	make_empty0file( $_ );
    }
    foreach(
      "$FFdir/urlclassifier3.sqlite",	# Checked from FF15 only: (would clobber symlink to /dev/null,) can handle empty dir (with whatever permissions)
    )
    {
	make_empty0dir( $_ );
    }
    # FF3 uses not bookmarks.html but places.sqlite, and does the automatic
    # translation or seeding only if there is no inaccessible bookmarkbackups
    # object. Use urlclassifierkey3.txt as a flag whether we need this.
    if( -e "$FFdir/urlclassifierkey3.txt" )
    {
	make_empty0file( "$FFdir/bookmarkbackups" );
    }
    else
    {
	# Remove a file, leave a directory alone
	unlink "$FFdir/bookmarkbackups";
    }


    #  For Thunderbird 1.5.X ... 8.0.X

    #  Run  L:\win\sfwinst\DataOnly\ThunderbirdSetup-2.0.X.exe  and do:
    #    accept licence,
    #    Standard install (or Custom without "Quality Feedback Agent"?)
    #    in C:\Program Files\Mozilla Thunderbird.
    #  Start thunderbird (as admin), as that still creates a few things.

    #  User should start thunderbird (to create mail directory structure),
    #  then quit. Copy mail files and address books e.g.
    #    ~/Windows/.netscape7/Mail/rome/Inbox
    #    ~/Windows/.netscape7/abook.mab
    #  to
    #    ~/Windows/.thunderbird/Mail/rome/
    #    ~/Windows/.thunderbird/
    #  respectively. (*.summary or *.msf files should not be copied; the
    #  TB *.msf files could be dropped to ensure they are re-created.)
    #  If you have more than just the one abook.mab, then in thunderbird
    #  pre-create new, empty ones named abook-N.mab with
    #    address book, file, new, address book
    #  then copy them on top.
    #  For NS4 users, the mail files e.g.
    #    ~/Windows/.netscape/mail/Inbox
    #  can be copied as above. But thunderbird does not understand the
    #  ~/Windows/.netscape/pab.na2 files: use NS7 to import and convert
    #  to *.mab format.
    #  When starting from UNIX NS4, the ~/nsmail/Inbox files will need
    #  to get DOS-like line termination e.g. with
    #    perl -i.bak -pe 's/\r/$/' Inbox Outbox
    #  while it seems that the UNIX ~/.netscape/pab.na2 address book cannot
    #  be "fed" to Windows NS7 to convert to abook.mab format.

    foreach(
      #'.profiles/Application Data/Thunderbird/profiles.ini',
      '.profiles.V2/AppData/Roaming/Thunderbird/profiles.ini',
      '.profiles.V6/AppData/Roaming/Thunderbird/profiles.ini' )
    {
	# Be kind to people who may have changed their profile (Dmitry Badziahin only?)
	$ini = ''; open F, "<$_" and ( $ini = join( '', <F> ), close F ) and $ini =~ m/Path=C:/ and not $ini =~ m/Path=C:[\/\\]+Users[\/\\]+/ and next;
$user eq 'dzmitry' and logmsg( "Skipping dzmitry $_ = $ini"), next;

	provide_file( $_, <<EO );
[General]
StartWithLastProfile=1

[Profile0]
Name=default
IsRelative=0
Path=H:\\Windows\\.thunderbird

EO
    }

    $TBdir = 'Windows/.thunderbird';
    $TBprefs = "$TBdir/prefs.js";
    #$TBaddrbook = "$TBdir/abook.mab";	# Not seeded

    #  Generate TB preferences and addressbook based on NS7.

    #  Could check if NS7 settings are newer, and re-create.
    #  Not really needed: we have "static" TB preferences; user will
    #  need to copy latest Inbox file, might as well do abook.mab also.
#    if( -f $TBprefs )
#    {
#	$M = -M _;
#	if( -f $NS7prefs and $M > -M _ )
#	{
#	    # logmsg( "/users/$group/$user/$TBprefs is older than $NS7prefs" );
#	    #  The TB file is older than the NS7 one:
#	    #  is unused yet, the default we gave some time ago?
#	    eval
#	    {
#		opendir D, $TBdir or die "Cannot opendir $TBdir\n";
#		while( $_ = readdir D )
#		{
#		    m/^(\.|\.\.|XUL.mfl|compreg.dat|compreg.dat.tmp|prefs.js)$/ or
#			die "Unexpected file $_ in $TBdir\n";
#		}
#		closedir D or die "Cannot closedir $TBdir\n";
#	    };
#	    unless( $@ )
#	    {
#		logmsg( "Removing unused /users/$group/$user/$TBprefs ($NS7prefs is newer)" );
#		unlink $TBprefs;
#		unlink $TBaddrbook;
#	    }
#	}
#    }

    unless( -f $TBprefs && -s _ )
    {
	setup_VAL();

	##  Tempting to copy NS7 preferences, but do not want to keep
	##  directory settings. Do afresh, from scratch.
#	#  Keep NS7 preferences.
#	#  Only mail lines are needed/used by TB: strip others out?
#	open F, $NS7prefs and (
#	  $prefs = join( '', <F> ),
#	  close F or die "Cannot close $NS7prefs (to copy to $TBprefs)\n"
#	);
#	$prefs .= <<EO;
#user_pref("app.update.autoUpdateEnabled", false);
#user_pref("extensions.update.autoUpdateEnabled", false);
#EO

	$prefs = <<EO;
# Non-JS comment
user_pref("app.update.auto", false);
user_pref("app.update.autoUpdateEnabled", false);
user_pref("app.update.enabled", false);
user_pref("browser.cache.disk.enable", false);
// Using browser.cache.disk.capacity=1 may allow thunderbird to clean up (when already higher)
user_pref("browser.cache.disk.capacity", 1);
user_pref("browser.download.dir", "C:\\\\Temp");
user_pref("browser.download.folderList", 2);
user_pref("extensions.update.autoUpdateEnabled", false);
////### Not useful with @sydney accounts
//user_pref("mail.account.account1.identities", "id1");
//user_pref("mail.account.account1.server", "server1");
//user_pref("mail.accountmanager.accounts", "account1");
//user_pref("mail.identity.default.autocompleteToMyDomain", true);
//user_pref("mail.identity.id1.compose_html", false);
//user_pref("mail.identity.id1.draft_folder", "mailbox://$VAL{USER}\@$host/Drafts");
//user_pref("mail.identity.id1.fcc_folder", "mailbox://$VAL{USER}\@$host/Sent");
//user_pref("mail.identity.id1.fullName", "$VAL{FULLNAME}");
//user_pref("mail.identity.id1.organization", "Maths & Stats, Uni of Sydney");
//user_pref("mail.identity.id1.smtpServer", "smtp1");
//user_pref("mail.identity.id1.stationery_folder", "mailbox://$VAL{USER}\@$host/Templates");
//user_pref("mail.identity.id1.useremail", "$VAL{USER}\@maths.usyd.edu.au");
//user_pref("mail.identity.id1.valid", true);
////user_pref("mail.server.server1.download_on_biff", true);
//user_pref("mail.server.server1.empty_trash_on_exit", true);
//user_pref("mail.server.server1.hostname", "$host");
////user_pref("mail.server.server1.login_at_startup", true);
//user_pref("mail.server.server1.name", "$VAL{USER} = $VAL{FULLNAME}");
//user_pref("mail.server.server1.type", "pop3");
//user_pref("mail.server.server1.userName", "$VAL{USER}");
//user_pref("mail.showCondensedAddresses", false);
//user_pref("mail.smtp.defaultserver", "smtp1");
//user_pref("mail.smtpserver.smtp1.auth_method", 0);
//user_pref("mail.smtpserver.smtp1.hostname", "mh");
////user_pref("mail.smtpserver.smtp1.port", 25);
////user_pref("mail.smtpserver.smtp1.try_ssl", 0);
////user_pref("mail.smtpserver.smtp1.username", "$VAL{USER}");
////user_pref("mail.smtpserver.smtp1.username", "");
//user_pref("mail.smtpservers", "smtp1");
////user_pref("mail.startup.enabledMailCheckOnce", true);
//user_pref("mailnews.message_display.disable_remote_images.useWhitelist", false);
//user_pref("mailnews.start_page.enabled", false);
////###
user_pref("mailnews.wraplength", 0);
user_pref("network.proxy.autoconfig_url", "http://siv/proxy.pac");
user_pref("network.proxy.type", 2);
user_pref("print.postscript.paper_size", "A4");
user_pref("mail.prompt_purge_threshhold", true);
user_pref("mail.purge_threshhold", 200);
user_pref("mail.purge_threshhold_mb", 1);
user_pref("mail.purge.ask", false);
user_pref("mail.content_disposition_type", 1);
EO

	provide_file( $TBprefs, $prefs );

	#unless( -f $TBaddrbook && -s _ )
	#{
	#    $addrbook = '';
	#    #  Use NS7 address book if we can; otherwise use nothing.
	#    #  (Thunderbird does not understand NS4 pab.na2 files: use
	#    #   NS7 to convert to abook.mab format.)
	#    open F, $NS7addrbook and (
	#      $addrbook = join( '', <F> ),
	#      close F or die "Cannot close $NS7addrbook (to copy to $TBaddrbook)\n"
	#    );
	#    $addrbook and provide_file( $TBaddrbook, $addrbook );
	#}

    }
    else
    {
	# There is $TBprefs file already: check/set auth_method=0
	# See /usr/sms/bin/thunderbird and RT ticket #4403 also
	# Is the problem that:
	#   with mail.smtpserver.smtp1.username set, thunderbird always tried a login;
	#   up until etch, rome did not know how to handle usernames and accepted;
	#   but since lenny, rome sendmail complains
	# Dec 22 18:48:27 rome sm-mta[6666]: unable to open Berkeley db /etc/sasldb2: No such file or directory
	#   and fails.
	# We should never have set smtp1.username ...
	#
	# Rome sendmail was allowing/offering AUTH, as seen by:
	#   psz@bari:~$ /usr/bin/telnet rome 25
	# (and saying "ehlo x" then quit).
	# I have now removed Debian package libsasl2-modules with:
	#   root@rome:~# apt-get remove libsasl2-modules
	# and restarted sendmail, and now rome does not offer AUTH anymore.
	# Package libsasl2-modules was installed on rome only (nowhere else). I do
	# not know what else it might have been used for (or why it was on rome).
	#
	# Another way of "stopping" AUTH seems to be to add the line
	#   SRV_Features: A
	# to file /etc/mail/access , see
	# http://www.sendmail.org/documentation/installGuide
	# http://www.sendmail.org/doc/sendmail-current/doc/op/op.pdf
	$pref = '';
	open F, "<$TBprefs" and (
		$pref = join( '', <F> ),
		close F
	);
	$repl = 0;
# BEWARE: some people use multiple smtp servers, or other than mh ...
	if( $pref and $pref !~ m/\"mail.smtpserver.smtp\d.hostname\",\s*\"(?!mh\")/ ) {
		$pref =~ s/(\"mail.smtpserver.smtp1.auth_method\",)\s*[1-9]\d*/$1 0/ and $repl = 1;
		$pref !~ m/auth_method/ and $pref .= "user_pref(\"mail.smtpserver.smtp1.auth_method\", 0);\n" and $repl = 1;
		$pref =~ s/^(user_pref\(\"mail.smtpserver.smtp1.username\",\s*\"\w+\"\);\s*)$/\/\/$1/m and $repl = 1;
	}
	if( $repl ) {
		-e "$TBprefs.pre-auth" or system( "cp", $TBprefs, "$TBprefs.pre-auth" );
		provide_file( $TBprefs, $pref );
	}
    }

    if( $is_undergrad )
    {
	#  Undergraduates don't need https (except for MyUni) so don't get
	#  certificates. Others may need this ...
	unlink "$TBdir/cert8.db";
    }

    #  Be double-safe even with browser.cache.disk.capacity set to 0
    #  and nglayout.debug.disable_xul_cache set to true.
    foreach(
     #"$TBdir/Cache",	# Can we do like for firefox?
     #"$TBdir/Cache.msf",
     #"$TBdir/Cache.sdb",
      "$TBdir/XPC.mfasl",
      "$TBdir/XPC.mfl",
      "$TBdir/XUL.mfasl",
      "$TBdir/XUL.mfl",
      "$TBdir/compreg.dat",
      "$TBdir/compreg.dat.tmp" )
     #"$TBdir/startupCache",
     #"$TBdir/startupCache.msf",
     #"$TBdir/thumbnails",
     #"$TBdir/urlclassifier2.sqlite",
     #"$TBdir/urlclassifier3.sqlite",	# FF12 tries and times out and slows down, cannot cope without
    {
	make_empty0file( $_ );
    }
    #foreach(
    #  "$TBdir/urlclassifier3.sqlite",	# Checked from FF15 only: (would clobber symlink to /dev/null,) can handle empty dir (with whatever permissions)
    #)
    #{
    #	make_empty0dir( $_ );
    #}


};

    if( $err = $@ )
    {
##	unless ($group eq 'cap' and $err =~ /^Could not open .* \(permission denied\)$/) {
	    logmsg( "died for $user.$group: $err" );
##	}
	die $err;
    }

##

sub makedirs_from_path
{
    my ( $path ) = @_;

    #  Recursively make directories under the mount point required for $path,
    #  which may be a file path (the file component is irrevelant) or a
    #  directory path ending in /.

    $path =~ s!^(.+)/[^/]*$!$1! and	# remove file component or trailing /
    ! -d $path and			# stop if directory already exists
        makedirs_from_path( $path ),	# make the ancestor directories
	mkdir( $path, 0700 ) ||		# make the bottom directory
            die "makedirs_from_path: cannot mkdir $path (\l$!)\n";
}

sub provide_file
{
    my ( $file, $cont ) = @_;

    makedirs_from_path( $file );

    open( F, ">$file" ) or die "Could not open $file (\l$!)\n";
    $cont =~ s!\r?\n!\r\n!g;
    print F $cont or die "Could not print $file (\l$!)\n";
    close F or die "Could not close $file (\l$!)\n";
}

sub make_symlink
{
    my ( $tgt, $lnk, $quiet ) = @_;

    lstat( $lnk );
    if( -e _ )
    {
	return if -l _ and readlink($lnk) eq $tgt;
	logmsg( "Removing, re-creating /users/$group/$user/$lnk -> $tgt" ) unless $quiet;
	unlink $lnk;
	system( "rm", "-rf", $lnk ) if -e $lnk;
    }
    makedirs_from_path( $lnk );
    symlink( $tgt, $lnk ) or die "Could not symlink $lnk -> $tgt (\l$!)\n";
}

sub make_empty0file
{
    my ( $f ) = @_;

    if( -e $f )
    {
	return if -f _ and ! -s _;
	logmsg( "Removing, re-creating /users/$group/$user/$f" );
	unlink $f;
	system( "rm", "-rf", $f ) if -e $f;
    }
    provide_file( $f, '' );
    chmod( 0000, $f ) or die "Cannot chmod 0 $f\n";
}

sub make_empty0dir
{
    my ( $f ) = @_;

    if( -e $f )
    {
	return if -d _;		# No fast and easy check that the directory is empty
	logmsg( "Removing, re-creating /users/$group/$user/$f" );
	unlink $f;
    }
    makedirs_from_path( "$f/" );
    chmod( 0000, $f ) or die "Cannot chmod 0 $f\n";
}

sub setup_VAL
{
    return if defined $VAL{ USER };

    %VAL = (
	USER =>		$user,
	GROUP =>	$group,
	FULLNAME =>	( getpwnam $user )[6],
	WINDIR =>	'H:\Windows',
	NOW =>		time,
    );
}

sub logmsg
{
    require WireSyslog;
    WireSyslog::syslog_options( IDENT => ( $cmd || 'setup-or-unset-profile' ), PID => 1 );
    WireSyslog::slog( @_ );
}

#!#
