\r
<br><b>OPTIONAL SETUP SECTION (Not required but increase AWStats features)</b><br>\r
<ul>\r
+<li><a href="#EnableLockForUpdate">EnableLockForUpdate</a>\r
<li><a href="#DNSStaticCacheFile">DNSStaticCacheFile</a>\r
<li><a href="#DNSLastUpdateCacheFile">DNSLastUpdateCacheFile</a>\r
<li><a href="#SkipDNSLookupFor">SkipDNSLookupFor</a>\r
<li><a href="#NbOfLinesForCorruptedLog">NbOfLinesForCorruptedLog</a>\r
<li><a href="#SplitSearchString">SplitSearchString</a>\r
<li><a href="#WrapperScript">WrapperScript</a>\r
+<li><a href="#DecodeUA">DecodeUA</a>\r
</ul>\r
\r
<br><b>OPTIONAL ACCURACY SETUP SECTION (Not required but increase AWStats features)</b><br>\r
\r
<br><br><hr>\r
\r
+<a name="EnableLockForUpdate"><b>EnableLockForUpdate</b></a><br>\r
+<b>Version : </b>5.0 +<br>\r
+<br># When the update process run, AWStats can set a lock file in TEMP or TMP\r
+<br># directory. This lock is to avoid to have 2 update processes running at the\r
+<br># same time to prevent unknown conflicts problems and avoid DoS attacks when\r
+<br># AllowToUpdateStatsFromBrowser is set to 1.\r
+<br># Because, when you use lock file, you can experience sometimes problems in\r
+<br># lock file not correctly removed (when process is killed for example that\r
+<br># require that you remove the file manualy), this option is not enabled by\r
+<br># default (Do not enable this option with no consol server access).\r
+<br># Possible values: 0 or 1\r
+<br># Default: 0\r
+<br>#\r
+<br>EnableLockForUpdate=0\r
+\r
+<br><br><hr>\r
+\r
<a name="DNSStaticCacheFile"><b>DNSStaticCacheFile</b></a><br>\r
<b>Version : </b>5.0 +<br>\r
<br># AWStats can do reverse DNS lookups through a static DNS cache file that was\r
\r
<br><br><hr>\r
\r
+<a name="DecodeUA"><b>DecodeUA</b></a><br>\r
+<b>Version : </b>5.0 +<br>\r
+<br># DecodeUA must be set to 1 if you use Roxen web server. This server converts\r
+<br># all spaces in user agent field into %20. This make the AWStats robots, os\r
+<br># and browsers detection fail in some cases. Just change it to 1 if and only\r
+<br># if your web server is Roxen.\r
+<br># Possible values: 0 or 1\r
+<br># Default: 0\r
+<br>#\r
+<br>DecodeUA=0\r
+\r
+<br><br><hr>\r
+\r
<a name="LevelFor"><b>LevelFor</b></a><br>\r
<b>Version : </b>4.0 +<br>\r
-<br># You can change value for following option to disable/enable AWStats capabilities.\r
-<br># Possible values: 0, 1\r
-<br># Possible values: 0, 1 or 2 for LevelForRobotsDetection\r
-<br># Default: 1\r
-<br># Default: 2 for LevelForRobotsDetection\r
+<br># Following values allows you to disable/enable some AWStats features.\r
+<br># Possible values: 0, 1 (or 2 for LevelForRobotsDetection)\r
+<br># Default: 1 (2 for LevelForRobotsDetection)\r
<br>#\r
<br>LevelForRobotsDetection=2 # 0 will increase AWStats speed by 1%.\r
<br>LevelForBrowsersDetection=1 # 0 disables Browsers detection. No speed gain.\r
<br>LevelForOSDetection=1 # 0 disables OS detection. No speed gain.\r
-<br>LevelForRefererAnalyze=1 # 0 will increase AWStats speed by 6%.\r
+<br>LevelForRefererAnalyze=1 # 0 will increase AWStats speed by 5%.\r
\r
<br><br><hr>\r
\r
$BarImageVertical_k = "barrevk.png";
$BarImageHorizontal_k = "barrehk.png";
use vars qw/
-$DNSLookup $AllowAccessFromWebToAuthenticatedUsersOnly $BarHeight $BarWidth
-$CreateDirDataIfNotExists $KeepBackupOfHistoricFiles $MaxLengthOfURL
+$EnableLockForUpdate $DNSLookup $AllowAccessFromWebToAuthenticatedUsersOnly
+$BarHeight $BarWidth $CreateDirDataIfNotExists $KeepBackupOfHistoricFiles $MaxLengthOfURL
$MaxNbOfDomain $MaxNbOfHostsShown $MaxNbOfKeyphrasesShown $MaxNbOfKeywordsShown
$MaxNbOfLoginShown $MaxNbOfPageShown $MaxNbOfRefererShown $MaxNbOfRobotShown
$MinHitFile $MinHitHost $MinHitKeyphrase $MinHitKeyword
$ShowAuthenticatedUsers $ShowCompressionStats $ShowFileSizesStats
$ShowDropped $ShowCorrupted $ShowUnknownOrigin $ShowLinksToWhoIs
$ShowEMailSenders $ShowEMailReceivers
-$Expires $UpdateStats $MigrateStats $URLWithQuery $UseFramesWhenCGI $Spec
+$Expires $UpdateStats $MigrateStats $URLWithQuery $UseFramesWhenCGI $DecodeUA
/;
-($DNSLookup, $AllowAccessFromWebToAuthenticatedUsersOnly, $BarHeight, $BarWidth,
-$CreateDirDataIfNotExists, $KeepBackupOfHistoricFiles, $MaxLengthOfURL,
+($EnableLockForUpdate, $DNSLookup, $AllowAccessFromWebToAuthenticatedUsersOnly,
+$BarHeight, $BarWidth, $CreateDirDataIfNotExists, $KeepBackupOfHistoricFiles, $MaxLengthOfURL,
$MaxNbOfDomain, $MaxNbOfHostsShown, $MaxNbOfKeyphrasesShown, $MaxNbOfKeywordsShown,
$MaxNbOfLoginShown, $MaxNbOfPageShown, $MaxNbOfRefererShown, $MaxNbOfRobotShown,
$MinHitFile, $MinHitHost, $MinHitKeyphrase, $MinHitKeyword,
$ShowAuthenticatedUsers, $ShowCompressionStats, $ShowFileSizesStats,
$ShowDropped, $ShowCorrupted, $ShowUnknownOrigin, $ShowLinksToWhoIs,
$ShowEMailSenders, $ShowEMailReceivers,
-$Expires, $UpdateStats, $MigrateStats, $URLWithQuery, $UseFramesWhenCGI, $Spec)=
-(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+$Expires, $UpdateStats, $MigrateStats, $URLWithQuery, $UseFramesWhenCGI, $DecodeUA)=
+(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
use vars qw/
$AllowToUpdateStatsFromBrowser $ArchiveLogRecords $DetailedReportsOnNewWindows
$FirstDayOfWeek $KeyWordsNotSensitive $SaveDatabaseFilesWithPermissionsForEveryone
if ($HTMLOutput) { print "</b><br>\n"; }
print "See AWStats documentation in 'docs' directory for informations on how to setup $PROG.\n";
}
- # Remove lock if set
- if ($DirLock && $message !~ /lock file/) {
+ # Remove lock if not a lock message
+ if ($EnableLockForUpdate && $message !~ /lock file/) {
&Lock_Update(0);
}
if ($HTMLOutput) { print "</BODY>\n</HTML>\n"; }
}
if ($param =~ /^HostAliases/) {
$value =~ s/\\\./\./g; $value =~ s/([^\\])\./$1\\\./g; $value =~ s/^\./\\\./; # Replace . into \.
- foreach my $elem (split(/\s+/,$value)) { push @HostAliases,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @HostAliases,$elem; }
next;
}
if ($param =~ /^AllowToUpdateStatsFromBrowser/) { $AllowToUpdateStatsFromBrowser=$value; next; }
# Read optional setup section
- if ($param =~ /^DNSStaticCacheFile/) { $DNSStaticCacheFile=$value; next; }
- if ($param =~ /^DNSLastUpdateCacheFile/) { $DNSLastUpdateCacheFile=$value; next; }
+ if ($param =~ /^EnableLockForUpdate/) { $EnableLockForUpdate=$value; next; }
+ if ($param =~ /^DNSStaticCacheFile/) { $DNSStaticCacheFile=$value; next; }
+ if ($param =~ /^DNSLastUpdateCacheFile/) { $DNSLastUpdateCacheFile=$value; next; }
if ($param =~ /^SkipDNSLookupFor/) {
$value =~ s/\\\./\./g; $value =~ s/([^\\])\./$1\\\./g; $value =~ s/^\./\\\./; # Replace . into \.
- foreach my $elem (split(/\s+/,$value)) { push @SkipDNSLookupFor,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @SkipDNSLookupFor,$elem; }
next;
}
if ($param =~ /^AllowAccessFromWebToAuthenticatedUsersOnly/) { $AllowAccessFromWebToAuthenticatedUsersOnly=$value; next; }
if ($param =~ /^AllowAccessFromWebToFollowingAuthenticatedUsers/) {
- foreach my $elem (split(/\s+/,$value)) { push @AllowAccessFromWebToFollowingAuthenticatedUsers,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @AllowAccessFromWebToFollowingAuthenticatedUsers,$elem; }
next;
}
if ($param =~ /^AllowAccessFromWebToFollowingIPAddresses/) { $AllowAccessFromWebToFollowingIPAddresses=$value; next; }
- if ($param =~ /^CreateDirDataIfNotExists/) { $CreateDirDataIfNotExists=$value; next; }
+ if ($param =~ /^CreateDirDataIfNotExists/) { $CreateDirDataIfNotExists=$value; next; }
if ($param =~ /^SaveDatabaseFilesWithPermissionsForEveryone/) { $SaveDatabaseFilesWithPermissionsForEveryone=$value; next; }
if ($param =~ /^PurgeLogFile/) { $PurgeLogFile=$value; next; }
if ($param =~ /^ArchiveLogRecords/) { $ArchiveLogRecords=$value; next; }
- if ($param =~ /^KeepBackupOfHistoricFiles/) { $KeepBackupOfHistoricFiles=$value; next; }
+ if ($param =~ /^KeepBackupOfHistoricFiles/) { $KeepBackupOfHistoricFiles=$value; next; }
if ($param =~ /^DefaultFile/) {
$value =~ s/\\\./\./g; $value =~ s/([^\\])\./$1\\\./g; $value =~ s/^\./\\\./; # Replace . into \.
- foreach my $elem (split(/\s+/,$value)) { push @DefaultFile,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @DefaultFile,$elem; }
next;
}
if ($param =~ /^SkipHosts/) {
$value =~ s/\\\./\./g; $value =~ s/([^\\])\./$1\\\./g; $value =~ s/^\./\\\./; # Replace . into \.
- foreach my $elem (split(/\s+/,$value)) { push @SkipHosts,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @SkipHosts,$elem; }
next;
}
if ($param =~ /^SkipFiles/) {
$value =~ s/\\\./\./g; $value =~ s/([^\\])\./$1\\\./g; $value =~ s/^\./\\\./; # Replace . into \.
- foreach my $elem (split(/\s+/,$value)) { push @SkipFiles,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @SkipFiles,$elem; }
next;
}
if ($param =~ /^OnlyFiles/) {
$value =~ s/\\\./\./g; $value =~ s/([^\\])\./$1\\\./g; $value =~ s/^\./\\\./; # Replace . into \.
- foreach my $elem (split(/\s+/,$value)) { push @OnlyFiles,$elem; }
+ foreach my $elem (split(/\s+/,$value)) { push @OnlyFiles,$elem; }
next;
}
if ($param =~ /^NotPageList/) {
- foreach my $elem (split(/\s+/,$value)) { $NotPageList{$elem}=1; }
+ foreach my $elem (split(/\s+/,$value)) { $NotPageList{$elem}=1; }
$foundNotPageList=1;
next;
}
if ($param =~ /^ValidHTTPCodes/) {
- foreach my $elem (split(/\s+/,$value)) { $ValidHTTPCodes{$elem}=1; }
+ foreach my $elem (split(/\s+/,$value)) { $ValidHTTPCodes{$elem}=1; }
$foundValidHTTPCodes=1;
next;
}
if ($param =~ /^NbOfLinesForCorruptedLog/) { $NbOfLinesForCorruptedLog=$value; next; }
if ($param =~ /^Expires/) { $Expires=$value; next; }
if ($param =~ /^WrapperScript/) { $WrapperScript=$value; next; }
+ if ($param =~ /^DecodeUA/) { $DecodeUA=$value; next; }
# Read optional accuracy setup section
if ($param =~ /^LevelForRobotsDetection/) { $LevelForRobotsDetection=$value; next; }
if ($param =~ /^LevelForBrowsersDetection/) { $LevelForBrowsersDetection=$value; next; }
if (! $SiteDomain) { error("Error: SiteDomain parameter not found in your config/domain file. You must add it for using this version."); }
if ($AllowToUpdateStatsFromBrowser !~ /[0-1]/) { $AllowToUpdateStatsFromBrowser=0; }
# Optional setup section
+ if ($EnableLockForUpdate !~ /[0-1]/) { $EnableLockForUpdate=0; }
if (! $DNSStaticCacheFile) { $DNSStaticCacheFile="dnscache.txt"; }
if (! $DNSLastUpdateCacheFile) { $DNSLastUpdateCacheFile="dnscachelastupdate.txt"; }
if ($AllowAccessFromWebToAuthenticatedUsersOnly !~ /[0-1]/) { $AllowAccessFromWebToAuthenticatedUsersOnly=0; }
if ($WarningMessages !~ /[0-1]/) { $WarningMessages=1; }
if ($NbOfLinesForCorruptedLog !~ /^\d+/ || $NbOfLinesForCorruptedLog<1) { $NbOfLinesForCorruptedLog=50; }
if ($Expires !~ /^\d+/) { $Expires=0; }
+ if ($DecodeUA !~ /[0-1]/) { $DecodeUA=0; }
# Optional accuracy setup section
if ($LevelForRobotsDetection !~ /^\d+/) { $LevelForRobotsDetection=2; }
if ($LevelForBrowsersDetection !~ /^\d+/) { $LevelForBrowsersDetection=1; }
#--------------------------------------------------------------------
# Function: Lock or unlock update
-# Parameters: 1 to lock, 0 to unlock
-# Input: $DirLock $PROG $FileSuffix
-# Output: $DirLock
+# Parameters: status (1 to lock, 0 to unlock)
+# Input: $DirLock (if status=0) $PROG $FileSuffix
+# Output: $DirLock (if status=1)
# Return: None
#--------------------------------------------------------------------
sub Lock_Update {
my $status=shift;
my $lock="$PROG$FileSuffix.lock";
- # Define dir where to write lock file into
- if (! $DirLock) {
- if (-d $ENV{"TEMP"}) { $DirLock=$ENV{"TEMP"}; }
- elsif (-d $ENV{"TMP"}) { $DirLock=$ENV{"TMP"}; }
- elsif (-d "/tmp") { $DirLock="/tmp"; }
- $DirLock =~ s/[\\\/]$//;
- }
if ($status) {
# We stop if there is at least one lock file wherever it is
- foreach my $key ($ENV{"TEMP"},$ENV{"TMP"},"/tmp","/") {
+ foreach my $key ($ENV{"TEMP"},$ENV{"TMP"},"/tmp","/",".") {
my $newkey =$key;
$newkey =~ s/[\\\/]$//;
if (-f "$newkey/$lock") { error("An AWStats update process seems to be already running for this config file. Try later.\nIf this is not true, remove manually lock file '$newkey/$lock'.","","",1); }
}
- # Set lock
- if ($Debug) { debug("Update lock file $DirLock/$lock is set"); }
- open(LOCK,">$DirLock/$lock") || error("Error: Failed to create lock file $DirLock/$lock","","",1);
- print LOCK "AWStats update started by process $$ at $nowyear-$nowmonth-$nowday $nowhour:$nowmin:$nowsec\n";
- close(LOCK);
+ # Set lock where we can
+ foreach my $key ($ENV{"TEMP"},$ENV{"TMP"},"/tmp","/",".") {
+ if (! -d $key) { next; }
+ $DirLock=$key;
+ $DirLock =~ s/[\\\/]$//;
+ if ($Debug) { debug("Update lock file $DirLock/$lock is set"); }
+ open(LOCK,">$DirLock/$lock") || error("Error: Failed to create lock file $DirLock/$lock","","",1);
+ print LOCK "AWStats update started by process $$ at $nowyear-$nowmonth-$nowday $nowhour:$nowmin:$nowsec\n";
+ close(LOCK);
+ last;
+ }
}
else {
# Remove lock
$FileSuffix=$5;
print "Start migration for file '$MigrateStats'.\n";
if (! -s $MigrateStats) { error("Error: File to migrate '$MigrateStats' not found.","","",1); }
- &Lock_Update(1);
+ if ($EnableLockForUpdate) { &Lock_Update(1); }
my $newhistory=&Read_History_With_TmpUpdate($YearRequired,$MonthRequired,1,0,"all");
if (rename("$newhistory","$MigrateStats")==0) {
unlink "$newhistory";
error("Error: Failed to rename \"$newhistory\" into \"$MigrateStats\".\nWrite permissions on \"$MigrateStats\" might be wrong".($ENV{"GATEWAY_INTERFACE"}?" for a 'migration from web'":"")." or file might be opened.");
}
- &Lock_Update(0);
+ if ($EnableLockForUpdate) { &Lock_Update(0); }
print "Migration for file '$MigrateStats' successful.\n";
exit 0;
}
# Processing log
#------------------------------------------
- # Trap signals to remove lock
- $SIG{INT} = \&SigHandler; # 2
- #$SIG{KILL} = \&SigHandler; # 9
- #$SIG{TERM} = \&SigHandler; # 15
-
- &Lock_Update(1);
+ if ($EnableLockForUpdate) {
+ # Trap signals to remove lock
+ $SIG{INT} = \&SigHandler; # 2
+ #$SIG{KILL} = \&SigHandler; # 9
+ #$SIG{TERM} = \&SigHandler; # 15
+ # Set AWStats update lock
+ &Lock_Update(1);
+ }
if ($Debug) { debug("Start Update process (lastprocessedmonth=$lastprocessedmonth, lastprocessedyear=$lastprocessedyear)"); }
$NbOfLinesRead=$NbOfLinesDropped=$NbOfLinesCorrupted=$NbOfOldLines=$NbOfNewLines=$NbOfLinesShowsteps=0;
# Analyze: Robot
#---------------
if ($pos_agent >= 0) {
- if ($Spec == 1) { $field[$pos_agent] =~ s/%20/_/g; } # This is to support servers (like Roxen) that writes user agent with %20 in it
+ if ($DecodeUA) { $field[$pos_agent] =~ s/%20/_/g; } # This is to support servers (like Roxen) that writes user agent with %20 in it
$UserAgent=$field[$pos_agent];
if ($LevelForRobotsDetection) {
Save_DNS_Cache_File(\%TmpDNSLookup,"$DirData/$DNSLastUpdateCacheFile","$FileSuffix"); # Save into file using FileSuffix
}
- &Lock_Update(0);
-
- # Restore signals handler
- $SIG{INT} = 'DEFAULT'; # 2
- #$SIG{KILL} = 'DEFAULT'; # 9
- #$SIG{TERM} = 'DEFAULT'; # 15
+ if ($EnableLockForUpdate) {
+ # Remove lock
+ &Lock_Update(0);
+ # Restore signals handler
+ $SIG{INT} = 'DEFAULT'; # 2
+ #$SIG{KILL} = 'DEFAULT'; # 9
+ #$SIG{TERM} = 'DEFAULT'; # 15
+ }
}
# End of log processing if ($UPdateStats)