~ubuntu-branches/ubuntu/breezy/awstats/breezy

« back to all changes in this revision

Viewing changes to wwwroot/cgi-bin/awstats.pl

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2004-05-05 05:12:07 UTC
  • Revision ID: james.westby@ubuntu.com-20040505051207-wfi8hydpa89pvuoi
Tags: upstream-6.0
ImportĀ upstreamĀ versionĀ 6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
#------------------------------------------------------------------------------
 
3
# Free realtime web server logfile analyzer to show advanced web statistics.
 
4
# Works from command line or as a CGI. You must use this script as often as
 
5
# necessary from your scheduler to update your statistics and from command
 
6
# line or a browser to read report results.
 
7
# See AWStats documentation (in docs/ directory) for all setup instructions.
 
8
#------------------------------------------------------------------------------
 
9
# $Revision: 1.704 $ - $Author: eldy $ - $Date: 2004/01/25 15:24:13 $
 
10
require 5.005;
 
11
 
 
12
#$|=1;
 
13
#use warnings;          # Must be used in test mode only. This reduce a little process speed
 
14
#use diagnostics;       # Must be used in test mode only. This reduce a lot of process speed
 
15
use strict;no strict "refs";
 
16
use Time::Local;        # use Time::Local 'timelocal_nocheck' is faster but not supported by all Time::Local modules
 
17
use Socket;
 
18
 
 
19
 
 
20
#------------------------------------------------------------------------------
 
21
# Defines
 
22
#------------------------------------------------------------------------------
 
23
use vars qw/ $REVISION $VERSION /;
 
24
$REVISION='$Revision: 1.704 $'; $REVISION =~ /\s(.*)\s/; $REVISION=$1;
 
25
$VERSION="6.0 (build $REVISION)";
 
26
 
 
27
# ----- Constants -----
 
28
use vars qw/
 
29
$DEBUGFORCED $NBOFLINESFORBENCHMARK $FRAMEWIDTH $NBOFLASTUPDATELOOKUPTOSAVE
 
30
$LIMITFLUSH $NEWDAYVISITTIMEOUT $VISITTIMEOUT $NOTSORTEDRECORDTOLERANCE $MAXDIFFEXTRA
 
31
$WIDTHCOLICON $TOOLTIPON
 
32
$lastyearbeforeupdate
 
33
/;
 
34
$DEBUGFORCED=0;                                         # Force debug level to log lesser level into debug.log file (Keep this value to 0)
 
35
$NBOFLINESFORBENCHMARK=8192;            # Benchmark info are printing every NBOFLINESFORBENCHMARK lines (Must be a power of 2)
 
36
$FRAMEWIDTH=240;                                        # Width of left frame when UseFramesWhenCGI is on
 
37
$NBOFLASTUPDATELOOKUPTOSAVE=500;        # Nb of records to save in DNS last update cache file
 
38
$LIMITFLUSH=5000;                                       # Nb of records in data arrays after how we need to flush data on disk
 
39
$NEWDAYVISITTIMEOUT=764041;                     # Delay between 01-23:59:59 and 02-00:00:00
 
40
$VISITTIMEOUT=10000;                            # Laps of time to consider a page load as a new visit. 10000 = 1 hour (Default = 10000)
 
41
$NOTSORTEDRECORDTOLERANCE=10000;        # Laps of time to accept a record if not in correct order. 10000 = 1 hour (Default = 10000)
 
42
$MAXDIFFEXTRA=500;
 
43
$WIDTHCOLICON=32;
 
44
$TOOLTIPON=0;                                           # Tooltips plugin loaded
 
45
# ----- Running variables -----
 
46
use vars qw/
 
47
$DIR $PROG $Extension
 
48
$Debug $ShowSteps
 
49
$DebugResetDone $DNSLookupAlreadyDone
 
50
$RunAsCli $UpdateFor $HeaderHTTPComplete $HeaderHTMLComplete
 
51
$LastLine $LastLineNumber $LastLineOffset $LastLineChecksum $LastUpdate
 
52
$lowerval
 
53
$PluginMode
 
54
$TotalUnique $TotalVisits $TotalHostsKnown $TotalHostsUnknown
 
55
$TotalPages $TotalHits $TotalBytes
 
56
$TotalNotViewedPages $TotalNotViewedHits $TotalNotViewedBytes
 
57
$TotalEntries $TotalExits $TotalBytesPages $TotalDifferentPages
 
58
$TotalKeyphrases $TotalKeywords $TotalDifferentKeyphrases $TotalDifferentKeywords
 
59
$TotalSearchEnginesPages $TotalSearchEnginesHits $TotalRefererPages $TotalRefererHits $TotalDifferentSearchEngines $TotalDifferentReferer
 
60
$FrameName $Center $FileConfig $FileSuffix $Host $DayRequired $MonthRequired $YearRequired
 
61
$QueryString $SiteConfig $StaticLinks $PageCode $PageDir $PerlParsingFormat
 
62
$SiteToAnalyze $SiteToAnalyzeWithoutwww $UserAgent
 
63
$pos_vh $pos_host $pos_logname $pos_date $pos_tz $pos_method $pos_url $pos_code $pos_size
 
64
$pos_referer $pos_agent $pos_query $pos_gzipin $pos_gzipout $pos_compratio
 
65
$pos_cluster $pos_emails $pos_emailr $pos_hostr
 
66
/;
 
67
$DIR=$PROG=$Extension='';
 
68
$Debug = $ShowSteps = 0;
 
69
$DebugResetDone = $DNSLookupAlreadyDone = 0;
 
70
$RunAsCli = $UpdateFor = $HeaderHTTPComplete = $HeaderHTMLComplete = 0;
 
71
$LastLine = $LastLineNumber = $LastLineOffset = $LastLineChecksum = $LastUpdate = 0;
 
72
$lowerval = 0;
 
73
$PluginMode = '';
 
74
$TotalUnique = $TotalVisits = $TotalHostsKnown = $TotalHostsUnknown = 0;
 
75
$TotalPages = $TotalHits = $TotalBytes = 0;
 
76
$TotalNotViewedPages = $TotalNotViewedHits = $TotalNotViewedBytes = 0;
 
77
$TotalEntries = $TotalExits = $TotalBytesPages = $TotalDifferentPages = 0;
 
78
$TotalKeyphrases = $TotalKeywords = $TotalDifferentKeyphrases = $TotalDifferentKeywords = 0;
 
79
$TotalSearchEnginesPages = $TotalSearchEnginesHits = $TotalRefererPages = $TotalRefererHits = $TotalDifferentSearchEngines = $TotalDifferentReferer = 0;
 
80
($FrameName, $Center, $FileConfig, $FileSuffix, $Host, $DayRequired, $MonthRequired, $YearRequired,
 
81
$QueryString, $SiteConfig, $StaticLinks, $PageCode, $PageDir, $PerlParsingFormat,
 
82
$SiteToAnalyze, $SiteToAnalyzeWithoutwww, $UserAgent)=
 
83
('','','','','','','','','','','','','','','','','');
 
84
$pos_vh = $pos_host = $pos_logname = $pos_date = $pos_tz = $pos_method = $pos_url = $pos_code = $pos_size = -1;
 
85
$pos_referer = $pos_agent = $pos_query = $pos_gzipin = $pos_gzipout = $pos_compratio = -1;
 
86
$pos_cluster = $pos_emails = $pos_emailr = $pos_hostr = -1;
 
87
# ----- Plugins variable -----
 
88
use vars qw/ %PluginsLoaded $PluginDir /;
 
89
%PluginsLoaded=();
 
90
$PluginDir='';
 
91
# ----- Time vars -----
 
92
use vars qw/
 
93
$starttime
 
94
$nowtime $tomorrowtime
 
95
$nowweekofmonth $nowweekofyear $nowdaymod $nowsmallyear
 
96
$nowsec $nowmin $nowhour $nowday $nowmonth $nowyear $nowwday $nowyday $nowns
 
97
$StartSeconds $StartMicroseconds
 
98
/;
 
99
$StartSeconds=$StartMicroseconds=0;
 
100
# ----- Variables for config file reading -----
 
101
use vars qw/
 
102
$FoundNotPageList $FoundValidHTTPCodes $FoundValidSMTPCodes
 
103
/;
 
104
$FoundNotPageList=$FoundValidHTTPCodes=$FoundValidSMTPCodes=0;
 
105
# ----- Config file variables -----
 
106
use vars qw/
 
107
$StaticExt
 
108
$DNSStaticCacheFile
 
109
$DNSLastUpdateCacheFile
 
110
$MiscTrackerUrl
 
111
$Lang
 
112
$MaxRowsInHTMLOutput
 
113
$MaxLengthOfShownURL
 
114
$MaxLengthOfStoredURL
 
115
$MaxLengthOfStoredUA
 
116
%BarPng
 
117
$BuildReportFormat
 
118
$BuildHistoryFormat 
 
119
/;
 
120
$StaticExt='html';
 
121
$DNSStaticCacheFile='dnscache.txt';
 
122
$DNSLastUpdateCacheFile='dnscachelastupdate.txt';
 
123
$MiscTrackerUrl='/js/awstats_misc_tracker.js';
 
124
$Lang='auto';
 
125
$MaxRowsInHTMLOutput=1000;
 
126
$MaxLengthOfShownURL=64;
 
127
$MaxLengthOfStoredURL=256;                      # Note: Apache LimitRequestLine is default to 8190
 
128
$MaxLengthOfStoredUA=256;
 
129
%BarPng=('vv'=>'vv.png','vu'=>'vu.png','hu'=>'hu.png','vp'=>'vp.png','hp'=>'hp.png',
 
130
'he'=>'he.png','hx'=>'hx.png','vh'=>'vh.png','hh'=>'hh.png','vk'=>'vk.png','hk'=>'hk.png');
 
131
$BuildReportFormat='html';
 
132
$BuildHistoryFormat='text';
 
133
use vars qw/
 
134
$EnableLockForUpdate $DNSLookup $AllowAccessFromWebToAuthenticatedUsersOnly
 
135
$BarHeight $BarWidth $CreateDirDataIfNotExists $KeepBackupOfHistoricFiles
 
136
$NbOfLinesParsed $NbOfLinesDropped $NbOfLinesCorrupted $NbOfOldLines $NbOfNewLines
 
137
$NbOfLinesShowsteps $NewLinePhase $NbOfLinesForCorruptedLog $PurgeLogFile
 
138
$ShowDropped $ShowCorrupted $ShowUnknownOrigin $ShowLinksToWhoIs
 
139
$ShowAuthenticatedUsers $ShowFileSizesStats $ShowScreenSizeStats $ShowSMTPErrorsStats
 
140
$ShowEMailSenders $ShowEMailReceivers $ShowWormsStats $ShowClusterStats
 
141
$AuthenticatedUsersNotCaseSensitive
 
142
$Expires $UpdateStats $MigrateStats $URLNotCaseSensitive $URLWithQuery $URLReferrerWithQuery
 
143
$DecodeUA
 
144
/;
 
145
($EnableLockForUpdate, $DNSLookup, $AllowAccessFromWebToAuthenticatedUsersOnly,
 
146
$BarHeight, $BarWidth, $CreateDirDataIfNotExists, $KeepBackupOfHistoricFiles,
 
147
$NbOfLinesParsed, $NbOfLinesDropped, $NbOfLinesCorrupted, $NbOfOldLines, $NbOfNewLines,
 
148
$NbOfLinesShowsteps, $NewLinePhase, $NbOfLinesForCorruptedLog, $PurgeLogFile,
 
149
$ShowDropped, $ShowCorrupted, $ShowUnknownOrigin, $ShowLinksToWhoIs,
 
150
$ShowAuthenticatedUsers, $ShowFileSizesStats, $ShowScreenSizeStats, $ShowSMTPErrorsStats,
 
151
$ShowEMailSenders, $ShowEMailReceivers, $ShowWormsStats, $ShowClusterStats,
 
152
$AuthenticatedUsersNotCaseSensitive,
 
153
$Expires, $UpdateStats, $MigrateStats, $URLNotCaseSensitive, $URLWithQuery, $URLReferrerWithQuery,
 
154
$DecodeUA)=
 
155
(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);
 
156
use vars qw/
 
157
$AllowToUpdateStatsFromBrowser
 
158
$ArchiveLogRecords $DetailedReportsOnNewWindows
 
159
$FirstDayOfWeek $KeyWordsNotSensitive $SaveDatabaseFilesWithPermissionsForEveryone
 
160
$WarningMessages $DebugMessages $ShowLinksOnUrl $UseFramesWhenCGI
 
161
$ShowMenu $ShowMonthStats $ShowDaysOfMonthStats $ShowDaysOfWeekStats
 
162
$ShowHoursStats $ShowDomainsStats $ShowHostsStats
 
163
$ShowRobotsStats $ShowSessionsStats $ShowPagesStats $ShowFileTypesStats
 
164
$ShowOSStats $ShowBrowsersStats $ShowOriginStats
 
165
$ShowKeyphrasesStats $ShowKeywordsStats $ShowMiscStats $ShowHTTPErrorsStats
 
166
$AddDataArrayMonthStats $AddDataArrayShowDaysOfMonthStats $AddDataArrayShowDaysOfWeekStats $AddDataArrayShowHoursStats
 
167
/;
 
168
($AllowToUpdateStatsFromBrowser,
 
169
$ArchiveLogRecords, $DetailedReportsOnNewWindows,
 
170
$FirstDayOfWeek, $KeyWordsNotSensitive, $SaveDatabaseFilesWithPermissionsForEveryone,
 
171
$WarningMessages, $DebugMessages, $ShowLinksOnUrl, $UseFramesWhenCGI,
 
172
$ShowMenu, $ShowMonthStats, $ShowDaysOfMonthStats, $ShowDaysOfWeekStats,
 
173
$ShowHoursStats, $ShowDomainsStats, $ShowHostsStats,
 
174
$ShowRobotsStats, $ShowSessionsStats, $ShowPagesStats, $ShowFileTypesStats,
 
175
$ShowOSStats, $ShowBrowsersStats, $ShowOriginStats,
 
176
$ShowKeyphrasesStats, $ShowKeywordsStats, $ShowMiscStats, $ShowHTTPErrorsStats,
 
177
$AddDataArrayMonthStats, $AddDataArrayShowDaysOfMonthStats, $AddDataArrayShowDaysOfWeekStats, $AddDataArrayShowHoursStats
 
178
)=
 
179
(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
 
180
use vars qw/
 
181
$AllowFullYearView 
 
182
$LevelForRobotsDetection $LevelForWormsDetection $LevelForBrowsersDetection $LevelForOSDetection $LevelForRefererAnalyze
 
183
$LevelForFileTypesDetection $LevelForSearchEnginesDetection $LevelForKeywordsDetection
 
184
/;
 
185
($AllowFullYearView,
 
186
$LevelForRobotsDetection, $LevelForWormsDetection, $LevelForBrowsersDetection, $LevelForOSDetection, $LevelForRefererAnalyze,
 
187
$LevelForFileTypesDetection, $LevelForSearchEnginesDetection, $LevelForKeywordsDetection)=
 
188
(2,2,0,2,2,2,2,2,2);
 
189
use vars qw/
 
190
$DirLock $DirCgi $DirConfig $DirData $DirIcons $DirLang $AWScript $ArchiveFileName
 
191
$AllowAccessFromWebToFollowingIPAddresses $HTMLHeadSection $HTMLEndSection $LinksToWhoIs $LinksToIPWhoIs
 
192
$LogFile $LogType $LogFormat $LogSeparator $Logo $LogoLink $StyleSheet $WrapperScript $SiteDomain
 
193
$UseHTTPSLinkForUrl $URLQuerySeparators $URLWithAnchor $ErrorMessages $ShowFlagLinks
 
194
/;
 
195
($DirLock, $DirCgi, $DirConfig, $DirData, $DirIcons, $DirLang, $AWScript, $ArchiveFileName,
 
196
$AllowAccessFromWebToFollowingIPAddresses, $HTMLHeadSection, $HTMLEndSection, $LinksToWhoIs, $LinksToIPWhoIs,
 
197
$LogFile, $LogType, $LogFormat, $LogSeparator, $Logo, $LogoLink, $StyleSheet, $WrapperScript, $SiteDomain,
 
198
$UseHTTPSLinkForUrl, $URLQuerySeparators, $URLWithAnchor, $ErrorMessages, $ShowFlagLinks)=
 
199
('','','','','','','','','','','','','','','','','','','','','','','','','','','');
 
200
use vars qw/
 
201
$color_Background $color_TableBG $color_TableBGRowTitle
 
202
$color_TableBGTitle $color_TableBorder $color_TableRowTitle $color_TableTitle
 
203
$color_text $color_textpercent $color_titletext $color_weekend $color_link $color_hover $color_other
 
204
$color_h $color_k $color_p $color_e $color_x $color_s $color_u $color_v
 
205
/;
 
206
($color_Background, $color_TableBG, $color_TableBGRowTitle,
 
207
$color_TableBGTitle, $color_TableBorder, $color_TableRowTitle, $color_TableTitle,
 
208
$color_text, $color_textpercent, $color_titletext, $color_weekend, $color_link, $color_hover, $color_other,
 
209
$color_h, $color_k, $color_p, $color_e, $color_x, $color_s, $color_u, $color_v)=
 
210
('','','','','','','','','','','','','','','','','','','','','','');
 
211
# ---------- Init arrays --------
 
212
use vars qw/
 
213
@RobotsSearchIDOrder_list1 @RobotsSearchIDOrder_list2 @RobotsSearchIDOrder_listgen
 
214
@SearchEnginesSearchIDOrder_list1 @SearchEnginesSearchIDOrder_list2 @SearchEnginesSearchIDOrder_listgen
 
215
@BrowsersSearchIDOrder @OSSearchIDOrder @WordsToExtractSearchUrl @WordsToCleanSearchUrl
 
216
@WormsSearchIDOrder
 
217
@RobotsSearchIDOrder @SearchEnginesSearchIDOrder
 
218
@_from_p @_from_h
 
219
@_time_p @_time_h @_time_k @_time_nv_p @_time_nv_h @_time_nv_k
 
220
@DOWIndex @fieldlib @keylist
 
221
/;
 
222
@RobotsSearchIDOrder = @SearchEnginesSearchIDOrder = ();
 
223
@_from_p = @_from_h = ();
 
224
@_time_p = @_time_h = @_time_k = @_time_nv_p = @_time_nv_h = @_time_nv_k = ();
 
225
@DOWIndex = @fieldlib = @keylist = ();
 
226
use vars qw/
 
227
@MiscListOrder %MiscListCalc
 
228
@OSFamily %BrowsersFamily @SessionsRange %SessionsAverage
 
229
%LangBrowserToLangAwstats %LangAWStatsToCountryAwstats
 
230
@HostAliases @AllowAccessFromWebToFollowingAuthenticatedUsers
 
231
@DefaultFile @SkipDNSLookupFor
 
232
@SkipHosts @SkipUserAgents @SkipFiles
 
233
@OnlyHosts @OnlyUserAgents @OnlyFiles 
 
234
@URLWithQueryWithOnly @URLWithQueryWithout
 
235
@ExtraName @ExtraCondition @ExtraStatTypes @MaxNbOfExtra @MinHitExtra
 
236
@ExtraFirstColumnTitle @ExtraFirstColumnValues @ExtraFirstColumnFormat
 
237
@ExtraConditionType @ExtraConditionTypeVal
 
238
@ExtraFirstColumnValuesType @ExtraFirstColumnValuesTypeVal
 
239
@ExtraAddAverageRow @ExtraAddSumRow
 
240
@PluginsToLoad 
 
241
/;
 
242
@MiscListOrder=('AddToFavourites','JavaEnabled','DirectorSupport','FlashSupport','RealPlayerSupport','QuickTimeSupport','WindowsMediaPlayerSupport','PDFSupport');
 
243
%MiscListCalc=('TotalMisc'=>'','AddToFavourites'=>'u','JavaEnabled'=>'hm','DirectorSupport'=>'hm','FlashSupport'=>'hm','RealPlayerSupport'=>'hm','QuickTimeSupport'=>'hm','WindowsMediaPlayerSupport'=>'hm','PDFSupport'=>'hm');
 
244
@OSFamily=('win','mac');
 
245
#%BrowsersFamily=('msie'=>1,'netscape'=>2,'mozilla'=>3);
 
246
%BrowsersFamily=('msie'=>1,'netscape'=>2);
 
247
@SessionsRange=('0s-30s','30s-2mn','2mn-5mn','5mn-15mn','15mn-30mn','30mn-1h','1h+');
 
248
%SessionsAverage=('0s-30s',15,'30s-2mn',75,'2mn-5mn',210,'5mn-15mn',600,'15mn-30mn',1350,'30mn-1h',2700,'1h+',3600);
 
249
# Values reported by HTTP-Accept with AWStats code to use
 
250
%LangBrowserToLangAwstats=('sq'=>'al','ba'=>'ba','bg'=>'bg','zh-tw'=>'tw','zh'=>'cn','cz'=>'cz',
 
251
'da'=>'dk','nl'=>'nl','en'=>'en','et'=>'et','fi'=>'fi','fr'=>'fr',
 
252
'de'=>'de','el'=>'gr','hu'=>'hu','is'=>'is','in'=>'id','it'=>'it',
 
253
'ja'=>'jp','ko'=>'kr','lv'=>'lv','no'=>'nb','nb'=>'nb','nn'=>'nn','pl'=>'pl','pt'=>'pt','pt-br'=>'br',
 
254
'ro'=>'ro','ru'=>'ru','sr'=>'sr','sk'=>'sk','es'=>'es','eu'=>'es_eu','ca'=>'es_cat','sv'=>'se','tr'=>'tr','uk'=>'ua','wlk'=>'wlk');
 
255
%LangAWStatsToCountryAwstats=('et'=>'ee','he'=>'il');
 
256
@HostAliases = @AllowAccessFromWebToFollowingAuthenticatedUsers=();
 
257
@DefaultFile = @SkipDNSLookupFor = ();
 
258
@SkipHosts = @SkipUserAgents = @SkipFiles = ();
 
259
@OnlyHosts = @OnlyUserAgents = @OnlyFiles = ();
 
260
@URLWithQueryWithOnly = @URLWithQueryWithout = ();
 
261
@ExtraName = @ExtraCondition = @ExtraStatTypes = @MaxNbOfExtra = @MinHitExtra = ();
 
262
@ExtraFirstColumnTitle = @ExtraFirstColumnValues = @ExtraFirstColumnFormat = ();
 
263
@ExtraConditionType = @ExtraConditionTypeVal = ();
 
264
@ExtraFirstColumnValuesType = @ExtraFirstColumnValuesTypeVal = ();
 
265
@ExtraAddAverageRow = @ExtraAddSumRow = ();
 
266
@PluginsToLoad = ();
 
267
# ---------- Init hash arrays --------
 
268
use vars qw/
 
269
%BrowsersHashIDLib %BrowsersHashIcon %BrowsersHereAreGrabbers 
 
270
%DomainsHashIDLib
 
271
%MimeHashLib %MimeHashIcon %MimeHashFamily
 
272
%OSHashID %OSHashLib
 
273
%RobotsHashIDLib
 
274
%SearchEnginesHashID %SearchEnginesHashLib %SearchEnginesKnownUrl %NotSearchEnginesKeys
 
275
%WormsHashID %WormsHashLib
 
276
/;
 
277
use vars qw/
 
278
%HTMLOutput %NoLoadPlugin %FilterIn %FilterEx
 
279
%BadFormatWarning
 
280
%MonthNumLib
 
281
%ValidHTTPCodes %ValidSMTPCodes
 
282
%TrapInfosForHTTPErrorCodes %NotPageList %DayBytes %DayHits %DayPages %DayVisits
 
283
%MaxNbOf %MinHit
 
284
%ListOfYears %HistoryAlreadyFlushed %PosInFile %ValueInFile
 
285
%val %nextval %egal
 
286
%TmpDNSLookup %TmpOS %TmpRefererServer %TmpRobot %TmpBrowser %MyDNSTable
 
287
/;
 
288
%HTMLOutput = %NoLoadPlugin = %FilterIn = %FilterEx = ();
 
289
%BadFormatWarning = ();
 
290
%MonthNumLib = ();
 
291
%ValidHTTPCodes = %ValidSMTPCodes = ();
 
292
%TrapInfosForHTTPErrorCodes=(); $TrapInfosForHTTPErrorCodes{404}=1;     # TODO Add this in config file
 
293
%NotPageList=();
 
294
%DayBytes = %DayHits = %DayPages = %DayVisits = ();
 
295
%MaxNbOf = %MinHit = ();
 
296
%ListOfYears = %HistoryAlreadyFlushed = %PosInFile = %ValueInFile = ();
 
297
%val = %nextval = %egal = ();
 
298
%TmpDNSLookup = %TmpOS = %TmpRefererServer = %TmpRobot = %TmpBrowser = %MyDNSTable = ();
 
299
use vars qw/
 
300
%FirstTime %LastTime
 
301
%MonthHostsKnown %MonthHostsUnknown
 
302
%MonthUnique %MonthVisits
 
303
%MonthPages %MonthHits %MonthBytes
 
304
%MonthNotViewedPages %MonthNotViewedHits %MonthNotViewedBytes
 
305
%_session %_browser_h
 
306
%_domener_p %_domener_h %_domener_k %_errors_h %_errors_k
 
307
%_filetypes_h %_filetypes_k %_filetypes_gz_in %_filetypes_gz_out
 
308
%_host_p %_host_h %_host_k %_host_l %_host_s %_host_u
 
309
%_waithost_e %_waithost_l %_waithost_s %_waithost_u
 
310
%_keyphrases %_keywords %_os_h %_pagesrefs_p %_pagesrefs_h %_robot_h %_robot_k %_robot_l %_robot_r
 
311
%_worm_h %_worm_k %_worm_l %_login_h %_login_p %_login_k %_login_l %_screensize_h
 
312
%_misc_p %_misc_h %_misc_k
 
313
%_cluster_p %_cluster_h %_cluster_k
 
314
%_se_referrals_p %_se_referrals_h %_sider404_h %_referer404_h %_url_p %_url_k %_url_e %_url_x
 
315
%_unknownreferer_l %_unknownrefererbrowser_l
 
316
%_emails_h %_emails_k %_emails_l %_emailr_h %_emailr_k %_emailr_l
 
317
/;
 
318
&Init_HashArray();
 
319
 
 
320
# ---------- Init Tie::hash arrays --------
 
321
# Didn't find a tie that increase speed
 
322
#use Tie::StdHash;
 
323
#use Tie::Cache::LRU;
 
324
#tie %_host_p, 'Tie::StdHash';
 
325
#tie %TmpOS, 'Tie::Cache::LRU';
 
326
 
 
327
# PROTOCOL CODES
 
328
use vars qw/ %httpcodelib %ftpcodelib %smtpcodelib /;
 
329
 
 
330
# DEFAULT MESSAGE
 
331
use vars qw/ @Message /;
 
332
@Message=(
 
333
'Unknown',
 
334
'Unknown (unresolved ip)',
 
335
'Others',
 
336
'View details',
 
337
'Day',
 
338
'Month',
 
339
'Year',
 
340
'Statistics for',
 
341
'First visit',
 
342
'Last visit',
 
343
'Number of visits',
 
344
'Unique visitors',
 
345
'Visit',
 
346
'different keywords',
 
347
'Search',
 
348
'Percent',
 
349
'Traffic',
 
350
'Domains/Countries',
 
351
'Visitors',
 
352
'Pages-URL',
 
353
'Hours',
 
354
'Browsers',
 
355
'',
 
356
'Referers',
 
357
'Never updated (See \'Build/Update\' on awstats_setup.html page)',
 
358
'Visitors domains/countries',
 
359
'hosts',
 
360
'pages',
 
361
'different pages-url',
 
362
'Viewed',
 
363
'Other words',
 
364
'Pages not found',
 
365
'HTTP Error codes',
 
366
'Netscape versions',
 
367
'IE versions',
 
368
'Last Update',
 
369
'Connect to site from',
 
370
'Origin',
 
371
'Direct address / Bookmarks',
 
372
'Origin unknown',
 
373
'Links from an Internet Search Engine',
 
374
'Links from an external page (other web sites except search engines)',
 
375
'Links from an internal page (other page on same site)',
 
376
'Keyphrases used on search engines',
 
377
'Keywords used on search engines',
 
378
'Unresolved IP Address',
 
379
'Unknown OS (Referer field)',
 
380
'Required but not found URLs (HTTP code 404)',
 
381
'IP Address',
 
382
'Error Hits',
 
383
'Unknown browsers (Referer field)',
 
384
'different robots',
 
385
'visits/visitor',
 
386
'Robots/Spiders visitors',
 
387
'Free realtime logfile analyzer for advanced web statistics',
 
388
'of',
 
389
'Pages',
 
390
'Hits',
 
391
'Versions',
 
392
'Operating Systems',
 
393
'Jan',
 
394
'Feb',
 
395
'Mar',
 
396
'Apr',
 
397
'May',
 
398
'Jun',
 
399
'Jul',
 
400
'Aug',
 
401
'Sep',
 
402
'Oct',
 
403
'Nov',
 
404
'Dec',
 
405
'Navigation',
 
406
'File type',
 
407
'Update now',
 
408
'Bandwidth',
 
409
'Back to main page',
 
410
'Top',
 
411
'dd mmm yyyy - HH:MM',
 
412
'Filter',
 
413
'Full list',
 
414
'Hosts',
 
415
'Known',
 
416
'Robots',
 
417
'Sun',
 
418
'Mon',
 
419
'Tue',
 
420
'Wed',
 
421
'Thu',
 
422
'Fri',
 
423
'Sat',
 
424
'Days of week',
 
425
'Who',
 
426
'When',
 
427
'Authenticated users',
 
428
'Min',
 
429
'Average',
 
430
'Max',
 
431
'Web compression',
 
432
'Bandwidth saved',
 
433
'Compression on',
 
434
'Compression result',
 
435
'Total',
 
436
'different keyphrases',
 
437
'Entry',
 
438
'Code',
 
439
'Average size',
 
440
'Links from a NewsGroup',
 
441
'KB',
 
442
'MB',
 
443
'GB',
 
444
'Grabber',
 
445
'Yes',
 
446
'No',
 
447
'Info.',
 
448
'OK',
 
449
'Exit',
 
450
'Visits duration',
 
451
'Close window',
 
452
'Bytes',
 
453
'Search Keyphrases',
 
454
'Search Keywords',
 
455
'different refering search engines',
 
456
'different refering sites',
 
457
'Other phrases',
 
458
'Other logins (and/or anonymous users)',
 
459
'Refering search engines',
 
460
'Refering sites',
 
461
'Summary',
 
462
'Exact value not available in "Year" view',
 
463
'Data value arrays',
 
464
'Sender EMail',
 
465
'Receiver EMail',
 
466
'Reported period',
 
467
'Extra/Marketing',
 
468
'Screen sizes',
 
469
'Worm/Virus attacks',
 
470
'Add to favorites (estimated)',
 
471
'Days of month',
 
472
'Miscellaneous',
 
473
'Browsers with Java support',
 
474
'Browsers with Macromedia Director Support',
 
475
'Browsers with Flash Support',
 
476
'Browsers with Real audio playing support',
 
477
'Browsers with Quictime audio playing support',
 
478
'Browsers with Windows Media audio playing support',
 
479
'Browsers with PDF support',
 
480
'SMTP Error codes',
 
481
'Countries',
 
482
'Mails',
 
483
'Size',
 
484
'First',
 
485
'Last',
 
486
'Exclude filter',
 
487
'Codes shown here gave hits or traffic "not viewed" by visitors, so they are not included in other charts.',
 
488
'Cluster',
 
489
'Robots shown here gave hits or traffic "not viewed" by visitors, so they are not included in other charts.',
 
490
'Numbers after + are successful hits on "robots.txt" files',
 
491
'Worms shown here gave hits or traffic "not viewed" by visitors, so thay are not included in other charts.',
 
492
'Not viewed trafic is trafic generated by robots, worms or answers with special HTTP status code',
 
493
'Traffic viewed',
 
494
'Traffic not viewed',
 
495
'Monthly history',
 
496
'Worms',
 
497
'different worms'
 
498
);
 
499
 
 
500
 
 
501
 
 
502
#------------------------------------------------------------------------------
 
503
# Functions
 
504
#------------------------------------------------------------------------------
 
505
 
 
506
#------------------------------------------------------------------------------
 
507
# Function:             Write on ouput header of HTML page
 
508
# Parameters:   None
 
509
# Input:                %HTMLOutput $PluginMode $Expires $Lang $StyleSheet $HTMLHeadSection $PageCode $PageDir
 
510
# Output:               $HeaderHTMLComplete=1
 
511
# Return:               None
 
512
#------------------------------------------------------------------------------
 
513
sub html_head {
 
514
        my $dir=$PageDir?'right':'left';
 
515
        if (scalar keys %HTMLOutput || $PluginMode) {
 
516
                my $MetaRobot=0;        # meta robots
 
517
                # Write head section
 
518
                if ($BuildReportFormat eq 'xml') {
 
519
                        if ($PageCode) { print "<?xml version=\"1.0\" encoding=\"$PageCode\"?>\n"; }
 
520
                        else { print "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"; };
 
521
            if ($FrameName ne 'index') { print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";  }
 
522
                        else { print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">\n"; }
 
523
                        print "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"$Lang\">\n";
 
524
                } else {
 
525
                        if ($FrameName ne 'index') { print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\n";  }
 
526
                        else { print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">\n\n"; }
 
527
                        print "<html lang='$Lang'".($PageDir?" dir='rtl'":"").">\n";
 
528
                }
 
529
                print "<head>\n";
 
530
                if ($MetaRobot) { print "<meta name=\"robots\" content=\"".($FrameName eq 'mainleft'?'no':'')."index,nofollow\" />\n"; }
 
531
                else { print "<meta name=\"robots\" content=\"noindex,nofollow\" />\n"; }
 
532
 
 
533
                # Affiche tag meta content-type
 
534
                if ($BuildReportFormat eq 'xml') { print ($ENV{'HTTP_USER_AGENT'}=~/MSIE|Googlebot/i?"<meta http-equiv=\"content-type\" content=\"text/html; charset=".($PageCode?$PageCode:"iso-8859-1")."\" />\n":"<meta http-equiv=\"content-type\" content=\"text/xml; charset=".($PageCode?$PageCode:"iso-8859-1")."\" />\n"); }
 
535
                else { print "<meta http-equiv=\"content-type\" content=\"text/html; charset=".($PageCode?$PageCode:"iso-8859-1")."\" />\n"; }
 
536
 
 
537
                if ($Expires)  { print "<meta http-equiv=\"expires\" content=\"".(gmtime($starttime+$Expires))."\" />\n"; }
 
538
                print "<meta http-equiv=\"description\" content=\"".ucfirst($PROG)." - Advanced Web Statistics for $SiteDomain\" />\n";
 
539
                if ($MetaRobot && $FrameName ne 'mainleft') { print "<meta http-equiv=\"keywords\" content=\"$SiteDomain, free, advanced, realtime, web, server, logfile, log, analyzer, analysis, statistics, stats, perl, analyse, performance, hits, visits\" />\n"; }
 
540
                print "<title>$Message[7] $SiteDomain</title>\n";
 
541
                if ($FrameName ne 'index') {
 
542
 
 
543
                        # A STYLE section must be in head section. Do not use " for number in a style section
 
544
                        print "<style type=\"text/css\">\n";
 
545
                        if ($BuildReportFormat eq 'xml') { print ($ENV{'HTTP_USER_AGENT'}=~/Firebird/i?"<!--\n":"<![CDATA[\n"); }
 
546
                        else { print "<!--\n"; }
 
547
print "body { font: 11px verdana, arial, helvetica, sans-serif; background-color: #$color_Background; margin-top: 0; margin-bottom: 0; }\n";
 
548
print ".aws_bodyl  { }\n";
 
549
print ".aws_border { background-color: #$color_TableBG; padding: 1px 1px ".($BuildReportFormat eq 'xml'?"2px":"1px")." 1px; margin-top: 0; margin-bottom: 0; }\n";
 
550
print ".aws_title  { font: 13px verdana, arial, helvetica, sans-serif; font-weight: bold; background-color: #$color_TableBGTitle; text-align: center; margin-top: 0; margin-bottom: 0; padding: 1px 1px 1px 1px; }\n";
 
551
print ".aws_blank  { font: 13px verdana, arial, helvetica, sans-serif; background-color: #".($ENV{'HTTP_USER_AGENT'} && $ENV{'HTTP_USER_AGENT'}=~/MSIE/i?$color_Background:$color_TableBG)."; text-align: center; margin-bottom: 0; padding: 1px 1px 1px 1px; }\n";
 
552
print <<EOF;
 
553
.aws_data {
 
554
        background-color: #$color_Background;
 
555
        border-top-width: 1px;   
 
556
        border-left-width: 0px;  
 
557
        border-right-width: 0px; 
 
558
        border-bottom-width: 0px;
 
559
}
 
560
.aws_formfield { font: 13px verdana, arial, helvetica; }
 
561
.aws_button {
 
562
        font-family: arial,verdana,helvetica, sans-serif;
 
563
        font-size: 12px;
 
564
        border: 1px solid #ccd7e0;
 
565
        background-image : url($DirIcons/other/button.gif);
 
566
}
 
567
th              { border-color: #$color_TableBorder; border-left-width: 0px; border-right-width: 1px; border-top-width: 0px; border-bottom-width: 1px; padding: 1px 2px 1px 1px; font: 11px verdana, arial, helvetica, sans-serif; text-align:center; color: #$color_titletext; }
 
568
th.aws  { border-color: #$color_TableBorder; border-left-width: 0px; border-right-width: 1px; border-top-width: 0px; border-bottom-width: 1px; padding: 1px 2px 1px 1px; font-size: 13px; font-weight: bold; }
 
569
td              { border-color: #$color_TableBorder; border-left-width: 0px; border-right-width: 1px; border-top-width: 0px; border-bottom-width: 1px; padding: 1px 1px 1px 1px; font: 11px verdana, arial, helvetica, sans-serif; text-align:center; color: #$color_text; }
 
570
td.aws  { border-color: #$color_TableBorder; border-left-width: 0px; border-right-width: 1px; border-top-width: 0px; border-bottom-width: 1px; padding: 1px 1px 1px 1px; font: 11px verdana, arial, helvetica, sans-serif; text-align:$dir; color: #$color_text; }
 
571
td.awsm { border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; padding: 0px 0px 0px 0px; font: 11px verdana, arial, helvetica, sans-serif; text-align:$dir; color: #$color_text; }
 
572
b { font-weight: bold; }
 
573
a { font: 11px verdana, arial, helvetica, sans-serif; }
 
574
a:link    { color: #$color_link; text-decoration: none; }
 
575
a:visited { color: #$color_link; text-decoration: none; }
 
576
a:hover   { color: #$color_hover; text-decoration: underline; }
 
577
EOF
 
578
                        # Call to plugins' function AddHTMLStyles
 
579
                        foreach my $pluginname (keys %{$PluginsLoaded{'AddHTMLStyles'}})  {
 
580
                                my $function="AddHTMLStyles_$pluginname()";
 
581
                                eval("$function");
 
582
                        }
 
583
        
 
584
                        if ($BuildReportFormat eq 'xml') { print ($ENV{'HTTP_USER_AGENT'}=~/Firebird/i?"//-->\n":"]]>\n"); }
 
585
                        else { print "//-->\n"; }
 
586
                        print "</style>\n";
 
587
 
 
588
                        if ($StyleSheet) {
 
589
                                print "<link rel=\"stylesheet\" href=\"$StyleSheet\" />\n";
 
590
                        }
 
591
                }
 
592
                print "</head>\n\n";
 
593
                if ($FrameName ne 'index') {
 
594
                        print "<body style=\"margin-top: 0px\"";
 
595
                        if ($FrameName eq 'mainleft') { print " class=\"aws_bodyl\""; }
 
596
                        print ">\n";
 
597
                }
 
598
        }
 
599
        $HeaderHTMLComplete=1;
 
600
}
 
601
 
 
602
#------------------------------------------------------------------------------
 
603
# Function:             Write on ouput end of HTML page
 
604
# Parameters:   0|1 (0=no list plugins,1=list plugins)
 
605
# Input:                %HTMLOutput $HTMLEndSection $FrameName $BuildReportFormat
 
606
# Output:               None
 
607
# Return:               None
 
608
#------------------------------------------------------------------------------
 
609
sub html_end {
 
610
        my $listplugins=shift||0;
 
611
        if (scalar keys %HTMLOutput) {
 
612
                if ($FrameName ne 'index' && $FrameName ne 'mainleft') {
 
613
                        print "$Center<br /><br />\n";
 
614
                        print "<span dir=\"ltr\" style=\"font: 11px verdana, arial, helvetica; color: #$color_text;\">";
 
615
                        print "<b>Advanced Web Statistics $VERSION</b> - <a href=\"http://awstats.sourceforge.net\" target=\"awstatshome\">Created by $PROG";
 
616
                        if ($listplugins) {
 
617
                                my $atleastoneplugin=0;
 
618
                                foreach my $pluginname (keys %{$PluginsLoaded{'init'}}) {
 
619
                                        if (! $atleastoneplugin) { $atleastoneplugin=1; print " (with plugin "; }
 
620
                                        else { print ", "; }
 
621
                                        print "$pluginname";
 
622
                                }
 
623
                                if ($atleastoneplugin) { print ")"; }
 
624
                        }
 
625
                        print "</a></span><br />\n";
 
626
                        if ($HTMLEndSection) { print "<br />\n$HTMLEndSection\n"; }
 
627
                }
 
628
                print "\n";
 
629
                if ($FrameName ne 'index') {
 
630
                        if ($FrameName ne 'mainleft' && $BuildReportFormat eq 'html') { print "<br />\n"; }
 
631
                        print "</body>\n";
 
632
                }
 
633
                print "</html>\n";
 
634
#               print "<!-- NEW PAGE --><!-- NEW SHEET -->\n";
 
635
        }
 
636
}
 
637
 
 
638
#------------------------------------------------------------------------------
 
639
# Function:             Print on stdout tab header of a chart
 
640
# Parameters:   $title $tooltip_number [$width percentage of chart title]
 
641
# Input:                None
 
642
# Output:               None
 
643
# Return:               None
 
644
#------------------------------------------------------------------------------
 
645
sub tab_head {
 
646
        my $title=shift;
 
647
        my $tooltip=shift;
 
648
        my $width=shift||70;
 
649
        my $class=shift;
 
650
        if ($width == 70 && $QueryString =~ /buildpdf/i) { print "<table class=\"aws_border\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\" width=\"800\">\n"; }
 
651
        else { print "<table class=\"aws_border\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">\n"; }
 
652
 
 
653
        if ($tooltip) {
 
654
                print "<tr><td class=\"aws_title\" width=\"$width%\"".($TOOLTIPON?" onmouseover=\"ShowTip($tooltip);\" onmouseout=\"HideTip($tooltip);\"":"").">$title </td>";
 
655
        }
 
656
        else {
 
657
                print "<tr><td class=\"aws_title\" width=\"$width%\">$title </td>";
 
658
        }
 
659
        print "<td class=\"aws_blank\">&nbsp;</td></tr>\n";
 
660
        print "<tr><td colspan=\"2\">\n";
 
661
        if ($width == 70 && $QueryString =~ /buildpdf/i) { print "<table class=\"aws_data $class\" border=\"2\" bordercolor=\"#$color_TableBorder\" cellpadding=\"2\" cellspacing=\"0\" width=\"796\">\n"; }
 
662
        else { print "<table class=\"aws_data $class\" border=\"2\" bordercolor=\"#$color_TableBorder\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">\n"; }
 
663
}
 
664
 
 
665
#------------------------------------------------------------------------------
 
666
# Function:             Print on stdout tab ender of a chart
 
667
# Parameters:   None
 
668
# Input:                None
 
669
# Output:               None
 
670
# Return:               None
 
671
#------------------------------------------------------------------------------
 
672
sub tab_end {
 
673
        my $string=shift;
 
674
        print "</table></td></tr></table>";
 
675
        if ($string) { print "<span style=\"font: 11px verdana, arial, helvetica;\">$string</span><br />\n"; }
 
676
        print "<br />\n\n";
 
677
}
 
678
 
 
679
#------------------------------------------------------------------------------
 
680
# Function:             Write error message and exit
 
681
# Parameters:   $message $secondmessage $thirdmessage $donotshowsetupinfo
 
682
# Input:                $HeaderHTTPComplete $HeaderHTMLComplete %HTMLOutput $LogSeparator $LogFormat
 
683
# Output:               None
 
684
# Return:               None
 
685
#------------------------------------------------------------------------------
 
686
sub error {
 
687
        my $message=shift||''; if (scalar keys %HTMLOutput) { $message =~ s/\</&lt;/g; $message =~ s/\>/&gt;/g; }
 
688
        my $secondmessage=shift||'';
 
689
        my $thirdmessage=shift||'';
 
690
        my $donotshowsetupinfo=shift||0;
 
691
 
 
692
        if (! $HeaderHTTPComplete && $ENV{'GATEWAY_INTERFACE'}) { print "\n"; $HeaderHTTPComplete=1; }
 
693
        if (! $HeaderHTMLComplete && scalar keys %HTMLOutput)   { print "<html><body>\n"; $HeaderHTMLComplete=1; }
 
694
        if ($Debug) { debug("$message $secondmessage $thirdmessage",1); }
 
695
        my $tagbold=''; my $tagunbold=''; my $tagbr=''; my $tagfontred=''; my $tagfontgrey=''; my $tagunfont='';
 
696
        if (scalar keys %HTMLOutput) {
 
697
                $tagbold='<b>'; $tagunbold='</b>'; $tagbr='<br />';
 
698
                $tagfontred='<span style="color: #880000">';
 
699
                $tagfontgrey='<span style="color: #888888">';
 
700
                $tagunfont='</span>';
 
701
        }
 
702
        if (! $ErrorMessages && $message =~ /^Format error$/i) {
 
703
                # Files seems to have bad format
 
704
                if (scalar keys %HTMLOutput) { print "<br /><br />\n"; }
 
705
                if ($message !~ $LogSeparator) {
 
706
                        # Bad LogSeparator parameter
 
707
                        print "${tagfontred}AWStats did not found the ${tagbold}LogSeparator${tagunbold} in your log records.${tagbr}${tagunfont}\n";
 
708
                }
 
709
                else {
 
710
                        # Bad LogFormat parameter
 
711
                        print "AWStats did not find any valid log lines that match your ${tagbold}LogFormat${tagunbold} parameter, in the ${NbOfLinesForCorruptedLog}th first non commented lines read of your log.${tagbr}\n";
 
712
                        print "${tagfontred}Your log file ${tagbold}$thirdmessage${tagunbold} must have a bad format or ${tagbold}LogFormat${tagunbold} parameter setup does not match this format.${tagbr}${tagbr}${tagunfont}\n";
 
713
                        print "Your AWStats ${tagbold}LogFormat${tagunbold} parameter is:\n";
 
714
                        print "${tagbold}$LogFormat${tagunbold}${tagbr}\n";
 
715
                        print "This means each line in your web server log file need to have ";
 
716
                        if ($LogFormat == 1) {
 
717
                                print "${tagbold}\"combined log format\"${tagunbold} like this:${tagbr}\n";
 
718
                                print (scalar keys %HTMLOutput?"$tagfontgrey<i>":"");
 
719
                                print "111.22.33.44 - - [10/Jan/2001:02:14:14 +0200] \"GET / HTTP/1.1\" 200 1234 \"http://www.fromserver.com/from.htm\" \"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\"\n";
 
720
                                print (scalar keys %HTMLOutput?"</i>$tagunfont${tagbr}${tagbr}\n":"");
 
721
                        }
 
722
                        if ($LogFormat == 2) {
 
723
                                print "${tagbold}\"MSIE Extended W3C log format\"${tagunbold} like this:${tagbr}\n";
 
724
                                print (scalar keys %HTMLOutput?"$tagfontgrey<i>":"");
 
725
                                print "date time c-ip c-username cs-method cs-uri-sterm sc-status sc-bytes cs-version cs(User-Agent) cs(Referer)\n";
 
726
                                print (scalar keys %HTMLOutput?"</i>$tagunfont${tagbr}${tagbr}\n":"");
 
727
                        }
 
728
                        if ($LogFormat == 3) {
 
729
                                print "${tagbold}\"WebStar native log format\"${tagunbold}${tagbr}\n";
 
730
                        }
 
731
                        if ($LogFormat == 4) {
 
732
                                print "${tagbold}\"common log format\"${tagunbold} like this:${tagbr}\n";
 
733
                                print (scalar keys %HTMLOutput?"$tagfontgrey<i>":"");
 
734
                                print "111.22.33.44 - - [10/Jan/2001:02:14:14 +0200] \"GET / HTTP/1.1\" 200 1234\n";
 
735
                                print (scalar keys %HTMLOutput?"</i>$tagunfont${tagbr}${tagbr}\n":"");
 
736
                        }
 
737
                        if ($LogFormat == 5) {
 
738
                                print "${tagbold}\"ISA native log format\"${tagunbold}${tagbr}\n";
 
739
                        }
 
740
                        if ($LogFormat == 6) {
 
741
                                print "${tagbold}\"Lotus Notes/Lotus Domino\"${tagunbold}${tagbr}\n";
 
742
                                print (scalar keys %HTMLOutput?"$tagfontgrey<i>":"");
 
743
                                print "111.22.33.44 - Firstname Middlename Lastname [10/Jan/2001:02:14:14 +0200] \"GET / HTTP/1.1\" 200 1234 \"http://www.fromserver.com/from.htm\" \"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\"\n";
 
744
                                print (scalar keys %HTMLOutput?"</i></span>${tagbr}${tagbr}\n":"");
 
745
                        }
 
746
                        if ($LogFormat !~ /^[1-6]$/) {
 
747
                                print "the following personalized log format:${tagbr}\n";
 
748
                                print (scalar keys %HTMLOutput?"$tagfontgrey<i>":"");
 
749
                                print "$LogFormat\n";
 
750
                                print (scalar keys %HTMLOutput?"</i>$tagunfont${tagbr}${tagbr}\n":"");
 
751
                        }
 
752
                        print "And this is a sample of records AWStats found in your log file (the record number $NbOfLinesForCorruptedLog in your log):\n";
 
753
                        print (scalar keys %HTMLOutput?"<br />$tagfontgrey<i>":"");
 
754
                        print "$secondmessage";
 
755
                        print (scalar keys %HTMLOutput?"</i>$tagunfont${tagbr}${tagbr}":"");
 
756
                        print "\n";
 
757
                }
 
758
                #print "Note: If your $NbOfLinesForCorruptedLog first lines in your log files are wrong because of ";
 
759
                #print "a worm virus attack, you can increase the NbOfLinesForCorruptedLog parameter in config file.\n";
 
760
                #print "\n";
 
761
        }
 
762
        else {
 
763
                print (scalar keys %HTMLOutput?"<br />$tagfontred\n":"");
 
764
                print ($ErrorMessages?"$ErrorMessages":"Error: $message");
 
765
                print (scalar keys %HTMLOutput?"\n</span><br />":"");
 
766
                print "\n";
 
767
        }
 
768
        if (! $ErrorMessages && ! $donotshowsetupinfo) {
 
769
                if ($message =~ /Couldn.t open config file/i) {
 
770
                        my $dir=$DIR;
 
771
                        if ($dir =~ /^\./) { $dir.='/../..'; }
 
772
                        else { $dir =~ s/[\\\/]?wwwroot[\/\\]cgi-bin[\\\/]?//; }
 
773
                        print "${tagbr}\n";
 
774
                        if ($ENV{'GATEWAY_INTERFACE'}) {
 
775
                                print "- ${tagbold}Did you use the correct URL ?${tagunbold}${tagbr}\n";
 
776
                                print "Example: http://localhost/awstats/awstats.pl?config=mysite${tagbr}\n";
 
777
                                print "Example: http://127.0.0.1/cgi-bin/awstats.pl?config=mysite${tagbr}\n";
 
778
                        } else {
 
779
                                print "- ${tagbold}Did you use correct config parameter ?${tagunbold}${tagbr}\n";
 
780
                                print "Example: If your config file is awstats.mysite.conf, you must use -config=mysite\n";
 
781
                        }
 
782
                        print "- ${tagbold}Did you create your config file 'awstats.$SiteConfig.conf' ?${tagunbold}${tagbr}\n";
 
783
                        print "If not, you can run \"$dir/tools/configure.pl\"${tagbr}\n";
 
784
                        print "${tagbr}\n";
 
785
                }
 
786
                else { print "${tagbr}${tagbold}Setup (".($FileConfig?"'".$FileConfig."'":"Config")." file, web server or permissions) may be wrong.${tagunbold}${tagbr}\n"; }
 
787
                print "See AWStats documentation in 'docs' directory for informations on how to setup $PROG.\n";
 
788
        }
 
789
        # Remove lock if not a lock message 
 
790
        if ($EnableLockForUpdate && $message !~ /lock file/) { &Lock_Update(0); }
 
791
        if (scalar keys %HTMLOutput) { print "</body></html>\n"; }
 
792
        exit 1;
 
793
}
 
794
 
 
795
#------------------------------------------------------------------------------
 
796
# Function:             Write a warning message
 
797
# Parameters:   $message
 
798
# Input:                $HeaderHTTPComplete $HeaderHTMLComplete $WarningMessage %HTMLOutput
 
799
# Output:               None
 
800
# Return:               None
 
801
#------------------------------------------------------------------------------
 
802
sub warning {
 
803
        my $messagestring=shift;
 
804
 
 
805
        if (! $HeaderHTTPComplete && $ENV{'GATEWAY_INTERFACE'}) { print "\n"; $HeaderHTTPComplete=1; }
 
806
        if (! $HeaderHTMLComplete) { html_head(); }
 
807
        if ($Debug) { debug("$messagestring",1); }
 
808
        if ($WarningMessages) {
 
809
                if (scalar keys %HTMLOutput) {
 
810
                        $messagestring =~ s/\n/\<br\>/g;
 
811
                        print "$messagestring<br />\n";
 
812
                }
 
813
                else {
 
814
                        print "$messagestring\n";
 
815
                }
 
816
        }
 
817
}
 
818
 
 
819
#------------------------------------------------------------------------------
 
820
# Function:     Write debug message and exit
 
821
# Parameters:   $string $level
 
822
# Input:        %HTMLOutput  $Debug=required level  $DEBUGFORCED=required level forced
 
823
# Output:               None
 
824
# Return:               None
 
825
#------------------------------------------------------------------------------
 
826
sub debug {
 
827
        my $level = $_[1] || 1;
 
828
        if ($level <= $DEBUGFORCED) {
 
829
                my $debugstring = $_[0];
 
830
                if (! $DebugResetDone) { open(DEBUGFORCEDFILE,"debug.log"); close DEBUGFORCEDFILE; chmod 0666,"debug.log"; $DebugResetDone=1; }
 
831
                open(DEBUGFORCEDFILE,">>debug.log");
 
832
                print DEBUGFORCEDFILE localtime(time)." - $$ - DEBUG $level - $debugstring\n";
 
833
                close DEBUGFORCEDFILE;
 
834
        }
 
835
        if ($DebugMessages && $level <= $Debug) {
 
836
                my $debugstring = $_[0];
 
837
                if (scalar keys %HTMLOutput) { $debugstring =~ s/^ /&nbsp;&nbsp; /; $debugstring .= "<br />"; }
 
838
                print localtime(time)." - DEBUG $level - $debugstring\n";
 
839
        }
 
840
}
 
841
 
 
842
#------------------------------------------------------------------------------
 
843
# Function:     Optimize an array removing duplicate entries
 
844
# Parameters:   @Array notcasesensitive=0|1
 
845
# Input:        None
 
846
# Output:               None
 
847
# Return:               None
 
848
#------------------------------------------------------------------------------
 
849
sub OptimizeArray {
 
850
        my $array=shift;
 
851
        my @arrayunreg=map{if (/\(\?[-\w]*:(.*)\)/) { $1 } } @$array;
 
852
        my $notcasesensitive=shift;
 
853
        my $searchlist=0;
 
854
        if ($Debug) { debug("OptimizeArray (notcasesensitive=$notcasesensitive)",4); }
 
855
        while ($searchlist>-1 && @arrayunreg) {
 
856
                my $elemtoremove=-1;
 
857
                OPTIMIZELOOP:
 
858
                foreach my $i ($searchlist..(scalar @arrayunreg)-1) {
 
859
                        # Search if $i elem is already treated by another elem
 
860
                        foreach my $j (0..(scalar @arrayunreg)-1) {
 
861
                                if ($i == $j) { next; }
 
862
                                my $parami=$notcasesensitive?lc($arrayunreg[$i]):$arrayunreg[$i];
 
863
                                my $paramj=$notcasesensitive?lc($arrayunreg[$j]):$arrayunreg[$j];
 
864
                                if ($Debug) { debug(" Compare $i ($parami) to $j ($paramj)",4); }
 
865
                                if (index($parami,$paramj)>-1) {
 
866
                                        if ($Debug) { debug(" Elem $i ($arrayunreg[$i]) already treated with elem $j ($arrayunreg[$j])",4); }
 
867
                                        $elemtoremove=$i;
 
868
                                        last OPTIMIZELOOP;
 
869
                                }
 
870
                        }
 
871
                }
 
872
                if ($elemtoremove > -1) {
 
873
                        if ($Debug) { debug(" Remove elem $elemtoremove - $arrayunreg[$elemtoremove]",4); }
 
874
                        splice @arrayunreg, $elemtoremove, 1;
 
875
                        $searchlist=$elemtoremove;
 
876
                }
 
877
                else {
 
878
                        $searchlist=-1;
 
879
                }
 
880
        }
 
881
        if ($notcasesensitive) { return map{qr/$_/i} @arrayunreg; }
 
882
        return map{qr/$_/} @arrayunreg;
 
883
}
 
884
 
 
885
#------------------------------------------------------------------------------
 
886
# Function:     Check if parameter is in SkipDNSLookupFor array
 
887
# Parameters:   ip @SkipDNSLookupFor (a NOT case sensitive precompiled regex array)
 
888
# Return:               0 Not found, 1 Found
 
889
#------------------------------------------------------------------------------
 
890
sub SkipDNSLookup {
 
891
        foreach (@SkipDNSLookupFor) { if ($_[0] =~ /$_/) { return 1; } }
 
892
        0; # Not in @SkipDNSLookupFor
 
893
}
 
894
 
 
895
#------------------------------------------------------------------------------
 
896
# Function:     Check if parameter is in SkipHosts array
 
897
# Parameters:   host @SkipHosts (a NOT case sensitive precompiled regex array)
 
898
# Return:               0 Not found, 1 Found
 
899
#------------------------------------------------------------------------------
 
900
sub SkipHost {
 
901
        foreach (@SkipHosts) { if ($_[0] =~ /$_/) { return 1; } }
 
902
        0; # Not in @SkipHosts
 
903
}
 
904
 
 
905
#------------------------------------------------------------------------------
 
906
# Function:     Check if parameter is in SkipUserAgents array
 
907
# Parameters:   useragent @SkipUserAgents (a NOT case sensitive precompiled regex array)
 
908
# Return:               0 Not found, 1 Found
 
909
#------------------------------------------------------------------------------
 
910
sub SkipUserAgent {
 
911
        foreach (@SkipUserAgents) { if ($_[0] =~ /$_/) { return 1; } }
 
912
        0; # Not in @SkipUserAgent
 
913
}
 
914
 
 
915
#------------------------------------------------------------------------------
 
916
# Function:     Check if parameter is in SkipFiles array
 
917
# Parameters:   url @SkipFiles (a NOT case sensitive precompiled regex array)
 
918
# Return:               0 Not found, 1 Found
 
919
#------------------------------------------------------------------------------
 
920
sub SkipFile {
 
921
        foreach (@SkipFiles) { if ($_[0] =~ /$_/) { return 1; } }
 
922
        0; # Not in @SkipFiles
 
923
}
 
924
 
 
925
#------------------------------------------------------------------------------
 
926
# Function:     Check if parameter is in OnlyHosts array
 
927
# Parameters:   host @OnlyHosts (a NOT case sensitive precompiled regex array)
 
928
# Return:               0 Not found, 1 Found
 
929
#------------------------------------------------------------------------------
 
930
sub OnlyHost {
 
931
        foreach (@OnlyHosts) { if ($_[0] =~ /$_/) { return 1; } }
 
932
        0; # Not in @OnlyHosts
 
933
}
 
934
 
 
935
#------------------------------------------------------------------------------
 
936
# Function:     Check if parameter is in OnlyUserAgents array
 
937
# Parameters:   useragent @OnlyUserAgents (a NOT case sensitive precompiled regex array)
 
938
# Return:               0 Not found, 1 Found
 
939
#------------------------------------------------------------------------------
 
940
sub OnlyUserAgent {
 
941
        foreach (@OnlyUserAgents) { if ($_[0] =~ /$_/) { return 1; } }
 
942
        0; # Not in @OnlyHosts
 
943
}
 
944
 
 
945
#------------------------------------------------------------------------------
 
946
# Function:     Check if parameter is in OnlyFiles array
 
947
# Parameters:   url @OnlyFiles (a NOT case sensitive precompiled regex array)
 
948
# Return:               0 Not found, 1 Found
 
949
#------------------------------------------------------------------------------
 
950
sub OnlyFile {
 
951
        foreach (@OnlyFiles) { if ($_[0] =~ /$_/) { return 1; } }
 
952
        0; # Not in @OnlyFiles
 
953
}
 
954
 
 
955
#------------------------------------------------------------------------------
 
956
# Function:     Return day of week of a day
 
957
# Parameters:   $day $month $year
 
958
# Return:               0-6
 
959
#------------------------------------------------------------------------------
 
960
sub DayOfWeek {
 
961
        my ($day, $month, $year) = @_;
 
962
        if ($Debug) { debug("DayOfWeek for $day $month $year",4); }
 
963
        if ($month < 3) {  $month += 10;  $year--; }
 
964
        else { $month -= 2; }
 
965
        my $cent = sprintf("%1i",($year/100));
 
966
        my $y = ($year % 100);
 
967
        my $dw = (sprintf("%1i",(2.6*$month)-0.2) + $day + $y + sprintf("%1i",($y/4)) + sprintf("%1i",($cent/4)) - (2*$cent)) % 7;
 
968
        $dw += 7 if ($dw<0);
 
969
        if ($Debug) { debug(" is $dw",4); }
 
970
        return $dw;
 
971
}
 
972
 
 
973
#------------------------------------------------------------------------------
 
974
# Function:     Return 1 if a date exists
 
975
# Parameters:   $day $month $year
 
976
# Return:               1 if date exists else 0
 
977
#------------------------------------------------------------------------------
 
978
sub DateIsValid {
 
979
        my ($day, $month, $year) = @_;
 
980
        if ($Debug) { debug("DateIsValid for $day $month $year",4); }
 
981
        if ($day < 1)  { return 0; }
 
982
        if ($day > 31) { return 0; }
 
983
        if ($month==4 || $month==6 || $month==9 || $month==11) {
 
984
                if ($day > 30) { return 0; }
 
985
        }
 
986
        elsif ($month==2) {
 
987
                my $leapyear=($year%4==0?1:0);                                          # A leap year every 4 years
 
988
                if ($year%100==0 && $year%400!=0) { $leapyear=0; }      # Except if year is 100x and not 400x
 
989
                if ($day > (28+$leapyear)) { return 0; }
 
990
        }
 
991
        return 1;
 
992
}
 
993
 
 
994
#------------------------------------------------------------------------------
 
995
# Function:     Return string of visit duration
 
996
# Parameters:   $starttime $endtime
 
997
# Input:        None
 
998
# Output:               None
 
999
# Return:               A string that identify the visit duration range
 
1000
#------------------------------------------------------------------------------
 
1001
sub GetSessionRange {
 
1002
        my $starttime = my $endtime;
 
1003
        if (shift =~ /(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/) { $starttime = Time::Local::timelocal($6,$5,$4,$3,$2-1,$1); }
 
1004
        if (shift =~ /(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/) { $endtime = Time::Local::timelocal($6,$5,$4,$3,$2-1,$1); }
 
1005
        my $delay=$endtime-$starttime;
 
1006
        if ($Debug) { debug("GetSessionRange $endtime - $starttime = $delay",4); }
 
1007
        if ($delay <= 30) { return $SessionsRange[0]; }
 
1008
        if ($delay > 30 && $delay <= 120) { return $SessionsRange[1]; }
 
1009
        if ($delay > 120 && $delay <= 300) { return $SessionsRange[2]; }
 
1010
        if ($delay > 300 && $delay <= 900) { return $SessionsRange[3]; }
 
1011
        if ($delay > 900 && $delay <= 1800) { return $SessionsRange[4]; }
 
1012
        if ($delay > 1800 && $delay <= 3600) { return $SessionsRange[5]; }
 
1013
        if ($delay > 3600) { return $SessionsRange[6]; }
 
1014
        return "error";
 
1015
}
 
1016
 
 
1017
#------------------------------------------------------------------------------
 
1018
# Function:     Read config file
 
1019
# Parameters:   None or configdir to scan
 
1020
# Input:        $DIR $PROG $SiteConfig
 
1021
# Output:               Global variables
 
1022
# Return:               -
 
1023
#------------------------------------------------------------------------------
 
1024
sub Read_Config {
 
1025
        # Check config file in common possible directories :
 
1026
        # Windows :                                             "$DIR" (same dir than awstats.pl)
 
1027
        # Standard, Mandrake and Debian package :       "/etc/awstats"
 
1028
        # Other possible directories :                          "/usr/local/etc/awstats", "/etc"
 
1029
        # FHS standard, Suse package :                          "/etc/opt/awstats"
 
1030
        my $configdir=shift;
 
1031
        my @PossibleConfigDir=();
 
1032
 
 
1033
        if ($configdir) { @PossibleConfigDir=("$configdir"); }
 
1034
        else { @PossibleConfigDir=("$DIR","/etc/awstats","/usr/local/etc/awstats","/etc","/etc/opt/awstats"); }
 
1035
 
 
1036
        # Open config file
 
1037
        $FileConfig=$FileSuffix='';
 
1038
        foreach (@PossibleConfigDir) {
 
1039
                my $searchdir=$_;
 
1040
                if ($searchdir && $searchdir !~ /[\\\/]$/) { $searchdir .= "/"; }
 
1041
                if (open(CONFIG,"$searchdir$PROG.$SiteConfig.conf"))    { $FileConfig="$searchdir$PROG.$SiteConfig.conf"; $FileSuffix=".$SiteConfig"; last; }
 
1042
                if (open(CONFIG,"$searchdir$PROG.conf"))                                { $FileConfig="$searchdir$PROG.conf"; $FileSuffix=''; last; }
 
1043
        }
 
1044
        if (! $FileConfig) { error("Couldn't open config file \"$PROG.$SiteConfig.conf\" nor \"$PROG.conf\" after searching in path \"".join(',',@PossibleConfigDir)."\": $!"); }
 
1045
 
 
1046
        # Analyze config file content and close it
 
1047
        &Parse_Config( *CONFIG , 1 , $FileConfig);
 
1048
        close CONFIG;
 
1049
        
 
1050
        # If parameter NotPageList not found, init for backward compatibility
 
1051
        if (! $FoundNotPageList) {
 
1052
                $NotPageList{'gif'}=$NotPageList{'jpg'}=$NotPageList{'jpeg'}=$NotPageList{'png'}=$NotPageList{'bmp'}=1;
 
1053
        }
 
1054
        # If parameter ValidHTTPCodes not found, init for backward compatibility
 
1055
        if (! $FoundValidHTTPCodes) {
 
1056
                $ValidHTTPCodes{"200"}=$ValidHTTPCodes{"304"}=1;
 
1057
        }
 
1058
        # If parameter ValidSMTPCodes not found, init for backward compatibility
 
1059
        if (! $FoundValidSMTPCodes) {
 
1060
                $ValidSMTPCodes{"1"}=$ValidSMTPCodes{"250"}=1;
 
1061
        }
 
1062
}
 
1063
 
 
1064
#------------------------------------------------------------------------------
 
1065
# Function:     Parse content of a config file
 
1066
# Parameters:   opened file handle, depth level, file name
 
1067
# Input:        -
 
1068
# Output:               Global variables
 
1069
# Return:               -
 
1070
#------------------------------------------------------------------------------
 
1071
sub Parse_Config {
 
1072
    my ( $confighandle ) = $_[0];
 
1073
        my $level = $_[1];
 
1074
        my $configFile = $_[2];
 
1075
        my $versionnum=0;
 
1076
        my $conflinenb=0;
 
1077
        
 
1078
        if ($level > 10) { error("$PROG can't read down more than 10 level of includes. Check that no 'included' config files include their parent config file (this cause infinite loop)."); }
 
1079
 
 
1080
        while (<$confighandle>) {
 
1081
                chomp $_; s/\r//;
 
1082
                $conflinenb++;
 
1083
 
 
1084
                # Extract version from first line
 
1085
                if (! $versionnum && $_ =~ /^# AWSTATS CONFIGURE FILE (\d+).(\d+)/i) {
 
1086
                        $versionnum=($1*1000)+$2;
 
1087
                        #if ($Debug) { debug(" Configure file version is $versionnum",1); }
 
1088
                        next;
 
1089
                }
 
1090
 
 
1091
                if ($_ =~ /^\s*$/) { next; }
 
1092
 
 
1093
                # Check includes
 
1094
                if ($_ =~ /^Include "([^\"]+)"/ || $_ =~ /^#include "([^\"]+)"/) {      # #include kept for backward compatibility
 
1095
                    my $includeFile = $1;
 
1096
                        if ($Debug) { debug("Found an include : $includeFile",2); }
 
1097
                    if ( $includeFile !~ /^[\\\/]/ ) {
 
1098
                            # Correct relative include files
 
1099
                                if ($FileConfig =~ /^(.*[\\\/])[^\\\/]*$/) { $includeFile = "$1$includeFile"; }
 
1100
                        }
 
1101
                        if ($level > 1) {
 
1102
                                warning("Warning: Perl versions before 5.6 cannot handle nested includes");
 
1103
                                next;
 
1104
                        }
 
1105
                    if ( open( CONFIG_INCLUDE, $includeFile ) ) {
 
1106
                                &Parse_Config( *CONFIG_INCLUDE , $level+1, $includeFile);
 
1107
                                close( CONFIG_INCLUDE );
 
1108
                    }
 
1109
                    else {
 
1110
                                error("Could not open include file: $includeFile" );
 
1111
                    }
 
1112
                        next;
 
1113
                }
 
1114
 
 
1115
                # Remove comments
 
1116
                if ($_ =~ /^\s*#/) { next; }
 
1117
                $_ =~ s/\s#.*$//;
 
1118
 
 
1119
                # Extract param and value
 
1120
                my ($param,$value)=split(/=/,$_,2);
 
1121
                $param =~ s/^\s+//; $param =~ s/\s+$//;
 
1122
 
 
1123
                # If not a param=value, try with next line
 
1124
                if (! $param) { warning("Warning: Syntax error line $conflinenb in file '$configFile'. Config line is ignored."); next; }
 
1125
                if (! defined $value) { warning("Warning: Syntax error line $conflinenb in file '$configFile'. Config line is ignored."); next; }
 
1126
 
 
1127
                if ($value) {
 
1128
                        $value =~ s/^\s+//; $value =~ s/\s+$//;
 
1129
                        $value =~ s/^\"//; $value =~ s/\";?$//;
 
1130
                        # Replace __MONENV__ with value of environnement variable MONENV
 
1131
                        # Must be able to replace __VAR_1____VAR_2__
 
1132
                        while ($value =~ /__([^\s_]+(?:_[^\s_]+)*)__/) { my $var=$1; $value =~ s/__${var}__/$ENV{$var}/g; }
 
1133
                }
 
1134
 
 
1135
                # Initialize parameter for (param,value)
 
1136
                if ($param =~ /^LogFile/) {
 
1137
                        if ($QueryString !~ /logfile=([^\s&]+)/i) { $LogFile=$value; }
 
1138
                        next;
 
1139
                        }
 
1140
                if ($param =~ /^DirIcons/) {
 
1141
                        if ($QueryString !~ /diricons=([^\s&]+)/i) { $DirIcons=$value; }
 
1142
                        next;
 
1143
                        }
 
1144
                if ($param =~ /^SiteDomain/)                    {
 
1145
                        # No regex test as SiteDomain is always exact value
 
1146
                        $SiteDomain=$value;
 
1147
                        next;
 
1148
                        }
 
1149
                if ($param =~ /^HostAliases/) {
 
1150
                        foreach my $elem (split(/\s+/,$value))  {
 
1151
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1152
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1153
                                if ($elem) { push @HostAliases, qr/$elem/i; }
 
1154
                        }
 
1155
                        next;
 
1156
                        }
 
1157
                # Special optional setup params
 
1158
                if ($param =~ /^SkipDNSLookupFor/) {
 
1159
                        foreach my $elem (split(/\s+/,$value))  {
 
1160
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1161
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1162
                                if ($elem) { push @SkipDNSLookupFor, qr/$elem/i; }
 
1163
                        }
 
1164
                        next;
 
1165
                        }
 
1166
                if ($param =~ /^AllowAccessFromWebToFollowingAuthenticatedUsers/) {
 
1167
                        foreach (split(/\s+/,$value))   { push @AllowAccessFromWebToFollowingAuthenticatedUsers,$_; }
 
1168
                        next;
 
1169
                        }
 
1170
                if ($param =~ /^DefaultFile/)           {
 
1171
                        foreach my $elem (split(/\s+/,$value))  {       
 
1172
                                # No REGEX for this option
 
1173
                                #if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1174
                                #else { $elem='^'.quotemeta($elem).'$'; }
 
1175
                                if ($elem) { push @DefaultFile,$elem; }
 
1176
                        }
 
1177
                        next;
 
1178
                        }
 
1179
                if ($param =~ /^SkipHosts/) {
 
1180
                        foreach my $elem (split(/\s+/,$value))  {
 
1181
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1182
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1183
                                if ($elem) { push @SkipHosts, qr/$elem/i; }
 
1184
                        }
 
1185
                        next;
 
1186
                        }
 
1187
                if ($param =~ /^SkipUserAgents/) {
 
1188
                        foreach my $elem (split(/\s+/,$value))  {
 
1189
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1190
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1191
                                if ($elem) { push @SkipUserAgents, qr/$elem/i; }
 
1192
                        }
 
1193
                        next;
 
1194
                        }
 
1195
                if ($param =~ /^SkipFiles/) {
 
1196
                        foreach my $elem (split(/\s+/,$value))  {
 
1197
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1198
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1199
                                if ($elem) { push @SkipFiles, qr/$elem/i; }
 
1200
                        }
 
1201
                        next;
 
1202
                        }
 
1203
                if ($param =~ /^OnlyHosts/) {
 
1204
                        foreach my $elem (split(/\s+/,$value))  {
 
1205
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1206
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1207
                                if ($elem) { push @OnlyHosts, qr/$elem/i; }
 
1208
                        }
 
1209
                        next;
 
1210
                        }
 
1211
                if ($param =~ /^OnlyUserAgents/) {
 
1212
                        foreach my $elem (split(/\s+/,$value))  {
 
1213
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1214
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1215
                                if ($elem) { push @OnlyUserAgents, qr/$elem/i; }
 
1216
                        }
 
1217
                        next;
 
1218
                        }
 
1219
                if ($param =~ /^OnlyFiles/) {
 
1220
                        foreach my $elem (split(/\s+/,$value))  {
 
1221
                                if ($elem =~ /^REGEX\[(.*)\]$/i) { $elem=$1; }
 
1222
                                else { $elem='^'.quotemeta($elem).'$'; }
 
1223
                                if ($elem) { push @OnlyFiles, qr/$elem/i; }
 
1224
                        }
 
1225
                        next;
 
1226
                        }
 
1227
                if ($param =~ /^NotPageList/) {
 
1228
                        foreach (split(/\s+/,$value))   { $NotPageList{$_}=1; }
 
1229
                        $FoundNotPageList=1;
 
1230
                        next;
 
1231
                        }
 
1232
                if ($param =~ /^ValidHTTPCodes/) {
 
1233
                        foreach (split(/\s+/,$value))   { $ValidHTTPCodes{$_}=1; }
 
1234
                        $FoundValidHTTPCodes=1;
 
1235
                        next;
 
1236
                        }
 
1237
                if ($param =~ /^ValidSMTPCodes/) {
 
1238
                        foreach (split(/\s+/,$value))   { $ValidSMTPCodes{$_}=1; }
 
1239
                        $FoundValidSMTPCodes=1;
 
1240
                        next;
 
1241
                        }
 
1242
                if ($param =~ /^URLWithQueryWithOnlyFollowingParameters$/)      {
 
1243
                        @URLWithQueryWithOnly=split(/\s+/,$value);
 
1244
                        next;
 
1245
                        }
 
1246
                if ($param =~ /^URLWithQueryWithoutFollowingParameters$/)       {
 
1247
                        @URLWithQueryWithout=split(/\s+/,$value);
 
1248
                        next;
 
1249
                        }
 
1250
                # Extra parameters
 
1251
                if ($param =~ /^ExtraSectionName(\d+)/)                 { $ExtraName[$1]=$value; next; }
 
1252
                if ($param =~ /^ExtraSectionCondition(\d+)/)    { $ExtraCondition[$1]=$value; next; }
 
1253
                if ($param =~ /^ExtraSectionStatTypes(\d+)/)    { $ExtraStatTypes[$1]=$value; next; }
 
1254
                if ($param =~ /^ExtraSectionFirstColumnTitle(\d+)/)     { $ExtraFirstColumnTitle[$1]=$value; next; }
 
1255
                if ($param =~ /^ExtraSectionFirstColumnValues(\d+)/)    { $ExtraFirstColumnValues[$1]=$value; next; }
 
1256
                if ($param =~ /^ExtraSectionFirstColumnFormat(\d+)/)    { $ExtraFirstColumnFormat[$1]=$value; next; }
 
1257
                if ($param =~ /^ExtraSectionAddAverageRow(\d+)/)        { $ExtraAddAverageRow[$1]=$value; next; }
 
1258
                if ($param =~ /^ExtraSectionAddSumRow(\d+)/)    { $ExtraAddSumRow[$1]=$value; next; }
 
1259
                if ($param =~ /^MaxNbOfExtra(\d+)/)                     { $MaxNbOfExtra[$1]=$value; next; }
 
1260
                if ($param =~ /^MinHitExtra(\d+)/)                              { $MinHitExtra[$1]=$value; next; }
 
1261
                # Special appearance parameters
 
1262
                if ($param =~ /^LoadPlugin/)                            { push @PluginsToLoad, $value; next; }
 
1263
                # Other that we need to put after MaxNbOfExtra and MinHitExtra
 
1264
                if ($param =~ /^MaxNbOf(\w+)/)  { $MaxNbOf{$1}=$value; next; }
 
1265
                if ($param =~ /^MinHit(\w+)/)   { $MinHit{$1}=$value; next; }
 
1266
                # Check if this is a known parameter
 
1267
#               if (! $ConfOk{$param}) { error("Unknown config parameter '$param' found line $conflinenb in file \"configFile\""); }
 
1268
                # If parameters was not found previously, defined variable with name of param to value
 
1269
                $$param=$value;
 
1270
        }
 
1271
 
 
1272
        # For backward compatibility
 
1273
        if ($versionnum < 5001) { $BarHeight=$BarHeight>>1; }
 
1274
 
 
1275
        if ($Debug) { debug("Config file read was \"$configFile\" (level $level)"); }
 
1276
}
 
1277
 
 
1278
 
 
1279
#------------------------------------------------------------------------------
 
1280
# Function:     Load the reference databases
 
1281
# Parameters:   List of files to load
 
1282
# Input:                $DIR
 
1283
# Output:               Arrays and Hash tables are defined
 
1284
# Return:       -
 
1285
#------------------------------------------------------------------------------
 
1286
sub Read_Ref_Data {
 
1287
        # Check lib files in common possible directories :
 
1288
        # Windows and standard package:                 "$DIR/lib" (lib in same dir than awstats.pl)
 
1289
        # Debian package :                              "/usr/share/awstats/lib"
 
1290
        my @PossibleLibDir=("$DIR/lib","/usr/share/awstats/lib");
 
1291
        my %FilePath=(); my %DirAddedInINC=();
 
1292
        my @FileListToLoad=();
 
1293
        while (my $file=shift) { push @FileListToLoad, "$file.pm"; }
 
1294
        if ($Debug) { debug("Call to Read_Ref_Data with files to load: ".(join(',',@FileListToLoad))); }
 
1295
        foreach my $file (@FileListToLoad) {
 
1296
                foreach my $dir (@PossibleLibDir) {
 
1297
                        my $searchdir=$dir;
 
1298
                        if ($searchdir && (!($searchdir =~ /\/$/)) && (!($searchdir =~ /\\$/)) ) { $searchdir .= "/"; }
 
1299
                        if (! $FilePath{$file}) {       # To not load twice same file in different path
 
1300
                                if (-s "${searchdir}${file}") {
 
1301
                                        $FilePath{$file}="${searchdir}${file}";
 
1302
                                        if ($Debug) { debug("Call to Read_Ref_Data [FilePath{$file}=\"$FilePath{$file}\"]"); }
 
1303
                                        # Note: cygwin perl 5.8 need a push + require file
 
1304
                                        if (! $DirAddedInINC{"$dir"}) { 
 
1305
                                                push @INC, "$dir";
 
1306
                                                $DirAddedInINC{"$dir"}=1;
 
1307
                                        }
 
1308
                                        my $loadret=require "$file";
 
1309
                                        #my $loadret=(require "$FilePath{$file}"||require "${file}");
 
1310
                                }
 
1311
                        }
 
1312
                }
 
1313
                if (! $FilePath{$file}) {
 
1314
                        my $filetext=$file; $filetext =~ s/\.pm$//; $filetext =~ s/_/ /g;
 
1315
                        warning("Warning: Can't read file \"$file\" ($filetext detection will not work correctly).\nCheck if file is in \"".($PossibleLibDir[0])."\" directory and is readable.");
 
1316
                }
 
1317
        }
 
1318
        # Sanity check (if loaded)
 
1319
        if ((scalar keys %OSHashID) && @OSSearchIDOrder != scalar keys %OSHashID) { error("Not same number of records of OSSearchIDOrder (".(@OSSearchIDOrder)." entries) and OSHashID (".(scalar keys %OSHashID)." entries) in OS database. Check your file ".$FilePath{"operating_systems.pm"}); }
 
1320
        if ((scalar keys %SearchEnginesHashID) && (@SearchEnginesSearchIDOrder_list1+@SearchEnginesSearchIDOrder_list2+@SearchEnginesSearchIDOrder_listgen) != scalar keys %SearchEnginesHashID) { error("Not same number of records of SearchEnginesSearchIDOrder_listx (total is ".(@SearchEnginesSearchIDOrder_list1+@SearchEnginesSearchIDOrder_list2+@SearchEnginesSearchIDOrder_listgen)." entries) and SearchEnginesHashID (".(scalar keys %SearchEnginesHashID)." entries) in Search Engines database. Check your file ".$FilePath{"search_engines.pm"}); }
 
1321
        if ((scalar keys %BrowsersHashIDLib) && @BrowsersSearchIDOrder != (scalar keys %BrowsersHashIDLib) - 2) { error("Not same number of records of BrowsersSearchIDOrder (".(@BrowsersSearchIDOrder)." entries) and BrowsersHashIDLib (".((scalar keys %BrowsersHashIDLib) - 2)." entries without msie and netscape) in Browsers database. Check your file ".$FilePath{"browsers.pm"}); }
 
1322
        if ((scalar keys %RobotsHashIDLib) && (@RobotsSearchIDOrder_list1+@RobotsSearchIDOrder_list2+@RobotsSearchIDOrder_listgen) != (scalar keys %RobotsHashIDLib) - 1) { error("Not same number of records of RobotsSearchIDOrder_listx (total is ".(@RobotsSearchIDOrder_list1+@RobotsSearchIDOrder_list2+@RobotsSearchIDOrder_listgen)." entries) and RobotsHashIDLib (".((scalar keys %RobotsHashIDLib) - 1)." entries without 'unknown') in Robots database. Check your file ".$FilePath{"robots.pm"}); }
 
1323
}
 
1324
 
 
1325
 
 
1326
#------------------------------------------------------------------------------
 
1327
# Function:     Get the messages for a specified language
 
1328
# Parameters:   LanguageId
 
1329
# Input:                $DirLang $DIR
 
1330
# Output:               $Message table is defined in memory
 
1331
# Return:               None
 
1332
#------------------------------------------------------------------------------
 
1333
sub Read_Language_Data {
 
1334
        # Check lang files in common possible directories :
 
1335
        # Windows and standard package:                 "$DIR/lang" (lang in same dir than awstats.pl)
 
1336
        # Debian package :                              "/usr/share/awstats/lang"
 
1337
        my @PossibleLangDir=("$DirLang","$DIR/lang","/usr/share/awstats/lang");
 
1338
 
 
1339
        my $FileLang='';
 
1340
        foreach (@PossibleLangDir) {
 
1341
                my $searchdir=$_;
 
1342
                if ($searchdir && (!($searchdir =~ /\/$/)) && (!($searchdir =~ /\\$/)) ) { $searchdir .= "/"; }
 
1343
                if (open(LANG,"${searchdir}awstats-$_[0].txt")) { $FileLang="${searchdir}awstats-$_[0].txt"; last; }
 
1344
        }
 
1345
        # If file not found, we try english
 
1346
        if (! $FileLang) {
 
1347
                foreach (@PossibleLangDir) {
 
1348
                        my $searchdir=$_;
 
1349
                        if ($searchdir && (!($searchdir =~ /\/$/)) && (!($searchdir =~ /\\$/)) ) { $searchdir .= "/"; }
 
1350
                        if (open(LANG,"${searchdir}awstats-en.txt")) { $FileLang="${searchdir}awstats-en.txt"; last; }
 
1351
                }
 
1352
        }
 
1353
        if ($Debug) { debug("Call to Read_Language_Data [FileLang=\"$FileLang\"]"); }
 
1354
        if ($FileLang) {
 
1355
                my $i = 0;
 
1356
                binmode LANG;   # Might avoid 'Malformed UTF-8 errors'
 
1357
                my $cregcode=qr/^PageCode=[\t\s\"\']*([\w-]+)/i;
 
1358
                my $cregdir=qr/^PageDir=[\t\s\"\']*([\w-]+)/i;
 
1359
                my $cregmessage=qr/^Message\d+=/i;
 
1360
                while (<LANG>) {
 
1361
                        chomp $_; s/\r//;
 
1362
                        if ($_ =~ /$cregcode/o) { $PageCode = $1; }
 
1363
                        if ($_ =~ /$cregdir/o)  { $PageDir = $1; }
 
1364
                        if ($_ =~ s/$cregmessage//o) {
 
1365
                                $_ =~ s/#.*//;                                                          # Remove comments
 
1366
                                $_ =~ tr/\t /  /s;                                                      # Change all blanks into " "
 
1367
                                $_ =~ s/^\s+//; $_ =~ s/\s+$//;
 
1368
                                $_ =~ s/^\"//; $_ =~ s/\"$//;
 
1369
                                $Message[$i] = $_;
 
1370
                                $i++;
 
1371
                        }
 
1372
                }
 
1373
                close(LANG);
 
1374
        }
 
1375
        else {
 
1376
                warning("Warning: Can't find language files for \"$_[0]\". English will be used.");
 
1377
        }
 
1378
        # Some language string changes
 
1379
        if ($LogType eq 'M') {  # For mail
 
1380
                $Message[8]=$Message[151];
 
1381
                $Message[9]=$Message[152];
 
1382
                $Message[57]=$Message[149];
 
1383
                $Message[75]=$Message[150];
 
1384
        }
 
1385
        if ($LogType eq 'F') {  # For web
 
1386
 
 
1387
        }
 
1388
}
 
1389
 
 
1390
 
 
1391
#------------------------------------------------------------------------------
 
1392
# Function:     Check if all parameters are correctly defined. If not set them to default.
 
1393
# Parameters:   None
 
1394
# Input:                All global variables
 
1395
# Output:               Change on some global variables
 
1396
# Return:               None
 
1397
#------------------------------------------------------------------------------
 
1398
sub Check_Config {
 
1399
        if ($Debug) { debug("Call to Check_Config"); }
 
1400
 
 
1401
        my %MonthNumLibEn = ("01","Jan","02","Feb","03","Mar","04","Apr","05","May","06","Jun","07","Jul","08","Aug","09","Sep","10","Oct","11","Nov","12","Dec");
 
1402
 
 
1403
        # Show initial values of main parameters before check
 
1404
        if ($Debug) {
 
1405
                debug(" LogFile='$LogFile'",2);
 
1406
                debug(" LogType='$LogType'",2);
 
1407
                debug(" LogFormat='$LogFormat'",2);
 
1408
                debug(" LogSeparator='$LogSeparator'",2);
 
1409
                debug(" DNSLookup='$DNSLookup'",2);
 
1410
                debug(" DirData='$DirData'",2);
 
1411
                debug(" DirCgi='$DirCgi'",2);
 
1412
                debug(" DirIcons='$DirIcons'",2);
 
1413
                debug(" NotPageList ".(join(',',keys %NotPageList)),2);
 
1414
                debug(" ValidHTTPCodes ".(join(',',keys %ValidHTTPCodes)),2);
 
1415
                debug(" ValidSMTPCodes ".(join(',',keys %ValidSMTPCodes)),2);
 
1416
                debug(" UseFramesWhenCGI=$UseFramesWhenCGI",2);
 
1417
                debug(" BuildReportFormat=$BuildReportFormat",2);
 
1418
                debug(" BuildHistoryFormat=$BuildHistoryFormat",2);
 
1419
                debug(" URLWithQueryWithOnlyFollowingParameters=".(join(',',@URLWithQueryWithOnly)),2);
 
1420
                debug(" URLWithQueryWithoutFollowingParameters=".(join(',',@URLWithQueryWithout)),2);
 
1421
        }
 
1422
 
 
1423
        # Main section
 
1424
        while ($LogFile =~ /%([ymdhwYMDHWNSO]+)-(\d+)/) {
 
1425
                my $timetag=$1;
 
1426
                my $timephase=$2;
 
1427
                if ($Debug) { debug(" Found a time tag '$timetag' with a phase of '$timephase' hour in log file name",1); }
 
1428
                # Get older time
 
1429
                my ($oldersec,$oldermin,$olderhour,$olderday,$oldermonth,$olderyear,$olderwday,$olderyday) = localtime($starttime-($timephase*3600));
 
1430
                my $olderweekofmonth=int($olderday/7);
 
1431
                my $olderweekofyear=int(($olderyday-1+6-($olderwday==0?6:$olderwday-1))/7)+1; if ($olderweekofyear > 52) { $olderweekofyear = 1; }
 
1432
                my $olderdaymod=$olderday%7;
 
1433
                $olderwday++;
 
1434
                my $olderns=Time::Local::timegm(0,0,0,$olderday,$oldermonth,$olderyear);
 
1435
                if ($olderdaymod <= $olderwday) { if (($olderwday != 7) || ($olderdaymod != 0)) { $olderweekofmonth=$olderweekofmonth+1; } }
 
1436
                if ($olderdaymod >  $olderwday) { $olderweekofmonth=$olderweekofmonth+2; }
 
1437
                # Change format of time variables
 
1438
                $olderweekofmonth = "0$olderweekofmonth";
 
1439
                if ($olderweekofyear < 10) { $olderweekofyear = "0$olderweekofyear"; }
 
1440
                if ($olderyear < 100) { $olderyear+=2000; } else { $olderyear+=1900; }
 
1441
                my $oldersmallyear=$olderyear;$oldersmallyear =~ s/^..//;
 
1442
                if (++$oldermonth < 10) { $oldermonth = "0$oldermonth"; }
 
1443
                if ($olderday < 10) { $olderday = "0$olderday"; }
 
1444
                if ($olderhour < 10) { $olderhour = "0$olderhour"; }
 
1445
                if ($oldermin < 10) { $oldermin = "0$oldermin"; }
 
1446
                if ($oldersec < 10) { $oldersec = "0$oldersec"; }
 
1447
                # Replace tag with new value
 
1448
                if ($timetag eq 'YYYY') { $LogFile =~ s/%YYYY-$timephase/$olderyear/ig; next; }
 
1449
                if ($timetag eq 'YY')   { $LogFile =~ s/%YY-$timephase/$oldersmallyear/ig; next; }
 
1450
                if ($timetag eq 'MM')   { $LogFile =~ s/%MM-$timephase/$oldermonth/ig; next; }
 
1451
                if ($timetag eq 'MO')   { $LogFile =~ s/%MO-$timephase/$MonthNumLibEn{$oldermonth}/ig; next; }
 
1452
                if ($timetag eq 'DD')   { $LogFile =~ s/%DD-$timephase/$olderday/ig; next; }
 
1453
                if ($timetag eq 'HH')   { $LogFile =~ s/%HH-$timephase/$olderhour/ig; next; }
 
1454
                if ($timetag eq 'NS')   { $LogFile =~ s/%NS-$timephase/$olderns/ig; next; }
 
1455
                if ($timetag eq 'WM')   { $LogFile =~ s/%WM-$timephase/$olderweekofmonth/g; next; }
 
1456
                if ($timetag eq 'Wm')   { my $olderweekofmonth0=$olderweekofmonth-1; $LogFile =~ s/%Wm-$timephase/$olderweekofmonth0/g; next; }
 
1457
                if ($timetag eq 'WY')   { $LogFile =~ s/%WY-$timephase/$olderweekofyear/g; next; }
 
1458
                if ($timetag eq 'Wy')   { my $olderweekofyear0=sprintf("%02d",$olderweekofyear-1); $LogFile =~ s/%Wy-$timephase/$olderweekofyear0/g; next; }
 
1459
                if ($timetag eq 'DW')   { $LogFile =~ s/%DW-$timephase/$olderwday/g; next; }
 
1460
                if ($timetag eq 'Dw')   { my $olderwday0=$olderwday-1; $LogFile =~ s/%Dw-$timephase/$olderwday0/g; next; }
 
1461
                # If unknown tag
 
1462
                error("Unknown tag '\%$timetag' in LogFile parameter.");
 
1463
        }
 
1464
        # Replace %YYYY %YY %MM %DD %HH with current value. Kept for backward compatibility.
 
1465
        $LogFile =~ s/%YYYY/$nowyear/ig;
 
1466
        $LogFile =~ s/%YY/$nowsmallyear/ig;
 
1467
        $LogFile =~ s/%MM/$nowmonth/ig;
 
1468
        $LogFile =~ s/%MO/$MonthNumLibEn{$nowmonth}/ig;
 
1469
        $LogFile =~ s/%DD/$nowday/ig;
 
1470
        $LogFile =~ s/%HH/$nowhour/ig;
 
1471
        $LogFile =~ s/%NS/$nowns/ig;
 
1472
        $LogFile =~ s/%WM/$nowweekofmonth/g;
 
1473
        my $nowweekofmonth0=$nowweekofmonth-1; $LogFile =~ s/%Wm/$nowweekofmonth0/g;
 
1474
        $LogFile =~ s/%WY/$nowweekofyear/g;
 
1475
        my $nowweekofyear0=$nowweekofyear-1; $LogFile =~ s/%Wy/$nowweekofyear0/g;
 
1476
        $LogFile =~ s/%DW/$nowwday/g;
 
1477
        my $nowwday0=$nowwday-1; $LogFile =~ s/%Dw/$nowwday0/g;
 
1478
        if (! $LogFile)   { error("LogFile parameter is not defined in config/domain file"); }
 
1479
        if ($LogType !~ /[WSMF]/i) { $LogType='W'; }
 
1480
        $LogFormat =~ s/\\//g;
 
1481
        if (! $LogFormat) { error("LogFormat parameter is not defined in config/domain file"); }
 
1482
        if ($LogFormat =~ /^\d$/ && $LogFormat !~ /[1-6]/)  { error("LogFormat parameter is wrong in config/domain file. Value is '$LogFormat' (should be 1,2,3,4,5 or a 'personalized AWStats log format string')"); }
 
1483
        $LogSeparator||="\\s";
 
1484
        $DirData||='.';
 
1485
        $DirCgi||='/cgi-bin';
 
1486
        $DirIcons||='/icon';
 
1487
        if ($DNSLookup !~ /[0-2]/)                      { error("DNSLookup parameter is wrong in config/domain file. Value is '$DNSLookup' (should be 0 or 1)"); }
 
1488
        if (! $SiteDomain)                              { error("SiteDomain parameter not defined in your config/domain file. You must add it for using this version of AWStats."); }
 
1489
        if ($AllowToUpdateStatsFromBrowser !~ /[0-1]/)  { $AllowToUpdateStatsFromBrowser=0; }
 
1490
        if ($AllowFullYearView !~ /[0-3]/)                              { $AllowFullYearView=2; }
 
1491
        # Optional setup section
 
1492
        if ($EnableLockForUpdate !~ /[0-1]/)            { $EnableLockForUpdate=0; }
 
1493
        $DNSStaticCacheFile||='dnscache.txt';
 
1494
        $DNSLastUpdateCacheFile||='dnscachelastupdate.txt';
 
1495
        if ($DNSStaticCacheFile eq $DNSLastUpdateCacheFile)     { error("DNSStaticCacheFile and DNSLastUpdateCacheFile must have different values."); }
 
1496
        if ($AllowAccessFromWebToAuthenticatedUsersOnly !~ /[0-1]/)     { $AllowAccessFromWebToAuthenticatedUsersOnly=0; }
 
1497
        if ($CreateDirDataIfNotExists !~ /[0-1]/)       { $CreateDirDataIfNotExists=0; }
 
1498
        if ($BuildReportFormat !~ /html|xml/i)                  { $BuildReportFormat='html'; }
 
1499
        if ($BuildHistoryFormat !~ /text/)                      { $BuildHistoryFormat='text'; }
 
1500
        if ($SaveDatabaseFilesWithPermissionsForEveryone !~ /[0-1]/)    { $SaveDatabaseFilesWithPermissionsForEveryone=1; }
 
1501
        if ($PurgeLogFile !~ /[0-1]/)                   { $PurgeLogFile=0; }
 
1502
        if ($ArchiveLogRecords !~ /[0-1]/)              { $ArchiveLogRecords=1; }
 
1503
        if ($KeepBackupOfHistoricFiles !~ /[0-1]/)      { $KeepBackupOfHistoricFiles=0; }
 
1504
        $DefaultFile[0]||='index.html';
 
1505
        if ($AuthenticatedUsersNotCaseSensitive !~ /[0-1]/)       { $AuthenticatedUsersNotCaseSensitive=0; }
 
1506
        if ($URLNotCaseSensitive !~ /[0-1]/)            { $URLNotCaseSensitive=0; }
 
1507
        if ($URLWithAnchor !~ /[0-1]/)                  { $URLWithAnchor=0; }
 
1508
        $URLQuerySeparators =~ s/\s//g; 
 
1509
        if (! $URLQuerySeparators)                              { $URLQuerySeparators='?;'; }
 
1510
        if ($URLWithQuery !~ /[0-1]/)                   { $URLWithQuery=0; }
 
1511
        if ($URLReferrerWithQuery !~ /[0-1]/)           { $URLReferrerWithQuery=0; }
 
1512
        if ($WarningMessages !~ /[0-1]/)                { $WarningMessages=1; }
 
1513
        if ($DebugMessages !~ /[0-1]/)                  { $DebugMessages=1; }
 
1514
        if ($NbOfLinesForCorruptedLog !~ /^\d+/ || $NbOfLinesForCorruptedLog<1) { $NbOfLinesForCorruptedLog=50; }
 
1515
        if ($Expires !~ /^\d+/)                                 { $Expires=0; }
 
1516
        if ($DecodeUA !~ /[0-1]/)                                               { $DecodeUA=0; }
 
1517
        $MiscTrackerUrl||='/js/awstats_misc_tracker.js';
 
1518
        # Optional accuracy setup section
 
1519
        if ($LevelForWormsDetection !~ /^\d+/)          { $LevelForWormsDetection=0; }
 
1520
        if ($LevelForRobotsDetection !~ /^\d+/)         { $LevelForRobotsDetection=2; }
 
1521
        if ($LevelForBrowsersDetection !~ /^\d+/)       { $LevelForBrowsersDetection=2; }
 
1522
        if ($LevelForOSDetection !~ /^\d+/)                     { $LevelForOSDetection=2; }
 
1523
        if ($LevelForRefererAnalyze !~ /^\d+/)                  { $LevelForRefererAnalyze=2; }
 
1524
        if ($LevelForFileTypesDetection !~ /^\d+/)              { $LevelForFileTypesDetection=2; }
 
1525
        if ($LevelForSearchEnginesDetection !~ /^\d+/)  { $LevelForSearchEnginesDetection=2; }
 
1526
        if ($LevelForKeywordsDetection !~ /^\d+/)               { $LevelForKeywordsDetection=2; }
 
1527
        # Optional extra setup section
 
1528
        foreach my $extracpt (1..@ExtraName-1) {
 
1529
                if ($ExtraStatTypes[$extracpt] !~ /[PHBL]/)  { $ExtraStatTypes[$extracpt]='PHBL'; }
 
1530
                if ($MaxNbOfExtra[$extracpt] !~ /^\d+$/ || $MaxNbOfExtra[$extracpt]<1) { $MaxNbOfExtra[$extracpt]=20; }
 
1531
                if ($MinHitExtra[$extracpt] !~ /^\d+$/ || $MinHitExtra[$extracpt]<1) { $MinHitExtra[$extracpt]=1; }
 
1532
                if (! $ExtraFirstColumnValues[$extracpt]) { error("Extra section number $extracpt is defined without ExtraSectionFirstColumnValues$extracpt parameter"); }
 
1533
                if (! $ExtraFirstColumnFormat[$extracpt]) { $ExtraFirstColumnFormat[$extracpt] = '%s'; }
 
1534
        }
 
1535
        # Optional appearance setup section
 
1536
        if ($MaxRowsInHTMLOutput !~ /^\d+/ || $MaxRowsInHTMLOutput<1)     { $MaxRowsInHTMLOutput=1000; }
 
1537
        if ($ShowMenu !~ /[01]/)                        { $ShowMenu=1; }
 
1538
        if ($ShowMonthStats !~ /[01UVPHB]/)             { $ShowMonthStats='UVPHB'; }
 
1539
        if ($ShowDaysOfMonthStats !~ /[01VPHB]/)        { $ShowDaysOfMonthStats='VPHB'; }
 
1540
        if ($ShowDaysOfWeekStats !~ /[01PHBL]/)         { $ShowDaysOfWeekStats='PHBL'; }
 
1541
        if ($ShowHoursStats !~ /[01PHBL]/)              { $ShowHoursStats='PHBL'; }
 
1542
        if ($ShowDomainsStats !~ /[01PHB]/)             { $ShowDomainsStats='PHB'; }
 
1543
        if ($ShowHostsStats !~ /[01PHBL]/)              { $ShowHostsStats='PHBL'; }
 
1544
        if ($ShowAuthenticatedUsers !~ /[01PHBL]/)      { $ShowAuthenticatedUsers=0; }
 
1545
        if ($ShowRobotsStats !~ /[01HBL]/)              { $ShowRobotsStats='HBL'; }
 
1546
        if ($ShowWormsStats !~ /[01HBL]/)               { $ShowWormsStats='HBL'; }
 
1547
        if ($ShowEMailSenders !~ /[01HBML]/)                    { $ShowEMailSenders=0; }
 
1548
        if ($ShowEMailReceivers !~ /[01HBML]/)          { $ShowEMailReceivers=0; }
 
1549
        if ($ShowSessionsStats !~ /[01]/)               { $ShowSessionsStats=1; }
 
1550
        if ($ShowPagesStats !~ /[01PBEX]/i)             { $ShowPagesStats='PBEX'; }
 
1551
        if ($ShowFileTypesStats !~ /[01HBC]/)           { $ShowFileTypesStats='HB'; }
 
1552
        if ($ShowFileSizesStats !~ /[01]/)              { $ShowFileSizesStats=1; }
 
1553
        if ($ShowOSStats !~ /[01]/)                     { $ShowOSStats=1; }
 
1554
        if ($ShowBrowsersStats !~ /[01]/)               { $ShowBrowsersStats=1; }
 
1555
        if ($ShowScreenSizeStats !~ /[01]/)             { $ShowScreenSizeStats=0; }
 
1556
        if ($ShowOriginStats !~ /[01PH]/)               { $ShowOriginStats='PH'; }
 
1557
        if ($ShowKeyphrasesStats !~ /[01]/)             { $ShowKeyphrasesStats=1; }
 
1558
        if ($ShowKeywordsStats !~ /[01]/)               { $ShowKeywordsStats=1; }
 
1559
        if ($ShowClusterStats !~ /[01PHB]/)             { $ShowClusterStats=0; }
 
1560
        if ($ShowMiscStats !~ /[01ajdfrqwp]/)               { $ShowMiscStats='a'; }
 
1561
        if ($ShowHTTPErrorsStats !~ /[01]/)             { $ShowHTTPErrorsStats=1; }
 
1562
        if ($ShowSMTPErrorsStats !~ /[01]/)             { $ShowSMTPErrorsStats=0; }
 
1563
        if ($AddDataArrayMonthStats !~ /[01]/)          { $AddDataArrayMonthStats=1; }
 
1564
        if ($AddDataArrayShowDaysOfMonthStats !~ /[01]/)       { $AddDataArrayShowDaysOfMonthStats=1; }
 
1565
        if ($AddDataArrayShowDaysOfWeekStats !~ /[01]/)         { $AddDataArrayShowDaysOfWeekStats=1; }
 
1566
        if ($AddDataArrayShowHoursStats !~ /[01]/)              { $AddDataArrayShowHoursStats=1; }
 
1567
        my @maxnboflist=('Domain','HostsShown','LoginShown','RobotShown','WormsShown','PageShown','OsShown','BrowsersShown','ScreenSizesShown','RefererShown','KeyphrasesShown','KeywordsShown','EMailsShown');
 
1568
        my @maxnboflistdefaultval=(10,10,10,10,5,10,10,10,5,10,10,10,20);
 
1569
        foreach my $i (0..(@maxnboflist-1)) {
 
1570
                if (! $MaxNbOf{$maxnboflist[$i]} || $MaxNbOf{$maxnboflist[$i]} !~ /^\d+$/ || $MaxNbOf{$maxnboflist[$i]}<1)      { $MaxNbOf{$maxnboflist[$i]}=$maxnboflistdefaultval[$i]; }
 
1571
        }
 
1572
        my @minhitlist=('Domain','Host','Login','Robot','Worm','File','Os','Browser','ScreenSize','Refer','Keyphrase','Keyword','EMail');
 
1573
        my @minhitlistdefaultval=(1,1,1,1,1,1,1,1,1,1,1,1,1);
 
1574
        foreach my $i (0..(@minhitlist-1)) {
 
1575
                if (! $MinHit{$minhitlist[$i]} || $MinHit{$minhitlist[$i]} !~ /^\d+$/ || $MinHit{$minhitlist[$i]}<1)    { $MinHit{$minhitlist[$i]}=$minhitlistdefaultval[$i]; }
 
1576
        }
 
1577
        if ($FirstDayOfWeek !~ /[01]/)                  { $FirstDayOfWeek=1; }
 
1578
        if ($UseFramesWhenCGI !~ /[01]/)                                { $UseFramesWhenCGI=1; }
 
1579
        if ($DetailedReportsOnNewWindows !~ /[012]/)    { $DetailedReportsOnNewWindows=1; }
 
1580
        if ($ShowLinksOnUrl !~ /[01]/)                  { $ShowLinksOnUrl=1; }
 
1581
        if ($MaxLengthOfShownURL !~ /^\d+/ || $MaxLengthOfShownURL<1) { $MaxLengthOfShownURL=64; }
 
1582
        if ($ShowLinksToWhoIs !~ /[01]/)                { $ShowLinksToWhoIs=0; }
 
1583
        $Logo||='awstats_logo6.png';
 
1584
        $LogoLink||='http://awstats.sourceforge.net';
 
1585
        if ($BarWidth !~ /^\d+/ || $BarWidth<1)                 { $BarWidth=260; }
 
1586
        if ($BarHeight !~ /^\d+/ || $BarHeight<1)               { $BarHeight=90; }
 
1587
        $color_Background =~ s/#//g; if ($color_Background !~ /^[0-9|A-H]+$/i)           { $color_Background='FFFFFF';  }
 
1588
        $color_TableBGTitle =~ s/#//g; if ($color_TableBGTitle !~ /^[0-9|A-H]+$/i)       { $color_TableBGTitle='CCCCDD'; }
 
1589
        $color_TableTitle =~ s/#//g; if ($color_TableTitle !~ /^[0-9|A-H]+$/i)           { $color_TableTitle='000000'; }
 
1590
        $color_TableBG =~ s/#//g; if ($color_TableBG !~ /^[0-9|A-H]+$/i)                 { $color_TableBG='CCCCDD'; }
 
1591
        $color_TableRowTitle =~ s/#//g; if ($color_TableRowTitle !~ /^[0-9|A-H]+$/i)     { $color_TableRowTitle='FFFFFF'; }
 
1592
        $color_TableBGRowTitle =~ s/#//g; if ($color_TableBGRowTitle !~ /^[0-9|A-H]+$/i) { $color_TableBGRowTitle='ECECEC'; }
 
1593
        $color_TableBorder =~ s/#//g; if ($color_TableBorder !~ /^[0-9|A-H]+$/i)         { $color_TableBorder='ECECEC'; }
 
1594
        $color_text =~ s/#//g; if ($color_text !~ /^[0-9|A-H]+$/i)                               { $color_text='000000'; }
 
1595
        $color_textpercent =~ s/#//g; if ($color_textpercent !~ /^[0-9|A-H]+$/i)                 { $color_textpercent='606060'; }
 
1596
        $color_titletext =~ s/#//g; if ($color_titletext !~ /^[0-9|A-H]+$/i)                     { $color_titletext='000000'; }
 
1597
        $color_weekend =~ s/#//g; if ($color_weekend !~ /^[0-9|A-H]+$/i)                         { $color_weekend='EAEAEA'; }
 
1598
        $color_link =~ s/#//g; if ($color_link !~ /^[0-9|A-H]+$/i)                               { $color_link='0011BB'; }
 
1599
        $color_hover =~ s/#//g; if ($color_hover !~ /^[0-9|A-H]+$/i)                             { $color_hover='605040'; }
 
1600
        $color_other =~ s/#//g; if ($color_other !~ /^[0-9|A-H]+$/i)                             { $color_other='666688'; }
 
1601
        $color_u =~ s/#//g; if ($color_u !~ /^[0-9|A-H]+$/i)                                     { $color_u='FFA060'; }
 
1602
        $color_v =~ s/#//g; if ($color_v !~ /^[0-9|A-H]+$/i)                                     { $color_v='F4F090'; }
 
1603
        $color_p =~ s/#//g; if ($color_p !~ /^[0-9|A-H]+$/i)                                     { $color_p='4477DD'; }
 
1604
        $color_h =~ s/#//g; if ($color_h !~ /^[0-9|A-H]+$/i)                                     { $color_h='66EEFF'; }
 
1605
        $color_k =~ s/#//g; if ($color_k !~ /^[0-9|A-H]+$/i)                                     { $color_k='2EA495'; }
 
1606
        $color_s =~ s/#//g; if ($color_s !~ /^[0-9|A-H]+$/i)                                     { $color_s='8888DD'; }
 
1607
        $color_e =~ s/#//g; if ($color_e !~ /^[0-9|A-H]+$/i)                                     { $color_e='CEC2E8'; }
 
1608
        $color_x =~ s/#//g; if ($color_x !~ /^[0-9|A-H]+$/i)                                     { $color_x='C1B2E2'; }
 
1609
 
 
1610
        # Correct param if default value is asked
 
1611
        if ($ShowMonthStats eq '1')             { $ShowMonthStats = 'UVPHB'; }
 
1612
        if ($ShowDaysOfMonthStats eq '1')       { $ShowDaysOfMonthStats = 'VPHB'; }
 
1613
        if ($ShowDaysOfWeekStats eq '1')    { $ShowDaysOfWeekStats = 'PHBL'; }
 
1614
        if ($ShowHoursStats eq '1')         { $ShowHoursStats = 'PHBL'; }
 
1615
        if ($ShowDomainsStats eq '1')       { $ShowDomainsStats = 'PHB'; }
 
1616
        if ($ShowHostsStats eq '1')         { $ShowHostsStats = 'PHBL'; }
 
1617
        if ($ShowEMailSenders eq '1')       { $ShowEMailSenders = 'HBML'; }
 
1618
        if ($ShowEMailReceivers eq '1')     { $ShowEMailReceivers = 'HBML'; }
 
1619
        if ($ShowAuthenticatedUsers eq '1') { $ShowAuthenticatedUsers = 'PHBL'; }
 
1620
        if ($ShowRobotsStats eq '1')            { $ShowRobotsStats = 'HBL'; }
 
1621
        if ($ShowWormsStats eq '1')             { $ShowWormsStats = 'HBL'; }
 
1622
        if ($ShowPagesStats eq '1')             { $ShowPagesStats = 'PBEX'; }
 
1623
        if ($ShowFileTypesStats eq '1')         { $ShowFileTypesStats = 'HB'; }
 
1624
        if ($ShowOriginStats eq '1')            { $ShowOriginStats = 'PH'; }
 
1625
        if ($ShowClusterStats eq '1')           { $ShowClusterStats = 'PHB'; }
 
1626
        if ($ShowMiscStats eq '1')                      { $ShowMiscStats = 'ajdfrqwp'; }
 
1627
 
 
1628
        # Convert extra sections data into @ExtraConditionType, @ExtraConditionTypeVal...
 
1629
        foreach my $extranum (1..@ExtraName-1) {
 
1630
                my $part=0;
 
1631
                foreach my $conditioncouple (split(/\s*\|\s*/, $ExtraCondition[$extranum])) {
 
1632
                        my ($conditiontype, $conditiontypeval)=split(/,/,$conditioncouple,2);
 
1633
                        $ExtraConditionType[$extranum][$part]=$conditiontype;
 
1634
                        if ($conditiontypeval =~ /^REGEX\[(.*)\]$/i) { $conditiontypeval=$1; }
 
1635
                        #else { $conditiontypeval=quotemeta($conditiontypeval); }
 
1636
                        $ExtraConditionTypeVal[$extranum][$part]=qr/$conditiontypeval/i;
 
1637
                        $part++;
 
1638
                }
 
1639
                $part=0;
 
1640
                foreach my $rowkeycouple (split(/\s*\|\s*/, $ExtraFirstColumnValues[$extranum])) {
 
1641
                        my ($rowkeytype, $rowkeytypeval)=split(/,/,$rowkeycouple,2);
 
1642
                        $ExtraFirstColumnValuesType[$extranum][$part]=$rowkeytype;
 
1643
                        if ($rowkeytypeval =~ /^REGEX\[(.*)\]$/i) { $rowkeytypeval=$1; }
 
1644
                        #else { $rowkeytype=quotemeta($rowkeytype); }
 
1645
                        $ExtraFirstColumnValuesTypeVal[$extranum][$part]=qr/$rowkeytypeval/i;
 
1646
                        $part++;
 
1647
                }
 
1648
        }
 
1649
 
 
1650
        # Show definitive value for major parameters
 
1651
        if ($Debug) {
 
1652
                debug(" LogFile='$LogFile'",2);
 
1653
                debug(" LogFormat='$LogFormat'",2);
 
1654
                debug(" LogSeparator='$LogSeparator'",2);
 
1655
                debug(" DNSLookup='$DNSLookup'",2);
 
1656
                debug(" DirData='$DirData'",2);
 
1657
                debug(" DirCgi='$DirCgi'",2);
 
1658
                debug(" DirIcons='$DirIcons'",2);
 
1659
                debug(" SiteDomain='$SiteDomain'",2);
 
1660
                debug(" MiscTrackerUrl='$MiscTrackerUrl'",2);
 
1661
                foreach (keys %MaxNbOf) { debug(" MaxNbOf{$_}=$MaxNbOf{$_}",2); }
 
1662
                foreach (keys %MinHit)  { debug(" MinHit{$_}=$MinHit{$_}",2); }
 
1663
                foreach my $extranum (1..@ExtraName-1) {
 
1664
                        debug(" ExtraConditionType[$extranum] is array ".join(',',@{$ExtraConditionType[$extranum]}),2);
 
1665
                        debug(" ExtraConditionTypeVal[$extranum] is array ".join(',',@{$ExtraConditionTypeVal[$extranum]}),2);
 
1666
                        debug(" ExtraFirstColumnValuesType[$extranum] is array ".join(',',@{$ExtraFirstColumnValuesType[$extranum]}),2);
 
1667
                        debug(" ExtraFirstColumnValuesTypeVal[$extranum] is array ".join(',',@{$ExtraFirstColumnValuesTypeVal[$extranum]}),2);
 
1668
                }
 
1669
        }
 
1670
 
 
1671
        # Deny URLWithQueryWithOnlyFollowingParameters and URLWithQueryWithoutFollowingParameters both set
 
1672
        if (@URLWithQueryWithOnly && @URLWithQueryWithout) {
 
1673
                error("URLWithQueryWithOnlyFollowingParameters and URLWithQueryWithoutFollowingParameters can't be both set at the same time");
 
1674
        }
 
1675
        # Deny $ShowHTTPErrorsStats and $ShowSMTPErrorsStats both set
 
1676
        if ($ShowHTTPErrorsStats && $ShowSMTPErrorsStats) {
 
1677
                error("ShowHTTPErrorsStats and ShowSMTPErrorsStats can't be both set at the same time");
 
1678
        }
 
1679
        
 
1680
        # Deny LogFile if contains a pipe and PurgeLogFile || ArchiveLogRecords set on
 
1681
        if (($PurgeLogFile || $ArchiveLogRecords) && $LogFile =~ /\|\s*$/) {
 
1682
                error("A pipe in log file name is not allowed if PurgeLogFile and ArchiveLogRecords are not set to 0");
 
1683
        }
 
1684
        # If not a migrate, check if DirData is OK
 
1685
        if (! $MigrateStats && ! -d $DirData) {
 
1686
                if ($CreateDirDataIfNotExists) {
 
1687
                        if ($Debug) { debug(" Make directory $DirData",2); }
 
1688
                        my $mkdirok=mkdir "$DirData", 0766;
 
1689
                        if (! $mkdirok) { error("$PROG failed to create directory DirData (DirData=\"$DirData\", CreateDirDataIfNotExists=$CreateDirDataIfNotExists)."); }
 
1690
                }
 
1691
                else {
 
1692
                        error("AWStats database directory defined in config file by 'DirData' parameter ($DirData) does not exist or is not writable.");
 
1693
                }
 
1694
        }
 
1695
 
 
1696
        if ($LogType eq 'S') { $NOTSORTEDRECORDTOLERANCE=1000000; }
 
1697
}
 
1698
 
 
1699
 
 
1700
#------------------------------------------------------------------------------
 
1701
# Function:     Common function used by init function of plugins
 
1702
# Parameters:   AWStats version required by plugin
 
1703
# Input:                $VERSION
 
1704
# Output:               None
 
1705
# Return:               '' if ok, "Error: xxx" if error
 
1706
#------------------------------------------------------------------------------
 
1707
sub Check_Plugin_Version {
 
1708
        my $PluginNeedAWStatsVersion=shift;
 
1709
        if (! $PluginNeedAWStatsVersion) { return 0; }
 
1710
        $VERSION =~ /^(\d+)\.(\d+)/;
 
1711
        my $numAWStatsVersion=($1*1000)+$2;
 
1712
        $PluginNeedAWStatsVersion =~ /^(\d+)\.(\d+)/;
 
1713
        my $numPluginNeedAWStatsVersion=($1*1000)+$2;
 
1714
        if      ($numPluginNeedAWStatsVersion > $numAWStatsVersion) {
 
1715
                return "Error: AWStats version $PluginNeedAWStatsVersion or higher is required. Detected $VERSION.";
 
1716
        }
 
1717
        return '';
 
1718
}
 
1719
 
 
1720
 
 
1721
#------------------------------------------------------------------------------
 
1722
# Function:     Return a checksum for an array of string
 
1723
# Parameters:   Array of string
 
1724
# Input:                None
 
1725
# Output:               None
 
1726
# Return:               Checksum number
 
1727
#------------------------------------------------------------------------------
 
1728
sub CheckSum {
 
1729
        my $string=shift;
 
1730
        my $checksum=0;
 
1731
#       use MD5;
 
1732
#       $checksum = MD5->hexhash($string);
 
1733
        my $i=0; my $j=0; 
 
1734
        while ($i < length($string)) { 
 
1735
                my $c=substr($string,$i,1);
 
1736
                $checksum+=(ord($c)<<(8*$j));
 
1737
                if ($j++ > 3) { $j=0; }
 
1738
                $i++;
 
1739
        }
 
1740
        return $checksum;
 
1741
}
 
1742
 
 
1743
 
 
1744
#------------------------------------------------------------------------------
 
1745
# Function:     Load plugins files
 
1746
# Parameters:   None
 
1747
# Input:                $DIR @PluginsToLoad
 
1748
# Output:               None
 
1749
# Return:               None
 
1750
#------------------------------------------------------------------------------
 
1751
sub Read_Plugins {
 
1752
        # Check plugin files in common possible directories :
 
1753
        # Windows and standard package:                 "$DIR/plugins" (plugins in same dir than awstats.pl)
 
1754
        # Redhat :                                  "/usr/local/awstats/wwwroot/cgi-bin/plugins"
 
1755
        # Debian package :                              "/usr/share/awstats/plugins"
 
1756
        my @PossiblePluginsDir=("$DIR/plugins","/usr/local/awstats/wwwroot/cgi-bin/plugins","/usr/share/awstats/plugins");
 
1757
        my %DirAddedInINC=();
 
1758
 
 
1759
        foreach my $key (keys %NoLoadPlugin) { if ($NoLoadPlugin{$key} < 0) { push @PluginsToLoad, $key; } }
 
1760
        if ($Debug) { debug("Call to Read_Plugins with list: ".join(',',@PluginsToLoad)); }
 
1761
        foreach my $plugininfo (@PluginsToLoad) {
 
1762
                my @loadplugin=split(/\s+/,$plugininfo,2);
 
1763
                my $pluginfile=$loadplugin[0]; $pluginfile =~ s/\.pm$//i;
 
1764
                # Check if we plugin is not disabled
 
1765
                if ($NoLoadPlugin{$pluginfile} && $NoLoadPlugin{$pluginfile} > 0) {
 
1766
                        if ($Debug) { debug(" Plugin load for '$pluginfile' has been disabled from parameters"); }
 
1767
                        next;   
 
1768
                }
 
1769
                my $pluginparam=$loadplugin[1]||'';
 
1770
                $pluginfile =~ /([^\/\\]*)$/;
 
1771
                my $pluginname=$1;
 
1772
                if ($pluginname) {
 
1773
                        if (! $PluginsLoaded{'init'}{"$pluginname"}) {          # Plugin not already loaded
 
1774
                                my %pluginisfor=('ipv6'=>'u','hashfiles'=>'u','geoip'=>'u','geoipfree'=>'u','timehires'=>'u','timezone'=>'ou',
 
1775
                                                                 'decodeutfkeys'=>'o','hostinfo'=>'o','userinfo'=>'o','urlalias'=>'o','tooltips'=>'o');
 
1776
                                if ($pluginisfor{$pluginname}) {
 
1777
                                        # Do not load "update plugins" if output only
 
1778
                                        if (! $UpdateStats && scalar keys %HTMLOutput && $pluginisfor{$pluginname} !~ /o/) { $PluginsLoaded{'init'}{"$pluginname"}=1; next; }
 
1779
                                        # Do not load "output plugins" if update only
 
1780
                                        if ($UpdateStats && ! scalar keys %HTMLOutput && $pluginisfor{$pluginname} !~ /u/) { $PluginsLoaded{'init'}{"$pluginname"}=1; next; }
 
1781
                                }
 
1782
                                else { $PluginsLoaded{'init'}{"$pluginname"}=1; }       # Unknown plugins always loaded
 
1783
                                # Load plugin
 
1784
                                foreach my $dir (@PossiblePluginsDir) {
 
1785
                                        my $searchdir=$dir;
 
1786
                                        if ($searchdir && (!($searchdir =~ /\/$/)) && (!($searchdir =~ /\\$/)) ) { $searchdir .= "/"; }
 
1787
                                        my $pluginpath="${searchdir}${pluginfile}.pm";
 
1788
                                        if (-s "$pluginpath") {
 
1789
                                                $PluginDir="${searchdir}";      # Set plugin dir
 
1790
                                                if ($Debug) { debug(" Try to init plugin '$pluginname' ($pluginpath) with param '$pluginparam'",1); }
 
1791
                                                if (! $DirAddedInINC{"$dir"}) { 
 
1792
                                                        push @INC, "$dir";
 
1793
                                                        $DirAddedInINC{"$dir"}=1;
 
1794
                                                }
 
1795
                                                my $loadret=0;
 
1796
                                                my $modperl=$ENV{"MOD_PERL"}? eval { require mod_perl; $mod_perl::VERSION >= 1.99 ? 2 : 1 } : 0;
 
1797
                                                if ($modperl == 2) { $loadret=require "$pluginpath"; }
 
1798
                                                else { $loadret=require "$pluginfile.pm"; }
 
1799
        
 
1800
                                                if (! $loadret || $loadret =~ /^error/i) {
 
1801
                                                        # Load failed, we stop here
 
1802
                                                        error("Plugin load for plugin '$pluginname' failed with return code: $loadret");
 
1803
                                                }
 
1804
                                                my $ret;        # To get init return
 
1805
                                                my $initfunction="\$ret=Init_$pluginname('$pluginparam')";
 
1806
                                                my $initret=eval("$initfunction");
 
1807
                                                if (! $initret || $initret =~ /^error/i) {
 
1808
                                                        # Init function failed, we stop here
 
1809
                                                        error("Plugin init for plugin '$pluginname' failed with return code: ".($initret?"$initret":"$@ (A module required by plugin might be missing)."));
 
1810
                                                }
 
1811
                                                # Plugin load and init successfull
 
1812
                                                foreach my $elem (split(/\s+/,$initret)) {
 
1813
                                                        # Some functions can only be plugged once
 
1814
                                                        my @UniquePluginsFunctions=('GetCountryCodeByName','GetCountryCodeByAddr','ChangeTime','GetTimeZoneTitle','GetTime','SearchFile','LoadCache','SaveHash','ShowMenu');
 
1815
                                                        my $isuniquefunc=0;
 
1816
                                                        foreach my $function (@UniquePluginsFunctions) {
 
1817
                                                                if ("$elem" eq "$function") {
 
1818
                                                                        # We try to load a 'unique' function, so we check and stop if already loaded
 
1819
                                                                        foreach my $otherpluginname (keys %{$PluginsLoaded{"$elem"}})  {
 
1820
                                                                                error("Conflict between plugin '$pluginname' and '$otherpluginname'. They both implements the 'must be unique' function '$elem'.\nYou must choose between one of them. Using together is not possible.");
 
1821
                                                                        }
 
1822
                                                                        $isuniquefunc=1;
 
1823
                                                                        last;
 
1824
                                                                }
 
1825
                                                        }
 
1826
                                                        if ($isuniquefunc) {
 
1827
                                                                # TODO Use $PluginsLoaded{"$elem"}="$pluginname"; for unique func
 
1828
                                                                $PluginsLoaded{"$elem"}{"$pluginname"}=1;
 
1829
                                                        }
 
1830
                                                        else { $PluginsLoaded{"$elem"}{"$pluginname"}=1; }
 
1831
                                                }
 
1832
                                                $PluginsLoaded{'init'}{"$pluginname"}=1;
 
1833
                                                if ($Debug) { debug(" Plugin '$pluginname' now hooks functions '$initret'",1); }
 
1834
                                                last;
 
1835
                                        }
 
1836
                                }
 
1837
                                if (! $PluginsLoaded{'init'}{"$pluginname"}) {
 
1838
                                        error("Can't open plugin file \"$pluginfile.pm\" for read.\nCheck if file is in \"".($PossiblePluginsDir[0])."\" directory and is readable.");
 
1839
                                }
 
1840
                        }
 
1841
                        else {
 
1842
                                warning("Warning: Tried to load plugin \"$pluginname\" twice. Fix config file.");
 
1843
                        }
 
1844
                }
 
1845
                else {
 
1846
                        error("Plugin \"$pluginfile\" is not a valid plugin name.");
 
1847
                }
 
1848
        }
 
1849
        # In output, geo ip plugins were not loaded, so message changes can't be done in plugin init function
 
1850
        if ($PluginsLoaded{'init'}{'geoip'} || $PluginsLoaded{'init'}{'geoipfree'}) { $Message[17]=$Message[25]=$Message[148]; }
 
1851
}
 
1852
 
 
1853
#------------------------------------------------------------------------------
 
1854
# Function:             Read history file and create/update tmp history file
 
1855
# Parameters:   year,month,withupdate,withpurge,part_to_load[,lastlinenumber,lastlineoffset,lastlinechecksum]
 
1856
# Input:                $DirData $PROG $FileSuffix $LastLine
 
1857
# Output:               None
 
1858
# Return:               Tmp history file name created/updated or '' if withupdate is 0
 
1859
#------------------------------------------------------------------------------
 
1860
sub Read_History_With_TmpUpdate {
 
1861
 
 
1862
        my $year=sprintf("%04i",shift||0);
 
1863
        my $month=sprintf("%02i",shift||0);
 
1864
        my $withupdate=shift||0;
 
1865
        my $withpurge=shift||0;
 
1866
        my $part=shift||'';
 
1867
 
 
1868
        my $lastlinenumber=shift||0;
 
1869
        my $lastlineoffset=shift||0;
 
1870
        my $lastlinechecksum=shift||0;
 
1871
 
 
1872
        my %allsections=('general'=>1,'misc'=>2,'time'=>3,'visitor'=>4,'day'=>5,
 
1873
                                         'domain'=>6,'cluster'=>7,'login'=>8,'robot'=>9,'worms'=>10,'emailsender'=>11,'emailreceiver'=>12,
 
1874
                                         'session'=>13,'sider'=>14,'filetypes'=>15,
 
1875
                                         'os'=>16,'browser'=>17,'screensize'=>18,'unknownreferer'=>19,'unknownrefererbrowser'=>20,
 
1876
                                         'origin'=>21,'sereferrals'=>22,'pagerefs'=>23,
 
1877
                                         'searchwords'=>24,'keywords'=>25,
 
1878
                                         'errors'=>26);
 
1879
        my $order=(scalar keys %allsections)+1;
 
1880
        foreach (keys %TrapInfosForHTTPErrorCodes) { $allsections{"sider_$_"}=$order++; }
 
1881
        foreach (1..@ExtraName-1) { $allsections{"extra_$_"}=$order++; }
 
1882
        my $withread=0;
 
1883
 
 
1884
        # Variable used to read old format history files
 
1885
        my $readvisitorforbackward=0;
 
1886
 
 
1887
        # In standard use of AWStats, the DayRequired variable is always empty
 
1888
        if ($DayRequired) { if ($Debug) { debug("Call to Read_History_With_TmpUpdate [$year,$month,withupdate=$withupdate,withpurge=$withpurge,part=$part,lastlinenumber=$lastlinenumber,lastlineoffset=$lastlineoffset,lastlinechecksum=$lastlinechecksum] ($DayRequired)"); } }
 
1889
        else { if ($Debug) { debug("Call to Read_History_With_TmpUpdate [$year,$month,withupdate=$withupdate,withpurge=$withpurge,part=$part,lastlinenumber=$lastlinenumber,lastlineoffset=$lastlineoffset,lastlinechecksum=$lastlinechecksum]"); } }
 
1890
 
 
1891
        # Define SectionsToLoad (which sections to load)
 
1892
        my %SectionsToLoad = ();
 
1893
        if ($part eq 'all') {   # Load all needed sections
 
1894
                my $order=1;
 
1895
                $SectionsToLoad{'general'}=$order++;
 
1896
                # When
 
1897
                $SectionsToLoad{'time'}=$order++;       # Always loaded because needed to count TotalPages, TotalHits, TotalBandwidth
 
1898
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowHostsStats) || $HTMLOutput{'allhosts'} || $HTMLOutput{'lasthosts'} || $HTMLOutput{'unknownip'}) { $SectionsToLoad{'visitor'}=$order++; }      # Must be before day, sider and session section
 
1899
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && ($ShowDaysOfWeekStats || $ShowDaysOfMonthStats)) || $HTMLOutput{'alldays'}) { $SectionsToLoad{'day'}=$order++; }
 
1900
                # Who
 
1901
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowDomainsStats) || $HTMLOutput{'alldomains'}) { $SectionsToLoad{'domain'}=$order++; }
 
1902
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowAuthenticatedUsers) || $HTMLOutput{'alllogins'} || $HTMLOutput{'lastlogins'}) { $SectionsToLoad{'login'}=$order++; }
 
1903
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowRobotsStats) || $HTMLOutput{'allrobots'} || $HTMLOutput{'lastrobots'}) { $SectionsToLoad{'robot'}=$order++; }
 
1904
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowWormsStats) || $HTMLOutput{'allworms'} || $HTMLOutput{'lastworms'}) { $SectionsToLoad{'worms'}=$order++; }
 
1905
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowEMailSenders) || $HTMLOutput{'allemails'} || $HTMLOutput{'lastemails'}) { $SectionsToLoad{'emailsender'}=$order++; }
 
1906
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowEMailReceivers) || $HTMLOutput{'allemailr'} || $HTMLOutput{'lastemailr'}) { $SectionsToLoad{'emailreceiver'}=$order++; }
 
1907
                # Navigation
 
1908
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowSessionsStats) || $HTMLOutput{'sessions'}) { $SectionsToLoad{'session'}=$order++; }
 
1909
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowPagesStats) || $HTMLOutput{'urldetail'} || $HTMLOutput{'urlentry'} || $HTMLOutput{'urlexit'}) { $SectionsToLoad{'sider'}=$order++; }
 
1910
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowFileTypesStats) || $HTMLOutput{'filetypes'}) { $SectionsToLoad{'filetypes'}=$order++; }
 
1911
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowOSStats) || $HTMLOutput{'osdetail'}) { $SectionsToLoad{'os'}=$order++; }
 
1912
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowBrowsersStats) || $HTMLOutput{'browserdetail'}) { $SectionsToLoad{'browser'}=$order++; }
 
1913
                if ($UpdateStats || $MigrateStats || $HTMLOutput{'unknownos'})      { $SectionsToLoad{'unknownreferer'}=$order++; }
 
1914
                if ($UpdateStats || $MigrateStats || $HTMLOutput{'unknownbrowser'}) { $SectionsToLoad{'unknownrefererbrowser'}=$order++; }
 
1915
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowScreenSizeStats)) { $SectionsToLoad{'screensize'}=$order++; }
 
1916
                # Referers
 
1917
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowOriginStats) || $HTMLOutput{'origin'}) { $SectionsToLoad{'origin'}=$order++; }
 
1918
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowOriginStats) || $HTMLOutput{'refererse'}) { $SectionsToLoad{'sereferrals'}=$order++; }
 
1919
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowOriginStats) || $HTMLOutput{'refererpages'}) { $SectionsToLoad{'pagerefs'}=$order++; }
 
1920
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowKeyphrasesStats) || $HTMLOutput{'keyphrases'} || $HTMLOutput{'keywords'}) { $SectionsToLoad{'searchwords'}=$order++; }
 
1921
                if (! $withupdate && $HTMLOutput{'main'} && $ShowKeywordsStats) { $SectionsToLoad{'keywords'}=$order++; }       # If we update, dont need to load
 
1922
                # Others
 
1923
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowMiscStats)) { $SectionsToLoad{'misc'}=$order++; }
 
1924
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && ($ShowHTTPErrorsStats || $ShowSMTPErrorsStats)) || $HTMLOutput{'errors'}) { $SectionsToLoad{'errors'}=$order++; }
 
1925
                foreach (keys %TrapInfosForHTTPErrorCodes) {
 
1926
                        if ($UpdateStats || $MigrateStats || $HTMLOutput{"errors$_"}) { $SectionsToLoad{"sider_$_"}=$order++; }
 
1927
                }
 
1928
                if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ShowClusterStats)) { $SectionsToLoad{'cluster'}=$order++; }
 
1929
                foreach (1..@ExtraName-1) {
 
1930
                        if ($UpdateStats || $MigrateStats || ($HTMLOutput{'main'} && $ExtraStatTypes[$_]) || $HTMLOutput{"extra$_"}) { $SectionsToLoad{"extra_$_"}=$order++; }
 
1931
                }
 
1932
        }
 
1933
        else {                                  # Load only required sections
 
1934
                my $order=1;
 
1935
                foreach (split(/\s+/,$part)) { $SectionsToLoad{$_}=$order++; }
 
1936
        }
 
1937
 
 
1938
        # Define SectionsToSave (which sections to save)
 
1939
        my %SectionsToSave = ();
 
1940
        if ($withupdate) { %SectionsToSave=%allsections; }
 
1941
 
 
1942
        if ($Debug) {
 
1943
                foreach (sort { $SectionsToLoad{$a} <=> $SectionsToLoad{$b} } keys %SectionsToLoad) { debug(" Section '$_' is marked for load",2); }
 
1944
                foreach (sort { $SectionsToSave{$a} <=> $SectionsToSave{$b} } keys %SectionsToSave) { debug(" Section '$_' is marked for save",2); }
 
1945
        }
 
1946
 
 
1947
        # Define value for filetowrite and filetoread (Month before Year kept for backward compatibility)
 
1948
        my $filetowrite='';
 
1949
        my $filetoread='';
 
1950
        if ($HistoryAlreadyFlushed{"$year$month"} && -s "$DirData/$PROG$month$year$FileSuffix.tmp.$$") {
 
1951
                # tmp history file was already flushed
 
1952
                $filetoread="$DirData/$PROG$month$year$FileSuffix.tmp.$$";
 
1953
                $filetowrite="$DirData/$PROG$month$year$FileSuffix.tmp.$$.bis";
 
1954
        }
 
1955
        else {
 
1956
                $filetoread="$DirData/$PROG$DayRequired$month$year$FileSuffix.txt";
 
1957
                $filetowrite="$DirData/$PROG$month$year$FileSuffix.tmp.$$";
 
1958
        }
 
1959
        if ($Debug) { debug(" History file to read is '$filetoread'",2); }
 
1960
 
 
1961
        # Is there an old data file to read or, if migrate, can we open the file for read
 
1962
        if (-s $filetoread || $MigrateStats) { $withread=1; }
 
1963
 
 
1964
        # Open files
 
1965
        if ($withread) {
 
1966
                open(HISTORY,$filetoread) || error("Couldn't open file \"$filetoread\" for read: $!","","",$MigrateStats);
 
1967
                binmode HISTORY;        # Avoid premature EOF due to history files corrupted with \cZ or bin chars
 
1968
        }
 
1969
        if ($withupdate) {
 
1970
                open(HISTORYTMP,">$filetowrite") || error("Couldn't open file \"$filetowrite\" for write: $!");
 
1971
                binmode HISTORYTMP;
 
1972
                Save_History("header",$year,$month);
 
1973
        }
 
1974
 
 
1975
        # Loop on read file
 
1976
        if ($withread) {
 
1977
                my $countlines=0;
 
1978
                my $versionnum=0;
 
1979
                my @field=();
 
1980
                while (<HISTORY>) {
 
1981
                        chomp $_; s/\r//;
 
1982
                        $countlines++;
 
1983
                        
 
1984
                        # Ignore lines started by a XML tag
 
1985
                        if ($_ =~ /^</) { next; }
 
1986
 
 
1987
                        # Extract version from first line
 
1988
                        if (! $versionnum && $_ =~ /^AWSTATS DATA FILE (\d+).(\d+)/i) {
 
1989
                                $versionnum=($1*1000)+$2;
 
1990
                                if ($Debug) { debug(" Data file version is $versionnum",1); }
 
1991
                                next;
 
1992
                        }
 
1993
 
 
1994
                        # Analyze fields
 
1995
                        @field=split(/\s+/,$_);
 
1996
                        if (! $field[0]) { next; }
 
1997
 
 
1998
                        # BEGIN_GENERAL
 
1999
                        if ($field[0] eq 'BEGIN_GENERAL')      {
 
2000
                                if ($Debug) { debug(" Begin of GENERAL section"); }
 
2001
                                next;
 
2002
                        }
 
2003
                        if ($field[0] eq 'LastLine')        {
 
2004
                                if (! $LastLine || $LastLine < int($field[1])) { $LastLine=int($field[1]); };
 
2005
                                if ($field[2]) { $LastLineNumber=int($field[2]); }
 
2006
                                if ($field[3]) { $LastLineOffset=int($field[3]); }
 
2007
                                if ($field[4]) { $LastLineChecksum=int($field[4]); }
 
2008
                                next;
 
2009
                        }
 
2010
                        if ($field[0] eq 'FirstTime')       { if (! $FirstTime{$year.$month} || $FirstTime{$year.$month} > int($field[1])) { $FirstTime{$year.$month}=int($field[1]); }; next; }
 
2011
                        if ($field[0] eq 'LastTime')        { if (! $LastTime{$year.$month} || $LastTime{$year.$month} < int($field[1])) { $LastTime{$year.$month}=int($field[1]); }; next; }
 
2012
                        if ($field[0] eq 'LastUpdate')      {
 
2013
                                if ($LastUpdate < $field[1]) {
 
2014
                                        $LastUpdate=int($field[1]);
 
2015
                                        #$LastUpdateLinesRead=int($field[2]);
 
2016
                                        #$LastUpdateNewLinesRead=int($field[3]);
 
2017
                                        #$LastUpdateLinesCorrupted=int($field[4]);
 
2018
                                };
 
2019
                                next;
 
2020
                        }
 
2021
                        if ($field[0] eq 'TotalVisits')       {
 
2022
                                if (! $withupdate) { $MonthVisits{$year.$month}+=int($field[1]); }
 
2023
                                # Save in MonthVisits also if migrate from a file < 4.x for backward compatibility
 
2024
                                if ($MigrateStats && $versionnum < 4000 && ! $MonthVisits{$year.$month}) {
 
2025
                                        if ($Debug) { debug("File is version < 4000. We save ".int($field[1])." visits in DayXxx arrays",1); }
 
2026
                                        $DayHits{$year.$month."00"}+=0;
 
2027
                                        $DayVisits{$year.$month."00"}+=int($field[1]);
 
2028
                                }
 
2029
                                next;
 
2030
                        }
 
2031
                        if ($field[0] eq 'TotalUnique')       { if (! $withupdate) { $MonthUnique{$year.$month}+=int($field[1]); } next; }
 
2032
                        if ($field[0] eq 'MonthHostsKnown')   { if (! $withupdate) { $MonthHostsKnown{$year.$month}+=int($field[1]); } next; }
 
2033
                        if ($field[0] eq 'MonthHostsUnknown') { if (! $withupdate) { $MonthHostsUnknown{$year.$month}+=int($field[1]); } next; }
 
2034
 
 
2035
                        if ($field[0] eq 'END_GENERAL'  # END_GENERAL didn't exist for history files < 5.0
 
2036
                         || ($versionnum < 5000 && $SectionsToLoad{"general"} && $FirstTime{$year.$month} && $LastTime{$year.$month}) )         {
 
2037
                                if ($Debug) { debug(" End of GENERAL section"); }
 
2038
 
 
2039
                                # Show migrate warning for backward compatibility
 
2040
                                if ($versionnum < 5000 && ! $MigrateStats && ! $BadFormatWarning{$year.$month}) {
 
2041
                                        if ($FrameName ne 'mainleft') {
 
2042
                                                $BadFormatWarning{$year.$month}=1;
 
2043
                                                my $message="Warning: Data file '$filetoread' has an old history file format (version $versionnum). You should upgrade it...\nFrom command line: $PROG.$Extension -migrate=\"$filetoread\"";
 
2044
                                                if ($ENV{'GATEWAY_INTERFACE'} && $AllowToUpdateStatsFromBrowser) { $message.="\nFrom your browser with URL: <a href=\"http://".$ENV{"SERVER_NAME"}.$ENV{"SCRIPT_NAME"}."?migrate=$filetoread\">http://".$ENV{"SERVER_NAME"}.$ENV{"SCRIPT_NAME"}."?migrate=$filetoread</a>"; }
 
2045
                                                warning("$message");
 
2046
                                        }
 
2047
                                }
 
2048
                                if (! ($versionnum < 5000) && $MigrateStats && ! $BadFormatWarning{$year.$month}) {
 
2049
                                        $BadFormatWarning{$year.$month}=1;
 
2050
                                        warning("Warning: You are migrating a file that is already a recent version (migrate not required for files version $versionnum).","","",1);
 
2051
                                }
 
2052
                                # If migrate and version < 4.x we need to include BEGIN_UNKNOWNIP into BEGIN_VISITOR for backward compatibility
 
2053
                                if ($MigrateStats && $versionnum < 4000) {
 
2054
                                        if ($Debug) { debug("File is version < 4000. We add UNKNOWNIP in sections to load",1); }
 
2055
                                        $SectionsToLoad{'unknownip'}=99;
 
2056
                                }
 
2057
 
 
2058
                                delete $SectionsToLoad{'general'};
 
2059
                                if ($SectionsToSave{'general'}) { Save_History('general',$year,$month,$lastlinenumber,$lastlineoffset,$lastlinechecksum); delete $SectionsToSave{'general'}; }
 
2060
 
 
2061
                                # Test for backward compatibility
 
2062
                                if ($versionnum < 5000 && ! $withupdate) {
 
2063
                                        # We must find another way to init MonthUnique MonthHostsKnown and MonthHostsUnknown
 
2064
                                        if ($Debug) { debug(" We ask to count MonthUnique, MonthHostsKnown and MonthHostsUnknown in visitor section because they are not stored in general section for this data file (version $versionnum)."); }
 
2065
                                        $readvisitorforbackward=($SectionsToLoad{"visitor"}?1:2);
 
2066
                                        $SectionsToLoad{"visitor"}=4;
 
2067
                                }
 
2068
                                else {
 
2069
                                        if (! scalar %SectionsToLoad) {
 
2070
                                                if ($Debug) { debug(" Stop reading history file. Got all we need."); }
 
2071
                                                last;
 
2072
                                        }
 
2073
                                }
 
2074
                                if ($versionnum >= 5000) { next; }      # We can forget 'END_GENERAL' line and read next one
 
2075
                        }
 
2076
 
 
2077
                        # BEGIN_MISC
 
2078
                        if ($field[0] eq 'BEGIN_MISC')      {
 
2079
                                if ($Debug) { debug(" Begin of MISC section"); }
 
2080
                                $field[0]='';
 
2081
                                my $count=0;my $countloaded=0;
 
2082
                                do {
 
2083
                                        if ($field[0]) {
 
2084
                                                $count++;
 
2085
                                                if ($SectionsToLoad{'misc'}) {
 
2086
                                                        $countloaded++;
 
2087
                                                        if ($field[1]) { $_misc_p{$field[0]}+=int($field[1]); }
 
2088
                                                        if ($field[2]) { $_misc_h{$field[0]}+=int($field[2]); }
 
2089
                                                        if ($field[3]) { $_misc_k{$field[0]}+=int($field[3]); }
 
2090
                                                }
 
2091
                                        }
 
2092
                                        $_=<HISTORY>;
 
2093
                                        chomp $_; s/\r//;
 
2094
                                        @field=split(/\s+/,$_); $countlines++;
 
2095
                                }
 
2096
                                until ($field[0] eq 'END_MISC' || ! $_);
 
2097
                                if ($field[0] ne 'END_MISC') { error("History file \"$filetoread\" is corrupted (End of section MISC not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2098
                                if ($Debug) { debug(" End of MISC section ($count entries, $countloaded loaded)"); }
 
2099
                                delete $SectionsToLoad{'misc'};
 
2100
                                if ($SectionsToSave{'misc'}) {
 
2101
                                        Save_History('misc',$year,$month); delete $SectionsToSave{'misc'};
 
2102
                                        if ($withpurge) { %_misc_p=(); %_misc_h=(); %_misc_k=(); }
 
2103
                                }
 
2104
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2105
                                next;
 
2106
                        }
 
2107
 
 
2108
                        # BEGIN_CLUSTER
 
2109
                        if ($field[0] eq 'BEGIN_CLUSTER')      {
 
2110
                                if ($Debug) { debug(" Begin of CLUSTER section"); }
 
2111
                                $field[0]='';
 
2112
                                my $count=0;my $countloaded=0;
 
2113
                                do {
 
2114
                                        if ($field[0]) {
 
2115
                                                $count++;
 
2116
                                                if ($SectionsToLoad{'cluster'}) {
 
2117
                                                        $countloaded++;
 
2118
                                                        if ($field[1]) { $_cluster_p{$field[0]}+=int($field[1]); }
 
2119
                                                        if ($field[2]) { $_cluster_h{$field[0]}+=int($field[2]); }
 
2120
                                                        if ($field[3]) { $_cluster_k{$field[0]}+=int($field[3]); }
 
2121
                                                }
 
2122
                                        }
 
2123
                                        $_=<HISTORY>;
 
2124
                                        chomp $_; s/\r//;
 
2125
                                        @field=split(/\s+/,$_); $countlines++;
 
2126
                                }
 
2127
                                until ($field[0] eq 'END_CLUSTER' || ! $_);
 
2128
                                if ($field[0] ne 'END_CLUSTER') { error("History file \"$filetoread\" is corrupted (End of section CLUSTER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2129
                                if ($Debug) { debug(" End of CLUSTER section ($count entries, $countloaded loaded)"); }
 
2130
                                delete $SectionsToLoad{'cluster'};
 
2131
                                if ($SectionsToSave{'cluster'}) {
 
2132
                                        Save_History('cluster',$year,$month); delete $SectionsToSave{'cluster'};
 
2133
                                        if ($withpurge) { %_cluster_p=(); %_cluster_h=(); %_cluster_k=(); }
 
2134
                                }
 
2135
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2136
                                next;
 
2137
                        }
 
2138
 
 
2139
                        # BEGIN_TIME
 
2140
                        if ($field[0] eq 'BEGIN_TIME')      {
 
2141
                                my $monthpages=0;my $monthhits=0;my $monthbytes=0;
 
2142
                                my $monthnotviewedpages=0;my $monthnotviewedhits=0;my $monthnotviewedbytes=0;
 
2143
                                if ($Debug) { debug(" Begin of TIME section"); }
 
2144
                                $field[0]='';
 
2145
                                my $count=0;my $countloaded=0;
 
2146
                                do {
 
2147
                                        if ($field[0] ne '') {  # Test on ne '' because field[0] is '0' for hour 0)
 
2148
                                                $count++;
 
2149
                                                if ($SectionsToLoad{'time'}) {
 
2150
                                                        if ($withupdate || $MonthRequired eq 'all' || $MonthRequired eq "$month") {     # Still required
 
2151
                                                                $countloaded++;
 
2152
                                                                if ($field[1]) { $_time_p[$field[0]]+=int($field[1]); }
 
2153
                                                                if ($field[2]) { $_time_h[$field[0]]+=int($field[2]); }
 
2154
                                                                if ($field[3]) { $_time_k[$field[0]]+=int($field[3]); }
 
2155
                                                                if ($field[4]) { $_time_nv_p[$field[0]]+=int($field[4]); }
 
2156
                                                                if ($field[5]) { $_time_nv_h[$field[0]]+=int($field[5]); }
 
2157
                                                                if ($field[6]) { $_time_nv_k[$field[0]]+=int($field[6]); }
 
2158
                                                        }
 
2159
                                                        $monthpages+=int($field[1]);
 
2160
                                                        $monthhits+=int($field[2]);
 
2161
                                                        $monthbytes+=int($field[3]);
 
2162
                                                        $monthnotviewedpages+=int($field[4]||0);
 
2163
                                                        $monthnotviewedhits+=int($field[5]||0);
 
2164
                                                        $monthnotviewedbytes+=int($field[6]||0);
 
2165
                                                }
 
2166
                                        }
 
2167
                                        $_=<HISTORY>;
 
2168
                                        chomp $_; s/\r//;
 
2169
                                        @field=split(/\s+/,$_); $countlines++;
 
2170
                                }
 
2171
                                until ($field[0] eq 'END_TIME' || ! $_);
 
2172
                                if ($field[0] ne 'END_TIME') { error("History file \"$filetoread\" is corrupted (End of section TIME not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2173
                                if ($Debug) { debug(" End of TIME section ($count entries, $countloaded loaded)"); }
 
2174
                                $MonthPages{$year.$month}+=$monthpages;
 
2175
                                $MonthHits{$year.$month}+=$monthhits;
 
2176
                                $MonthBytes{$year.$month}+=$monthbytes;
 
2177
                                $MonthNotViewedPages{$year.$month}+=$monthnotviewedpages;
 
2178
                                $MonthNotViewedHits{$year.$month}+=$monthnotviewedhits;
 
2179
                                $MonthNotViewedBytes{$year.$month}+=$monthnotviewedbytes;
 
2180
                                delete $SectionsToLoad{'time'};
 
2181
                                if ($SectionsToSave{'time'}) {
 
2182
                                        Save_History('time',$year,$month); delete $SectionsToSave{'time'};
 
2183
                                        if ($withpurge) { @_time_p=(); @_time_h=(); @_time_k=(); @_time_nv_p=(); @_time_nv_h=(); @_time_nv_k=(); }
 
2184
                                }
 
2185
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2186
                                next;
 
2187
                        }
 
2188
 
 
2189
                        # BEGIN_ORIGIN
 
2190
                        if ($field[0] eq 'BEGIN_ORIGIN')        {
 
2191
                                if ($Debug) { debug(" Begin of ORIGIN section"); }
 
2192
                                $field[0]='';
 
2193
                                my $count=0;my $countloaded=0;
 
2194
                                do {
 
2195
                                        if ($field[0]) {
 
2196
                                                $count++;
 
2197
                                                if ($SectionsToLoad{'origin'}) {
 
2198
                                                        if ($field[0] eq 'From0') { $_from_p[0]+=$field[1]; $_from_h[0]+=$field[2]; }
 
2199
                                                        elsif ($field[0] eq 'From1') { $_from_p[1]+=$field[1]; $_from_h[1]+=$field[2]; }
 
2200
                                                        elsif ($field[0] eq 'From2') { $_from_p[2]+=$field[1]; $_from_h[2]+=$field[2]; }
 
2201
                                                        elsif ($field[0] eq 'From3') { $_from_p[3]+=$field[1]; $_from_h[3]+=$field[2]; }
 
2202
                                                        elsif ($field[0] eq 'From4') { $_from_p[4]+=$field[1]; $_from_h[4]+=$field[2]; }
 
2203
                                                        elsif ($field[0] eq 'From5') { $_from_p[5]+=$field[1]; $_from_h[5]+=$field[2]; }
 
2204
                                                }
 
2205
                                        }
 
2206
                                        $_=<HISTORY>;
 
2207
                                        chomp $_; s/\r//;
 
2208
                                        @field=split(/\s+/,$_); $countlines++;
 
2209
                                }
 
2210
                                until ($field[0] eq 'END_ORIGIN' || ! $_);
 
2211
                                if ($field[0] ne 'END_ORIGIN') { error("History file \"$filetoread\" is corrupted (End of section ORIGIN not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2212
                                if ($Debug) { debug(" End of ORIGIN section ($count entries, $countloaded loaded)"); }
 
2213
                                delete $SectionsToLoad{'origin'};
 
2214
                                if ($SectionsToSave{'origin'}) {
 
2215
                                        Save_History('origin',$year,$month); delete $SectionsToSave{'origin'};
 
2216
                                        if ($withpurge) { @_from_p=(); @_from_h=(); }
 
2217
                                }
 
2218
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2219
                                next;
 
2220
                        }
 
2221
                        # BEGIN_DAY
 
2222
                        if ($field[0] eq 'BEGIN_DAY')      {
 
2223
                                if ($Debug) { debug(" Begin of DAY section"); }
 
2224
                                $field[0]='';
 
2225
                                my $count=0;my $countloaded=0;
 
2226
                                do {
 
2227
                                        if ($field[0]) {
 
2228
                                                $count++;
 
2229
                                                if ($SectionsToLoad{'day'}) {
 
2230
                                                        $countloaded++;
 
2231
                                                        if ($field[1]) { $DayPages{$field[0]}+=int($field[1]); }
 
2232
                                                        $DayHits{$field[0]}+=int($field[2]);                                            # DayHits always load (should be >0 and if not it's a day YYYYMM00 resulting of an old file migration)
 
2233
                                                        if ($field[3]) { $DayBytes{$field[0]}+=int($field[3]); }
 
2234
                                                        if ($field[4]) { $DayVisits{$field[0]}+=int($field[4]); }
 
2235
                                                }
 
2236
                                        }
 
2237
                                        $_=<HISTORY>;
 
2238
                                        chomp $_; s/\r//;
 
2239
                                        @field=split(/\s+/,$_); $countlines++;
 
2240
                                }
 
2241
                                until ($field[0] eq 'END_DAY' || ! $_);
 
2242
                                if ($field[0] ne 'END_DAY') { error("History file \"$filetoread\" is corrupted (End of section DAY not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2243
                                if ($Debug) { debug(" End of DAY section ($count entries, $countloaded loaded)"); }
 
2244
                                delete $SectionsToLoad{'day'};
 
2245
                                # WE DO NOT SAVE SECTION NOW BECAUSE VALUES CAN BE CHANGED AFTER READING VISITOR
 
2246
                                #if ($SectionsToSave{'day'}) {  # Must be made after read of visitor
 
2247
                                #       Save_History('day',$year,$month); delete $SectionsToSave{'day'};
 
2248
                                #       if ($withpurge) { %DayPages=(); %DayHits=(); %DayBytes=(); %DayVisits=(); }
 
2249
                                #}
 
2250
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2251
                                next;
 
2252
                        }
 
2253
                        # BEGIN_VISITOR
 
2254
                        if ($field[0] eq 'BEGIN_VISITOR')   {
 
2255
                                if ($Debug) { debug(" Begin of VISITOR section"); }
 
2256
                                $field[0]='';
 
2257
                                my $count=0;my $countloaded=0;
 
2258
                                do {
 
2259
                                        if ($field[0]) {
 
2260
                                                $count++;
 
2261
 
 
2262
                                                # For backward compatibility
 
2263
                                                if ($readvisitorforbackward) {
 
2264
                                                        if ($field[1]) { $MonthUnique{$year.$month}++; }
 
2265
                                                        if ($MonthRequired ne 'all') {
 
2266
                                                                if ($field[0] !~ /^\d+\.\d+\.\d+\.\d+$/ && $field[0] !~ /^[0-9A-F]*:/i) { $MonthHostsKnown{$year.$month}++; }
 
2267
                                                                else { $MonthHostsUnknown{$year.$month}++; }
 
2268
                                                        }
 
2269
                                                }
 
2270
 
 
2271
                                                # Process data saved in 'wait' arrays
 
2272
                                                if ($withupdate && $_waithost_e{$field[0]}){
 
2273
                                                        my $timehostl=int($field[4]||0);
 
2274
                                                        my $timehosts=int($field[5]||0);
 
2275
                                                        my $newtimehosts=($_waithost_s{$field[0]}?$_waithost_s{$field[0]}:$_host_s{$field[0]});
 
2276
                                                        my $newtimehostl=($_waithost_l{$field[0]}?$_waithost_l{$field[0]}:$_host_l{$field[0]});
 
2277
                                                        if ($newtimehosts > $timehostl + $VISITTIMEOUT ) {
 
2278
                                                                if ($Debug) { debug(" Visit for $field[0] in 'wait' arrays is a new visit different than last in history",4); }
 
2279
                                                                if ($field[6]) { $_url_x{$field[6]}++; }
 
2280
                                                                $_url_e{$_waithost_e{$field[0]}}++;
 
2281
                                                                $newtimehosts =~ /^(\d\d\d\d\d\d\d\d)/; $DayVisits{$1}++;
 
2282
                                                                if ($timehosts && $timehostl) { $_session{GetSessionRange($timehosts,$timehostl)}++; }
 
2283
                                                                if ($_waithost_s{$field[0]}) {
 
2284
                                                                        # First session found in log was followed by another one so it's finished
 
2285
                                                                        $_session{GetSessionRange($newtimehosts,$newtimehostl)}++;
 
2286
                                                                }
 
2287
                                                                # Here $_host_l $_host_s and $_host_u are correctly defined
 
2288
                                                        }
 
2289
                                                        else {
 
2290
                                                                if ($Debug) { debug(" Visit for $field[0] in 'wait' arrays is following of last visit in history",4); }
 
2291
                                                                if ($_waithost_s{$field[0]}) {
 
2292
                                                                        # First session found in log was followed by another one so it's finished
 
2293
                                                                        $_session{GetSessionRange(MinimumButNoZero($timehosts,$newtimehosts),$timehostl>$newtimehostl?$timehostl:$newtimehostl)}++;
 
2294
                                                                        # Here $_host_l $_host_s and $_host_u are correctly defined
 
2295
                                                                }
 
2296
                                                                else {
 
2297
                                                                        # We correct $_host_l $_host_s and $_host_u
 
2298
                                                                        if ($timehostl > $newtimehostl) {
 
2299
                                                                                $_host_l{$field[0]}=$timehostl;
 
2300
                                                                                $_host_u{$field[0]}=$field[6];
 
2301
                                                                        }
 
2302
                                                                        if ($timehosts < $newtimehosts) {
 
2303
                                                                                $_host_s{$field[0]}=$timehosts;
 
2304
                                                                        }
 
2305
                                                                }
 
2306
                                                        }
 
2307
                                                        delete $_waithost_e{$field[0]};
 
2308
                                                        delete $_waithost_l{$field[0]};
 
2309
                                                        delete $_waithost_s{$field[0]};
 
2310
                                                        delete $_waithost_u{$field[0]};
 
2311
                                                }
 
2312
 
 
2313
                                                # Load records
 
2314
                                                if ($readvisitorforbackward!=2 && $SectionsToLoad{'visitor'}) { # if readvisitorforbackward==2 we do not load
 
2315
                                                        my $loadrecord=0;
 
2316
                                                        if ($withupdate) {
 
2317
                                                                $loadrecord=1;
 
2318
                                                        }
 
2319
                                                        else {
 
2320
                                                                if ($HTMLOutput{'allhosts'} || $HTMLOutput{'lasthosts'}) {
 
2321
                                                                        if ((!$FilterIn{'host'} || $field[0] =~ /$FilterIn{'host'}/)
 
2322
                                                                         && (!$FilterEx{'host'} || $field[0] !~ /$FilterEx{'host'}/)) { $loadrecord=1; }
 
2323
                                                                }
 
2324
                                                                elsif ($MonthRequired eq 'all' || $field[2] >= $MinHit{'Host'}) {
 
2325
                                                                        if ($HTMLOutput{'unknownip'} && ($field[0] =~ /^\d+\.\d+\.\d+\.\d+$/ || $field[0] =~ /^[0-9A-F]*:/i)) { $loadrecord=1; }
 
2326
                                                                        elsif ($HTMLOutput{'main'} && ($MonthRequired eq 'all' || $countloaded < $MaxNbOf{'HostsShown'})) { $loadrecord=1; }
 
2327
                                                                }
 
2328
                                                        }
 
2329
                                                        if ($loadrecord) {
 
2330
                                                                if ($field[1]) { $_host_p{$field[0]}+=$field[1]; }
 
2331
                                                                if ($field[2]) { $_host_h{$field[0]}+=$field[2]; }
 
2332
                                                                if ($field[3]) { $_host_k{$field[0]}+=$field[3]; }
 
2333
                                                                if ($field[4] && ! $_host_l{$field[0]}) {       # We save last connexion params if not previously defined
 
2334
                                                                        $_host_l{$field[0]}=int($field[4]);
 
2335
                                                                        if ($withupdate) {              # field[5] field[6] are used only for update
 
2336
                                                                                if ($field[5] && ! $_host_s{$field[0]}) { $_host_s{$field[0]}=int($field[5]); }
 
2337
                                                                                if ($field[6] && ! $_host_u{$field[0]}) { $_host_u{$field[0]}=$field[6]; }
 
2338
                                                                        }
 
2339
                                                                }
 
2340
                                                                $countloaded++;
 
2341
                                                        }
 
2342
                                                }
 
2343
                                        }
 
2344
                                        $_=<HISTORY>;
 
2345
                                        chomp $_; s/\r//;
 
2346
                                        @field=split(/\s+/,$_); $countlines++;
 
2347
                                }
 
2348
                                until ($field[0] eq 'END_VISITOR' || ! $_);
 
2349
                                if ($field[0] ne 'END_VISITOR') { error("History file \"$filetoread\" is corrupted (End of section VISITOR not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2350
                                if ($Debug) { debug(" End of VISITOR section ($count entries, $countloaded loaded)"); }
 
2351
                                delete $SectionsToLoad{'visitor'};
 
2352
                                # WE DO NOT SAVE SECTION NOW TO BE SURE TO HAVE THIS LARGE SECTION NOT AT THE BEGINNING OF FILE
 
2353
                                #if ($SectionsToSave{'visitor'}) {
 
2354
                                #       Save_History('visitor',$year,$month); delete $SectionsToSave{'visitor'};
 
2355
                                #       if ($withpurge) { %_host_p=(); %_host_h=(); %_host_k=(); %_host_l=(); %_host_s=(); %_host_u=(); }
 
2356
                                #}
 
2357
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2358
                                next;
 
2359
                        }
 
2360
                        # BEGIN_UNKNOWNIP for backward compatibility
 
2361
                        if ($field[0] eq 'BEGIN_UNKNOWNIP')   {
 
2362
                                my %iptomigrate=();
 
2363
                                if ($Debug) { debug(" Begin of UNKNOWNIP section"); }
 
2364
                                $field[0]='';
 
2365
                                my $count=0;my $countloaded=0;
 
2366
                                do {
 
2367
                                        if ($field[0]) {
 
2368
                                                $count++;
 
2369
                                                if ($SectionsToLoad{'unknownip'}) {
 
2370
                                                        $iptomigrate{$field[0]}=$field[1]||0;
 
2371
                                                        $countloaded++;
 
2372
                                                }
 
2373
                                        }
 
2374
                                        $_=<HISTORY>;
 
2375
                                        chomp $_; s/\r//;
 
2376
                                        @field=split(/\s+/,$_); $countlines++;
 
2377
                                }
 
2378
                                until ($field[0] eq 'END_UNKNOWNIP' || ! $_);
 
2379
                                if ($field[0] ne 'END_UNKNOWNIP') { error("History file \"$filetoread\" is corrupted (End of section UNKOWNIP not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2380
                                if ($Debug) { debug(" End of UNKOWNIP section ($count entries, $countloaded loaded)"); }
 
2381
                                delete $SectionsToLoad{'visitor'};
 
2382
                                # THIS SECTION IS NEVER SAVED. ONLY READ FOR MIGRATE AND CONVERTED INTO VISITOR SECTION
 
2383
                                foreach (keys %iptomigrate) {
 
2384
                                        $_host_p{$_}+=int($_host_p{'Unknown'}/$countloaded);
 
2385
                                        $_host_h{$_}+=int($_host_h{'Unknown'}/$countloaded);
 
2386
                                        $_host_k{$_}+=int($_host_k{'Unknown'}/$countloaded);
 
2387
                                        if ($iptomigrate{$_} > 0) { $_host_l{$_}=$iptomigrate{$_} };
 
2388
                                }
 
2389
                                delete $_host_p{'Unknown'};
 
2390
                                delete $_host_h{'Unknown'};
 
2391
                                delete $_host_k{'Unknown'};
 
2392
                                delete $_host_l{'Unknown'};
 
2393
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2394
                                next;
 
2395
                        }
 
2396
                        # BEGIN_LOGIN
 
2397
                        if ($field[0] eq 'BEGIN_LOGIN')   {
 
2398
                                if ($Debug) { debug(" Begin of LOGIN section"); }
 
2399
                                $field[0]='';
 
2400
                                my $count=0;my $countloaded=0;
 
2401
                                do {
 
2402
                                        if ($field[0]) {
 
2403
                                                $count++;
 
2404
                                                if ($SectionsToLoad{'login'}) {
 
2405
                                                        $countloaded++;
 
2406
                                                        if ($field[1]) { $_login_p{$field[0]}+=$field[1]; }
 
2407
                                                        if ($field[2]) { $_login_h{$field[0]}+=$field[2]; }
 
2408
                                                        if ($field[3]) { $_login_k{$field[0]}+=$field[3]; }
 
2409
                                                        if (! $_login_l{$field[0]} && $field[4]) { $_login_l{$field[0]}=int($field[4]); }
 
2410
                                                }
 
2411
                                        }
 
2412
                                        $_=<HISTORY>;
 
2413
                                        chomp $_; s/\r//;
 
2414
                                        @field=split(/\s+/,$_); $countlines++;
 
2415
                                }
 
2416
                                until ($field[0] eq 'END_LOGIN' || ! $_);
 
2417
                                if ($field[0] ne 'END_LOGIN') { error("History file \"$filetoread\" is corrupted (End of section LOGIN not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2418
                                if ($Debug) { debug(" End of LOGIN section ($count entries, $countloaded loaded)"); }
 
2419
                                delete $SectionsToLoad{'login'};
 
2420
                                if ($SectionsToSave{'login'}) {
 
2421
                                        Save_History('login',$year,$month); delete $SectionsToSave{'login'};
 
2422
                                        if ($withpurge) { %_login_p=(); %_login_h=(); %_login_k=(); %_login_l=(); }
 
2423
                                }
 
2424
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2425
                                next;
 
2426
                        }
 
2427
                        # BEGIN_DOMAIN
 
2428
                        if ($field[0] eq 'BEGIN_DOMAIN')   {
 
2429
                                if ($Debug) { debug(" Begin of DOMAIN section"); }
 
2430
                                $field[0]='';
 
2431
                                my $count=0;my $countloaded=0;
 
2432
                                do {
 
2433
                                        if ($field[0]) {
 
2434
                                                $count++;
 
2435
                                                if ($SectionsToLoad{'domain'}) {
 
2436
                                                        $countloaded++;
 
2437
                                                        if ($field[1]) { $_domener_p{$field[0]}+=$field[1]; }
 
2438
                                                        if ($field[2]) { $_domener_h{$field[0]}+=$field[2]; }
 
2439
                                                        if ($field[3]) { $_domener_k{$field[0]}+=$field[3]; }
 
2440
                                                }
 
2441
                                        }
 
2442
                                        $_=<HISTORY>;
 
2443
                                        chomp $_; s/\r//;
 
2444
                                        @field=split(/\s+/,$_); $countlines++;
 
2445
                                }
 
2446
                                until ($field[0] eq 'END_DOMAIN' || ! $_);
 
2447
                                if ($field[0] ne 'END_DOMAIN') { error("History file \"$filetoread\" is corrupted (End of section DOMAIN not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2448
                                if ($Debug) { debug(" End of DOMAIN section ($count entries, $countloaded loaded)"); }
 
2449
                                delete $SectionsToLoad{'domain'};
 
2450
                                if ($SectionsToSave{'domain'}) {
 
2451
                                        Save_History('domain',$year,$month); delete $SectionsToSave{'domain'};
 
2452
                                        if ($withpurge) { %_domener_p=(); %_domener_h=(); %_domener_k=(); }
 
2453
                                }
 
2454
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2455
                                next;
 
2456
                        }
 
2457
                        # BEGIN_SESSION
 
2458
                        if ($field[0] eq 'BEGIN_SESSION')   {
 
2459
                                if ($Debug) { debug(" Begin of SESSION section"); }
 
2460
                                $field[0]='';
 
2461
                                my $count=0;my $countloaded=0;
 
2462
                                do {
 
2463
                                        if ($field[0]) {
 
2464
                                                $count++;
 
2465
                                                if ($SectionsToLoad{'session'}) {
 
2466
                                                        $countloaded++;
 
2467
                                                        if ($field[1]) { $_session{$field[0]}+=$field[1]; }
 
2468
                                                }
 
2469
                                        }
 
2470
                                        $_=<HISTORY>;
 
2471
                                        chomp $_; s/\r//;
 
2472
                                        @field=split(/\s+/,$_); $countlines++;
 
2473
                                }
 
2474
                                until ($field[0] eq 'END_SESSION' || ! $_);
 
2475
                                if ($field[0] ne 'END_SESSION') { error("History file \"$filetoread\" is corrupted (End of section SESSION not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2476
                                if ($Debug) { debug(" End of SESSION section ($count entries, $countloaded loaded)"); }
 
2477
                                delete $SectionsToLoad{'session'};
 
2478
                                # WE DO NOT SAVE SECTION NOW BECAUSE VALUES CAN BE CHANGED AFTER READING VISITOR
 
2479
                                #if ($SectionsToSave{'session'}) {
 
2480
                                #       Save_History('session',$year,$month); delete $SectionsToSave{'session'}; }
 
2481
                                #       if ($withpurge) { %_session=(); }
 
2482
                                #}
 
2483
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2484
                                next;
 
2485
                        }
 
2486
                        # BEGIN_OS
 
2487
                        if ($field[0] eq 'BEGIN_OS')   {
 
2488
                                if ($Debug) { debug(" Begin of OS section"); }
 
2489
                                $field[0]='';
 
2490
                                my $count=0;my $countloaded=0;
 
2491
                                do {
 
2492
                                        if ($field[0]) {
 
2493
                                                $count++;
 
2494
                                                if ($SectionsToLoad{'os'}) {
 
2495
                                                        $countloaded++;
 
2496
                                                        if ($field[1]) { $_os_h{$field[0]}+=$field[1]; }
 
2497
                                                }
 
2498
                                        }
 
2499
                                        $_=<HISTORY>;
 
2500
                                        chomp $_; s/\r//;
 
2501
                                        @field=split(/\s+/,$_); $countlines++;
 
2502
                                }
 
2503
                                until ($field[0] eq 'END_OS' || ! $_);
 
2504
                                if ($field[0] ne 'END_OS') { error("History file \"$filetoread\" is corrupted (End of section OS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2505
                                if ($Debug) { debug(" End of OS section ($count entries, $countloaded loaded)"); }
 
2506
                                delete $SectionsToLoad{'os'};
 
2507
                                if ($SectionsToSave{'os'}) {
 
2508
                                        Save_History('os',$year,$month); delete $SectionsToSave{'os'};
 
2509
                                        if ($withpurge) { %_os_h=(); }
 
2510
                                }
 
2511
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2512
                                next;
 
2513
                        }
 
2514
                        # BEGIN_BROWSER
 
2515
                        if ($field[0] eq 'BEGIN_BROWSER')   {
 
2516
                                if ($Debug) { debug(" Begin of BROWSER section"); }
 
2517
                                $field[0]='';
 
2518
                                my $count=0;my $countloaded=0;
 
2519
                                do {
 
2520
                                        if ($field[0]) {
 
2521
                                                $count++;
 
2522
                                                if ($SectionsToLoad{'browser'}) {
 
2523
                                                        $countloaded++;
 
2524
                                                        if ($field[1]) { $_browser_h{$field[0]}+=$field[1]; }
 
2525
                                                }
 
2526
                                        }
 
2527
                                        $_=<HISTORY>;
 
2528
                                        chomp $_; s/\r//;
 
2529
                                        @field=split(/\s+/,$_); $countlines++;
 
2530
                                }
 
2531
                                until ($field[0] eq 'END_BROWSER' || ! $_);
 
2532
                                if ($field[0] ne 'END_BROWSER') { error("History file \"$filetoread\" is corrupted (End of section BROWSER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2533
                                if ($Debug) { debug(" End of BROWSER section ($count entries, $countloaded loaded)"); }
 
2534
                                delete $SectionsToLoad{'browser'};
 
2535
                                if ($SectionsToSave{'browser'}) {
 
2536
                                        Save_History('browser',$year,$month); delete $SectionsToSave{'browser'};
 
2537
                                        if ($withpurge) { %_browser_h=(); }
 
2538
                                }
 
2539
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2540
                                next;
 
2541
                        }
 
2542
                        # BEGIN_UNKNOWNREFERER
 
2543
                        if ($field[0] eq 'BEGIN_UNKNOWNREFERER')   {
 
2544
                                if ($Debug) { debug(" Begin of UNKNOWNREFERER section"); }
 
2545
                                $field[0]='';
 
2546
                                my $count=0;my $countloaded=0;
 
2547
                                do {
 
2548
                                        if ($field[0]) {
 
2549
                                                $count++;
 
2550
                                                if ($SectionsToLoad{'unknownreferer'}) {
 
2551
                                                        $countloaded++;
 
2552
                                                        if (! $_unknownreferer_l{$field[0]}) { $_unknownreferer_l{$field[0]}=int($field[1]); }
 
2553
                                                }
 
2554
                                        }
 
2555
                                        $_=<HISTORY>;
 
2556
                                        chomp $_; s/\r//;
 
2557
                                        @field=split(/\s+/,$_); $countlines++;
 
2558
                                }
 
2559
                                until ($field[0] eq 'END_UNKNOWNREFERER' || ! $_);
 
2560
                                if ($field[0] ne 'END_UNKNOWNREFERER') { error("History file \"$filetoread\" is corrupted (End of section UNKNOWNREFERER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2561
                                if ($Debug) { debug(" End of UNKNOWNREFERER section ($count entries, $countloaded loaded)"); }
 
2562
                                delete $SectionsToLoad{'unknownreferer'};
 
2563
                                if ($SectionsToSave{'unknownreferer'}) {
 
2564
                                        Save_History('unknownreferer',$year,$month); delete $SectionsToSave{'unknownreferer'};
 
2565
                                        if ($withpurge) { %_unknownreferer_l=(); }
 
2566
                                }
 
2567
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2568
                                next;
 
2569
                        }
 
2570
                        # BEGIN_UNKNOWNREFERERBROWSER
 
2571
                        if ($field[0] eq 'BEGIN_UNKNOWNREFERERBROWSER')   {
 
2572
                                if ($Debug) { debug(" Begin of UNKNOWNREFERERBROWSER section"); }
 
2573
                                $field[0]='';
 
2574
                                my $count=0;my $countloaded=0;
 
2575
                                do {
 
2576
                                        if ($field[0]) {
 
2577
                                                $count++;
 
2578
                                                if ($SectionsToLoad{'unknownrefererbrowser'}) {
 
2579
                                                        $countloaded++;
 
2580
                                                        if (! $_unknownrefererbrowser_l{$field[0]}) { $_unknownrefererbrowser_l{$field[0]}=int($field[1]); }
 
2581
                                                }
 
2582
                                        }
 
2583
                                        $_=<HISTORY>;
 
2584
                                        chomp $_; s/\r//;
 
2585
                                        @field=split(/\s+/,$_); $countlines++;
 
2586
                                }
 
2587
                                until ($field[0] eq 'END_UNKNOWNREFERERBROWSER' || ! $_);
 
2588
                                if ($field[0] ne 'END_UNKNOWNREFERERBROWSER') { error("History file \"$filetoread\" is corrupted (End of section UNKNOWNREFERERBROWSER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2589
                                if ($Debug) { debug(" End of UNKNOWNREFERERBROWSER section ($count entries, $countloaded loaded)"); }
 
2590
                                delete $SectionsToLoad{'unknownrefererbrowser'};
 
2591
                                if ($SectionsToSave{'unknownrefererbrowser'}) {
 
2592
                                        Save_History('unknownrefererbrowser',$year,$month); delete $SectionsToSave{'unknownrefererbrowser'};
 
2593
                                        if ($withpurge) { %_unknownrefererbrowser_l=(); }
 
2594
                                }
 
2595
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2596
                                next;
 
2597
                        }
 
2598
                        # BEGIN_SCREENSIZE
 
2599
                        if ($field[0] eq 'BEGIN_SCREENSIZE')   {
 
2600
                                if ($Debug) { debug(" Begin of SCREENSIZE section"); }
 
2601
                                $field[0]='';
 
2602
                                my $count=0;my $countloaded=0;
 
2603
                                do {
 
2604
                                        if ($field[0]) {
 
2605
                                                $count++;
 
2606
                                                if ($SectionsToLoad{'screensize'}) {
 
2607
                                                        $countloaded++;
 
2608
                                                        if ($field[1]) { $_screensize_h{$field[0]}+=$field[1]; }
 
2609
                                                }
 
2610
                                        }
 
2611
                                        $_=<HISTORY>;
 
2612
                                        chomp $_; s/\r//;
 
2613
                                        @field=split(/\s+/,$_); $countlines++;
 
2614
                                }
 
2615
                                until ($field[0] eq 'END_SCREENSIZE' || ! $_);
 
2616
                                if ($field[0] ne 'END_SCREENSIZE') { error("History file \"$filetoread\" is corrupted (End of section SCREENSIZE not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2617
                                if ($Debug) { debug(" End of SCREENSIZE section ($count entries, $countloaded loaded)"); }
 
2618
                                delete $SectionsToLoad{'screensize'};
 
2619
                                if ($SectionsToSave{'screensize'}) {
 
2620
                                        Save_History('screensize',$year,$month); delete $SectionsToSave{'screensize'};
 
2621
                                        if ($withpurge) { %_screensize_h=(); }
 
2622
                                }
 
2623
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2624
                                next;
 
2625
                        }
 
2626
                        # BEGIN_ROBOT
 
2627
                        if ($field[0] eq 'BEGIN_ROBOT')   {
 
2628
                                if ($Debug) { debug(" Begin of ROBOT section"); }
 
2629
                                $field[0]='';
 
2630
                                my $count=0;my $countloaded=0;
 
2631
                                do {
 
2632
                                        if ($field[0]) {
 
2633
                                                $count++;
 
2634
                                                if ($SectionsToLoad{'robot'}) {
 
2635
                                                        $countloaded++;
 
2636
                                                        if ($field[1]) { $_robot_h{$field[0]}+=$field[1]; }
 
2637
                                                        if ($versionnum < 5000 || ! $field[3]) {                # For backward compatibility
 
2638
                                                                if (! $_robot_l{$field[0]}) { $_robot_l{$field[0]}=int($field[2]); }
 
2639
                                                        }
 
2640
                                                        else {
 
2641
                                                                $_robot_k{$field[0]}+=$field[2];
 
2642
                                                                if (! $_robot_l{$field[0]}) { $_robot_l{$field[0]}=int($field[3]); }
 
2643
                                                        }
 
2644
                                                        if ($field[4]) { $_robot_r{$field[0]}+=$field[4]; }
 
2645
                                                }
 
2646
                                        }
 
2647
                                        $_=<HISTORY>;
 
2648
                                        chomp $_; s/\r//;
 
2649
                                        @field=split(/\s+/,$_); $countlines++;
 
2650
                                }
 
2651
                                until ($field[0] eq 'END_ROBOT' || ! $_);
 
2652
                                if ($field[0] ne 'END_ROBOT') { error("History file \"$filetoread\" is corrupted (End of section ROBOT not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2653
                                if ($Debug) { debug(" End of ROBOT section ($count entries, $countloaded loaded)"); }
 
2654
                                delete $SectionsToLoad{'robot'};
 
2655
                                if ($SectionsToSave{'robot'}) {
 
2656
                                        Save_History('robot',$year,$month); delete $SectionsToSave{'robot'};
 
2657
                                        if ($withpurge) { %_robot_h=(); %_robot_k=(); %_robot_l=(); %_robot_r=(); }
 
2658
                                }
 
2659
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2660
                                next;
 
2661
                        }
 
2662
                        # BEGIN_WORMS
 
2663
                        if ($field[0] eq 'BEGIN_WORMS')   {
 
2664
                                if ($Debug) { debug(" Begin of WORMS section"); }
 
2665
                                $field[0]='';
 
2666
                                my $count=0;my $countloaded=0;
 
2667
                                do {
 
2668
                                        if ($field[0]) {
 
2669
                                                $count++;
 
2670
                                                if ($SectionsToLoad{'worms'}) {
 
2671
                                                        $countloaded++;
 
2672
                                                        if ($field[1]) { $_worm_h{$field[0]}+=$field[1]; }
 
2673
                                                        $_worm_k{$field[0]}+=$field[2];
 
2674
                                                        if (! $_worm_l{$field[0]}) { $_worm_l{$field[0]}=int($field[3]); }
 
2675
                                                }
 
2676
                                        }
 
2677
                                        $_=<HISTORY>;
 
2678
                                        chomp $_; s/\r//;
 
2679
                                        @field=split(/\s+/,$_); $countlines++;
 
2680
                                }
 
2681
                                until ($field[0] eq 'END_WORMS' || ! $_);
 
2682
                                if ($field[0] ne 'END_WORMS') { error("History file \"$filetoread\" is corrupted (End of section WORMS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2683
                                if ($Debug) { debug(" End of WORMS section ($count entries, $countloaded loaded)"); }
 
2684
                                delete $SectionsToLoad{'worms'};
 
2685
                                if ($SectionsToSave{'worms'}) {
 
2686
                                        Save_History('worms',$year,$month); delete $SectionsToSave{'worms'};
 
2687
                                        if ($withpurge) { %_worm_h=(); %_worm_k=(); %_worm_l=(); }
 
2688
                                }
 
2689
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2690
                                next;
 
2691
                        }
 
2692
                        # BEGIN_EMAILS
 
2693
                        if ($field[0] eq 'BEGIN_EMAILSENDER')   {
 
2694
                                if ($Debug) { debug(" Begin of EMAILSENDER section"); }
 
2695
                                $field[0]='';
 
2696
                                my $count=0;my $countloaded=0;
 
2697
                                do {
 
2698
                                        if ($field[0]) {
 
2699
                                                $count++;
 
2700
                                                if ($SectionsToLoad{'emailsender'}) {
 
2701
                                                        $countloaded++;
 
2702
                                                        if ($field[1]) { $_emails_h{$field[0]}+=$field[1]; }
 
2703
                                                        if ($field[2]) { $_emails_k{$field[0]}+=$field[2]; }
 
2704
                                                        if (! $_emails_l{$field[0]}) { $_emails_l{$field[0]}=int($field[3]); }
 
2705
                                                }
 
2706
                                        }
 
2707
                                        $_=<HISTORY>;
 
2708
                                        chomp $_; s/\r//;
 
2709
                                        @field=split(/\s+/,$_); $countlines++;
 
2710
                                }
 
2711
                                until ($field[0] eq 'END_EMAILSENDER' || ! $_);
 
2712
                                if ($field[0] ne 'END_EMAILSENDER') { error("History file \"$filetoread\" is corrupted (End of section EMAILSENDER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2713
                                if ($Debug) { debug(" End of EMAILSENDER section ($count entries, $countloaded loaded)"); }
 
2714
                                delete $SectionsToLoad{'emailsender'};
 
2715
                                if ($SectionsToSave{'emailsender'}) {
 
2716
                                        Save_History('emailsender',$year,$month); delete $SectionsToSave{'emailsender'};
 
2717
                                        if ($withpurge) { %_emails_h=(); %_emails_k=(); %_emails_l=(); }
 
2718
                                }
 
2719
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2720
                                next;
 
2721
                        }
 
2722
                        # BEGIN_EMAILR
 
2723
                        if ($field[0] eq 'BEGIN_EMAILRECEIVER')   {
 
2724
                                if ($Debug) { debug(" Begin of EMAILRECEIVER section"); }
 
2725
                                $field[0]='';
 
2726
                                my $count=0;my $countloaded=0;
 
2727
                                do {
 
2728
                                        if ($field[0]) {
 
2729
                                                $count++;
 
2730
                                                if ($SectionsToLoad{'emailreceiver'}) {
 
2731
                                                        $countloaded++;
 
2732
                                                        if ($field[1]) { $_emailr_h{$field[0]}+=$field[1]; }
 
2733
                                                        if ($field[2]) { $_emailr_k{$field[0]}+=$field[2]; }
 
2734
                                                        if (! $_emailr_l{$field[0]}) { $_emailr_l{$field[0]}=int($field[3]); }
 
2735
                                                }
 
2736
                                        }
 
2737
                                        $_=<HISTORY>;
 
2738
                                        chomp $_; s/\r//;
 
2739
                                        @field=split(/\s+/,$_); $countlines++;
 
2740
                                }
 
2741
                                until ($field[0] eq 'END_EMAILRECEIVER' || ! $_);
 
2742
                                if ($field[0] ne 'END_EMAILRECEIVER') { error("History file \"$filetoread\" is corrupted (End of section EMAILRECEIVER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2743
                                if ($Debug) { debug(" End of EMAILRECEIVER section ($count entries, $countloaded loaded)"); }
 
2744
                                delete $SectionsToLoad{'emailreceiver'};
 
2745
                                if ($SectionsToSave{'emailreceiver'}) {
 
2746
                                        Save_History('emailreceiver',$year,$month); delete $SectionsToSave{'emailreceiver'};
 
2747
                                        if ($withpurge) { %_emailr_h=(); %_emailr_k=(); %_emailr_l=(); }
 
2748
                                }
 
2749
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2750
                                next;
 
2751
                        }
 
2752
                        # BEGIN_SIDER
 
2753
                        if ($field[0] eq 'BEGIN_SIDER')  {
 
2754
                                if ($Debug) { debug(" Begin of SIDER section"); }
 
2755
                                $field[0]='';
 
2756
                                my $count=0;my $countloaded=0;
 
2757
                                do {
 
2758
                                        if ($field[0]) {
 
2759
                                                $count++;
 
2760
                                                if ($SectionsToLoad{'sider'}) {
 
2761
                                                        my $loadrecord=0;
 
2762
                                                        if ($withupdate) {
 
2763
                                                                $loadrecord=1;
 
2764
                                                        }
 
2765
                                                        else {
 
2766
                                                                if ($HTMLOutput{'main'}) {
 
2767
                                                                        if ($MonthRequired eq 'all') { $loadrecord=1; }
 
2768
                                                                        else {
 
2769
                                                                                if ($countloaded < $MaxNbOf{'PageShown'} && $field[1] >= $MinHit{'File'}) { $loadrecord=1; }
 
2770
                                                                                $TotalDifferentPages++;
 
2771
                                                                        }
 
2772
                                                                }
 
2773
                                                                else {  # This is for $HTMLOutput = urldetail, urlentry or urlexit
 
2774
                                                                        if ($MonthRequired eq 'all' ) {
 
2775
                                                                                if ((!$FilterIn{'url'} || $field[0] =~ /$FilterIn{'url'}/)
 
2776
                                                                                 && (!$FilterEx{'url'} || $field[0] !~ /$FilterEx{'url'}/)) { $loadrecord=1; }
 
2777
                                                                        }
 
2778
                                                                        else {
 
2779
                                                                                if ((!$FilterIn{'url'} || $field[0] =~ /$FilterIn{'url'}/)
 
2780
                                                                                 && (!$FilterEx{'url'} || $field[0] !~ /$FilterEx{'url'}/)
 
2781
                                                                                 && $field[1] >= $MinHit{'File'}) { $loadrecord=1; }
 
2782
                                                                                $TotalDifferentPages++;
 
2783
                                                                        }
 
2784
                                                                }
 
2785
                                                                # Posssibilite de mettre if ($FilterIn{'url'} && $field[0] =~ /$FilterIn{'url'}/) mais il faut gerer TotalPages de la meme maniere
 
2786
                                                                if ($versionnum < 4000) {       # For history files < 4.0
 
2787
                                                                        $TotalEntries+=($field[2]||0);
 
2788
                                                                }
 
2789
                                                                else {
 
2790
                                                                        $TotalBytesPages+=($field[2]||0);
 
2791
                                                                        $TotalEntries+=($field[3]||0);
 
2792
                                                                        $TotalExits+=($field[4]||0);
 
2793
                                                                }
 
2794
                                                        }
 
2795
                                                        if ($loadrecord) {
 
2796
                                                                if ($field[1]) { $_url_p{$field[0]}+=$field[1]; }
 
2797
                                                                if ($versionnum < 4000) {       # For history files < 4.0
 
2798
                                                                        if ($field[2]) { $_url_e{$field[0]}+=$field[2]; }
 
2799
                                                                        $_url_k{$field[0]}=0;
 
2800
                                                                }
 
2801
                                                                else {
 
2802
                                                                        if ($field[2]) { $_url_k{$field[0]}+=$field[2]; }
 
2803
                                                                        if ($field[3]) { $_url_e{$field[0]}+=$field[3]; }
 
2804
                                                                        if ($field[4]) { $_url_x{$field[0]}+=$field[4]; }
 
2805
                                                                }
 
2806
                                                                $countloaded++;
 
2807
                                                        }
 
2808
                                                }
 
2809
                                        }
 
2810
                                        $_=<HISTORY>;
 
2811
                                        chomp $_; s/\r//;
 
2812
                                        @field=split(/\s+/,$_); $countlines++;
 
2813
                                }
 
2814
                                until ($field[0] eq 'END_SIDER' || ! $_);
 
2815
                                if ($field[0] ne 'END_SIDER') { error("History file \"$filetoread\" is corrupted (End of section SIDER not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2816
                                if ($Debug) { debug(" End of SIDER section ($count entries, $countloaded loaded)"); }
 
2817
                                delete $SectionsToLoad{'sider'};
 
2818
                                # WE DO NOT SAVE SECTION NOW BECAUSE VALUES CAN BE CHANGED AFTER READING VISITOR
 
2819
                                #if ($SectionsToSave{'sider'}) {
 
2820
                                #       Save_History('sider',$year,$month); delete $SectionsToSave{'sider'};
 
2821
                                #       if ($withpurge) { %_url_p=(); %_url_k=(); %_url_e=(); %_url_x=(); }
 
2822
                                #}
 
2823
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2824
                                next;
 
2825
                        }
 
2826
                        # BEGIN_FILETYPES
 
2827
                        if ($field[0] eq 'BEGIN_FILETYPES')   {
 
2828
                                if ($Debug) { debug(" Begin of FILETYPES section"); }
 
2829
                                $field[0]='';
 
2830
                                my $count=0;my $countloaded=0;
 
2831
                                do {
 
2832
                                        if ($field[0]) {
 
2833
                                                $count++;
 
2834
                                                if ($SectionsToLoad{'filetypes'}) {
 
2835
                                                        $countloaded++;
 
2836
                                                        if ($field[1]) { $_filetypes_h{$field[0]}+=$field[1]; }
 
2837
                                                        if ($field[2]) { $_filetypes_k{$field[0]}+=$field[2]; }
 
2838
                                                        if ($field[3]) { $_filetypes_gz_in{$field[0]}+=$field[3]; }
 
2839
                                                        if ($field[4]) { $_filetypes_gz_out{$field[0]}+=$field[4]; }
 
2840
                                                }
 
2841
                                        }
 
2842
                                        $_=<HISTORY>;
 
2843
                                        chomp $_; s/\r//;
 
2844
                                        @field=split(/\s+/,$_); $countlines++;
 
2845
                                }
 
2846
                                until ($field[0] eq 'END_FILETYPES' || ! $_);
 
2847
                                if ($field[0] ne 'END_FILETYPES') { error("History file \"$filetoread\" is corrupted (End of section FILETYPES not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2848
                                if ($Debug) { debug(" End of FILETYPES section ($count entries, $countloaded loaded)"); }
 
2849
                                delete $SectionsToLoad{'filetypes'};
 
2850
                                if ($SectionsToSave{'filetypes'}) {
 
2851
                                        Save_History('filetypes',$year,$month); delete $SectionsToSave{'filetypes'};
 
2852
                                        if ($withpurge) { %_filetypes_h=(); %_filetypes_k=(); %_filetypes_gz_in=(); %_filetypes_gz_out=(); }
 
2853
                                }
 
2854
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2855
                                next;
 
2856
                        }
 
2857
                        # BEGIN_SEREFERRALS
 
2858
                        if ($field[0] eq 'BEGIN_SEREFERRALS')   {
 
2859
                                if ($Debug) { debug(" Begin of SEREFERRALS section"); }
 
2860
                                $field[0]='';
 
2861
                                my $count=0;my $countloaded=0;
 
2862
                                do {
 
2863
                                        if ($field[0]) {
 
2864
                                                $count++;
 
2865
                                                if ($SectionsToLoad{'sereferrals'}) {
 
2866
                                                        $countloaded++;
 
2867
                                                        if ($versionnum < 5004) {               # For history files < 5.4
 
2868
                                                                my $se=$field[0]; $se=~s/\./\\./g;
 
2869
                                                                if ($SearchEnginesHashID{$se}) {
 
2870
                                                                        $_se_referrals_h{$SearchEnginesHashID{$se}}+=$field[1]||0;
 
2871
                                                                }
 
2872
                                                                else {
 
2873
                                                                        $_se_referrals_h{$field[0]}+=$field[1]||0;
 
2874
                                                                }
 
2875
                                                        }
 
2876
                                                        elsif ($versionnum < 5091) {    # For history files < 5.91
 
2877
                                                                my $se=$field[0]; $se=~s/\./\\./g;
 
2878
                                                                if ($SearchEnginesHashID{$se}) {
 
2879
                                                                        $_se_referrals_p{$SearchEnginesHashID{$se}}+=$field[1]||0;
 
2880
                                                                        $_se_referrals_h{$SearchEnginesHashID{$se}}+=$field[2]||0;
 
2881
                                                                }
 
2882
                                                                else {
 
2883
                                                                        $_se_referrals_p{$field[0]}+=$field[1]||0;
 
2884
                                                                        $_se_referrals_h{$field[0]}+=$field[2]||0;
 
2885
                                                                }
 
2886
                                                        } else {
 
2887
                                                                if ($field[1]) { $_se_referrals_p{$field[0]}+=$field[1]; }
 
2888
                                                                if ($field[2]) { $_se_referrals_h{$field[0]}+=$field[2]; }
 
2889
                                                        }
 
2890
                                                }
 
2891
                                        }
 
2892
                                        $_=<HISTORY>;
 
2893
                                        chomp $_; s/\r//;
 
2894
                                        @field=split(/\s+/,$_); $countlines++;
 
2895
                                }
 
2896
                                until ($field[0] eq 'END_SEREFERRALS' || ! $_);
 
2897
                                if ($field[0] ne 'END_SEREFERRALS') { error("History file \"$filetoread\" is corrupted (End of section SEREFERRALS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2898
                                if ($Debug) { debug(" End of SEREFERRALS section ($count entries, $countloaded loaded)"); }
 
2899
                                delete $SectionsToLoad{'sereferrals'};
 
2900
                                if ($SectionsToSave{'sereferrals'}) {
 
2901
                                        Save_History('sereferrals',$year,$month); delete $SectionsToSave{'sereferrals'};
 
2902
                                        if ($withpurge) { %_se_referrals_p=(); %_se_referrals_h=(); }
 
2903
                                }
 
2904
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2905
                                next;
 
2906
                        }
 
2907
                        # BEGIN_PAGEREFS
 
2908
                        if ($field[0] eq 'BEGIN_PAGEREFS')   {
 
2909
                                if ($Debug) { debug(" Begin of PAGEREFS section"); }
 
2910
                                $field[0]='';
 
2911
                                my $count=0;my $countloaded=0;
 
2912
                                do {
 
2913
                                        if ($field[0]) {
 
2914
                                                $count++;
 
2915
                                                if ($SectionsToLoad{'pagerefs'}) {
 
2916
                                                        my $loadrecord=0;
 
2917
                                                        if ($withupdate) {
 
2918
                                                                $loadrecord=1;
 
2919
                                                        }
 
2920
                                                        else {
 
2921
                                                                if ((!$FilterIn{'refererpages'} || $field[0] =~ /$FilterIn{'refererpages'}/)
 
2922
                                                                 && (!$FilterEx{'refererpages'} || $field[0] !~ /$FilterEx{'refererpages'}/)) { $loadrecord=1; }
 
2923
                                                        }
 
2924
                                                        if ($loadrecord) {
 
2925
                                                                if ($versionnum < 5004) {       # For history files < 5.4
 
2926
                                                                        if ($field[1]) { $_pagesrefs_h{$field[0]}+=int($field[1]); }
 
2927
                                                                } else {
 
2928
                                                                        if ($field[1]) { $_pagesrefs_p{$field[0]}+=int($field[1]); }
 
2929
                                                                        if ($field[2]) { $_pagesrefs_h{$field[0]}+=int($field[2]); }
 
2930
                                                                }
 
2931
                                                                $countloaded++;
 
2932
                                                        }
 
2933
                                                }
 
2934
                                        }
 
2935
                                        $_=<HISTORY>;
 
2936
                                        chomp $_; s/\r//;
 
2937
                                        @field=split(/\s+/,$_); $countlines++;
 
2938
                                }
 
2939
                                until ($field[0] eq 'END_PAGEREFS' || ! $_);
 
2940
                                if ($field[0] ne 'END_PAGEREFS') { error("History file \"$filetoread\" is corrupted (End of section PAGEREFS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
2941
                                if ($Debug) { debug(" End of PAGEREFS section ($count entries, $countloaded loaded)"); }
 
2942
                                delete $SectionsToLoad{'pagerefs'};
 
2943
                                if ($SectionsToSave{'pagerefs'}) {
 
2944
                                        Save_History('pagerefs',$year,$month); delete $SectionsToSave{'pagerefs'};
 
2945
                                        if ($withpurge) { %_pagesrefs_p=(); %_pagesrefs_h=(); }
 
2946
                                }
 
2947
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
2948
                                next;
 
2949
                        }
 
2950
                        # BEGIN_SEARCHWORDS
 
2951
                        if ($field[0] eq 'BEGIN_SEARCHWORDS')   {
 
2952
                                if ($Debug) { debug(" Begin of SEARCHWORDS section ($MaxNbOf{'KeyphrasesShown'},$MinHit{'Keyphrase'})"); }
 
2953
                                $field[0]='';
 
2954
                                my $count=0;my $countloaded=0;
 
2955
                                do {
 
2956
                                        if ($field[0]) {
 
2957
                                                $count++;
 
2958
                                                if ($SectionsToLoad{'searchwords'}) {
 
2959
                                                        my $loadrecord=0;
 
2960
                                                        if ($withupdate) {
 
2961
                                                                $loadrecord=1;
 
2962
                                                        }
 
2963
                                                        else {
 
2964
                                                                if ($HTMLOutput{'main'}) {
 
2965
                                                                        if ($MonthRequired eq 'all') { $loadrecord=1; }
 
2966
                                                                        else {
 
2967
                                                                                if ($countloaded < $MaxNbOf{'KeyphrasesShown'} && $field[1] >= $MinHit{'Keyphrase'}) { $loadrecord=1; }
 
2968
                                                                                $TotalDifferentKeyphrases++;
 
2969
                                                                                $TotalKeyphrases+=($field[1]||0);
 
2970
                                                                        }
 
2971
                                                                }
 
2972
                                                                elsif ($HTMLOutput{'keyphrases'}) {     # Load keyphrases for keyphrases chart
 
2973
                                                                        if ($MonthRequired eq 'all' ) { $loadrecord=1; }
 
2974
                                                                        else {
 
2975
                                                                                if ($field[1] >= $MinHit{'Keyphrase'}) { $loadrecord=1; }
 
2976
                                                                                $TotalDifferentKeyphrases++;
 
2977
                                                                                $TotalKeyphrases+=($field[1]||0);
 
2978
                                                                        }
 
2979
                                                                }
 
2980
                                                                if ($HTMLOutput{'keywords'}) {  # Load keyphrases for keywords chart
 
2981
                                                                        $loadrecord=2;
 
2982
                                                                }
 
2983
                                                        }
 
2984
                                                        if ($loadrecord) {
 
2985
                                                                if ($field[1]) {
 
2986
                                                                        if ($loadrecord==2) {
 
2987
                                                                                foreach (split(/\+/,$field[0])) {       # field[0] is "val1+val2+..."
 
2988
                                                                                        $_keywords{$_}+=$field[1];
 
2989
                                                                                }
 
2990
                                                                        }
 
2991
                                                                        else {
 
2992
                                                                                $_keyphrases{$field[0]}+=$field[1];
 
2993
                                                                        }
 
2994
                                                                }
 
2995
                                                                $countloaded++;
 
2996
                                                        }
 
2997
                                                }
 
2998
                                        }
 
2999
                                        $_=<HISTORY>;
 
3000
                                        chomp $_; s/\r//;
 
3001
                                        @field=split(/\s+/,$_); $countlines++;
 
3002
                                }
 
3003
                                until ($field[0] eq 'END_SEARCHWORDS' || ! $_);
 
3004
                                if ($field[0] ne 'END_SEARCHWORDS') { error("History file \"$filetoread\" is corrupted (End of section SEARCHWORDS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
3005
                                if ($Debug) { debug(" End of SEARCHWORDS section ($count entries, $countloaded loaded)"); }
 
3006
                                delete $SectionsToLoad{'searchwords'};
 
3007
                                if ($SectionsToSave{'searchwords'}) {
 
3008
                                        Save_History('searchwords',$year,$month); delete $SectionsToSave{'searchwords'};        # This save searwords and keywords sections
 
3009
                                        if ($withpurge) { %_keyphrases=(); }
 
3010
                                }
 
3011
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
3012
                                next;
 
3013
                        }
 
3014
                        # BEGIN_KEYWORDS
 
3015
                        if ($field[0] eq 'BEGIN_KEYWORDS')   {
 
3016
                                if ($Debug) { debug(" Begin of KEYWORDS section ($MaxNbOf{'KeywordsShown'},$MinHit{'Keyword'})"); }
 
3017
                                $field[0]='';
 
3018
                                my $count=0;my $countloaded=0;
 
3019
                                do {
 
3020
                                        if ($field[0]) {
 
3021
                                                $count++;
 
3022
                                                if ($SectionsToLoad{'keywords'}) {
 
3023
                                                        my $loadrecord=0;
 
3024
                                                        if ($MonthRequired eq 'all') { $loadrecord=1; }
 
3025
                                                        else {
 
3026
                                                                if ($countloaded < $MaxNbOf{'KeywordsShown'} && $field[1] >= $MinHit{'Keyword'}) { $loadrecord=1; }
 
3027
                                                                $TotalDifferentKeywords++;
 
3028
                                                                $TotalKeywords+=($field[1]||0);
 
3029
                                                        }
 
3030
                                                        if ($loadrecord) {
 
3031
                                                                if ($field[1]) { $_keywords{$field[0]}+=$field[1]; }
 
3032
                                                                $countloaded++;
 
3033
                                                        }
 
3034
                                                }
 
3035
                                        }
 
3036
                                        $_=<HISTORY>;
 
3037
                                        chomp $_; s/\r//;
 
3038
                                        @field=split(/\s+/,$_); $countlines++;
 
3039
                                }
 
3040
                                until ($field[0] eq 'END_KEYWORDS' || ! $_);
 
3041
                                if ($field[0] ne 'END_KEYWORDS') { error("History file \"$filetoread\" is corrupted (End of section KEYWORDS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
3042
                                if ($Debug) { debug(" End of KEYWORDS section ($count entries, $countloaded loaded)"); }
 
3043
                                delete $SectionsToLoad{'keywords'};
 
3044
                                if ($SectionsToSave{'keywords'}) {
 
3045
                                        Save_History('keywords',$year,$month); delete $SectionsToSave{'keywords'};
 
3046
                                        if ($withpurge) { %_keywords=(); }
 
3047
                                }
 
3048
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
3049
                                next;
 
3050
                        }
 
3051
                        # BEGIN_ERRORS
 
3052
                        if ($field[0] eq 'BEGIN_ERRORS')   {
 
3053
                                if ($Debug) { debug(" Begin of ERRORS section"); }
 
3054
                                $field[0]='';
 
3055
                                my $count=0;my $countloaded=0;
 
3056
                                do {
 
3057
                                        if ($field[0]) {
 
3058
                                                $count++;
 
3059
                                                if ($SectionsToLoad{'errors'}) {
 
3060
                                                        $countloaded++;
 
3061
                                                        if ($field[1]) { $_errors_h{$field[0]}+=$field[1]; }
 
3062
                                                        if ($field[2]) { $_errors_k{$field[0]}+=$field[2]; }
 
3063
                                                }
 
3064
                                        }
 
3065
                                        $_=<HISTORY>;
 
3066
                                        chomp $_; s/\r//;
 
3067
                                        @field=split(/\s+/,$_); $countlines++;
 
3068
                                }
 
3069
                                until ($field[0] eq 'END_ERRORS' || ! $_);
 
3070
                                if ($field[0] ne 'END_ERRORS') { error("History file \"$filetoread\" is corrupted (End of section ERRORS not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
3071
                                if ($Debug) { debug(" End of ERRORS section ($count entries, $countloaded loaded)"); }
 
3072
                                delete $SectionsToLoad{'errors'};
 
3073
                                if ($SectionsToSave{'errors'}) {
 
3074
                                        Save_History('errors',$year,$month); delete $SectionsToSave{'errors'};
 
3075
                                        if ($withpurge) { %_errors_h=(); %_errors_k=(); }
 
3076
                                }
 
3077
                                if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
3078
                                next;
 
3079
                        }
 
3080
                        # BEGIN_SIDER_xxx
 
3081
                        foreach my $code (keys %TrapInfosForHTTPErrorCodes) {
 
3082
                                if ($field[0] eq "BEGIN_SIDER_$code")   {
 
3083
                                        if ($Debug) { debug(" Begin of SIDER_$code section"); }
 
3084
                                        $field[0]='';
 
3085
                                        my $count=0;my $countloaded=0;
 
3086
                                        do {
 
3087
                                                if ($field[0]) {
 
3088
                                                        $count++;
 
3089
                                                        if ($SectionsToLoad{"sider_$code"}) {
 
3090
                                                                $countloaded++;
 
3091
                                                                if ($field[1]) { $_sider404_h{$field[0]}+=$field[1]; }
 
3092
                                                                if ($withupdate || $HTMLOutput{"errors$code"}) {
 
3093
                                                                        if ($field[2]) { $_referer404_h{$field[0]}=$field[2]; }
 
3094
                                                                }
 
3095
                                                        }
 
3096
                                                }
 
3097
                                                $_=<HISTORY>;
 
3098
                                                chomp $_; s/\r//;
 
3099
                                                @field=split(/\s+/,$_); $countlines++;
 
3100
                                        }
 
3101
                                        until ($field[0] eq "END_SIDER_$code" || ! $_);
 
3102
                                        if ($field[0] ne "END_SIDER_$code") { error("History file \"$filetoread\" is corrupted (End of section SIDER_$code not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
3103
                                        if ($Debug) { debug(" End of SIDER_$code section ($count entries, $countloaded loaded)"); }
 
3104
                                        delete $SectionsToLoad{"sider_$code"};
 
3105
                                        if ($SectionsToSave{"sider_$code"}) {
 
3106
                                                Save_History("sider_$code",$year,$month); delete $SectionsToSave{"sider_$code"};
 
3107
                                                if ($withpurge) { %_sider404_h=(); %_referer404_h=(); }
 
3108
                                        }
 
3109
                                        if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
3110
                                        next;
 
3111
                                }
 
3112
                        }
 
3113
                        # BEGIN_EXTRA_xxx
 
3114
                        foreach my $extranum (1..@ExtraName-1) {
 
3115
                                if ($field[0] eq "BEGIN_EXTRA_$extranum")   {
 
3116
                                        if ($Debug) { debug(" Begin of EXTRA_$extranum"); }
 
3117
                                        $field[0]='';
 
3118
                                        my $count=0;my $countloaded=0;
 
3119
                                        do {
 
3120
                                                if ($field[0] ne '') {
 
3121
                                                        $count++;
 
3122
                                                        if ($SectionsToLoad{"extra_$extranum"}) {
 
3123
                                                                if ($ExtraStatTypes[$extranum] =~ /P/i && $field[1]) { ${'_section_' . $extranum . '_p'}{$field[0]}+=$field[1]; }
 
3124
                                                                ${'_section_' . $extranum . '_h'}{$field[0]}+=$field[2];
 
3125
                                                                if ($ExtraStatTypes[$extranum] =~ /B/i && $field[3]) { ${'_section_' . $extranum . '_k'}{$field[0]}+=$field[3]; }
 
3126
                                                                if ($ExtraStatTypes[$extranum] =~ /L/i && ! ${'_section_' . $extranum . '_l'}{$field[0]} && $field[4]) { ${'_section_' . $extranum . '_l'}{$field[0]}=int($field[4]); }
 
3127
                                                                $countloaded++;
 
3128
                                                        }
 
3129
                                                }
 
3130
                                                $_=<HISTORY>;
 
3131
                                                chomp $_; s/\r//;
 
3132
                                                @field=split(/\s+/,$_); $countlines++;
 
3133
                                        }
 
3134
                                        until ($field[0] eq "END_EXTRA_$extranum" || ! $_);
 
3135
                                        if ($field[0] ne "END_EXTRA_$extranum") { error("History file \"$filetoread\" is corrupted (End of section EXTRA_$extranum not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
 
3136
                                        if ($Debug) { debug(" End of EXTRA_$extranum section ($count entries, $countloaded loaded)"); }
 
3137
                                        delete $SectionsToLoad{"extra_$extranum"};
 
3138
                                        if ($SectionsToSave{"extra_$extranum"}) {
 
3139
                                                Save_History("extra_$extranum",$year,$month); delete $SectionsToSave{"extra_$extranum"};
 
3140
                                                if ($withpurge) { %{'_section_' . $extranum . '_p'}=(); %{'_section_' . $extranum . '_h'}=(); %{'_section_' . $extranum . '_b'}=(); %{'_section_' . $extranum . '_l'}=(); }
 
3141
                                        }
 
3142
                                        if (! scalar %SectionsToLoad) { debug(" Stop reading history file. Got all we need."); last; }
 
3143
                                        next;
 
3144
                                }
 
3145
                        }
 
3146
 
 
3147
                        # For backward compatibility (ORIGIN section was "HitFromx" in old history files)
 
3148
                        if ($SectionsToLoad{'origin'}) {
 
3149
                                if ($field[0] eq 'HitFrom0') { $_from_p[0]+=0; $_from_h[0]+=$field[1]; next; }
 
3150
                                if ($field[0] eq 'HitFrom1') { $_from_p[1]+=0; $_from_h[1]+=$field[1]; next; }
 
3151
                                if ($field[0] eq 'HitFrom2') { $_from_p[2]+=0; $_from_h[2]+=$field[1]; next; }
 
3152
                                if ($field[0] eq 'HitFrom3') { $_from_p[3]+=0; $_from_h[3]+=$field[1]; next; }
 
3153
                                if ($field[0] eq 'HitFrom4') { $_from_p[4]+=0; $_from_h[4]+=$field[1]; next; }
 
3154
                                if ($field[0] eq 'HitFrom5') { $_from_p[5]+=0; $_from_h[5]+=$field[1]; next; }
 
3155
                        }
 
3156
                }
 
3157
        }
 
3158
 
 
3159
        if ($withupdate) {
 
3160
                # Process rest of data saved in 'wait' arrays (data for hosts that are not in history file or no history file found)
 
3161
                # This can change some values for day, sider and session sections
 
3162
                if ($Debug) { debug(" Processing data in 'wait' arrays",3); }
 
3163
                foreach (keys %_waithost_e) {
 
3164
                        if ($Debug) { debug("  Visit in 'wait' array for $_ is a new visit",4); }
 
3165
                        my $newtimehosts=($_waithost_s{$_}?$_waithost_s{$_}:$_host_s{$_});
 
3166
                        my $newtimehostl=($_waithost_l{$_}?$_waithost_l{$_}:$_host_l{$_});
 
3167
                        $_url_e{$_waithost_e{$_}}++;
 
3168
                        $newtimehosts =~ /^(\d\d\d\d\d\d\d\d)/; $DayVisits{$1}++;
 
3169
                        if ($_waithost_s{$_}) {
 
3170
                                # There was also a second session in processed log
 
3171
                                $_session{GetSessionRange($newtimehosts,$newtimehostl)}++;
 
3172
                        }
 
3173
                }
 
3174
        }
 
3175
 
 
3176
        # Write all unwrote sections in section order ('general','time', 'day','sider','session' and other...)
 
3177
        foreach my $key (sort { $SectionsToSave{$a} <=> $SectionsToSave{$b} } keys %SectionsToSave) {
 
3178
                Save_History("$key",$year,$month,$lastlinenumber,$lastlineoffset,$lastlinechecksum);
 
3179
        }
 
3180
        %SectionsToSave=();
 
3181
 
 
3182
        # Update offset in map section and last data in general section then close files
 
3183
        if ($withupdate) {
 
3184
                # Update offset of sections in the MAP section
 
3185
                foreach (sort { $PosInFile{$a} <=> $PosInFile{$b} } keys %ValueInFile) {
 
3186
                        if ($Debug) { debug(" Update offset of section $_=$ValueInFile{$_} in file at offset $PosInFile{$_}"); }
 
3187
                        if ($PosInFile{"$_"}) {
 
3188
                                seek(HISTORYTMP,$PosInFile{"$_"},0); print HISTORYTMP $ValueInFile{"$_"};
 
3189
                        }
 
3190
                }
 
3191
                # Save last data in general sections
 
3192
                if ($Debug) { debug(" Update MonthVisits=$MonthVisits{$year.$month} in file at offset $PosInFile{TotalVisits}"); }
 
3193
                seek(HISTORYTMP,$PosInFile{"TotalVisits"},0); print HISTORYTMP $MonthVisits{$year.$month};
 
3194
                if ($Debug) { debug(" Update MonthUnique=$MonthUnique{$year.$month} in file at offset $PosInFile{TotalUnique}"); }
 
3195
                seek(HISTORYTMP,$PosInFile{"TotalUnique"},0); print HISTORYTMP $MonthUnique{$year.$month};
 
3196
                if ($Debug) { debug(" Update MonthHostsKnown=$MonthHostsKnown{$year.$month} in file at offset $PosInFile{MonthHostsKnown}"); }
 
3197
                seek(HISTORYTMP,$PosInFile{"MonthHostsKnown"},0); print HISTORYTMP $MonthHostsKnown{$year.$month};
 
3198
                if ($Debug) { debug(" Update MonthHostsUnknown=$MonthHostsUnknown{$year.$month} in file at offset $PosInFile{MonthHostsUnknown}"); }
 
3199
                seek(HISTORYTMP,$PosInFile{"MonthHostsUnknown"},0); print HISTORYTMP $MonthHostsUnknown{$year.$month};
 
3200
                close(HISTORYTMP) || error("Failed to write temporary history file");
 
3201
        }
 
3202
        if ($withread) {
 
3203
                close(HISTORY) || error("Command for pipe '$filetoread' failed");
 
3204
        }
 
3205
 
 
3206
        # Purge data
 
3207
        if ($withpurge) { &Init_HashArray(); }
 
3208
 
 
3209
        # If update, rename tmp file bis into tmp file or set HistoryAlreadyFlushed
 
3210
        if ($withupdate) {
 
3211
                if ($HistoryAlreadyFlushed{"$year$month"}) {
 
3212
                        if (rename($filetowrite,$filetoread)==0) {
 
3213
                                error("Failed to update tmp history file $filetoread");
 
3214
                        }
 
3215
                }
 
3216
                else {
 
3217
                        $HistoryAlreadyFlushed{"$year$month"}=1;
 
3218
                }
 
3219
                if (! $ListOfYears{"$year"} || $ListOfYears{"$year"} lt "$month") { $ListOfYears{"$year"}="$month"; }
 
3220
        }
 
3221
 
 
3222
        # For backward compatibility, if LastLine does not exist, set to LastTime
 
3223
        $LastLine||=$LastTime{$year.$month};
 
3224
 
 
3225
        return ($withupdate?"$filetowrite":"");
 
3226
}
 
3227
 
 
3228
#------------------------------------------------------------------------------
 
3229
# Function:             Save a part of history file
 
3230
# Parameters:   sectiontosave,year,month[,lastlinenumber,lastlineoffset,lastlinechecksum]
 
3231
# Input:                $VERSION HISTORYTMP $nowyear $nowmonth $nowday $nowhour $nowmin $nowsec $LastLineNumber $LastLineOffset $LastLineChecksum
 
3232
# Output:               None
 
3233
# Return:               None
 
3234
#------------------------------------------------------------------------------
 
3235
sub Save_History {
 
3236
        my $sectiontosave=shift||'';
 
3237
        my $year=shift||'';
 
3238
        my $month=shift||'';
 
3239
 
 
3240
        my $lastlinenumber=shift||0;
 
3241
        my $lastlineoffset=shift||0;
 
3242
        my $lastlinechecksum=shift||0;
 
3243
        if (! $lastlinenumber) {        # This happens for migrate
 
3244
                $lastlinenumber=$LastLineNumber;
 
3245
                $lastlineoffset=$LastLineOffset;
 
3246
                $lastlinechecksum=$LastLineChecksum;
 
3247
        }
 
3248
        
 
3249
        if ($Debug) { debug(" Save_History [sectiontosave=$sectiontosave,year=$year,month=$month,lastlinenumber=$lastlinenumber,lastlineoffset=$lastlineoffset,lastlinechecksum=$lastlinechecksum]",1); }
 
3250
        my $spacebar="                    ";
 
3251
        my %keysinkeylist=();
 
3252
 
 
3253
        # Header
 
3254
        if ($sectiontosave eq 'header') {
 
3255
                print HISTORYTMP "AWSTATS DATA FILE $VERSION\n";
 
3256
                print HISTORYTMP "# If you remove this file, all statistics for date $year-$month will be lost/reset.\n";
 
3257
                print HISTORYTMP "\n";
 
3258
                print HISTORYTMP "# Position (offset in bytes) in this file of beginning of each section for\n";
 
3259
                print HISTORYTMP "# direct I/O access. If you made changes somewhere in this file, you should\n";
 
3260
                print HISTORYTMP "# also remove completely the MAP section (AWStats will rewrite it at next\n";
 
3261
                print HISTORYTMP "# update).\n";
 
3262
                print HISTORYTMP "BEGIN_MAP ".(26+(scalar keys %TrapInfosForHTTPErrorCodes)+(scalar @ExtraName?scalar @ExtraName-1:0))."\n";
 
3263
                print HISTORYTMP "POS_GENERAL ";$PosInFile{"general"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3264
                # When
 
3265
                print HISTORYTMP "POS_TIME ";$PosInFile{"time"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3266
                print HISTORYTMP "POS_VISITOR ";$PosInFile{"visitor"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3267
                print HISTORYTMP "POS_DAY ";$PosInFile{"day"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3268
                # Who
 
3269
                print HISTORYTMP "POS_DOMAIN ";$PosInFile{"domain"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3270
                print HISTORYTMP "POS_LOGIN ";$PosInFile{"login"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3271
                print HISTORYTMP "POS_ROBOT ";$PosInFile{"robot"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3272
                print HISTORYTMP "POS_WORMS ";$PosInFile{"worms"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3273
                print HISTORYTMP "POS_EMAILSENDER ";$PosInFile{"emailsender"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3274
                print HISTORYTMP "POS_EMAILRECEIVER ";$PosInFile{"emailreceiver"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3275
                # Navigation
 
3276
                print HISTORYTMP "POS_SESSION ";$PosInFile{"session"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3277
                print HISTORYTMP "POS_SIDER ";$PosInFile{"sider"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3278
                print HISTORYTMP "POS_FILETYPES ";$PosInFile{"filetypes"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3279
                print HISTORYTMP "POS_OS ";$PosInFile{"os"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3280
                print HISTORYTMP "POS_BROWSER ";$PosInFile{"browser"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3281
                print HISTORYTMP "POS_SCREENSIZE ";$PosInFile{"screensize"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3282
                print HISTORYTMP "POS_UNKNOWNREFERER ";$PosInFile{'unknownreferer'}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3283
                print HISTORYTMP "POS_UNKNOWNREFERERBROWSER ";$PosInFile{'unknownrefererbrowser'}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3284
                # Referers
 
3285
                print HISTORYTMP "POS_ORIGIN ";$PosInFile{"origin"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3286
                print HISTORYTMP "POS_SEREFERRALS ";$PosInFile{"sereferrals"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3287
                print HISTORYTMP "POS_PAGEREFS ";$PosInFile{"pagerefs"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3288
                print HISTORYTMP "POS_SEARCHWORDS ";$PosInFile{"searchwords"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3289
                print HISTORYTMP "POS_KEYWORDS ";$PosInFile{"keywords"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3290
                # Others
 
3291
                print HISTORYTMP "POS_MISC ";$PosInFile{"misc"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3292
                print HISTORYTMP "POS_ERRORS ";$PosInFile{"errors"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3293
                print HISTORYTMP "POS_CLUSTER ";$PosInFile{"cluster"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3294
                foreach (keys %TrapInfosForHTTPErrorCodes) {
 
3295
                        print HISTORYTMP "POS_SIDER_$_ ";$PosInFile{"sider_$_"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3296
                }
 
3297
                foreach (1..@ExtraName-1) {
 
3298
                        print HISTORYTMP "POS_EXTRA_$_ ";$PosInFile{"extra_$_"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3299
                }
 
3300
                print HISTORYTMP "END_MAP\n";
 
3301
        }
 
3302
 
 
3303
        # General
 
3304
        if ($sectiontosave eq 'general') {
 
3305
                if ($LastUpdate < int("$nowyear$nowmonth$nowday$nowhour$nowmin$nowsec")) { $LastUpdate=int("$nowyear$nowmonth$nowday$nowhour$nowmin$nowsec"); }
 
3306
                print HISTORYTMP "\n";
 
3307
                print HISTORYTMP "# LastLine    = Date of last record processed - Last record line number in last log - Last record offset in last log - Last record signature value\n";
 
3308
                print HISTORYTMP "# FirstTime   = Date of first visit for history file\n";
 
3309
                print HISTORYTMP "# LastTime    = Date of last visit for history file\n";
 
3310
                print HISTORYTMP "# LastUpdate  = Date of last update - Nb of parsed records - Nb of old records - Nb of new records - Nb of corrupted - Nb of dropped\n";
 
3311
                print HISTORYTMP "# TotalVisits = Number of visits\n";
 
3312
                print HISTORYTMP "# TotalUnique = Number of unique visitors\n";
 
3313
                print HISTORYTMP "# MonthHostsKnown   = Number of hosts known\n";
 
3314
                print HISTORYTMP "# MonthHostsUnKnown = Number of hosts unknown\n";
 
3315
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3316
                print HISTORYTMP "BEGIN_GENERAL 8\n";
 
3317
                print HISTORYTMP "LastLine ".($LastLine>0?$LastLine:$LastTime{$year.$month})." $lastlinenumber $lastlineoffset $lastlinechecksum\n";
 
3318
                print HISTORYTMP "FirstTime $FirstTime{$year.$month}\n";
 
3319
                print HISTORYTMP "LastTime $LastTime{$year.$month}\n";
 
3320
                print HISTORYTMP "LastUpdate $LastUpdate $NbOfLinesParsed $NbOfOldLines $NbOfNewLines $NbOfLinesCorrupted $NbOfLinesDropped\n";
 
3321
                print HISTORYTMP "TotalVisits ";$PosInFile{"TotalVisits"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3322
                print HISTORYTMP "TotalUnique ";$PosInFile{"TotalUnique"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3323
                print HISTORYTMP "MonthHostsKnown ";$PosInFile{"MonthHostsKnown"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3324
                print HISTORYTMP "MonthHostsUnknown ";$PosInFile{"MonthHostsUnknown"}=tell HISTORYTMP;print HISTORYTMP "$spacebar\n";
 
3325
                print HISTORYTMP "END_GENERAL\n";
 
3326
        }
 
3327
 
 
3328
        # When
 
3329
        if ($sectiontosave eq 'time') {
 
3330
                print HISTORYTMP "\n";
 
3331
                print HISTORYTMP "# Hour - Pages - Hits - Bandwidth - Not viewed Pages - Not viewed Hits - Not viewed Bandwidth\n";
 
3332
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3333
                print HISTORYTMP "BEGIN_TIME 24\n";
 
3334
                for (my $ix=0; $ix<=23; $ix++) { print HISTORYTMP "$ix ".int($_time_p[$ix])." ".int($_time_h[$ix])." ".int($_time_k[$ix])." ".int($_time_nv_p[$ix])." ".int($_time_nv_h[$ix])." ".int($_time_nv_k[$ix])."\n"; }
 
3335
                print HISTORYTMP "END_TIME\n";
 
3336
        }
 
3337
        if ($sectiontosave eq 'day') {  # This section must be saved after VISITOR section is read
 
3338
                print HISTORYTMP "\n";
 
3339
                print HISTORYTMP "# Date - Pages - Hits - Bandwidth - Visits\n";
 
3340
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3341
                print HISTORYTMP "BEGIN_DAY ".(scalar keys %DayHits)."\n";
 
3342
                my $monthvisits=0;
 
3343
                foreach (sort keys %DayHits) {
 
3344
                        if ($_ =~ /^$year$month/i) {    # Found a day entry of the good month
 
3345
                                my $page=$DayPages{$_}||0;
 
3346
                                my $hits=$DayHits{$_}||0;
 
3347
                                my $bytes=$DayBytes{$_}||0;
 
3348
                                my $visits=$DayVisits{$_}||0;
 
3349
                                print HISTORYTMP "$_ $page $hits $bytes $visits\n";
 
3350
                                $monthvisits+=$visits;
 
3351
                        }
 
3352
                }
 
3353
                $MonthVisits{$year.$month}=$monthvisits;
 
3354
                print HISTORYTMP "END_DAY\n";
 
3355
        }
 
3356
 
 
3357
        # Who
 
3358
        if ($sectiontosave eq 'domain') {
 
3359
                print HISTORYTMP "\n";
 
3360
                print HISTORYTMP "# Domain - Pages - Hits - Bandwidth\n";
 
3361
                print HISTORYTMP "# The $MaxNbOf{'Domain'} first Pages must be first (order not required for others)\n";
 
3362
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3363
                print HISTORYTMP "BEGIN_DOMAIN ".(scalar keys %_domener_h)."\n";
 
3364
                # We save page list in score sorted order to get a -output faster and with less use of memory.
 
3365
                &BuildKeyList($MaxNbOf{'Domain'},$MinHit{'Domain'},\%_domener_h,\%_domener_p);
 
3366
                my %keysinkeylist=();
 
3367
                foreach (@keylist) {
 
3368
                        $keysinkeylist{$_}=1;
 
3369
                        my $page=$_domener_p{$_}||0;
 
3370
                        my $bytes=$_domener_k{$_}||0;           # ||0 could be commented to reduce history file size
 
3371
                        print HISTORYTMP "$_ $page $_domener_h{$_} $bytes\n";
 
3372
                }
 
3373
                foreach (keys %_domener_h) {
 
3374
                        if ($keysinkeylist{$_}) { next; }
 
3375
                        my $page=$_domener_p{$_}||0;
 
3376
                        my $bytes=$_domener_k{$_}||0;           # ||0 could be commented to reduce history file size
 
3377
                        print HISTORYTMP "$_ $page $_domener_h{$_} $bytes\n";
 
3378
                }
 
3379
                print HISTORYTMP "END_DOMAIN\n";
 
3380
        }
 
3381
        if ($sectiontosave eq 'visitor') {
 
3382
                print HISTORYTMP "\n";
 
3383
                print HISTORYTMP "# Host - Pages - Hits - Bandwidth - Last visit date - [Start of last visit date] - [Last page of last visit]\n";
 
3384
                print HISTORYTMP "# [Start of last visit date] and [Last page of last visit] are saved only if session is not finished\n";
 
3385
                print HISTORYTMP "# The $MaxNbOf{'HostsShown'} first Hits must be first (order not required for others)\n";
 
3386
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3387
                print HISTORYTMP "BEGIN_VISITOR ".(scalar keys %_host_h)."\n";
 
3388
                my $monthhostsknown=0;
 
3389
                # We save page list in score sorted order to get a -output faster and with less use of memory.
 
3390
                &BuildKeyList($MaxNbOf{'HostsShown'},$MinHit{'Host'},\%_host_h,\%_host_p);
 
3391
                my %keysinkeylist=();
 
3392
                foreach my $key (@keylist) {
 
3393
                        if ($key !~ /^\d+\.\d+\.\d+\.\d+$/ &&  $key !~ /^[0-9A-F]*:/i) { $monthhostsknown++; }
 
3394
                        $keysinkeylist{$key}=1;
 
3395
                        my $page=$_host_p{$key}||0;
 
3396
                        my $bytes=$_host_k{$key}||0;
 
3397
                        my $timehostl=$_host_l{$key}||0;
 
3398
                        my $timehosts=$_host_s{$key}||0;
 
3399
                        my $lastpage=$_host_u{$key}||'';
 
3400
                        if ($timehostl && $timehosts && $lastpage) {
 
3401
                                if (($timehostl+$VISITTIMEOUT) < $LastLine) {
 
3402
                                        # Session for this user is expired
 
3403
                                        if ($timehosts) { $_session{GetSessionRange($timehosts,$timehostl)}++; }
 
3404
                                        if ($lastpage) { $_url_x{$lastpage}++; }
 
3405
                                        delete $_host_s{$key};
 
3406
                                        delete $_host_u{$key};
 
3407
                                        print HISTORYTMP "$key $page $_host_h{$key} $bytes $timehostl\n";
 
3408
                                }
 
3409
                                else {
 
3410
                                        # If this user has started a new session that is not expired
 
3411
                                        print HISTORYTMP "$key $page $_host_h{$key} $bytes $timehostl $timehosts $lastpage\n";
 
3412
                                }
 
3413
                        }
 
3414
                        else {
 
3415
                                my $hostl=$timehostl||'';
 
3416
                                print HISTORYTMP "$key $page $_host_h{$key} $bytes $hostl\n";
 
3417
                        }
 
3418
                }
 
3419
                foreach my $key (keys %_host_h) {
 
3420
                        if ($keysinkeylist{$key}) { next; }
 
3421
                        if ($key !~ /^\d+\.\d+\.\d+\.\d+$/ && $key !~ /^[0-9A-F]*:/i) { $monthhostsknown++; }
 
3422
                        my $page=$_host_p{$key}||0;
 
3423
                        my $bytes=$_host_k{$key}||0;
 
3424
                        my $timehostl=$_host_l{$key}||0;
 
3425
                        my $timehosts=$_host_s{$key}||0;
 
3426
                        my $lastpage=$_host_u{$key}||'';
 
3427
                        if ($timehostl && $timehosts && $lastpage) {
 
3428
                                if (($timehostl+$VISITTIMEOUT) < $LastLine) {
 
3429
                                        # Session for this user is expired
 
3430
                                        if ($timehosts) { $_session{GetSessionRange($timehosts,$timehostl)}++; }
 
3431
                                        if ($lastpage) { $_url_x{$lastpage}++; }
 
3432
                                        delete $_host_s{$key};
 
3433
                                        delete $_host_u{$key};
 
3434
                                        print HISTORYTMP "$key $page $_host_h{$key} $bytes $timehostl\n";
 
3435
                                }
 
3436
                                else {
 
3437
                                        # If this user has started a new session that is not expired
 
3438
                                        print HISTORYTMP "$key $page $_host_h{$key} $bytes $timehostl $timehosts $lastpage\n";
 
3439
                                }
 
3440
                        }
 
3441
                        else {
 
3442
                                my $hostl=$timehostl||'';
 
3443
                                print HISTORYTMP "$key $page $_host_h{$key} $bytes $hostl\n";
 
3444
                        }
 
3445
                }
 
3446
                $MonthUnique{$year.$month}=(scalar keys %_host_p);
 
3447
                $MonthHostsKnown{$year.$month}=$monthhostsknown;
 
3448
                $MonthHostsUnknown{$year.$month}=(scalar keys %_host_h) - $monthhostsknown;
 
3449
                print HISTORYTMP "END_VISITOR\n";
 
3450
        }
 
3451
        if ($sectiontosave eq 'login') {
 
3452
                print HISTORYTMP "\n";
 
3453
                print HISTORYTMP "# Login - Pages - Hits - Bandwidth - Last visit\n";
 
3454
                print HISTORYTMP "# The $MaxNbOf{'LoginShown'} first Pages must be first (order not required for others)\n";
 
3455
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3456
                print HISTORYTMP "BEGIN_LOGIN ".(scalar keys %_login_h)."\n";
 
3457
                # We save login list in score sorted order to get a -output faster and with less use of memory.
 
3458
                &BuildKeyList($MaxNbOf{'LoginShown'},$MinHit{'Login'},\%_login_h,\%_login_p);
 
3459
                my %keysinkeylist=();
 
3460
                foreach (@keylist) {
 
3461
                        $keysinkeylist{$_}=1;
 
3462
                        print HISTORYTMP "$_ ".int($_login_p{$_}||0)." ".int($_login_h{$_}||0)." ".int($_login_k{$_}||0)." ".($_login_l{$_}||'')."\n";
 
3463
                }
 
3464
                foreach (keys %_login_h) {
 
3465
                        if ($keysinkeylist{$_}) { next; }
 
3466
                        print HISTORYTMP "$_ ".int($_login_p{$_}||0)." ".int($_login_h{$_}||0)." ".int($_login_k{$_}||0)." ".($_login_l{$_}||'')."\n";
 
3467
                }
 
3468
                print HISTORYTMP "END_LOGIN\n";
 
3469
        }
 
3470
        if ($sectiontosave eq 'robot') {
 
3471
                print HISTORYTMP "\n";
 
3472
                print HISTORYTMP "# Robot ID - Hits - Bandwidth - Last visit - Hits on robots.txt\n";
 
3473
                print HISTORYTMP "# The $MaxNbOf{'RobotShown'} first Hits must be first (order not required for others)\n";
 
3474
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3475
                print HISTORYTMP "BEGIN_ROBOT ".(scalar keys %_robot_h)."\n";
 
3476
                # We save robot list in score sorted order to get a -output faster and with less use of memory.
 
3477
                &BuildKeyList($MaxNbOf{'RobotShown'},$MinHit{'Robot'},\%_robot_h,\%_robot_h);
 
3478
                my %keysinkeylist=();
 
3479
                foreach (@keylist) {
 
3480
                        $keysinkeylist{$_}=1;
 
3481
                        print HISTORYTMP "$_ ".int($_robot_h{$_})." ".int($_robot_k{$_})." $_robot_l{$_} ".int($_robot_r{$_})." \n";
 
3482
                }
 
3483
                foreach (keys %_robot_h) {
 
3484
                        if ($keysinkeylist{$_}) { next; }
 
3485
                        print HISTORYTMP "$_ ".int($_robot_h{$_})." ".int($_robot_k{$_})." $_robot_l{$_} ".int($_robot_r{$_})." \n";
 
3486
                }
 
3487
                print HISTORYTMP "END_ROBOT\n";
 
3488
        }
 
3489
        if ($sectiontosave eq 'worms') {
 
3490
                print HISTORYTMP "\n";
 
3491
                print HISTORYTMP "# Worm ID - Hits - Bandwidth - Last visit\n";
 
3492
                print HISTORYTMP "# The $MaxNbOf{'WormsShown'} first Hits must be first (order not required for others)\n";
 
3493
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3494
                print HISTORYTMP "BEGIN_WORMS ".(scalar keys %_worm_h)."\n";
 
3495
                # We save worm list in score sorted order to get a -output faster and with less use of memory.
 
3496
                &BuildKeyList($MaxNbOf{'WormsShown'},$MinHit{'Worm'},\%_worm_h,\%_worm_h);
 
3497
                my %keysinkeylist=();
 
3498
                foreach (@keylist) {
 
3499
                        $keysinkeylist{$_}=1;
 
3500
                        print HISTORYTMP "$_ ".int($_worm_h{$_})." ".int($_worm_k{$_})." $_worm_l{$_}\n";
 
3501
                }
 
3502
                foreach (keys %_worm_h) {
 
3503
                        if ($keysinkeylist{$_}) { next; }
 
3504
                        print HISTORYTMP "$_ ".int($_worm_h{$_})." ".int($_worm_k{$_})." $_worm_l{$_}\n";
 
3505
                }
 
3506
                print HISTORYTMP "END_WORMS\n";
 
3507
        }
 
3508
        if ($sectiontosave eq 'emailsender') {
 
3509
                print HISTORYTMP "\n";
 
3510
                print HISTORYTMP "# EMail - Hits - Bandwidth - Last visit\n";
 
3511
                print HISTORYTMP "# The $MaxNbOf{'EMailsShown'} first Hits must be first (order not required for others)\n";
 
3512
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3513
                print HISTORYTMP "BEGIN_EMAILSENDER ".(scalar keys %_emails_h)."\n";
 
3514
                # We save sender email list in score sorted order to get a -output faster and with less use of memory.
 
3515
                &BuildKeyList($MaxNbOf{'EMailsShown'},$MinHit{'EMail'},\%_emails_h,\%_emails_h);
 
3516
                my %keysinkeylist=();
 
3517
                foreach (@keylist) {
 
3518
                        $keysinkeylist{$_}=1;
 
3519
                        print HISTORYTMP "$_ ".int($_emails_h{$_}||0)." ".int($_emails_k{$_}||0)." $_emails_l{$_}\n";
 
3520
                }
 
3521
                foreach (keys %_emails_h) {
 
3522
                        if ($keysinkeylist{$_}) { next; }
 
3523
                        print HISTORYTMP "$_ ".int($_emails_h{$_}||0)." ".int($_emails_k{$_}||0)." $_emails_l{$_}\n";
 
3524
                }
 
3525
                print HISTORYTMP "END_EMAILSENDER\n";
 
3526
        }
 
3527
        if ($sectiontosave eq 'emailreceiver') {
 
3528
                print HISTORYTMP "\n";
 
3529
                print HISTORYTMP "# EMail - Hits - Bandwidth - Last visit\n";
 
3530
                print HISTORYTMP "# The $MaxNbOf{'EMailsShown'} first hits must be first (order not required for others)\n";
 
3531
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3532
                print HISTORYTMP "BEGIN_EMAILRECEIVER ".(scalar keys %_emailr_h)."\n";
 
3533
                # We save receiver email list in score sorted order to get a -output faster and with less use of memory.
 
3534
                &BuildKeyList($MaxNbOf{'EMailsShown'},$MinHit{'EMail'},\%_emailr_h,\%_emailr_h);
 
3535
                my %keysinkeylist=();
 
3536
                foreach (@keylist) {
 
3537
                        $keysinkeylist{$_}=1;
 
3538
                        print HISTORYTMP "$_ ".int($_emailr_h{$_}||0)." ".int($_emailr_k{$_}||0)." $_emailr_l{$_}\n";
 
3539
                }
 
3540
                foreach (keys %_emailr_h) {
 
3541
                        if ($keysinkeylist{$_}) { next; }
 
3542
                        print HISTORYTMP "$_ ".int($_emailr_h{$_}||0)." ".int($_emailr_k{$_}||0)." $_emailr_l{$_}\n";
 
3543
                }
 
3544
                print HISTORYTMP "END_EMAILRECEIVER\n";
 
3545
        }
 
3546
 
 
3547
        # Navigation
 
3548
        if ($sectiontosave eq 'session') {      # This section must be saved after VISITOR section is read
 
3549
                print HISTORYTMP "\n";
 
3550
                print HISTORYTMP "# Session range - Number of visits\n";
 
3551
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3552
                print HISTORYTMP "BEGIN_SESSION ".(scalar keys %_session)."\n";
 
3553
                foreach (keys %_session) { print HISTORYTMP "$_ ".int($_session{$_})."\n"; }
 
3554
                print HISTORYTMP "END_SESSION\n";
 
3555
        }
 
3556
        if ($sectiontosave eq 'sider') {        # This section must be saved after VISITOR section is read
 
3557
                print HISTORYTMP "\n";
 
3558
                print HISTORYTMP "# URL - Pages - Bandwidth - Entry - Exit\n";
 
3559
                print HISTORYTMP "# The $MaxNbOf{'PageShown'} first Pages must be first (order not required for others)\n";
 
3560
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3561
                print HISTORYTMP "BEGIN_SIDER ".(scalar keys %_url_p)."\n";
 
3562
                # We save page list in score sorted order to get a -output faster and with less use of memory.
 
3563
                &BuildKeyList($MaxNbOf{'PageShown'},$MinHit{'File'},\%_url_p,\%_url_p);
 
3564
                %keysinkeylist=();
 
3565
                foreach (@keylist) {
 
3566
                        $keysinkeylist{$_}=1;
 
3567
                        my $newkey=$_;
 
3568
                        $newkey =~ s/([^:])\/\//$1\//g;         # Because some targeted url were taped with 2 / (Ex: //rep//file.htm). We must keep http://rep/file.htm
 
3569
                        print HISTORYTMP "$newkey ".int($_url_p{$_}||0)." ".int($_url_k{$_}||0)." ".int($_url_e{$_}||0)." ".int($_url_x{$_}||0)."\n";
 
3570
                }
 
3571
                foreach (keys %_url_p) {
 
3572
                        if ($keysinkeylist{$_}) { next; }
 
3573
                        my $newkey=$_;
 
3574
                        $newkey =~ s/([^:])\/\//$1\//g;         # Because some targeted url were taped with 2 / (Ex: //rep//file.htm). We must keep http://rep/file.htm
 
3575
                        print HISTORYTMP "$newkey ".int($_url_p{$_}||0)." ".int($_url_k{$_}||0)." ".int($_url_e{$_}||0)." ".int($_url_x{$_}||0)."\n";
 
3576
                }
 
3577
                print HISTORYTMP "END_SIDER\n";
 
3578
        }
 
3579
        if ($sectiontosave eq 'filetypes') {
 
3580
                print HISTORYTMP "\n";
 
3581
                print HISTORYTMP "# Files type - Hits - Bandwidth - Bandwidth without compression - Bandwidth after compression\n";
 
3582
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3583
                print HISTORYTMP "BEGIN_FILETYPES ".(scalar keys %_filetypes_h)."\n";
 
3584
                foreach (keys %_filetypes_h) {
 
3585
                        my $hits=$_filetypes_h{$_}||0;
 
3586
                        my $bytes=$_filetypes_k{$_}||0;
 
3587
                        my $bytesbefore=$_filetypes_gz_in{$_}||0;
 
3588
                        my $bytesafter=$_filetypes_gz_out{$_}||0;
 
3589
                        print HISTORYTMP "$_ $hits $bytes $bytesbefore $bytesafter\n";
 
3590
                }
 
3591
                print HISTORYTMP "END_FILETYPES\n";
 
3592
        }
 
3593
        if ($sectiontosave eq 'os') {
 
3594
                print HISTORYTMP "\n";
 
3595
                print HISTORYTMP "# OS ID - Hits\n";
 
3596
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3597
                print HISTORYTMP "BEGIN_OS ".(scalar keys %_os_h)."\n";
 
3598
                foreach (keys %_os_h) { print HISTORYTMP "$_ $_os_h{$_}\n"; }
 
3599
                print HISTORYTMP "END_OS\n";
 
3600
        }
 
3601
        if ($sectiontosave eq 'browser') {
 
3602
                print HISTORYTMP "\n";
 
3603
                print HISTORYTMP "# Browser ID - Hits\n";
 
3604
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3605
                print HISTORYTMP "BEGIN_BROWSER ".(scalar keys %_browser_h)."\n";
 
3606
                foreach (keys %_browser_h) { print HISTORYTMP "$_ $_browser_h{$_}\n"; }
 
3607
                print HISTORYTMP "END_BROWSER\n";
 
3608
        }
 
3609
        if ($sectiontosave eq 'screensize') {
 
3610
                print HISTORYTMP "\n";
 
3611
                print HISTORYTMP "# Screen size - Hits\n";
 
3612
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3613
                print HISTORYTMP "BEGIN_SCREENSIZE ".(scalar keys %_screensize_h)."\n";
 
3614
                foreach (keys %_screensize_h) { print HISTORYTMP "$_ $_screensize_h{$_}\n"; }
 
3615
                print HISTORYTMP "END_SCREENSIZE\n";
 
3616
        }
 
3617
 
 
3618
        # Referer
 
3619
        if ($sectiontosave eq 'unknownreferer') {
 
3620
                print HISTORYTMP "\n";
 
3621
                print HISTORYTMP "# Unknown referer OS - Last visit date\n";
 
3622
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3623
                print HISTORYTMP "BEGIN_UNKNOWNREFERER ".(scalar keys %_unknownreferer_l)."\n";
 
3624
                foreach (keys %_unknownreferer_l) { print HISTORYTMP "$_ $_unknownreferer_l{$_}\n"; }
 
3625
                print HISTORYTMP "END_UNKNOWNREFERER\n";
 
3626
        }
 
3627
        if ($sectiontosave eq 'unknownrefererbrowser') {
 
3628
                print HISTORYTMP "\n";
 
3629
                print HISTORYTMP "# Unknown referer Browser - Last visit date\n";
 
3630
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3631
                print HISTORYTMP "BEGIN_UNKNOWNREFERERBROWSER ".(scalar keys %_unknownrefererbrowser_l)."\n";
 
3632
                foreach (keys %_unknownrefererbrowser_l) { print HISTORYTMP "$_ $_unknownrefererbrowser_l{$_}\n"; }
 
3633
                print HISTORYTMP "END_UNKNOWNREFERERBROWSER\n";
 
3634
        }
 
3635
        if ($sectiontosave eq 'origin') {
 
3636
                print HISTORYTMP "\n";
 
3637
                print HISTORYTMP "# Origin - Pages - Hits \n";
 
3638
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3639
                print HISTORYTMP "BEGIN_ORIGIN 6\n";
 
3640
                print HISTORYTMP "From0 ".int($_from_p[0])." ".int($_from_h[0])."\n";
 
3641
                print HISTORYTMP "From1 ".int($_from_p[1])." ".int($_from_h[1])."\n";
 
3642
                print HISTORYTMP "From2 ".int($_from_p[2])." ".int($_from_h[2])."\n";
 
3643
                print HISTORYTMP "From3 ".int($_from_p[3])." ".int($_from_h[3])."\n";
 
3644
                print HISTORYTMP "From4 ".int($_from_p[4])." ".int($_from_h[4])."\n";           # Same site
 
3645
                print HISTORYTMP "From5 ".int($_from_p[5])." ".int($_from_h[5])."\n";           # News
 
3646
                print HISTORYTMP "END_ORIGIN\n";
 
3647
        }
 
3648
        if ($sectiontosave eq 'sereferrals') {
 
3649
                print HISTORYTMP "\n";
 
3650
                print HISTORYTMP "# Search engine referers ID - Pages - Hits\n";
 
3651
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3652
                print HISTORYTMP "BEGIN_SEREFERRALS ".(scalar keys %_se_referrals_h)."\n";
 
3653
                foreach (keys %_se_referrals_h) { print HISTORYTMP "$_ ".int($_se_referrals_p{$_}||0)." $_se_referrals_h{$_}\n"; }
 
3654
                print HISTORYTMP "END_SEREFERRALS\n";
 
3655
        }
 
3656
        if ($sectiontosave eq 'pagerefs') {
 
3657
                print HISTORYTMP "\n";
 
3658
                print HISTORYTMP "# External page referers - Pages - Hits\n";
 
3659
                print HISTORYTMP "# The $MaxNbOf{'RefererShown'} first Pages must be first (order not required for others)\n";
 
3660
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3661
                print HISTORYTMP "BEGIN_PAGEREFS ".(scalar keys %_pagesrefs_h)."\n";
 
3662
                # We save page list in score sorted order to get a -output faster and with less use of memory.
 
3663
                &BuildKeyList($MaxNbOf{'RefererShown'},$MinHit{'Refer'},\%_pagesrefs_h,\%_pagesrefs_p);
 
3664
                %keysinkeylist=();
 
3665
                foreach (@keylist) {
 
3666
                        $keysinkeylist{$_}=1;
 
3667
                        my $newkey=$_;
 
3668
                        $newkey =~ s/^http(s|):\/\/([^\/]+)\/$/http$1:\/\/$2/i; # Remove / at end of http://.../ but not at end of http://.../dir/
 
3669
                        $newkey =~ s/\s/%20/g;
 
3670
                        print HISTORYTMP "$newkey ".int($_pagesrefs_p{$_}||0)." $_pagesrefs_h{$_}\n";
 
3671
                }
 
3672
                foreach (keys %_pagesrefs_h) {
 
3673
                        if ($keysinkeylist{$_}) { next; }
 
3674
                        my $newkey=$_;
 
3675
                        $newkey =~ s/^http(s|):\/\/([^\/]+)\/$/http$1:\/\/$2/i; # Remove / at end of http://.../ but not at end of http://.../dir/
 
3676
                        $newkey =~ s/\s/%20/g;
 
3677
                        print HISTORYTMP "$newkey ".int($_pagesrefs_p{$_}||0)." $_pagesrefs_h{$_}\n";
 
3678
                }
 
3679
                print HISTORYTMP "END_PAGEREFS\n";
 
3680
        }
 
3681
        if ($sectiontosave eq 'searchwords') {
 
3682
                print HISTORYTMP "\n";
 
3683
                print HISTORYTMP "# Search keyphrases - Number of search\n";
 
3684
                print HISTORYTMP "# The $MaxNbOf{'KeyphrasesShown'} first number of search must be first (order not required for others)\n";
 
3685
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3686
                print HISTORYTMP "BEGIN_SEARCHWORDS ".(scalar keys %_keyphrases)."\n";
 
3687
                # We will also build _keywords
 
3688
                %_keywords=();
 
3689
                # We save key list in score sorted order to get a -output faster and with less use of memory.
 
3690
                &BuildKeyList($MaxNbOf{'KeywordsShown'},$MinHit{'Keyword'},\%_keyphrases,\%_keyphrases);
 
3691
                %keysinkeylist=();
 
3692
                foreach my $key (@keylist) {
 
3693
                        $keysinkeylist{$key}=1;
 
3694
                        my $keyphrase=$key;
 
3695
                        print HISTORYTMP "$keyphrase $_keyphrases{$key}\n";
 
3696
                        foreach (split(/\+/,$key)) { $_keywords{$_}+=$_keyphrases{$key}; }      # To init %_keywords
 
3697
                }
 
3698
                foreach my $key (keys %_keyphrases) {
 
3699
                        if ($keysinkeylist{$key}) { next; }
 
3700
                        my $keyphrase=$key;
 
3701
                        print HISTORYTMP "$keyphrase $_keyphrases{$key}\n";
 
3702
                        foreach (split(/\+/,$key)) { $_keywords{$_}+=$_keyphrases{$key}; }      # To init %_keywords
 
3703
                }
 
3704
                print HISTORYTMP "END_SEARCHWORDS\n";
 
3705
                # Now save keywords section
 
3706
                print HISTORYTMP "\n";
 
3707
                print HISTORYTMP "# Search keywords - Number of search\n";
 
3708
                print HISTORYTMP "# The $MaxNbOf{'KeywordsShown'} first number of search must be first (order not required for others)\n";
 
3709
                $ValueInFile{"keywords"}=tell HISTORYTMP;
 
3710
                print HISTORYTMP "BEGIN_KEYWORDS ".(scalar keys %_keywords)."\n";
 
3711
                # We save key list in score sorted order to get a -output faster and with less use of memory.
 
3712
                &BuildKeyList($MaxNbOf{'KeywordsShown'},$MinHit{'Keyword'},\%_keywords,\%_keywords);
 
3713
                %keysinkeylist=();
 
3714
                foreach (@keylist) {
 
3715
                        $keysinkeylist{$_}=1;
 
3716
                        my $keyword=$_;
 
3717
                        print HISTORYTMP "$keyword $_keywords{$_}\n";
 
3718
                }
 
3719
                foreach (keys %_keywords) {
 
3720
                        if ($keysinkeylist{$_}) { next; }
 
3721
                        my $keyword=$_;
 
3722
                        print HISTORYTMP "$keyword $_keywords{$_}\n";
 
3723
                }
 
3724
                print HISTORYTMP "END_KEYWORDS\n";
 
3725
        }
 
3726
 
 
3727
        # Other - Errors
 
3728
        if ($sectiontosave eq 'cluster') {
 
3729
                print HISTORYTMP "\n";
 
3730
                print HISTORYTMP "# Cluster ID - Pages - Hits - Bandwidth\n";
 
3731
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3732
                print HISTORYTMP "BEGIN_CLUSTER ".(scalar keys %_cluster_h)."\n";
 
3733
                foreach (keys %_cluster_h) { print HISTORYTMP "$_ ".int($_cluster_p{$_}||0)." ".int($_cluster_h{$_}||0)." ".int($_cluster_k{$_}||0)."\n"; }
 
3734
                print HISTORYTMP "END_CLUSTER\n";
 
3735
        }
 
3736
        if ($sectiontosave eq 'misc') {
 
3737
                print HISTORYTMP "\n";
 
3738
                print HISTORYTMP "# Misc ID - Pages - Hits - Bandwidth\n";
 
3739
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3740
                print HISTORYTMP "BEGIN_MISC ".(scalar keys %MiscListCalc)."\n";
 
3741
                foreach (keys %MiscListCalc) { print HISTORYTMP "$_ ".int($_misc_p{$_}||0)." ".int($_misc_h{$_}||0)." ".int($_misc_k{$_}||0)."\n"; }
 
3742
                print HISTORYTMP "END_MISC\n";
 
3743
        }
 
3744
        if ($sectiontosave eq 'errors') {
 
3745
                print HISTORYTMP "\n";
 
3746
                print HISTORYTMP "# Errors - Hits - Bandwidth\n";
 
3747
                $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3748
                print HISTORYTMP "BEGIN_ERRORS ".(scalar keys %_errors_h)."\n";
 
3749
                foreach (keys %_errors_h) { print HISTORYTMP "$_ $_errors_h{$_} ".int($_errors_k{$_}||0)."\n"; }
 
3750
                print HISTORYTMP "END_ERRORS\n";
 
3751
        }
 
3752
        # Other - Trapped errors
 
3753
        foreach my $code (keys %TrapInfosForHTTPErrorCodes) {
 
3754
                if ($sectiontosave eq "sider_$code") {
 
3755
                        print HISTORYTMP "\n";
 
3756
                        print HISTORYTMP "# URL with $code errors - Hits - Last URL referer\n";
 
3757
                        $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3758
                        print HISTORYTMP "BEGIN_SIDER_$code ".(scalar keys %_sider404_h)."\n";
 
3759
                        foreach (keys %_sider404_h) {
 
3760
                                my $newkey=$_;
 
3761
                                my $newreferer=$_referer404_h{$_}||''; $newreferer =~ s/\s/%20/g;
 
3762
                                print HISTORYTMP "$newkey $_sider404_h{$_} $newreferer\n";
 
3763
                        }
 
3764
                        print HISTORYTMP "END_SIDER_$code\n";
 
3765
                }
 
3766
        }
 
3767
        # Other - Extra stats sections
 
3768
        foreach my $extranum (1..@ExtraName-1) {
 
3769
                if ($sectiontosave eq "extra_$extranum") {
 
3770
                        print HISTORYTMP "\n";
 
3771
                        print HISTORYTMP "# Extra key - Pages - Hits - Last access - Bandwidth\n";
 
3772
                        $ValueInFile{$sectiontosave}=tell HISTORYTMP;
 
3773
                        print HISTORYTMP "BEGIN_EXTRA_$extranum\n";
 
3774
                        &BuildKeyList($MaxNbOfExtra[$extranum],$MinHitExtra[$extranum],\%{'_section_' . $extranum . '_h'},\%{'_section_' . $extranum . '_p'});
 
3775
                        %keysinkeylist=();
 
3776
                        foreach (@keylist) {
 
3777
                                $keysinkeylist{$_}=1;
 
3778
                                my $page=${'_section_' . $extranum . '_p'}{$_}||0;
 
3779
                                my $bytes=${'_section_' . $extranum . '_k'}{$_}||0;
 
3780
                                my $lastaccess=${'_section_' . $extranum . '_l'}{$_}||'';
 
3781
                                print HISTORYTMP "$_ $page ", ${'_section_' . $extranum . '_h'}{$_}, " $bytes $lastaccess\n"; next;
 
3782
                        }
 
3783
                        foreach (keys %{'_section_' . $extranum . '_h'}) {
 
3784
                                if ($keysinkeylist{$_}) { next; }
 
3785
                                my $page=${'_section_' . $extranum . '_p'}{$_}||0;
 
3786
                                my $bytes=${'_section_' . $extranum . '_k'}{$_}||0;
 
3787
                                my $lastaccess=${'_section_' . $extranum . '_l'}{$_}||'';
 
3788
                                print HISTORYTMP "$_ $page ", ${'_section_' . $extranum . '_h'}{$_}, " $bytes $lastaccess\n"; next;
 
3789
                        }
 
3790
                        print HISTORYTMP "END_EXTRA_$extranum\n";
 
3791
                }
 
3792
        }
 
3793
        
 
3794
        %keysinkeylist=();
 
3795
}
 
3796
 
 
3797
#--------------------------------------------------------------------
 
3798
# Function:     Rename all tmp history file into history
 
3799
# Parameters:   None
 
3800
# Input:        $DirData $PROG $FileSuffix
 
3801
#               $KeepBackupOfHistoricFile $SaveDatabaseFilesWithPermissionsForEveryone
 
3802
# Output:       None
 
3803
# Return:       1 Ok, 0 at least one error (tmp files are removed)
 
3804
#--------------------------------------------------------------------
 
3805
sub Rename_All_Tmp_History {
 
3806
        my $pid=$$;
 
3807
        my $renameok=1;
 
3808
 
 
3809
        if ($Debug) { debug("Call to Rename_All_Tmp_History"); }
 
3810
 
 
3811
        opendir(DIR,"$DirData");
 
3812
        foreach (grep /^$PROG(\d\d\d\d\d\d)$FileSuffix\.tmp\.$pid$/, sort readdir DIR) {
 
3813
                /^$PROG(\d\d\d\d\d\d)$FileSuffix\.tmp\.$pid$/;
 
3814
                if ($renameok) {        # No rename error yet
 
3815
                        if ($Debug) { debug(" Rename new tmp history file $PROG$1$FileSuffix.tmp.$$ into $PROG$1$FileSuffix.txt",1); }
 
3816
                        if (-s "$DirData/$PROG$1$FileSuffix.tmp.$$") {          # Rename tmp files if size > 0
 
3817
                                if ($KeepBackupOfHistoricFiles) {
 
3818
                                        if (-s "$DirData/$PROG$1$FileSuffix.txt") {     # History file already exists. We backup it
 
3819
                                                if ($Debug) { debug("  Make a backup of old history file into $PROG$1$FileSuffix.bak before",1); }
 
3820
                                                #if (FileCopy("$DirData/$PROG$1$FileSuffix.txt","$DirData/$PROG$1$FileSuffix.bak")) {
 
3821
                                                if (rename("$DirData/$PROG$1$FileSuffix.txt", "$DirData/$PROG$1$FileSuffix.bak")==0) {
 
3822
                                                        warning("Warning: Failed to make a backup of \"$DirData/$PROG$1$FileSuffix.txt\" into \"$DirData/$PROG$1$FileSuffix.bak\".");
 
3823
                                                }
 
3824
                                                if ($SaveDatabaseFilesWithPermissionsForEveryone) {
 
3825
                                                        chmod 0666,"$DirData/$PROG$1$FileSuffix.bak";
 
3826
                                                }
 
3827
                                        }
 
3828
                                        else {
 
3829
                                                if ($Debug) { debug("  No need to backup old history file",1); }
 
3830
                                        }
 
3831
                                }
 
3832
                                if (rename("$DirData/$PROG$1$FileSuffix.tmp.$$", "$DirData/$PROG$1$FileSuffix.txt")==0) {
 
3833
                                        $renameok=0;    # At least one error in renaming working files
 
3834
                                        # Remove tmp file
 
3835
                                        unlink "$DirData/$PROG$1$FileSuffix.tmp.$$";
 
3836
                                        warning("Warning: Failed to rename \"$DirData/$PROG$1$FileSuffix.tmp.$$\" into \"$DirData/$PROG$1$FileSuffix.txt\".\nWrite permissions on \"$PROG$1$FileSuffix.txt\" might be wrong".($ENV{'GATEWAY_INTERFACE'}?" for an 'update from web'":"")." or file might be opened.");
 
3837
                                        next;
 
3838
                                }
 
3839
                                if ($SaveDatabaseFilesWithPermissionsForEveryone) {
 
3840
                                        chmod 0666,"$DirData/$PROG$1$FileSuffix.txt";
 
3841
                                }
 
3842
                        }
 
3843
                }
 
3844
                else {                          # Because of rename error, we remove all remaining tmp files
 
3845
                        unlink "$DirData/$PROG$1$FileSuffix.tmp.$$";
 
3846
                }
 
3847
        }
 
3848
        close DIR;
 
3849
        return $renameok;
 
3850
}
 
3851
 
 
3852
#------------------------------------------------------------------------------
 
3853
# Function:     Load DNS cache file entries into a memory hash array
 
3854
# Parameters:   Hash array ref to load into,
 
3855
#               File name to load,
 
3856
#                               File suffix to use
 
3857
#               Save to a second plugin file if not up to date
 
3858
# Input:                None
 
3859
# Output:               Hash array is loaded
 
3860
# Return:               1 No DNS Cache file found, 0 OK
 
3861
#------------------------------------------------------------------------------
 
3862
sub Read_DNS_Cache {
 
3863
        my $hashtoload=shift;
 
3864
        my $dnscachefile=shift;
 
3865
        my $filesuffix=shift;
 
3866
        my $savetohash=shift;
 
3867
 
 
3868
        my $dnscacheext='';
 
3869
        my $filetoload='';
 
3870
        my $timetoload = time();
 
3871
 
 
3872
        if ($Debug) { debug("Call to Read_DNS_Cache [file=\"$dnscachefile\"]"); }
 
3873
        if ($dnscachefile =~ s/(\.\w+)$//) { $dnscacheext=$1; }
 
3874
        foreach my $dir ("$DirData",".","") {
 
3875
                my $searchdir=$dir;
 
3876
                if ($searchdir && (!($searchdir =~ /\/$/)) && (!($searchdir =~ /\\$/)) ) { $searchdir .= "/"; }
 
3877
                if (-f "${searchdir}$dnscachefile$filesuffix$dnscacheext") { $filetoload="${searchdir}$dnscachefile$filesuffix$dnscacheext"; }
 
3878
                # Plugin call : Change filetoload
 
3879
                if ($PluginsLoaded{'SearchFile'}{'hashfiles'}) { SearchFile_hashfiles($searchdir,$dnscachefile,$filesuffix,$dnscacheext,$filetoload); }
 
3880
                if ($filetoload) { last; }      # We found a file to load
 
3881
        }
 
3882
 
 
3883
        if (! $filetoload) {
 
3884
                if ($Debug) { debug(" No DNS Cache file found"); }
 
3885
                return 1;
 
3886
        }
 
3887
 
 
3888
        # Plugin call : Load hashtoload
 
3889
        if ($PluginsLoaded{'LoadCache'}{'hashfiles'}) { LoadCache_hashfiles($filetoload,$hashtoload); }
 
3890
        if (! scalar keys %$hashtoload) {
 
3891
                open(DNSFILE,"$filetoload") or error("Couldn't open DNS Cache file \"$filetoload\": $!");
 
3892
                #binmode DNSFILE;               # If we set binmode here, it seems that the load is broken on ActiveState 5.8
 
3893
                # This is a fast way to load with regexp
 
3894
                %$hashtoload = map(/^(?:\d{0,10}\s+)?([0-9A-F:\.]+)\s+([^\s]+)$/oi,<DNSFILE>);
 
3895
                close DNSFILE;
 
3896
                if ($savetohash) {
 
3897
                        # Plugin call : Save hash file (all records) with test if up to date to save
 
3898
                        if ($PluginsLoaded{'SaveHash'}{'hashfiles'}) { SaveHash_hashfiles($filetoload,$hashtoload,1,0); }
 
3899
                }
 
3900
        }
 
3901
        if ($Debug) { debug(" Loaded ".(scalar keys %$hashtoload)." items from $filetoload in ".(time()-$timetoload)." seconds.",1); }
 
3902
        return 0;
 
3903
}
 
3904
 
 
3905
#------------------------------------------------------------------------------
 
3906
# Function:     Save a memory hash array into a DNS cache file
 
3907
# Parameters:   Hash array ref to save,
 
3908
#               File name to save,
 
3909
#                               File suffix to use
 
3910
# Input:                None
 
3911
# Output:               None
 
3912
# Return:               0 OK, 1 Error
 
3913
#------------------------------------------------------------------------------
 
3914
sub Save_DNS_Cache_File {
 
3915
        my $hashtosave=shift;
 
3916
        my $dnscachefile=shift;
 
3917
        my $filesuffix=shift;
 
3918
 
 
3919
        my $dnscacheext='';
 
3920
        my $filetosave='';
 
3921
        my $timetosave = time();
 
3922
        my $nbofelemtosave=$NBOFLASTUPDATELOOKUPTOSAVE;
 
3923
        my $nbofelemsaved=0;
 
3924
 
 
3925
        if ($Debug) { debug("Call to Save_DNS_Cache_File [file=\"$dnscachefile\"]"); }
 
3926
        if (! scalar keys %$hashtosave) {
 
3927
                if ($Debug) { debug(" No data to save"); }
 
3928
                return 0;
 
3929
        }
 
3930
        if ($dnscachefile =~ s/(\.\w+)$//) { $dnscacheext=$1; }
 
3931
        $filetosave="$dnscachefile$filesuffix$dnscacheext";
 
3932
        # Plugin call : Save hash file (only $NBOFLASTUPDATELOOKUPTOSAVE records) with no test if up to date
 
3933
        if ($PluginsLoaded{'SaveHash'}{'hashfiles'}) { SaveHash_hashfiles($filetosave,$hashtosave,0,$nbofelemtosave,$nbofelemsaved); }
 
3934
        if (! $nbofelemsaved) {
 
3935
                $filetosave="$dnscachefile$filesuffix$dnscacheext";
 
3936
                if ($Debug) { debug(" Save data ".($nbofelemtosave?"($nbofelemtosave records max)":"(all records)")." into file $filetosave"); }
 
3937
                if (! open(DNSFILE,">$filetosave")) {
 
3938
                        warning("Warning: Failed to open for writing last update DNS Cache file \"$filetosave\": $!");
 
3939
                        return 1;
 
3940
                }
 
3941
                binmode DNSFILE;
 
3942
                my $starttimemin=int($starttime/60);
 
3943
                foreach my $key (keys %$hashtosave) {
 
3944
                        #if ($hashtosave->{$key} ne '*') {
 
3945
                                my $ipsolved=$hashtosave->{$key};
 
3946
                                print DNSFILE "$starttimemin\t$key\t".($ipsolved eq 'ip'?'*':$ipsolved)."\n";   # Change 'ip' to '*' for backward compatibility
 
3947
                                if (++$nbofelemsaved >= $NBOFLASTUPDATELOOKUPTOSAVE) { last; }
 
3948
                        #}
 
3949
                }
 
3950
                close DNSFILE;
 
3951
                
 
3952
                if ($SaveDatabaseFilesWithPermissionsForEveryone) {
 
3953
                        chmod 0666,"$filetosave";
 
3954
                }
 
3955
 
 
3956
        }
 
3957
        if ($Debug) { debug(" Saved $nbofelemsaved items into $filetosave in ".(time()-$timetosave)." seconds.",1); }
 
3958
        return 0;
 
3959
}
 
3960
 
 
3961
#------------------------------------------------------------------------------
 
3962
# Function:     Return time elapsed since last call in miliseconds
 
3963
# Parameters:   0|1 (0 reset counter, 1 no reset)
 
3964
# Input:                None
 
3965
# Output:               None
 
3966
# Return:               Number of miliseconds elapsed since last call
 
3967
#------------------------------------------------------------------------------
 
3968
sub GetDelaySinceStart {
 
3969
        if (shift) { $StartSeconds=0; } # Reset chrono
 
3970
        my ($newseconds, $newmicroseconds)=(time(),0);
 
3971
        # Plugin call : Return seconds and milliseconds
 
3972
        if ($PluginsLoaded{'GetTime'}{'timehires'}) { GetTime_timehires($newseconds, $newmicroseconds); }
 
3973
        if (! $StartSeconds) { $StartSeconds=$newseconds; $StartMicroseconds=$newmicroseconds; }
 
3974
        return (($newseconds-$StartSeconds)*1000+int(($newmicroseconds-$StartMicroseconds)/1000));
 
3975
}
 
3976
 
 
3977
#------------------------------------------------------------------------------
 
3978
# Function:     Reset all variables whose name start with _ because a new month start
 
3979
# Parameters:   None
 
3980
# Input:        $YearRequired All variables whose name start with _
 
3981
# Output:       All variables whose name start with _
 
3982
# Return:               None
 
3983
#------------------------------------------------------------------------------
 
3984
sub Init_HashArray {
 
3985
        if ($Debug) { debug("Call to Init_HashArray"); }
 
3986
        # Reset global hash arrays
 
3987
        %FirstTime = %LastTime = ();
 
3988
        %MonthHostsKnown = %MonthHostsUnknown = ();
 
3989
        %MonthVisits = %MonthUnique = ();
 
3990
        %MonthPages = %MonthHits = %MonthBytes = ();
 
3991
        %MonthNotViewedPages = %MonthNotViewedHits = %MonthNotViewedBytes = ();
 
3992
        %DayPages = %DayHits = %DayBytes = %DayVisits = ();
 
3993
        # Reset all arrays with name beginning by _
 
3994
        for (my $ix=0; $ix<6; $ix++)  { $_from_p[$ix]=0; $_from_h[$ix]=0; }
 
3995
        for (my $ix=0; $ix<24; $ix++) { $_time_h[$ix]=0; $_time_k[$ix]=0; $_time_p[$ix]=0; $_time_nv_h[$ix]=0; $_time_nv_k[$ix]=0; $_time_nv_p[$ix]=0; }
 
3996
        # Reset all hash arrays with name beginning by _
 
3997
        %_session = %_browser_h = ();
 
3998
        %_domener_p = %_domener_h = %_domener_k = %_errors_h = %_errors_k = ();
 
3999
        %_filetypes_h = %_filetypes_k = %_filetypes_gz_in = %_filetypes_gz_out = ();
 
4000
        %_host_p = %_host_h = %_host_k = %_host_l = %_host_s = %_host_u = ();
 
4001
        %_waithost_e = %_waithost_l = %_waithost_s = %_waithost_u = ();
 
4002
        %_keyphrases = %_keywords = %_os_h = %_pagesrefs_p = %_pagesrefs_h = %_robot_h = %_robot_k = %_robot_l = %_robot_r = ();
 
4003
        %_worm_h = %_worm_k = %_worm_l = %_login_p = %_login_h = %_login_k = %_login_l = %_screensize_h = ();
 
4004
        %_misc_p = %_misc_h = %_misc_k = ();
 
4005
        %_cluster_p = %_cluster_h = %_cluster_k = ();
 
4006
        %_se_referrals_p = %_se_referrals_h = %_sider404_h = %_referer404_h = %_url_p = %_url_k = %_url_e = %_url_x = ();
 
4007
        %_unknownreferer_l = %_unknownrefererbrowser_l = ();
 
4008
        %_emails_h = %_emails_k = %_emails_l = %_emailr_h = %_emailr_k = %_emailr_l = ();
 
4009
        for (my $ix=1; $ix < @ExtraName; $ix++) {
 
4010
                %{'_section_' . $ix . '_h'} = %{'_section_' . $ix . '_o'} = %{'_section_' . $ix . '_k'} =
 
4011
                %{'_section_' . $ix . '_l'} = %{'_section_' . $ix . '_p'} = ();
 
4012
        }
 
4013
}
 
4014
 
 
4015
#------------------------------------------------------------------------------
 
4016
# Function:     Change word separators of a keyphrase string into space and
 
4017
#               remove bad coded chars
 
4018
# Parameters:   stringtodecode
 
4019
# Input:        None
 
4020
# Output:       None
 
4021
# Return:               decodedstring
 
4022
#------------------------------------------------------------------------------
 
4023
sub ChangeWordSeparatorsIntoSpace {
 
4024
        $_[0] =~ s/%0[ad]/ /ig;                         # LF,CR
 
4025
        $_[0] =~ s/%2[02789abc]/ /ig;           # 
 
4026
        $_[0] =~ s/%3a/ /ig;                            # :
 
4027
        $_[0] =~ tr/\+\'\(\)\"\*,:/        /s;          # "&" and "=" must not be in this list
 
4028
}
 
4029
 
 
4030
#------------------------------------------------------------------------------
 
4031
# Function:             Transforms & into &amp; as needed in XML/XHTML
 
4032
# Parameters:   stringtoencode
 
4033
# Return:               encodedstring
 
4034
#------------------------------------------------------------------------------
 
4035
sub XMLEncode {
 
4036
        my $string = shift;
 
4037
        if ($BuildReportFormat ne 'xml') { return $string; }
 
4038
        $string =~ s/&/&amp;/g;
 
4039
        return $string;
 
4040
}
 
4041
 
 
4042
#------------------------------------------------------------------------------
 
4043
# Function:     Encode a binary string into an ASCII string
 
4044
# Parameters:   stringtoencode
 
4045
# Return:               encodedstring
 
4046
#------------------------------------------------------------------------------
 
4047
sub EncodeString {
 
4048
        my $string = shift;
 
4049
#       use bytes;
 
4050
        $string =~ s/([\x2B\x80-\xFF])/sprintf ("%%%2x", ord($1))/eg;
 
4051
#       no bytes;
 
4052
        $string =~ tr/ /+/s;
 
4053
        return $string;
 
4054
}
 
4055
 
 
4056
#------------------------------------------------------------------------------
 
4057
# Function:     Decode an only text string into a binary string
 
4058
# Parameters:   stringtodecode
 
4059
# Input:        None
 
4060
# Output:       None
 
4061
# Return:               decodedstring
 
4062
#------------------------------------------------------------------------------
 
4063
sub DecodeEncodedString {
 
4064
        my $stringtodecode=shift;
 
4065
        $stringtodecode =~ tr/\+/ /s;
 
4066
        $stringtodecode =~ s/%([A-F0-9][A-F0-9])/pack("C", hex($1))/ieg;
 
4067
        return $stringtodecode;
 
4068
}
 
4069
 
 
4070
#------------------------------------------------------------------------------
 
4071
# Function:     Decode an precompiled regex value to a common regex value
 
4072
# Parameters:   compiledregextodecode
 
4073
# Input:        None
 
4074
# Output:       None
 
4075
# Return:               standardregex
 
4076
#------------------------------------------------------------------------------
 
4077
sub UnCompileRegex {
 
4078
        shift =~ /\(\?[-\w]*:(.*)\)/;
 
4079
        return $1;
 
4080
}
 
4081
 
 
4082
#------------------------------------------------------------------------------
 
4083
# Function:     Clean a string of HTML tags to avoid 'Cross Site Scripting attacks'
 
4084
# Parameters:   stringtodecode
 
4085
# Input:        None
 
4086
# Output:       None
 
4087
# Return:               decodedstring
 
4088
#------------------------------------------------------------------------------
 
4089
sub CleanFromCSSA {
 
4090
        my $stringtoclean=shift;
 
4091
#       $stringtoclean =~ s/[<>].*$//;
 
4092
        $stringtoclean =~ s/</&lt;/g;
 
4093
        $stringtoclean =~ s/>/&gt;/g;
 
4094
        return $stringtoclean;
 
4095
}
 
4096
 
 
4097
#------------------------------------------------------------------------------
 
4098
# Function:     Copy one file into another
 
4099
# Parameters:   sourcefilename targetfilename
 
4100
# Input:        None
 
4101
# Output:       None
 
4102
# Return:               0 if copy is ok, 1 else
 
4103
#------------------------------------------------------------------------------
 
4104
sub FileCopy {
 
4105
        my $filesource = shift;
 
4106
        my $filetarget = shift;
 
4107
        if ($Debug) { debug("FileCopy($filesource,$filetarget)",1); }
 
4108
        open(FILESOURCE,"$filesource") || return 1;
 
4109
        open(FILETARGET,">$filetarget") || return 1;
 
4110
        binmode FILESOURCE;
 
4111
        binmode FILETARGET;
 
4112
        # ...
 
4113
        close(FILETARGET);
 
4114
        close(FILESOURCE);
 
4115
        if ($Debug) { debug(" File copied",1); }
 
4116
        return 0;
 
4117
}
 
4118
 
 
4119
#------------------------------------------------------------------------------
 
4120
# Function:     Show flags for other language translations
 
4121
# Parameters:   Current languade id (en, fr, ...)
 
4122
# Input:        None
 
4123
# Output:       None
 
4124
# Return:       None
 
4125
#------------------------------------------------------------------------------
 
4126
sub Show_Flag_Links {
 
4127
        my $CurrentLang = shift;
 
4128
 
 
4129
        # Build flags link
 
4130
        my $NewLinkParams=$QueryString;
 
4131
        my $NewLinkTarget='';
 
4132
        if ($ENV{'GATEWAY_INTERFACE'}) {
 
4133
                $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
4134
                $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
4135
                $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
4136
                $NewLinkParams =~ s/(^|&)lang=[^&]*//i;
 
4137
                if ($FrameName eq 'mainright') { $NewLinkTarget=" target=\"_parent\""; }
 
4138
                $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
4139
                if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
4140
        }
 
4141
        else {
 
4142
                $NewLinkParams=($SiteConfig?"config=$SiteConfig&":"")."year=$YearRequired&month=$MonthRequired&";
 
4143
        }
 
4144
        if ($FrameName eq 'mainright') { $NewLinkParams.='framename=index&'; }
 
4145
 
 
4146
        foreach my $lng (split(/\s+/,$ShowFlagLinks)) {
 
4147
                if ($lng ne $CurrentLang) {
 
4148
                        my %lngtitle=('en','English','fr','French','de','German','it','Italian','nl','Dutch','es','Spanish');
 
4149
                        my $lngtitle=($lngtitle{$lng}?$lngtitle{$lng}:$lng);
 
4150
                        my $flag=($LangAWStatsToCountryAwstats{$lng}?$LangAWStatsToCountryAwstats{$lng}:$lng);
 
4151
                        print "<a href=\"".XMLEncode("$AWScript?${NewLinkParams}lang=$lng")."\"$NewLinkTarget><img src=\"$DirIcons\/flags\/$flag.png\" height=\"14\" border=\"0\"".AltTitle("$lngtitle")." /></a>&nbsp;\n";
 
4152
                }
 
4153
        }
 
4154
}
 
4155
 
 
4156
#------------------------------------------------------------------------------
 
4157
# Function:             Format value in bytes in a string (Bytes, Kb, Mb, Gb)
 
4158
# Parameters:   bytes (integer value or "0.00")
 
4159
# Input:        None
 
4160
# Output:       None
 
4161
# Return:       "x.yz MB" or "x.yy KB" or "x Bytes" or "0"
 
4162
#------------------------------------------------------------------------------
 
4163
sub Format_Bytes {
 
4164
        my $bytes = shift||0;
 
4165
        my $fudge = 1;
 
4166
        # Do not use exp/log function to calculate 1024power, function make segfault on some unix/perl versions
 
4167
        if ($bytes >= ($fudge << 30)) { return sprintf("%.2f", $bytes/1073741824)." $Message[110]"; }
 
4168
        if ($bytes >= ($fudge << 20)) { return sprintf("%.2f", $bytes/1048576)." $Message[109]"; }
 
4169
        if ($bytes >= ($fudge << 10)) { return sprintf("%.2f", $bytes/1024)." $Message[108]"; }
 
4170
        if ($bytes < 0) { $bytes="?"; }
 
4171
        return int($bytes).(int($bytes)?" $Message[119]":"");
 
4172
}
 
4173
 
 
4174
#------------------------------------------------------------------------------
 
4175
# Function:             Return " alt=string title=string"
 
4176
# Parameters:   string
 
4177
# Input:        None
 
4178
# Output:       None
 
4179
# Return:       "alt=string title=string"
 
4180
#------------------------------------------------------------------------------
 
4181
sub AltTitle {
 
4182
        my $string = shift||'';
 
4183
        return " alt='$string' title='$string'";
 
4184
#       return " alt=\"$string\" title=\"$string\"";
 
4185
#       return ($BuildReportFormat?"":" alt=\"$string\"")." title=\"$string\"";
 
4186
}
 
4187
 
 
4188
#------------------------------------------------------------------------------
 
4189
# Function:             Tell if an email is a local or external email
 
4190
# Parameters:   email
 
4191
# Input:        $SiteDomain(exact string) $HostAliases(quoted regex string)
 
4192
# Output:       None
 
4193
# Return:       -1, 0 or 1
 
4194
#------------------------------------------------------------------------------
 
4195
sub IsLocalEMail {
 
4196
        my $email=shift||'unknown';
 
4197
        if ($email !~ /\@(.*)$/) { return 0; }
 
4198
        my $domain=$1;
 
4199
        if ($domain =~ /^$SiteDomain$/i) { return 1; }
 
4200
        foreach (@HostAliases) { if ($domain =~ /$_/) { return 1; } }
 
4201
        return -1;
 
4202
}
 
4203
 
 
4204
#------------------------------------------------------------------------------
 
4205
# Function:             Format a date according to Message[78] (country date format)
 
4206
# Parameters:   String date YYYYMMDDHHMMSS
 
4207
#               Option 0=LastUpdate and LastTime date
 
4208
#                      1=Arrays date except daymonthvalues
 
4209
#                      2=daymonthvalues date (only year month and day)
 
4210
# Input:        $Message[78]
 
4211
# Output:       None
 
4212
# Return:       Date with format defined by Message[78] and option
 
4213
#------------------------------------------------------------------------------
 
4214
sub Format_Date {
 
4215
        my $date=shift;
 
4216
        my $option=shift||0;
 
4217
        my $year=substr("$date",0,4);
 
4218
        my $month=substr("$date",4,2);
 
4219
        my $day=substr("$date",6,2);
 
4220
        my $hour=substr("$date",8,2);
 
4221
        my $min=substr("$date",10,2);
 
4222
        my $sec=substr("$date",12,2);
 
4223
        my $dateformat=$Message[78];
 
4224
        if ($option == 2) {
 
4225
                $dateformat =~ s/^[^ymd]+//g;
 
4226
                $dateformat =~ s/[^ymd]+$//g;
 
4227
        }
 
4228
        $dateformat =~ s/yyyy/$year/g;
 
4229
        $dateformat =~ s/yy/$year/g;
 
4230
        $dateformat =~ s/mmm/$MonthNumLib{$month}/g;
 
4231
        $dateformat =~ s/mm/$month/g;
 
4232
        $dateformat =~ s/dd/$day/g;
 
4233
        $dateformat =~ s/HH/$hour/g;
 
4234
        $dateformat =~ s/MM/$min/g;
 
4235
        $dateformat =~ s/SS/$sec/g;
 
4236
        return "$dateformat";
 
4237
}
 
4238
 
 
4239
#------------------------------------------------------------------------------
 
4240
# Function:     Return 1 if string contains only ascii chars
 
4241
# Parameters:   string
 
4242
# Input:        None
 
4243
# Output:       None
 
4244
# Return:       0 or 1
 
4245
#------------------------------------------------------------------------------
 
4246
sub IsAscii {
 
4247
        my $string=shift;
 
4248
        if ($Debug) { debug("IsAscii($string)",5); }
 
4249
        if ($string =~ /^[\w\+\-\/\\\.%,;:=\"\'&?!\s]+$/) {
 
4250
                if ($Debug) { debug(" Yes",6); }
 
4251
                return 1;               # Only alphanum chars (and _) or + - / \ . % , ; : = " ' & ? space \t
 
4252
        }
 
4253
        if ($Debug) { debug(" No",6); }
 
4254
        return 0;
 
4255
}
 
4256
 
 
4257
#------------------------------------------------------------------------------
 
4258
# Function:     Return the lower value between 2 but exclude value if 0
 
4259
# Parameters:   Val1 and Val2
 
4260
# Input:        None
 
4261
# Output:       None
 
4262
# Return:       min(Val1,Val2)
 
4263
#------------------------------------------------------------------------------
 
4264
sub MinimumButNoZero {
 
4265
        my ($val1,$val2)=@_;
 
4266
        return ($val1&&($val1<$val2||!$val2)?$val1:$val2);
 
4267
}
 
4268
 
 
4269
#------------------------------------------------------------------------------
 
4270
# Function:     Add a val from sorting tree
 
4271
# Parameters:   keytoadd keyval [firstadd]
 
4272
# Input:        None
 
4273
# Output:       None
 
4274
# Return:       None
 
4275
#------------------------------------------------------------------------------
 
4276
sub AddInTree {
 
4277
        my $keytoadd=shift;
 
4278
        my $keyval=shift;
 
4279
        my $firstadd=shift||0;
 
4280
        if ($firstadd==1) {                     # Val is the first one
 
4281
                if ($Debug) { debug("  firstadd",4); }
 
4282
                $val{$keyval}=$keytoadd;
 
4283
                $lowerval=$keyval;
 
4284
                if ($Debug) { debug("  lowerval=$lowerval, nb elem val=".(scalar keys %val).", nb elem egal=".(scalar keys %egal).".",4); }
 
4285
                return;
 
4286
        }
 
4287
        if ($val{$keyval}) {            # Val is already in tree
 
4288
                if ($Debug) { debug("  val is already in tree",4); }
 
4289
                $egal{$keytoadd}=$val{$keyval};
 
4290
                $val{$keyval}=$keytoadd;
 
4291
                if ($Debug) { debug("  lowerval=$lowerval, nb elem val=".(scalar keys %val).", nb elem egal=".(scalar keys %egal).".",4); }
 
4292
                return;
 
4293
        }
 
4294
        if ($keyval <= $lowerval) {     # Val is a new one lower (should happens only when tree is not full)
 
4295
                if ($Debug) { debug("  keytoadd val=$keyval is lower or equal to lowerval=$lowerval",4); }
 
4296
                $val{$keyval}=$keytoadd;
 
4297
                $nextval{$keyval}=$lowerval;
 
4298
                $lowerval=$keyval;
 
4299
                if ($Debug) { debug("  lowerval=$lowerval, nb elem val=".(scalar keys %val).", nb elem egal=".(scalar keys %egal).".",4); }
 
4300
                return;
 
4301
        }
 
4302
        # Val is a new one higher
 
4303
        if ($Debug) { debug("  keytoadd val=$keyval is higher than lowerval=$lowerval",4); }
 
4304
        $val{$keyval}=$keytoadd;
 
4305
        my $valcursor=$lowerval;        # valcursor is value just before keyval
 
4306
        while ($nextval{$valcursor} && ($nextval{$valcursor} < $keyval)) { $valcursor=$nextval{$valcursor}; }
 
4307
        if ($nextval{$valcursor}) {     # keyval is between valcursor and nextval{valcursor}
 
4308
                $nextval{$keyval}=$nextval{$valcursor};
 
4309
        }
 
4310
        $nextval{$valcursor}=$keyval;
 
4311
        if ($Debug) { debug("  lowerval=$lowerval, nb elem val=".(scalar keys %val).", nb elem egal=".(scalar keys %egal).".",4); }
 
4312
}
 
4313
 
 
4314
#------------------------------------------------------------------------------
 
4315
# Function:     Remove a val from sorting tree
 
4316
# Parameters:   None
 
4317
# Input:        $lowerval %val %egal
 
4318
# Output:       None
 
4319
# Return:       None
 
4320
#------------------------------------------------------------------------------
 
4321
sub Removelowerval {
 
4322
        my $keytoremove=$val{$lowerval};        # This is lower key
 
4323
        if ($Debug) { debug("   remove for lowerval=$lowerval: key=$keytoremove",4); }
 
4324
        if ($egal{$keytoremove}) {
 
4325
                $val{$lowerval}=$egal{$keytoremove};
 
4326
                delete $egal{$keytoremove};
 
4327
        }
 
4328
        else {
 
4329
                delete $val{$lowerval};
 
4330
                $lowerval=$nextval{$lowerval};  # Set new lowerval
 
4331
        }
 
4332
        if ($Debug) { debug("   new lower value=$lowerval, val size=".(scalar keys %val).", egal size=".(scalar keys %egal),4); }
 
4333
}
 
4334
 
 
4335
#------------------------------------------------------------------------------
 
4336
# Function:     Build @keylist array
 
4337
# Parameters:   Size max for @keylist array,
 
4338
#               Min value in hash for select,
 
4339
#               Hash used for select,
 
4340
#               Hash used for order
 
4341
# Input:        None
 
4342
# Output:       None
 
4343
# Return:       @keylist response array
 
4344
#------------------------------------------------------------------------------
 
4345
sub BuildKeyList {
 
4346
        my $ArraySize=shift||error("System error. Call to BuildKeyList function with incorrect value for first param","","",1);
 
4347
        my $MinValue=shift||error("System error. Call to BuildKeyList function with incorrect value for second param","","",1);
 
4348
        my $hashforselect=shift;
 
4349
        my $hashfororder=shift;
 
4350
        if ($Debug) { debug(" BuildKeyList($ArraySize,$MinValue,$hashforselect with size=".(scalar keys %$hashforselect).",$hashfororder with size=".(scalar keys %$hashfororder).")",2); }
 
4351
        delete $hashforselect->{0};delete $hashforselect->{''};         # Those is to protect from infinite loop when hash array has an incorrect null key
 
4352
        my $count=0;
 
4353
        $lowerval=0;    # Global because used in AddInTree and Removelowerval
 
4354
        %val=(); %nextval=(); %egal=();
 
4355
        foreach my $key (keys %$hashforselect) {
 
4356
                if ($count < $ArraySize) {
 
4357
                        if ($hashforselect->{$key} >= $MinValue) {
 
4358
                                $count++;
 
4359
                                if ($Debug) { debug("  Add in tree entry $count : $key (value=".($hashfororder->{$key}||0).", tree not full)",4); }
 
4360
                                AddInTree($key,$hashfororder->{$key}||0,$count);
 
4361
                        }
 
4362
                        next;
 
4363
                }
 
4364
                $count++;
 
4365
                if (($hashfororder->{$key}||0)<=$lowerval) { next; }
 
4366
                if ($Debug) { debug("  Add in tree entry $count : $key (value=".($hashfororder->{$key}||0)." > lowerval=$lowerval)",4); }
 
4367
                AddInTree($key,$hashfororder->{$key}||0);
 
4368
                if ($Debug) { debug("  Removelower in tree",4); }
 
4369
                Removelowerval();
 
4370
        }
 
4371
 
 
4372
        # Build key list and sort it
 
4373
        if ($Debug) { debug("  Build key list and sort it. lowerval=$lowerval, nb elem val=".(scalar keys %val).", nb elem egal=".(scalar keys %egal).".",2); }
 
4374
        my %notsortedkeylist=();
 
4375
        foreach my $key (values %val) { $notsortedkeylist{$key}=1; }
 
4376
        foreach my $key (values %egal) { $notsortedkeylist{$key}=1; }
 
4377
        @keylist=();
 
4378
        @keylist=(sort {($hashfororder->{$b}||0) <=> ($hashfororder->{$a}||0) } keys %notsortedkeylist);
 
4379
        if ($Debug) { debug(" BuildKeyList End (keylist size=".(@keylist).")",2); }
 
4380
        return;
 
4381
}
 
4382
 
 
4383
#------------------------------------------------------------------------------
 
4384
# Function:     Lock or unlock update
 
4385
# Parameters:   status (1 to lock, 0 to unlock)
 
4386
# Input:        $DirLock (if status=0) $PROG $FileSuffix
 
4387
# Output:       $DirLock (if status=1)
 
4388
# Return:       None
 
4389
#------------------------------------------------------------------------------
 
4390
sub Lock_Update {
 
4391
        my $status=shift;
 
4392
        my $lock="$PROG$FileSuffix.lock";
 
4393
        if ($status) {
 
4394
                # We stop if there is at least one lock file wherever it is
 
4395
                foreach my $key ($ENV{"TEMP"},$ENV{"TMP"},"/tmp","/",".") {
 
4396
                        my $newkey =$key;
 
4397
                        $newkey =~ s/[\\\/]$//;
 
4398
                        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); }
 
4399
                }
 
4400
                # Set lock where we can
 
4401
                foreach my $key ($ENV{"TEMP"},$ENV{"TMP"},"/tmp","/",".") {
 
4402
                        if (! -d "$key") { next; }
 
4403
                        $DirLock=$key;
 
4404
                        $DirLock =~ s/[\\\/]$//;
 
4405
                        if ($Debug) { debug("Update lock file $DirLock/$lock is set"); }
 
4406
                        open(LOCK,">$DirLock/$lock") || error("Failed to create lock file $DirLock/$lock","","",1);
 
4407
                        print LOCK "AWStats update started by process $$ at $nowyear-$nowmonth-$nowday $nowhour:$nowmin:$nowsec\n";
 
4408
                        close(LOCK);
 
4409
                        last;
 
4410
                }
 
4411
        }
 
4412
        else {
 
4413
                # Remove lock
 
4414
                if ($Debug) { debug("Update lock file $DirLock/$lock is removed"); }
 
4415
                unlink("$DirLock/$lock");
 
4416
        }
 
4417
        return;
 
4418
}
 
4419
 
 
4420
#------------------------------------------------------------------------------
 
4421
# Function:     Signal handler to call Lock_Update to remove lock file
 
4422
# Parameters:   Signal name
 
4423
# Input:        None
 
4424
# Output:       None
 
4425
# Return:       None
 
4426
#------------------------------------------------------------------------------
 
4427
sub SigHandler {
 
4428
        my $signame = shift;
 
4429
        print ucfirst($PROG)." process (ID $$) interrupted by signal $signame.\n";
 
4430
        &Lock_Update(0);
 
4431
        exit 1;
 
4432
}
 
4433
 
 
4434
#------------------------------------------------------------------------------
 
4435
# Function:     Convert an IPAddress into an integer
 
4436
# Parameters:   IPAddress
 
4437
# Input:        None
 
4438
# Output:       None
 
4439
# Return:       Int
 
4440
#------------------------------------------------------------------------------
 
4441
sub Convert_IP_To_Decimal {
 
4442
        my ($IPAddress) = @_;
 
4443
        my @ip_seg_arr = split(/\./,$IPAddress);
 
4444
        my $decimal_ip_address = 256 * 256 *256 * $ip_seg_arr[0] + 256 * 256 * $ip_seg_arr[1] + 256 * $ip_seg_arr[2] + $ip_seg_arr[3];
 
4445
        return($decimal_ip_address);
 
4446
}
 
4447
 
 
4448
#------------------------------------------------------------------------------
 
4449
# Function:     Test there is at least on value in list not null
 
4450
# Parameters:   List of values
 
4451
# Input:        None
 
4452
# Output:       None
 
4453
# Return:       1 There is at least one not null value, 0 else
 
4454
#------------------------------------------------------------------------------
 
4455
sub AtLeastOneNotNull {
 
4456
        if ($Debug) { debug(" Call to AtLeastOneNotNull (".join('-',@_).")",3); }
 
4457
        foreach my $val (@_) { if ($val) { return 1; } }
 
4458
        return 0;
 
4459
}
 
4460
 
 
4461
#------------------------------------------------------------------------------
 
4462
# Function:     Insert a form filter
 
4463
# Parameters:   Name of filter field, default for filter field, default for exclude filter field
 
4464
# Input:        $StaticLinks, $QueryString, $SiteConfig, $DirConfig
 
4465
# Output:       HTML Form
 
4466
# Return:       None
 
4467
#------------------------------------------------------------------------------
 
4468
sub ShowFormFilter {
 
4469
        my $fieldfiltername=shift;
 
4470
        my $fieldfilterinvalue=shift;
 
4471
        my $fieldfilterexvalue=shift;
 
4472
        if (! $StaticLinks) {
 
4473
                my $NewLinkParams=${QueryString};
 
4474
                $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
4475
                $NewLinkParams =~ s/(^|&)output(=\w*|$)//i;
 
4476
                $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
4477
                $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
4478
                if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
4479
                print "\n<form name=\"FormFilter\" action=\"".XMLEncode("$AWScript?${NewLinkParams}")."\" class=\"aws_border\">\n";
 
4480
                print "<table valign=\"middle\" width=\"99%\" border=\"0\" cellspacing=\"0\" cellpadding=\"2\"><tr>\n";
 
4481
                print "<td align=\"left\" width=\"50\">$Message[79]&nbsp;:</td>\n";
 
4482
                print "<td align=\"left\" width=\"100\"><input type=\"text\" name=\"${fieldfiltername}\" value=\"$fieldfilterinvalue\" class=\"aws_formfield\" /></td>\n";
 
4483
                print "<td> &nbsp; </td>";
 
4484
                print "<td align=\"left\" width=\"100\">$Message[153]&nbsp;:</td>\n";
 
4485
                print "<td align=\"left\" width=\"100\"><input type=\"text\" name=\"${fieldfiltername}ex\" value=\"$fieldfilterexvalue\" class=\"aws_formfield\" /></td>\n";
 
4486
                print "<td>";
 
4487
                print "<input type=\"hidden\" name=\"output\" value=\"".join(',',keys %HTMLOutput)."\" />\n";
 
4488
                if ($SiteConfig) { print "<input type=\"hidden\" name=\"config\" value=\"$SiteConfig\" />\n"; }
 
4489
                if ($DirConfig)  { print "<input type=\"hidden\" name=\"configdir\" value=\"$DirConfig\" />\n"; }
 
4490
                if ($QueryString =~ /(^|&)year=(\d\d\d\d)/i) { print "<input type=\"hidden\" name=\"year\" value=\"$2\" />\n"; }
 
4491
                if ($QueryString =~ /(^|&)month=(\d\d)/i || $QueryString =~ /(^|&)month=(all)/i) { print "<input type=\"hidden\" name=\"month\" value=\"$2\" />\n"; }
 
4492
                if ($QueryString =~ /(^|&)lang=(\w+)/i) { print "<input type=\"hidden\" name=\"lang\" value=\"$2\" />\n"; }
 
4493
                if ($QueryString =~ /(^|&)debug=(\d+)/i) { print "<input type=\"hidden\" name=\"debug\" value=\"$2\" />\n"; }
 
4494
                if ($QueryString =~ /(^|&)framename=(\w+)/i) { print "<input type=\"hidden\" name=\"framename\" value=\"$2\" />\n"; }
 
4495
                print "<input type=\"submit\" value=\" $Message[115] \" class=\"aws_button\" /></td>\n";
 
4496
                print "<td> &nbsp; </td>";
 
4497
                print "</tr></table>\n";
 
4498
                print "</form>\n";
 
4499
                print "<br />\n";
 
4500
                print "\n";
 
4501
        }
 
4502
}
 
4503
 
 
4504
#------------------------------------------------------------------------------
 
4505
# Function:     Write other user info (with help of plugin)
 
4506
# Parameters:   $user
 
4507
# Input:        $SiteConfig
 
4508
# Output:       URL link
 
4509
# Return:       None
 
4510
#------------------------------------------------------------------------------
 
4511
sub ShowUserInfo {
 
4512
        my $user=shift;
 
4513
        # Call to plugins' function ShowInfoUser
 
4514
        foreach my $pluginname (keys %{$PluginsLoaded{'ShowInfoUser'}})  {
 
4515
                my $function="ShowInfoUser_$pluginname('$user')";
 
4516
                eval("$function");
 
4517
        }
 
4518
}
 
4519
 
 
4520
#------------------------------------------------------------------------------
 
4521
# Function:     Write other host info (with help of plugin)
 
4522
# Parameters:   $host
 
4523
# Input:        $LinksToWhoIs $LinksToWhoIsIp
 
4524
# Output:       None
 
4525
# Return:       None
 
4526
#------------------------------------------------------------------------------
 
4527
sub ShowHostInfo {
 
4528
        my $host=shift;
 
4529
        # Call to plugins' function ShowInfoHost
 
4530
        foreach my $pluginname (keys %{$PluginsLoaded{'ShowInfoHost'}})  {
 
4531
                my $function="ShowInfoHost_$pluginname('$host')";
 
4532
                eval("$function");
 
4533
        }
 
4534
}
 
4535
 
 
4536
#------------------------------------------------------------------------------
 
4537
# Function:     Write other url info (with help of plugin)
 
4538
# Parameters:   $url
 
4539
# Input:        %Aliases $MaxLengthOfShownURL $ShowLinksOnUrl $SiteDomain $UseHTTPSLinkForUrl
 
4540
# Output:       URL link
 
4541
# Return:       None
 
4542
#------------------------------------------------------------------------------
 
4543
sub ShowURLInfo {
 
4544
        my $url=shift;
 
4545
        my $nompage=CleanFromCSSA($url);
 
4546
 
 
4547
        # Call to plugins' function ShowInfoURL
 
4548
        foreach my $pluginname (keys %{$PluginsLoaded{'ShowInfoURL'}})  {
 
4549
                my $function="ShowInfoURL_$pluginname('$url')";
 
4550
                eval("$function");
 
4551
        }
 
4552
 
 
4553
        if (length($nompage)>$MaxLengthOfShownURL) { $nompage=substr($nompage,0,$MaxLengthOfShownURL)."..."; }
 
4554
        if ($ShowLinksOnUrl) {
 
4555
                my $newkey=CleanFromCSSA($url);
 
4556
                if ($LogType eq 'W' || $LogType eq 'S') {               # Web or streaming log file
 
4557
                        if ($newkey =~ /^http(s|):/i) { # URL seems to be extracted from a proxy log file
 
4558
                                print "<a href=\"".XMLEncode("$newkey")."\" target=\"url\">".XMLEncode($nompage)."</a>";
 
4559
                        }
 
4560
                        elsif ($newkey =~ /^\//) {              # URL seems to be an url extracted from a web or wap server log file
 
4561
                                $newkey =~ s/^\/$SiteDomain//i;
 
4562
                                # Define urlprot
 
4563
                                my $urlprot='http';
 
4564
                                if ($UseHTTPSLinkForUrl && $newkey =~ /^$UseHTTPSLinkForUrl/) { $urlprot='https'; }
 
4565
                                print "<a href=\"".XMLEncode("$urlprot://$SiteDomain$newkey\"")." target=\"url\">".XMLEncode($nompage)."</a>";
 
4566
                        }
 
4567
                        else {
 
4568
                                print XMLEncode($nompage);
 
4569
                        }
 
4570
                }
 
4571
                elsif ($LogType eq 'F') {       # Ftp log file
 
4572
                        print XMLEncode($nompage);
 
4573
                }
 
4574
                elsif ($LogType eq 'M') {       # Smtp log file
 
4575
                        print XMLEncode($nompage);
 
4576
                }
 
4577
                else {                                          # Other type log file
 
4578
                        print XMLEncode($nompage);
 
4579
                }
 
4580
        }
 
4581
        else {
 
4582
                print XMLEncode($nompage);
 
4583
        }
 
4584
}
 
4585
 
 
4586
#------------------------------------------------------------------------------
 
4587
# Function:     Define value for PerlParsingFormat (used for regex log record parsing)
 
4588
# Parameters:   -
 
4589
# Input:        $LogFormat
 
4590
# Output:       @fieldlib
 
4591
# Return:       -
 
4592
#------------------------------------------------------------------------------
 
4593
sub DefinePerlParsingFormat {
 
4594
        # Log records examples:
 
4595
        # Apache combined: 62.161.78.73 user - [dd/mmm/yyyy:hh:mm:ss +0000] "GET / HTTP/1.1" 200 1234 "http://www.from.com/from.htm" "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"
 
4596
        # Apache combined (408 error): my.domain.com - user [09/Jan/2001:11:38:51 -0600] "OPTIONS /mime-tmp/xxx file.doc HTTP/1.1" 408 - "-" "-"
 
4597
        # Apache combined (408 error): 62.161.78.73 user - [dd/mmm/yyyy:hh:mm:ss +0000] "-" 408 - "-" "-"
 
4598
        # Apache common_with_mod_gzip_info1: %h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_compression_ratio}npct.
 
4599
        # Apache common_with_mod_gzip_info2: %h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n:%{mod_gzip_compression_ratio}npct.
 
4600
        # Apache deflate: %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" (%{ratio}n)
 
4601
        # IIS: 2000-07-19 14:14:14 62.161.78.73 - GET / 200 1234 HTTP/1.1 Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0) http://www.from.com/from.htm
 
4602
        # WebStar: 05/21/00     00:17:31        OK      200     212.242.30.6    Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)  http://www.cover.dk/    "www.cover.dk"  :Documentation:graphics:starninelogo.white.gif  1133
 
4603
        # Squid extended: 12.229.91.170 - - [27/Jun/2002:03:30:50 -0700] "GET http://www.callistocms.com/images/printable.gif HTTP/1.1" 304 354 "-" "Mozilla/5.0 Galeon/1.0.3 (X11; Linux i686; U;) Gecko/0" TCP_REFRESH_HIT:DIRECT
 
4604
        if ($Debug) { debug("Call To DefinePerlParsingFormat (LogType='$LogType', LogFormat='$LogFormat')"); }
 
4605
        @fieldlib=();
 
4606
        if ($LogFormat =~ /^[1-6]$/) {  # Pre-defined log format
 
4607
                if ($LogFormat eq '1' || $LogFormat eq '6') {   # Same than "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"".
 
4608
                        # %u (user) is "([^\\[]+)" instead of "[^ ]+" because can contain space (Lotus Notes). referer and ua might be "".
 
4609
#                       $PerlParsingFormat="([^ ]+) [^ ]+ ([^\\[]+) \\[([^ ]+) [^ ]+\\] \\\"([^ ]+) (.+) [^\\\"]+\\\" ([\\d|-]+) ([\\d|-]+) \\\"(.*?)\\\" \\\"([^\\\"]*)\\\"";
 
4610
                        $PerlParsingFormat="([^ ]+) [^ ]+ ([^\\[]+) \\[([^ ]+) [^ ]+\\] \\\"([^ ]+) ([^ ]+) [^\\\"]+\\\" ([\\d|-]+) ([\\d|-]+) \\\"(.*?)\\\" \\\"([^\\\"]*)\\\"";
 
4611
                        $pos_host=0;$pos_logname=1;$pos_date=2;$pos_method=3;$pos_url=4;$pos_code=5;$pos_size=6;$pos_referer=7;$pos_agent=8;
 
4612
                        @fieldlib=('host','logname','date','method','url','code','size','referer','ua');
 
4613
                }
 
4614
                elsif ($LogFormat eq '2') {     # Same than "date time c-ip cs-username cs-method cs-uri-stem sc-status sc-bytes cs-version cs(User-Agent) cs(Referer)"
 
4615
                        $PerlParsingFormat="(\\S+ \\S+) (\\S+) (\\S+) (\\S+) (\\S+) ([\\d|-]+) ([\\d|-]+) \\S+ (\\S+) (\\S+)";
 
4616
                        $pos_date=0;$pos_host=1;$pos_logname=2;$pos_method=3;$pos_url=4;$pos_code=5;$pos_size=6;$pos_agent=7;$pos_referer=8;
 
4617
                        @fieldlib=('date','host','logname','method','url','code','size','ua','referer');
 
4618
                }
 
4619
                elsif ($LogFormat eq '3') {
 
4620
                        $PerlParsingFormat="([^\\t]*\\t[^\\t]*)\\t([^\\t]*)\\t([\\d|-]*)\\t([^\\t]*)\\t([^\\t]*)\\t([^\\t]*)\\t[^\\t]*\\t([^\\t]*)\\t([\\d]*)";
 
4621
                        $pos_date=0;$pos_method=1;$pos_code=2;$pos_host=3;$pos_agent=4;$pos_referer=5;$pos_url=6;$pos_size=7;
 
4622
                        @fieldlib=('date','method','code','host','ua','referer','url','size');
 
4623
                }
 
4624
                elsif ($LogFormat eq '4') {     # Same than "%h %l %u %t \"%r\" %>s %b"
 
4625
                        # %u (user) is "(.+)" instead of "[^ ]+" because can contain space (Lotus Notes).
 
4626
                        $PerlParsingFormat="([^ ]+) [^ ]+ (.+) \\[([^ ]+) [^ ]+\\] \\\"([^ ]+) ([^ ]+) [^\\\"]+\\\" ([\\d|-]+) ([\\d|-]+)";
 
4627
                        $pos_host=0;$pos_logname=1;$pos_date=2;$pos_method=3;$pos_url=4;$pos_code=5;$pos_size=6;
 
4628
                        @fieldlib=('host','logname','date','method','url','code','size');
 
4629
                }
 
4630
                # This is a deprecated option, will be removed in a next version.
 
4631
                elsif ($LogFormat eq '5') {     # Same than "c-ip cs-username c-agent sc-authenticated date time s-svcname s-computername cs-referred r-host r-ip r-port time-taken cs-bytes sc-bytes cs-protocol cs-transport s-operation cs-uri cs-mime-type s-object-source sc-status s-cache-info"
 
4632
                        $PerlParsingFormat="([^\\t]*)\\t([^\\t]*)\\t([^\\t]*)\\t[^\\t]*\\t([^\\t]*\\t[^\\t]*)\\t[^\\t]*\\t[^\\t]*\\t([^\\t]*)\\t[^\\t]*\\t[^\\t]*\\t[^\\t]*\\t[^\\t]*\\t[^\\t]*\\t([^\\t]*)\\t[^\\t]*\\t[^\\t]*\\t([^\\t]*)\\t([^\\t]*)\\t[^\\t]*\\t[^\\t]*\\t([^\\t]*)\\t[^\\t]*";
 
4633
                        $pos_host=0;$pos_logname=1;$pos_agent=2;$pos_date=3;$pos_referer=4;$pos_size=5;$pos_method=6;$pos_url=7;$pos_code=8;
 
4634
                        @fieldlib=('host','logname','ua','date','referer','size','method','url','code');
 
4635
                }
 
4636
        }
 
4637
        else {                                                  # Personalized log format
 
4638
                my $LogFormatString=$LogFormat;
 
4639
                # Replacement for Notes format string that are not Apache
 
4640
                $LogFormatString =~ s/%vh/%virtualname/g;
 
4641
                # Replacement for Apache format string
 
4642
                $LogFormatString =~ s/%v(\s)/%virtualname$1/g; $LogFormatString =~ s/%v$/%virtualname/g;
 
4643
                $LogFormatString =~ s/%h(\s)/%host$1/g; $LogFormatString =~ s/%h$/%host/g;
 
4644
                $LogFormatString =~ s/%l(\s)/%other$1/g; $LogFormatString =~ s/%l$/%other/g;
 
4645
                $LogFormatString =~ s/\"%u\"/%lognamequot/g;
 
4646
                $LogFormatString =~ s/%u(\s)/%logname$1/g; $LogFormatString =~ s/%u$/%logname/g;
 
4647
                $LogFormatString =~ s/%t(\s)/%time1$1/g; $LogFormatString =~ s/%t$/%time1/g;
 
4648
                $LogFormatString =~ s/\"%r\"/%methodurl/g;
 
4649
                $LogFormatString =~ s/%>s/%code/g;
 
4650
                $LogFormatString =~ s/%b(\s)/%bytesd$1/g;       $LogFormatString =~ s/%b$/%bytesd/g;
 
4651
                $LogFormatString =~ s/\"%{Referer}i\"/%refererquot/g;
 
4652
                $LogFormatString =~ s/\"%{User-Agent}i\"/%uaquot/g;
 
4653
                $LogFormatString =~ s/%{mod_gzip_input_size}n/%gzipin/g;
 
4654
                $LogFormatString =~ s/%{mod_gzip_output_size}n/%gzipout/g;
 
4655
                $LogFormatString =~ s/%{mod_gzip_compression_ratio}n/%gzipratio/g;
 
4656
                $LogFormatString =~ s/\(%{ratio}n\)/%deflateratio/g;
 
4657
                # Replacement for a IIS and ISA format string
 
4658
                $LogFormatString =~ s/cs-uri-query/%query/g;    # Must be before cs-uri
 
4659
                $LogFormatString =~ s/date\stime/%time2/g;
 
4660
                $LogFormatString =~ s/c-ip/%host/g;
 
4661
                $LogFormatString =~ s/cs-username/%logname/g;
 
4662
                $LogFormatString =~ s/cs-method/%method/g;              # GET, POST, SMTP, RETR STOR
 
4663
                $LogFormatString =~ s/cs-uri-stem/%url/g; $LogFormatString =~ s/cs-uri/%url/g;
 
4664
                $LogFormatString =~ s/sc-status/%code/g;
 
4665
                $LogFormatString =~ s/sc-bytes/%bytesd/g;
 
4666
                $LogFormatString =~ s/cs-version/%other/g;              # Protocol
 
4667
                $LogFormatString =~ s/cs\(User-Agent\)/%ua/g; $LogFormatString =~ s/c-agent/%ua/g;
 
4668
                $LogFormatString =~ s/cs\(Referer\)/%referer/g; $LogFormatString =~ s/cs-referred/%referer/g;
 
4669
                $LogFormatString =~ s/sc-authenticated/%other/g;
 
4670
                $LogFormatString =~ s/s-svcname/%other/g;
 
4671
                $LogFormatString =~ s/s-computername/%other/g;
 
4672
                $LogFormatString =~ s/r-host/%virtualname/g;
 
4673
                $LogFormatString =~ s/r-ip/%other/g;
 
4674
                $LogFormatString =~ s/r-port/%other/g;
 
4675
                $LogFormatString =~ s/time-taken/%other/g;
 
4676
                $LogFormatString =~ s/cs-bytes/%other/g;
 
4677
                $LogFormatString =~ s/cs-protocol/%other/g;
 
4678
                $LogFormatString =~ s/cs-transport/%other/g;
 
4679
                $LogFormatString =~ s/s-operation/%method/g;    # GET, POST, SMTP, RETR STOR
 
4680
                $LogFormatString =~ s/cs-mime-type/%other/g;
 
4681
                $LogFormatString =~ s/s-object-source/%other/g;
 
4682
                $LogFormatString =~ s/s-cache-info/%other/g;
 
4683
                # Added for MMS
 
4684
                $LogFormatString =~ s/protocol/%protocolmms/g;  # cs-method might not be available
 
4685
                $LogFormatString =~ s/c-status/%codemms/g;              # c-status used when sc-status not available
 
4686
                if ($Debug) { debug(" LogFormatString=$LogFormatString"); }
 
4687
                # $LogFormatString has an AWStats format, so we can generate PerlParsingFormat variable
 
4688
                my $i = 0;
 
4689
                my $LogSeparatorWithoutStar=$LogSeparator; $LogSeparatorWithoutStar =~ s/[\*\+]//g;
 
4690
                foreach my $f (split(/\s+/,$LogFormatString)) {
 
4691
                        # Add separator for next field
 
4692
                        if ($PerlParsingFormat) { $PerlParsingFormat.="$LogSeparator"; }
 
4693
                        # Special for logname
 
4694
                        if ($f =~ /%lognamequot$/) {
 
4695
                                $pos_logname = $i; $i++; push @fieldlib, 'logname';
 
4696
                                $PerlParsingFormat .= "\\\"?([^\\\"]*)\\\"?";                   # logname can be "value", "" and - in same log (Lotus notes)
 
4697
                        }
 
4698
                        # Date format
 
4699
                        elsif ($f =~ /%time1$/ || $f =~ /%time1b$/) {   # [dd/mmm/yyyy:hh:mm:ss +0000] ou [dd/mmm/yyyy:hh:mm:ss],  time1b kept for backward compatibility
 
4700
                                $pos_date = $i; $i++; push @fieldlib, 'date';
 
4701
                                $pos_tz = $i; $i++; push @fieldlib, 'tz';
 
4702
                                $PerlParsingFormat .= "\\[([^$LogSeparatorWithoutStar]+)( [^$LogSeparatorWithoutStar]+)?\\]";
 
4703
                        }
 
4704
                        elsif ($f =~ /%time2$/) {       # yyyy-mm-dd hh:mm:ss
 
4705
                                $pos_date = $i; $i++; push @fieldlib, 'date';
 
4706
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+\\s[^$LogSeparatorWithoutStar]+)";  # Need \s for Exchange log files
 
4707
                        }
 
4708
                        elsif ($f =~ /%time3$/) {       # mon d hh:mm:ss
 
4709
                                $pos_date = $i; $i++; push @fieldlib, 'date';
 
4710
                                $PerlParsingFormat .= "(\\w\\w\\w \\s??\\d+ \\d\\d:\\d\\d:\\d\\d)";
 
4711
                        }
 
4712
                        # Special for methodurl and methodurlnoprot
 
4713
                        elsif ($f =~ /%methodurl$/) {
 
4714
                                $pos_method = $i; $i++; push @fieldlib, 'method';
 
4715
                                $pos_url = $i; $i++; push @fieldlib, 'url';
 
4716
                                $PerlParsingFormat .= "\\\"([^$LogSeparatorWithoutStar]+) ([^$LogSeparatorWithoutStar]+) [^\\\"]+\\\"";
 
4717
                        }
 
4718
                        elsif ($f =~ /%methodurlnoprot$/) {
 
4719
                                $pos_method = $i; $i++; push @fieldlib, 'method';
 
4720
                                $pos_url = $i; $i++; push @fieldlib, 'url';
 
4721
                                $PerlParsingFormat .= "\\\"([^$LogSeparatorWithoutStar]+) ([^$LogSeparatorWithoutStar]+)\\\"";
 
4722
                        }
 
4723
                        # Common command tags
 
4724
                        elsif ($f =~ /%virtualname$/) {
 
4725
                                $pos_vh = $i; $i++; push @fieldlib, 'vhost';
 
4726
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4727
                        }
 
4728
                        elsif ($f =~ /%host_r$/) {
 
4729
                                $pos_hostr = $i; $i++; push @fieldlib, 'hostr';
 
4730
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4731
                        }
 
4732
                        elsif ($f =~ /%host$/) {
 
4733
                                $pos_host = $i; $i++; push @fieldlib, 'host';
 
4734
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4735
                        }
 
4736
                        elsif ($f =~ /%logname$/) {
 
4737
                                $pos_logname = $i; $i++; push @fieldlib, 'logname';
 
4738
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4739
                        }
 
4740
                        elsif ($f =~ /%method$/) {
 
4741
                                $pos_method = $i; $i++; push @fieldlib, 'method';
 
4742
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4743
                        }
 
4744
                        elsif ($f =~ /%url$/) {
 
4745
                                $pos_url = $i; $i++; push @fieldlib, 'url';
 
4746
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4747
                        }
 
4748
                        elsif ($f =~ /%query$/) {
 
4749
                                $pos_query = $i; $i++; push @fieldlib, 'query';
 
4750
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4751
                        }
 
4752
                        elsif ($f =~ /%code$/) {
 
4753
                                $pos_code = $i; $i++; push @fieldlib, 'code';
 
4754
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4755
                        }
 
4756
                        elsif ($f =~ /%bytesd$/) {
 
4757
                                $pos_size = $i; $i++; push @fieldlib, 'size';
 
4758
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4759
                        }
 
4760
                        elsif ($f =~ /%refererquot$/) {
 
4761
                                $pos_referer = $i; $i++; push @fieldlib, 'referer';
 
4762
                                $PerlParsingFormat .= "\\\"([^\\\"]*)\\\"";             # referer might be ""
 
4763
                        }
 
4764
                        elsif ($f =~ /%referer$/) {
 
4765
                                $pos_referer = $i; $i++; push @fieldlib, 'referer';
 
4766
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4767
                        }
 
4768
                        elsif ($f =~ /%uaquot$/) {
 
4769
                                $pos_agent = $i; $i++; push @fieldlib, 'ua';
 
4770
                                $PerlParsingFormat .= "\\\"([^\\\"]*)\\\"";                     # ua might be ""
 
4771
                        }
 
4772
                        elsif ($f =~ /%uabracket$/) {
 
4773
                                $pos_agent = $i; $i++; push @fieldlib, 'ua';
 
4774
                                $PerlParsingFormat .= "\\\[([^\\\]]*)\\\]";             # ua might be []
 
4775
                        }
 
4776
                        elsif ($f =~ /%ua$/) {
 
4777
                                $pos_agent = $i; $i++; push @fieldlib, 'ua';
 
4778
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4779
                        }
 
4780
                        elsif ($f =~ /%gzipin$/ ) {
 
4781
                                $pos_gzipin=$i;$i++; push @fieldlib, 'gzipin';
 
4782
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4783
                        }
 
4784
                        elsif ($f =~ /%gzipout/ ) {             # Compare $f to /%gzipout/ and not to /%gzipout$/ like other fields
 
4785
                                $pos_gzipout=$i;$i++; push @fieldlib, 'gzipout';
 
4786
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4787
                        }
 
4788
                        elsif ($f =~ /%gzipratio/ ) {   # Compare $f to /%gzipratio/ and not to /%gzipratio$/ like other fields
 
4789
                                $pos_compratio=$i;$i++; push @fieldlib, 'gzipratio';
 
4790
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4791
                        }
 
4792
                        elsif ($f =~ /%deflateratio/ ) {        # Compare $f to /%deflateratio/ and not to /%deflateratio$/ like other fields
 
4793
                                $pos_compratio=$i;$i++; push @fieldlib, 'deflateratio';
 
4794
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4795
                        }
 
4796
                        elsif ($f =~ /%email_r$/) {
 
4797
                                $pos_emailr = $i; $i++; push @fieldlib, 'email_r';
 
4798
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4799
                        }
 
4800
                        elsif ($f =~ /%email$/) {
 
4801
                                $pos_emails = $i; $i++; push @fieldlib, 'email';
 
4802
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4803
                        }
 
4804
                        elsif ($f =~ /%cluster$/) {
 
4805
                                $pos_cluster = $i; $i++; push @fieldlib, 'clusternb';
 
4806
                                $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4807
                        }
 
4808
                        # Special for protocolmms, used for method if method not already found (for MMS)
 
4809
                        elsif ($f =~ /%protocolmms$/) {
 
4810
                                if ($pos_method < 0) {
 
4811
                                        $pos_method = $i; $i++; push @fieldlib, 'method';
 
4812
                                        $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4813
                                }
 
4814
                        }
 
4815
                        # Special for codemms, used for code only if code not already found (for MMS)
 
4816
                        elsif ($f =~ /%codemms$/) {
 
4817
                                if ($pos_code < 0) {
 
4818
                                        $pos_code = $i; $i++; push @fieldlib, 'code';
 
4819
                                        $PerlParsingFormat .= "([^$LogSeparatorWithoutStar]+)";
 
4820
                                }
 
4821
                        }
 
4822
                        # Other tag
 
4823
                        elsif ($f =~ /%other$/) {
 
4824
                                $PerlParsingFormat .= "[^$LogSeparatorWithoutStar]+";
 
4825
                        }
 
4826
                        elsif ($f =~ /%otherquot$/) {
 
4827
                                $PerlParsingFormat .= "\\\"[^\\\"]*\\\"";
 
4828
                        }
 
4829
                        # Unknown tag (no parenthesis)
 
4830
                        else {
 
4831
                                $PerlParsingFormat .= "[^$LogSeparatorWithoutStar]+";
 
4832
                        }
 
4833
                }
 
4834
                if (! $PerlParsingFormat) { error("No recognized format tag in personalized LogFormat string"); }
 
4835
        }
 
4836
        if ($pos_host < 0) { error("Your personalized LogFormat does not include all fields required by AWStats (Add \%host in your LogFormat string)."); }
 
4837
        if ($pos_date < 0) { error("Your personalized LogFormat does not include all fields required by AWStats (Add \%time1 or \%time2 in your LogFormat string)."); }
 
4838
        if ($pos_method < 0) { error("Your personalized LogFormat does not include all fields required by AWStats (Add \%methodurl or \%method in your LogFormat string)."); }
 
4839
        if ($pos_url < 0) { error("Your personalized LogFormat does not include all fields required by AWStats (Add \%methodurl or \%url in your LogFormat string)."); }
 
4840
        if ($pos_code < 0) { error("Your personalized LogFormat does not include all fields required by AWStats (Add \%code in your LogFormat string)."); }
 
4841
        if ($pos_size < 0) { error("Your personalized LogFormat does not include all fields required by AWStats (Add \%bytesd in your LogFormat string)."); }
 
4842
        $PerlParsingFormat=qr/^$PerlParsingFormat/;
 
4843
        if ($Debug) { debug(" PerlParsingFormat is $PerlParsingFormat"); }
 
4844
}
 
4845
 
 
4846
 
 
4847
sub ShowEmailSendersChart {
 
4848
        my $NewLinkParams=shift;
 
4849
        my $NewLinkTarget=shift;
 
4850
        my $MaxLengthOfShownEMail=48;
 
4851
 
 
4852
        my $total_p;my $total_h;my $total_k;
 
4853
        my $max_p;my $max_h;my $max_k;
 
4854
        my $rest_p;my $rest_h;my $rest_k;
 
4855
 
 
4856
        # Show filter form
 
4857
        #&ShowFormFilter("emailsfilter",$EmailsFilter);
 
4858
        # Show emails list
 
4859
 
 
4860
        print "$Center<a name=\"emailsenders\">&nbsp;</a><br />\n";
 
4861
        my $title;
 
4862
        if ($HTMLOutput{'allemails'} || $HTMLOutput{'lastemails'}) {
 
4863
                $title="$Message[131]";
 
4864
        }
 
4865
        else {
 
4866
                $title="$Message[131] ($Message[77] $MaxNbOf{'EMailsShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allemails"):"$PROG$StaticLinks.allemails.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>";
 
4867
                if ($ShowEMailSenders =~ /L/i) { $title.=" &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastemails"):"$PROG$StaticLinks.lastemails.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>"; }
 
4868
        }
 
4869
        &tab_head("$title",19,0,'emailsenders');
 
4870
        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"3\">$Message[131] : ".(scalar keys %_emails_h)."</th>";
 
4871
        if ($ShowEMailSenders =~ /H/i) { print "<th rowspan=\"2\" bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
4872
        if ($ShowEMailSenders =~ /B/i) { print "<th rowspan=\"2\" bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
4873
        if ($ShowEMailSenders =~ /M/i) { print "<th rowspan=\"2\" bgcolor=\"#$color_k\" width=\"80\">$Message[106]</th>"; }
 
4874
        if ($ShowEMailSenders =~ /L/i) { print "<th rowspan=\"2\" width=\"120\">$Message[9]</th>"; }
 
4875
        print "</tr>\n";
 
4876
        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th width=\"30%\">Local</th><th>&nbsp;</th><th width=\"30%\">External</th></tr>";
 
4877
        $total_p=$total_h=$total_k=0;
 
4878
        $max_h=1; foreach (values %_emails_h) { if ($_ > $max_h) { $max_h = $_; } }
 
4879
        $max_k=1; foreach (values %_emails_k) { if ($_ > $max_k) { $max_k = $_; } }
 
4880
        my $count=0;
 
4881
        if (! $HTMLOutput{'allemails'} && ! $HTMLOutput{'lastemails'}) { &BuildKeyList($MaxNbOf{'EMailsShown'},$MinHit{'EMail'},\%_emails_h,\%_emails_h); }
 
4882
        if ($HTMLOutput{'allemails'})  { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'EMail'},\%_emails_h,\%_emails_h); }
 
4883
        if ($HTMLOutput{'lastemails'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'EMail'},\%_emails_h,\%_emails_l); }
 
4884
        foreach my $key (@keylist) {
 
4885
                my $newkey=$key;
 
4886
                if (length($key)>$MaxLengthOfShownEMail) { $newkey=substr($key,0,$MaxLengthOfShownEMail)."..."; }
 
4887
                my $bredde_h=0;my $bredde_k=0;
 
4888
                if ($max_h > 0) { $bredde_h=int($BarWidth*$_emails_h{$key}/$max_h)+1; }
 
4889
                if ($max_k > 0) { $bredde_k=int($BarWidth*$_emails_k{$key}/$max_k)+1; }
 
4890
                print "<tr>";
 
4891
                my $direction=IsLocalEMail($key);
 
4892
                if ($direction > 0) { print "<td class=\"aws\">$newkey</td><td>-></td><td>&nbsp;</td>"; }
 
4893
                if ($direction == 0) { print "<td colspan=\"3\"><span style=\"color: #$color_other\">$newkey</span></td>"; }
 
4894
                if ($direction < 0) { print "<td class=\"aws\">&nbsp;</td><td><-</td><td>$newkey</td>"; }
 
4895
                if ($ShowEMailSenders =~ /H/i) { print "<td>$_emails_h{$key}</td>"; }
 
4896
                if ($ShowEMailSenders =~ /B/i) { print "<td>".Format_Bytes($_emails_k{$key})."</td>"; }
 
4897
                if ($ShowEMailSenders =~ /M/i) { print "<td>".Format_Bytes($_emails_k{$key}/($_emails_h{$key}||1))."</td>"; }
 
4898
                if ($ShowEMailSenders =~ /L/i) { print "<td>".($_emails_l{$key}?Format_Date($_emails_l{$key},1):'-')."</td>"; }
 
4899
                print "</tr>\n";
 
4900
                #$total_p += $_emails_p{$key};
 
4901
                $total_h += $_emails_h{$key};
 
4902
                $total_k += $_emails_k{$key};
 
4903
                $count++;
 
4904
        }
 
4905
        $rest_p=0;      # $rest_p=$TotalPages-$total_p;
 
4906
        $rest_h=$TotalHits-$total_h;
 
4907
        $rest_k=$TotalBytes-$total_k;
 
4908
        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other sender emails
 
4909
                print "<tr><td colspan=\"3\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
4910
                if ($ShowEMailSenders =~ /H/i) { print "<td>$rest_h</td>"; }
 
4911
                if ($ShowEMailSenders =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
4912
                if ($ShowEMailSenders =~ /M/i) { print "<td>".Format_Bytes($rest_k/($rest_h||1))."</td>"; }
 
4913
                if ($ShowEMailSenders =~ /L/i) { print "<td>&nbsp;</td>"; }
 
4914
                print "</tr>\n";
 
4915
        }
 
4916
        &tab_end;
 
4917
}
 
4918
 
 
4919
 
 
4920
sub ShowEmailReceiversChart {
 
4921
        my $NewLinkParams=shift;
 
4922
        my $NewLinkTarget=shift;
 
4923
        my $MaxLengthOfShownEMail=48;
 
4924
 
 
4925
        my $total_p;my $total_h;my $total_k;
 
4926
        my $max_p;my $max_h;my $max_k;
 
4927
        my $rest_p;my $rest_h;my $rest_k;
 
4928
 
 
4929
        # Show filter form
 
4930
        #&ShowFormFilter("emailrfilter",$EmailrFilter);
 
4931
        # Show emails list
 
4932
 
 
4933
        print "$Center<a name=\"emailreceivers\">&nbsp;</a><br />\n";
 
4934
        my $title;
 
4935
        if ($HTMLOutput{'allemailr'} || $HTMLOutput{'lastemailr'}) {
 
4936
                $title="$Message[132]";
 
4937
        }
 
4938
        else {
 
4939
                $title="$Message[132] ($Message[77] $MaxNbOf{'EMailsShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allemailr"):"$PROG$StaticLinks.allemailr.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>";
 
4940
                if ($ShowEMailReceivers =~ /L/i) { $title.=" &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastemailr"):"$PROG$StaticLinks.lastemailr.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>"; }
 
4941
        }
 
4942
        &tab_head("$title",19,0,'emailreceivers');
 
4943
        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"3\">$Message[132] : ".(scalar keys %_emailr_h)."</th>";
 
4944
        if ($ShowEMailReceivers =~ /H/i) { print "<th rowspan=\"2\" bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
4945
        if ($ShowEMailReceivers =~ /B/i) { print "<th rowspan=\"2\" bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
4946
        if ($ShowEMailReceivers =~ /M/i) { print "<th rowspan=\"2\" bgcolor=\"#$color_k\" width=\"80\">$Message[106]</th>"; }
 
4947
        if ($ShowEMailReceivers =~ /L/i) { print "<th rowspan=\"2\" width=\"120\">$Message[9]</th>"; }
 
4948
        print "</tr>\n";
 
4949
        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th width=\"30%\">Local</th><th>&nbsp;</th><th width=\"30%\">External</th></tr>";
 
4950
        $total_p=$total_h=$total_k=0;
 
4951
        $max_h=1; foreach (values %_emailr_h) { if ($_ > $max_h) { $max_h = $_; } }
 
4952
        $max_k=1; foreach (values %_emailr_k) { if ($_ > $max_k) { $max_k = $_; } }
 
4953
        my $count=0;
 
4954
        if (! $HTMLOutput{'allemailr'} && ! $HTMLOutput{'lastemailr'}) { &BuildKeyList($MaxNbOf{'EMailsShown'},$MinHit{'EMail'},\%_emailr_h,\%_emailr_h); }
 
4955
        if ($HTMLOutput{'allemailr'})  { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'EMail'},\%_emailr_h,\%_emailr_h); }
 
4956
        if ($HTMLOutput{'lastemailr'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'EMail'},\%_emailr_h,\%_emailr_l); }
 
4957
        foreach my $key (@keylist) {
 
4958
                my $newkey=$key;
 
4959
                if (length($key)>$MaxLengthOfShownEMail) { $newkey=substr($key,0,$MaxLengthOfShownEMail)."..."; }
 
4960
                my $bredde_h=0;my $bredde_k=0;
 
4961
                if ($max_h > 0) { $bredde_h=int($BarWidth*$_emailr_h{$key}/$max_h)+1; }
 
4962
                if ($max_k > 0) { $bredde_k=int($BarWidth*$_emailr_k{$key}/$max_k)+1; }
 
4963
                print "<tr>";
 
4964
                my $direction=IsLocalEMail($key);
 
4965
                if ($direction > 0) { print "<td class=\"aws\">$newkey</td><td><-</td><td>&nbsp;</td>"; }
 
4966
                if ($direction == 0) { print "<td colspan=\"3\"><span style=\"color: #$color_other\">$newkey</span></td>"; }
 
4967
                if ($direction < 0) { print "<td class=\"aws\">&nbsp;</td><td>-></td><td>$newkey</td>"; }
 
4968
                if ($ShowEMailReceivers =~ /H/i) { print "<td>$_emailr_h{$key}</td>"; }
 
4969
                if ($ShowEMailReceivers =~ /B/i) { print "<td>".Format_Bytes($_emailr_k{$key})."</td>"; }
 
4970
                if ($ShowEMailReceivers =~ /M/i) { print "<td>".Format_Bytes($_emailr_k{$key}/($_emailr_h{$key}||1))."</td>"; }
 
4971
                if ($ShowEMailReceivers =~ /L/i) { print "<td>".($_emailr_l{$key}?Format_Date($_emailr_l{$key},1):'-')."</td>"; }
 
4972
                print "</tr>\n";
 
4973
                #$total_p += $_emailr_p{$key};
 
4974
                $total_h += $_emailr_h{$key};
 
4975
                $total_k += $_emailr_k{$key};
 
4976
                $count++;
 
4977
        }
 
4978
        $rest_p=0;      # $rest_p=$TotalPages-$total_p;
 
4979
        $rest_h=$TotalHits-$total_h;
 
4980
        $rest_k=$TotalBytes-$total_k;
 
4981
        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other receiver emails
 
4982
                print "<tr><td colspan=\"3\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
4983
                if ($ShowEMailReceivers =~ /H/i) { print "<td>$rest_h</td>"; }
 
4984
                if ($ShowEMailReceivers =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
4985
                if ($ShowEMailReceivers =~ /M/i) { print "<td>".Format_Bytes($rest_k/($rest_h||1))."</td>"; }
 
4986
                if ($ShowEMailReceivers =~ /L/i) { print "<td>&nbsp;</td>"; }
 
4987
                print "</tr>\n";
 
4988
        }
 
4989
        &tab_end;
 
4990
}
 
4991
 
 
4992
 
 
4993
 
 
4994
#------------------------------------------------------------------------------
 
4995
# MAIN
 
4996
#------------------------------------------------------------------------------
 
4997
($DIR=$0) =~ s/([^\/\\]+)$//; ($PROG=$1) =~ s/\.([^\.]*)$//; $Extension=$1;
 
4998
$DIR||='.'; $DIR =~ s/([^\/\\])[\\\/]+$/$1/;
 
4999
 
 
5000
$starttime=time();
 
5001
 
 
5002
# Get current time (time when AWStats was started)
 
5003
($nowsec,$nowmin,$nowhour,$nowday,$nowmonth,$nowyear,$nowwday,$nowyday) = localtime($starttime);
 
5004
$nowweekofmonth=int($nowday/7);
 
5005
$nowweekofyear=int(($nowyday-1+6-($nowwday==0?6:$nowwday-1))/7)+1; if ($nowweekofyear > 52) { $nowweekofyear = 1; }
 
5006
$nowdaymod=$nowday%7;
 
5007
$nowwday++;
 
5008
$nowns=Time::Local::timegm(0,0,0,$nowday,$nowmonth,$nowyear);
 
5009
if ($nowdaymod <= $nowwday) { if (($nowwday != 7) || ($nowdaymod != 0)) { $nowweekofmonth=$nowweekofmonth+1; } }
 
5010
if ($nowdaymod >  $nowwday) { $nowweekofmonth=$nowweekofmonth+2; }
 
5011
# Change format of time variables
 
5012
$nowweekofmonth="0$nowweekofmonth";
 
5013
if ($nowweekofyear < 10) { $nowweekofyear = "0$nowweekofyear"; }
 
5014
if ($nowyear < 100) { $nowyear+=2000; } else { $nowyear+=1900; }
 
5015
$nowsmallyear=$nowyear;$nowsmallyear =~ s/^..//;
 
5016
if (++$nowmonth < 10) { $nowmonth = "0$nowmonth"; }
 
5017
if ($nowday < 10) { $nowday = "0$nowday"; }
 
5018
if ($nowhour < 10) { $nowhour = "0$nowhour"; }
 
5019
if ($nowmin < 10) { $nowmin = "0$nowmin"; }
 
5020
if ($nowsec < 10) { $nowsec = "0$nowsec"; }
 
5021
$nowtime=int($nowyear.$nowmonth.$nowday.$nowhour.$nowmin.$nowsec);
 
5022
# Get tomorrow time (will be used to discard some record with corrupted date (future date))
 
5023
my ($tomorrowsec,$tomorrowmin,$tomorrowhour,$tomorrowday,$tomorrowmonth,$tomorrowyear) = localtime($starttime+86400);
 
5024
if ($tomorrowyear < 100) { $tomorrowyear+=2000; } else { $tomorrowyear+=1900; }
 
5025
if (++$tomorrowmonth < 10) { $tomorrowmonth = "0$tomorrowmonth"; }
 
5026
if ($tomorrowday < 10) { $tomorrowday = "0$tomorrowday"; }
 
5027
if ($tomorrowhour < 10) { $tomorrowhour = "0$tomorrowhour"; }
 
5028
if ($tomorrowmin < 10) { $tomorrowmin = "0$tomorrowmin"; }
 
5029
if ($tomorrowsec < 10) { $tomorrowsec = "0$tomorrowsec"; }
 
5030
$tomorrowtime=int($tomorrowyear.$tomorrowmonth.$tomorrowday.$tomorrowhour.$tomorrowmin.$tomorrowsec);
 
5031
 
 
5032
# Allowed option
 
5033
my @AllowedCLIArgs=('migrate','config',
 
5034
'logfile','output','runascli','update',
 
5035
'staticlinks','staticlinksext','noloadplugin','loadplugin',
 
5036
'hostfilter','urlfilter','refererpagesfilter',
 
5037
'lang','month','year','framename','debug',
 
5038
'showsteps','showdropped','showcorrupted','showunknownorigin',
 
5039
'limitflush','confdir','updatefor',
 
5040
'hostfilter','hostfilterex','urlfilter','urlfilterex','refererpagesfilter','refererpagesfilterex',
 
5041
'pluginmode','filterrawlog');
 
5042
 
 
5043
$QueryString='';
 
5044
# AWStats use GATEWAY_INTERFACE to known if ran as CLI or CGI. AWSTATS_DEL_GATEWAY_INTERFACE can
 
5045
# be set to force AWStats to be ran as CLI even from a web page.
 
5046
if ($ENV{'AWSTATS_DEL_GATEWAY_INTERFACE'}) { $ENV{'GATEWAY_INTERFACE'}=''; }
 
5047
if ($ENV{'GATEWAY_INTERFACE'}) {        # Run from a browser as CGI
 
5048
        if ($BuildReportFormat eq 'xml') { print ($ENV{'HTTP_USER_AGENT'}=~/MSIE|Googlebot/i?"Content-type: text/html\n":"Content-type: text/xml\n"); }
 
5049
        else { print "Content-type: text/html\n"; }
 
5050
 
 
5051
        # Prepare QueryString
 
5052
        if ($ENV{'CONTENT_LENGTH'}) {
 
5053
                binmode STDIN;
 
5054
                read(STDIN, $QueryString, $ENV{'CONTENT_LENGTH'});
 
5055
        }
 
5056
        if ($ENV{'QUERY_STRING'}) { $QueryString = $ENV{'QUERY_STRING'}; }
 
5057
 
 
5058
        $QueryString = CleanFromCSSA($QueryString);
 
5059
        # No update but report by default when run from a browser
 
5060
        $UpdateStats=($QueryString=~/update=1/i?1:0);
 
5061
 
 
5062
        if ($QueryString =~ /config=([^&]+)/i)                          { $SiteConfig=&DecodeEncodedString("$1"); }
 
5063
        if ($QueryString =~ /logfile=([^&]+)/i)                         { $LogFile=&DecodeEncodedString("$1"); }
 
5064
        if ($QueryString =~ /diricons=([^&]+)/i)                        { $DirIcons=&DecodeEncodedString("$1"); }
 
5065
        if ($QueryString =~ /pluginmode=([^&]+)/i)                      { $PluginMode=&DecodeEncodedString("$1"); }
 
5066
        if ($QueryString =~ /configdir=([^&]+)/i)                       { $DirConfig=&DecodeEncodedString("$1"); }
 
5067
        # All filters
 
5068
        if ($QueryString =~ /hostfilter=([^&]+)/i)                      { $FilterIn{'host'}=&DecodeEncodedString("$1"); }                       # Filter on host list can also be defined with hostfilter=filter
 
5069
        if ($QueryString =~ /hostfilterex=([^&]+)/i)            { $FilterEx{'host'}=&DecodeEncodedString("$1"); }                       #
 
5070
        if ($QueryString =~ /urlfilter=([^&]+)/i)                       { $FilterIn{'url'}=&DecodeEncodedString("$1"); }                        # Filter on URL list can also be defined with urlfilter=filter
 
5071
        if ($QueryString =~ /urlfilterex=([^&]+)/i)                     { $FilterEx{'url'}=&DecodeEncodedString("$1"); }                        #
 
5072
        if ($QueryString =~ /refererpagesfilter=([^&]+)/i)      { $FilterIn{'refererpages'}=&DecodeEncodedString("$1"); }       # Filter on referer list can also be defined with refererpagesfilter=filter
 
5073
        if ($QueryString =~ /refererpagesfilterex=([^&]+)/i) { $FilterEx{'refererpages'}=&DecodeEncodedString("$1"); }  #
 
5074
        # All output
 
5075
        if ($QueryString =~ /output=allhosts:([^&]+)/i)         { $FilterIn{'host'}=&DecodeEncodedString("$1"); }                       # Filter on host list can be defined with output=allhosts:filter to reduce number of lines read and showed
 
5076
        if ($QueryString =~ /output=lasthosts:([^&]+)/i)        { $FilterIn{'host'}=&DecodeEncodedString("$1"); }                       # Filter on host list can be defined with output=lasthosts:filter to reduce number of lines read and showed
 
5077
        if ($QueryString =~ /output=urldetail:([^&]+)/i)        { $FilterIn{'url'}=&DecodeEncodedString("$1"); }                        # Filter on URL list can be defined with output=urldetail:filter to reduce number of lines read and showed
 
5078
        if ($QueryString =~ /output=refererpages:([^&]+)/i)     { $FilterIn{'refererpages'}=&DecodeEncodedString("$1"); }       # Filter on referer list can be defined with output=refererpages:filter to reduce number of lines read and showed
 
5079
 
 
5080
        # If migrate
 
5081
        if ($QueryString =~ /(^|-|&)migrate=([^&]+)/i)  {
 
5082
                $MigrateStats=&DecodeEncodedString("$2"); 
 
5083
                $MigrateStats =~ /^(.*)$PROG(\d{0,2})(\d\d)(\d\d\d\d)(.*)\.txt$/;
 
5084
                $SiteConfig=$5?$5:'xxx'; $SiteConfig =~ s/^\.//;                # SiteConfig is used to find config file
 
5085
        }
 
5086
}
 
5087
else {                                                          # Run from command line
 
5088
        # Prepare QueryString
 
5089
        for (0..@ARGV-1) {
 
5090
                # If migrate
 
5091
                if ($ARGV[$_] =~ /(^|-|&)migrate=([^&]+)/i) {
 
5092
                        $MigrateStats="$2";
 
5093
                        $MigrateStats =~ /^(.*)$PROG(\d{0,2})(\d\d)(\d\d\d\d)(.*)\.txt$/;
 
5094
                        $SiteConfig=$5?$5:'xxx'; $SiteConfig =~ s/^\.//;        # SiteConfig is used to find config file
 
5095
                        next;
 
5096
                }
 
5097
                # TODO Check if ARGV is in @AllowedArg
 
5098
                if ($QueryString) { $QueryString .= '&'; }
 
5099
                my $NewLinkParams=$ARGV[$_]; $NewLinkParams =~ s/^-+//;
 
5100
                $QueryString .= "$NewLinkParams";
 
5101
        }
 
5102
 
 
5103
        $QueryString = CleanFromCSSA($QueryString);
 
5104
        # Update with no report by default when run from command line
 
5105
        $UpdateStats=1;
 
5106
 
 
5107
        if ($QueryString =~ /config=([^&]+)/i)                          { $SiteConfig="$1"; }
 
5108
        if ($QueryString =~ /logfile=([^&]+)/i)                         { $LogFile="$1"; }
 
5109
        if ($QueryString =~ /diricons=([^&]+)/i)                        { $DirIcons="$1"; }
 
5110
        if ($QueryString =~ /pluginmode=([^&]+)/i)                      { $PluginMode="$1"; }
 
5111
        if ($QueryString =~ /configdir=([^&]+)/i)                       { $DirConfig="$1"; }
 
5112
        # All filters
 
5113
        if ($QueryString =~ /hostfilter=([^&]+)/i)                      { $FilterIn{'host'}="$1"; }                     # Filter on host list can also be defined with hostfilter=filter
 
5114
        if ($QueryString =~ /hostfilterex=([^&]+)/i)            { $FilterEx{'host'}="$1"; }                     #
 
5115
        if ($QueryString =~ /urlfilter=([^&]+)/i)                       { $FilterIn{'url'}="$1"; }                      # Filter on URL list can also be defined with urlfilter=filter
 
5116
        if ($QueryString =~ /urlfilterex=([^&]+)/i)                     { $FilterEx{'url'}="$1"; }                      #
 
5117
        if ($QueryString =~ /refererpagesfilter=([^&]+)/i)      { $FilterIn{'refererpages'}="$1"; }     # Filter on referer list can also be defined with refererpagesfilter=filter
 
5118
        if ($QueryString =~ /refererpagesfilterex=([^&]+)/i) { $FilterEx{'refererpages'}="$1"; } #
 
5119
        # All output
 
5120
        if ($QueryString =~ /output=allhosts:([^&]+)/i)         { $FilterIn{'host'}="$1"; }                     # Filter on host list can be defined with output=allhosts:filter to reduce number of lines read and showed
 
5121
        if ($QueryString =~ /output=lasthosts:([^&]+)/i)        { $FilterIn{'host'}="$1"; }                     # Filter on host list can be defined with output=lasthosts:filter to reduce number of lines read and showed
 
5122
        if ($QueryString =~ /output=urldetail:([^&]+)/i)        { $FilterIn{'url'}="$1"; }                      # Filter on URL list can be defined with output=urldetail:filter to reduce number of lines read and showed
 
5123
        if ($QueryString =~ /output=refererpages:([^&]+)/i)     { $FilterIn{'refererpages'}="$1"; }     # Filter on referer list can be defined with output=refererpages:filter to reduce number of lines read and showed
 
5124
 
 
5125
        # If show options
 
5126
        if ($QueryString =~ /showsteps/i)                                       { $ShowSteps=1; $QueryString=~s/showsteps[^&]*//i; }
 
5127
        if ($QueryString =~ /showcorrupted/i)                           { $ShowCorrupted=1; $QueryString=~s/showcorrupted[^&]*//i; }
 
5128
        if ($QueryString =~ /showdropped/i)                                     { $ShowDropped=1; $QueryString=~s/showdropped[^&]*//i; }
 
5129
        if ($QueryString =~ /showunknownorigin/i)                       { $ShowUnknownOrigin=1; $QueryString=~s/showunknownorigin[^&]*//i; }
 
5130
}
 
5131
if ($QueryString =~ /(^|&)staticlinks/i)                        { $StaticLinks=".$SiteConfig"; }
 
5132
if ($QueryString =~ /(^|&)staticlinks=([^&]+)/i)        { $StaticLinks=".$2"; }         # When ran from awstatsbuildstaticpages.pl
 
5133
if ($QueryString =~ /(^|&)staticlinksext=([^&]+)/i) { $StaticExt="$2"; }
 
5134
if ($QueryString =~ /(^|&)framename=([^&]+)/i)          { $FrameName="$2"; }
 
5135
if ($QueryString =~ /(^|&)debug=(\d+)/i)                        { $Debug=$2; }
 
5136
if ($QueryString =~ /(^|&)updatefor=(\d+)/i)            { $UpdateFor=$2; }
 
5137
if ($QueryString =~ /(^|&)noloadplugin=([^&]+)/i)       { foreach (split(/,/,$2)) { $NoLoadPlugin{"$_"}=1; } }
 
5138
if ($QueryString =~ /(^|&)loadplugin=([^&]+)/i)         { foreach (split(/,/,$2)) { $NoLoadPlugin{"$_"}=-1; } }
 
5139
if ($QueryString =~ /(^|&)limitflush=(\d+)/i)           { $LIMITFLUSH=$2; }
 
5140
# Get/Define output
 
5141
if ($QueryString =~ /(^|&)output(=[^&]*|)(.*)&output(=[^&]*|)(&|$)/i) { error("Only 1 output option is allowed","","",1); }
 
5142
if ($QueryString =~ /(^|&)output(=[^&]*|)(&|$)/i) {
 
5143
        # At least one output expected. We define %HTMLOutput
 
5144
        my $outputlist="$2";
 
5145
        if ($outputlist) {
 
5146
                $outputlist =~ s/^=//;
 
5147
                foreach my $outputparam (split(/,/,$outputlist)) {
 
5148
                        $outputparam=~s/:(.*)$//;
 
5149
                        if ($outputparam) { $HTMLOutput{lc($outputparam)}="$1"||1; }
 
5150
                }
 
5151
        }
 
5152
        # If on command line and no update
 
5153
        if (! $ENV{'GATEWAY_INTERFACE'} && $QueryString !~ /update/i) { $UpdateStats=0; }
 
5154
        # If no output defined, used default value
 
5155
        if (! scalar keys %HTMLOutput) { $HTMLOutput{'main'}=1; }
 
5156
}
 
5157
if ($ENV{'GATEWAY_INTERFACE'} && ! scalar keys %HTMLOutput) { $HTMLOutput{'main'}=1; }
 
5158
        
 
5159
# Remove -output option with no = from QueryString
 
5160
$QueryString=~s/(^|&)output(&|$)/$1/i; $QueryString=~s/&+$//;
 
5161
 
 
5162
# Check year and month parameters
 
5163
if ($QueryString =~ /(^|&)month=(year)/i) { error("month=year is a deprecated option. Use month=all instead."); }
 
5164
if ($QueryString =~ /(^|&)year=(\d\d\d\d)/i) { $YearRequired=sprintf("%04d",$2); }
 
5165
else { $YearRequired="$nowyear"; }
 
5166
if ($QueryString =~ /(^|&)month=(\d{1,2})/i) { $MonthRequired=sprintf("%02d",$2); }
 
5167
elsif ($QueryString =~ /(^|&)month=(all)/i) { $MonthRequired='all'; }
 
5168
else { $MonthRequired="$nowmonth"; }
 
5169
if ($QueryString =~ /(^|&)day=(\d{1,2})/i) { $DayRequired=sprintf("%02d",$2); } # day is a hidden option. Must not be used (Make results not understandable). Available for users that rename history files with day.
 
5170
else { $DayRequired=''; }
 
5171
 
 
5172
# Check parameter validity
 
5173
# TODO
 
5174
 
 
5175
# Print AWStats and Perl version 
 
5176
if ($Debug) {
 
5177
        if ($ENV{'GATEWAY_INTERFACE'}) { print "\n"; }  # To end the HTTP header and see all debug
 
5178
        debug(ucfirst($PROG)." - $VERSION - Perl $^X $]",1);
 
5179
        debug("DIR=$DIR PROG=$PROG",2);
 
5180
        debug("QUERY_STRING=$QueryString",2);
 
5181
        debug("HTMLOutput=".join(',',keys %HTMLOutput),1);
 
5182
        debug("YearRequired=$YearRequired, MonthRequired=$MonthRequired",2);
 
5183
        debug("UpdateFor=$UpdateFor",2);
 
5184
        debug("PluginMode=$PluginMode",2);
 
5185
        debug("DirConfig=$DirConfig",2);
 
5186
}
 
5187
 
 
5188
# Force SiteConfig if AWSTATS_FORCE_CONFIG is defined
 
5189
if ($ENV{'AWSTATS_CONFIG'}) { $ENV{'AWSTATS_FORCE_CONFIG'}=$ENV{'AWSTATS_CONFIG'}; } # For backward compatibility
 
5190
if ($ENV{'AWSTATS_FORCE_CONFIG'}) {
 
5191
        if ($Debug) { debug("AWSTATS_FORCE_CONFIG parameter is defined to '".$ENV{'AWSTATS_FORCE_CONFIG'}."'. $PROG will use this as config value."); }
 
5192
        $SiteConfig=$ENV{'AWSTATS_FORCE_CONFIG'};
 
5193
}
 
5194
 
 
5195
if ((! $ENV{'GATEWAY_INTERFACE'}) && (! $SiteConfig)) {
 
5196
        &Read_Ref_Data('browsers','domains','operating_systems','robots','search_engines','worms');
 
5197
        print "----- $PROG $VERSION (c) Laurent Destailleur -----\n";
 
5198
        print "$PROG is a free web server logfile analyzer to show you advanced web\n";
 
5199
        print "statistics.\n";
 
5200
        print "$PROG comes with ABSOLUTELY NO WARRANTY. It's a free software distributed\n";
 
5201
        print "with a GNU General Public License (See LICENSE file for details).\n";
 
5202
        print "\n";
 
5203
        print "Syntax: $PROG.$Extension -config=virtualhostname [options]\n";
 
5204
        print "\n";
 
5205
        print "  This runs $PROG in command line to update statistics of a web site, from\n";
 
5206
        print "  the log file defined in config file, and/or returns a HTML report.\n";
 
5207
        print "  First, $PROG tries to read $PROG.virtualhostname.conf as the config file.\n";
 
5208
        print "  If not found, $PROG tries to read $PROG.conf\n";
 
5209
        print "  Note 1: Config files ($PROG.virtualhostname.conf or $PROG.conf) must be\n";
 
5210
        print "   in /etc/awstats, /usr/local/etc/awstats, /etc or same directory than\n";
 
5211
        print "   awstats.pl file.\n";
 
5212
        print "  Note 2: If AWSTATS_FORCE_CONFIG environment variable is defined, AWStats will\n";
 
5213
        print "   use it as the \"config\" value, whatever is the value on command line or URL.\n";
 
5214
        print "   See AWStats documentation for all setup instrutions.\n";
 
5215
        print "\n";
 
5216
        print "Options to update statistics:\n";
 
5217
        print "  -update        to update statistics (default)\n";
 
5218
        print "  -showsteps     to add benchmark information every $NBOFLINESFORBENCHMARK lines processed\n";
 
5219
        print "  -showcorrupted to add output for each corrupted lines found, with reason\n";
 
5220
        print "  -showdropped   to add output for each dropped lines found, with reason\n";
 
5221
        print "  -logfile=x     to change log to analyze whatever is 'LogFile' in config file\n";
 
5222
        print "  -updatefor=n   to stop the update process after parsing n lines\n";
 
5223
        print "  Be care to process log files in chronological order when updating statistics.\n";
 
5224
        print "\n";
 
5225
        print "Options to show statistics:\n";
 
5226
        print "  -output      to output main HTML report (no update made except with -update)\n";
 
5227
        print "  -output=x    to output other report pages where x is:\n";
 
5228
        print "               alldomains       to build page of all domains/countries\n";
 
5229
        print "               allhosts         to build page of all hosts\n";
 
5230
        print "               lasthosts        to build page of last hits for hosts\n";
 
5231
        print "               unknownip        to build page of all unresolved IP\n";
 
5232
        print "               allemails        to build page of all email senders (maillog)\n";
 
5233
        print "               lastemails       to build page of last email senders (maillog)\n";
 
5234
        print "               allemailr        to build page of all email receivers (maillog)\n";
 
5235
        print "               lastemailr       to build page of last email receivers (maillog)\n";
 
5236
        print "               alllogins        to build page of all logins used\n";
 
5237
        print "               lastlogins       to build page of last hits for logins\n";
 
5238
        print "               allrobots        to build page of all robots/spider visits\n";
 
5239
        print "               lastrobots       to build page of last hits for robots\n";
 
5240
        print "               urldetail        to list most often viewed pages \n";
 
5241
        print "               urldetail:filter to list most often viewed pages matching filter\n";
 
5242
        print "               urlentry         to list entry pages\n";
 
5243
        print "               urlentry:filter  to list entry pages matching filter\n";
 
5244
        print "               urlexit          to list exit pages\n";
 
5245
        print "               urlexit:filter   to list exit pages matching filter\n";
 
5246
        print "               osdetail         to build page with os detailed versions\n";
 
5247
        print "               browserdetail    to build page with browsers detailed versions\n";
 
5248
        print "               unknownbrowser   to list 'User Agents' with unknown browser\n";
 
5249
        print "               unknownos        to list 'User Agents' with unknown OS\n";
 
5250
        print "               refererse        to build page of all refering search engines\n";
 
5251
        print "               refererpages     to build page of all refering pages\n";
 
5252
        #print "               referersites     to build page of all refering sites\n";
 
5253
        print "               keyphrases       to list all keyphrases used on search engines\n";
 
5254
        print "               keywords         to list all keywords used on search engines\n";
 
5255
        print "               errors404        to list 'Referers' for 404 errors\n";
 
5256
        print "  -staticlinks to have static links in HTML report page\n";
 
5257
        print "  -staticlinksext=xxx to have static links with .xxx extension instead of .html\n";
 
5258
        print "  -lang=LL     to output a HTML report in language LL (en,de,es,fr,it,nl,...)\n";
 
5259
        print "  -month=MM    to output a HTML report for an old month MM\n";
 
5260
        print "  -year=YYYY   to output a HTML report for an old year YYYY\n";
 
5261
        print "  Those 'date' options doesn't allow you to process old log file. They only\n";
 
5262
        print "  allow you to see a past report for a chosen month/year period instead of\n";
 
5263
        print "  current month/year.\n";
 
5264
        print "\n";
 
5265
        print "Other options:\n";
 
5266
        print "  -debug=X     to add debug informations lesser than level X (speed reduced)\n";
 
5267
        print "\n";
 
5268
        print "Now supports/detects:\n";
 
5269
        print "  Web/Ftp/Mail log analyze\n";
 
5270
        print "  Reverse DNS lookup (IPv4 and IPv6) and GeoIP lookup\n";
 
5271
        print "  Number of visits, number of unique visitors\n";
 
5272
        print "  Visits duration and list of last visits\n";
 
5273
        print "  Authenticated users\n";
 
5274
        print "  Days of week and rush hours\n";
 
5275
        print "  Hosts list and unresolved IP addresses list\n";
 
5276
        print "  Most viewed, entry and exit pages\n";
 
5277
        print "  Files type and Web compression\n";
 
5278
        print "  Screen size\n";
 
5279
        print "  Number of times site is 'added to favorites bookmarks'\n";
 
5280
        print "  Ratio of Browsers with support of: Java, Flash, RealG2 reader,\n";
 
5281
        print "                        Quicktime reader, WMA reader, PDF reader\n";
 
5282
        print "  Personalized reports\n";
 
5283
        print "  ".(scalar keys %DomainsHashIDLib)." domains/countries\n";
 
5284
        print "  ".(scalar keys %RobotsHashIDLib)." robots\n";
 
5285
        print "  ".(scalar keys %OSHashLib)." operating systems\n";
 
5286
        print "  ".(scalar keys %BrowsersHashIDLib)." browsers\n";
 
5287
        print "  ".(scalar keys %SearchEnginesHashLib)." search engines (and keyphrases/keywords used from them)\n";
 
5288
        print "  All HTTP errors with last referrer\n";
 
5289
        print "  Report by day/month/year\n";
 
5290
        print "  Dynamic or static HTML reports, static PDF reports\n";
 
5291
        print "  And a lot of other advanced options...\n";
 
5292
        print "New versions and FAQ at http://awstats.sourceforge.net\n";
 
5293
        exit 2;
 
5294
}
 
5295
$SiteConfig||=$ENV{'SERVER_NAME'};
 
5296
#$ENV{'SERVER_NAME'}||=$SiteConfig;     # For thoose who use __SERVER_NAME__ in conf file and use CLI.
 
5297
$ENV{'AWSTATS_CURRENT_CONFIG'}=$SiteConfig;
 
5298
 
 
5299
# Read config file (SiteConfig must be defined)
 
5300
&Read_Config($DirConfig);
 
5301
 
 
5302
if ($ENV{'GATEWAY_INTERFACE'}) {        # Run from a browser as CGI
 
5303
        # Expires must be GMT ANSI asctime and must be after Content-type to avoid pb with some servers (SAMBAR)
 
5304
        if (! $HeaderHTTPComplete) {
 
5305
                if ($Expires =~ /^\d+$/) {
 
5306
                    print "Cache-Control: public\n";
 
5307
                    print "Last-Modified: ".gmtime($starttime)."\n";
 
5308
                    print "Expires: ".(gmtime($starttime+$Expires))."\n";
 
5309
                }
 
5310
                print "\n";
 
5311
        }
 
5312
        $HeaderHTTPComplete=1;
 
5313
}
 
5314
 
 
5315
# Check language
 
5316
if ($QueryString =~ /(^|&)lang=([^&]+)/i)       { $Lang="$2"; }
 
5317
if (! $Lang || $Lang eq 'auto') {       # If lang not defined or forced to auto
 
5318
        my $langlist=$ENV{'HTTP_ACCEPT_LANGUAGE'}||''; $langlist =~ s/;[^,]*//g;
 
5319
        if ($Debug) { debug("Search an available language among HTTP_ACCEPT_LANGUAGE=$langlist",1); }
 
5320
        foreach my $code (split(/,/,$langlist)) {       # Search for a valid lang in priority
 
5321
                if ($LangBrowserToLangAwstats{$code}) { $Lang=$LangBrowserToLangAwstats{$code}; if ($Debug) { debug(" Will try to use Lang=$Lang",1); } last; }
 
5322
                $code =~ s/-.*$//;
 
5323
                if ($LangBrowserToLangAwstats{$code}) { $Lang=$LangBrowserToLangAwstats{$code}; if ($Debug) { debug(" Will try to use Lang=$Lang",1); } last; }
 
5324
        }
 
5325
}
 
5326
if (! $Lang || $Lang eq 'auto') {
 
5327
        if ($Debug) { debug(" No language defined or available. Will use Lang=en",1); }
 
5328
        $Lang='en';
 
5329
}
 
5330
 
 
5331
# Check and correct bad parameters
 
5332
&Check_Config();
 
5333
# Now SiteDomain is defined
 
5334
 
 
5335
# Define frame name and correct variable for frames
 
5336
if (! $FrameName) {
 
5337
        if ($ENV{'GATEWAY_INTERFACE'} && $UseFramesWhenCGI && $HTMLOutput{'main'} && ! $PluginMode) { $FrameName='index'; }
 
5338
        else { $FrameName='main'; }
 
5339
}
 
5340
 
 
5341
# Load Message files, Reference data files and Plugins
 
5342
if ($Debug) { debug("FrameName=$FrameName",1); }
 
5343
if ($FrameName ne 'index') {
 
5344
        &Read_Language_Data($Lang);
 
5345
        if ($FrameName ne 'mainleft') {
 
5346
                my %datatoload=();
 
5347
                if ($UpdateStats) {                             # If update
 
5348
                        if ($LevelForFileTypesDetection<2)      { $datatoload{'mime'}=1; }              # Only if need to filter on known extensions
 
5349
                        if ($LevelForRobotsDetection)           { $datatoload{'robots'}=1; }    # ua
 
5350
                        if ($LevelForWormsDetection)            { $datatoload{'worms'}=1; }             # url
 
5351
                        if ($LevelForBrowsersDetection)         { $datatoload{'browsers'}=1; }  # ua
 
5352
                        if ($LevelForOSDetection)                       { $datatoload{'operating_systems'}=1; } # ua
 
5353
                        if ($LevelForRefererAnalyze)            { $datatoload{'search_engines'}=1; }    # referer
 
5354
                        # if (...) { $datatoload{'referer_spam'}=1; }
 
5355
                }
 
5356
                if (scalar keys %HTMLOutput) {  # If output
 
5357
                        if ($ShowDomainsStats)                          { $datatoload{'domains'}=1; }
 
5358
                        if ($ShowFileTypesStats)                        { $datatoload{'mime'}=1; }
 
5359
                        if ($ShowRobotsStats)                           { $datatoload{'robots'}=1; }
 
5360
                        if ($ShowWormsStats)                            { $datatoload{'worms'}=1; }
 
5361
                        if ($ShowBrowsersStats)                         { $datatoload{'browsers'}=1; }
 
5362
                        if ($ShowOSStats)                                       { $datatoload{'operating_systems'}=1; }
 
5363
                        if ($ShowOriginStats)                           { $datatoload{'search_engines'}=1; }
 
5364
                        if ($ShowHTTPErrorsStats)                       { $datatoload{'status_http'}=1; }
 
5365
                        if ($ShowSMTPErrorsStats)                       { $datatoload{'status_smtp'}=1; }
 
5366
                }
 
5367
                &Read_Ref_Data(keys %datatoload);
 
5368
                &Read_Plugins();
 
5369
        }
 
5370
}
 
5371
 
 
5372
# Init other parameters
 
5373
$NBOFLINESFORBENCHMARK--;
 
5374
if ($ENV{'GATEWAY_INTERFACE'}) { $DirCgi=''; }
 
5375
if ($DirCgi && !($DirCgi =~ /\/$/) && !($DirCgi =~ /\\$/)) { $DirCgi .= '/'; }
 
5376
if (! $DirData || $DirData =~ /^\./) {
 
5377
     if (! $DirData || $DirData eq '.') { $DirData="$DIR"; }      # If not defined or chosen to '.' value then DirData is current dir
 
5378
     elsif ($DIR && $DIR ne '.') { $DirData="$DIR/$DirData"; }
 
5379
}
 
5380
$DirData||='.';         # If current dir not defined then we put it to '.'
 
5381
$DirData =~ s/[\\\/]+$//;
 
5382
# Define SiteToAnalyze and SiteToAnalyzeWithoutwww for regex operations
 
5383
$SiteToAnalyze=lc($SiteDomain); $SiteToAnalyze =~ s/\./\\\./g;
 
5384
$SiteToAnalyzeWithoutwww = $SiteToAnalyze; $SiteToAnalyzeWithoutwww =~ s/www\.//;
 
5385
if ($FirstDayOfWeek == 1) { @DOWIndex = (1,2,3,4,5,6,0); }
 
5386
else { @DOWIndex = (0,1,2,3,4,5,6); }
 
5387
 
 
5388
# Should we link to ourselves or to a wrapper script
 
5389
$AWScript=($WrapperScript?"$WrapperScript":"$DirCgi$PROG.$Extension");
 
5390
 
 
5391
# Print html header (Need HTMLOutput,Expires,Lang,StyleSheet,HTMLHeadSectionExpires defined by Read_Config, PageCodes defined by Read_Language_Data)
 
5392
if (! $HeaderHTMLComplete) { &html_head; }
 
5393
 
 
5394
# AWStats output is replaced by a plugin output
 
5395
if ($PluginMode) {
 
5396
        my $function="BuildFullHTMLOutput_$PluginMode()";
 
5397
        eval("$function");
 
5398
        if ($? || $@) { error("$@"); }
 
5399
        &html_end(0);
 
5400
        exit 0; 
 
5401
}
 
5402
 
 
5403
# Security check
 
5404
if ($AllowAccessFromWebToAuthenticatedUsersOnly && $ENV{'GATEWAY_INTERFACE'}) {
 
5405
        if ($Debug) { debug("REMOTE_USER=".$ENV{"REMOTE_USER"}); }
 
5406
        if (! $ENV{"REMOTE_USER"}) {
 
5407
                error("Access to statistics is only allowed from an authenticated session to authenticated users.");
 
5408
        }
 
5409
        if (@AllowAccessFromWebToFollowingAuthenticatedUsers) {
 
5410
                my $userisinlist=0;
 
5411
                my $currentuser=$ENV{"REMOTE_USER"};
 
5412
                $currentuser =~ s/\s/%20/g;     # Allow authenticated user with space in name to be compared to allowed user list
 
5413
                foreach my $key (@AllowAccessFromWebToFollowingAuthenticatedUsers) {
 
5414
                        if ($currentuser eq $key) { $userisinlist=1; last; }
 
5415
                }
 
5416
                if (! $userisinlist) {
 
5417
                        error("User '$currentuser' is not allowed to access statistics of this domain/config.");
 
5418
                }
 
5419
        }
 
5420
}
 
5421
if ($AllowAccessFromWebToFollowingIPAddresses && $ENV{'GATEWAY_INTERFACE'}) {
 
5422
        my $useripaddress=&Convert_IP_To_Decimal($ENV{"REMOTE_ADDR"});
 
5423
        my @allowaccessfromipaddresses = split (/[\s,]+/, $AllowAccessFromWebToFollowingIPAddresses);
 
5424
        my $allowaccess = 0;
 
5425
        foreach my $ipaddressrange (@allowaccessfromipaddresses) {
 
5426
            if ($ipaddressrange !~ /^(\d+\.\d+\.\d+\.\d+)(?:-(\d+\.\d+\.\d+\.\d+))*$/) {
 
5427
                        error("AllowAccessFromWebToFollowingIPAddresses is defined to '$AllowAccessFromWebToFollowingIPAddresses' but does not match the correct syntax: IPAddressMin[-IPAddressMax]");
 
5428
                }
 
5429
                my $ipmin=&Convert_IP_To_Decimal($1);
 
5430
                my $ipmax=$2?&Convert_IP_To_Decimal($2):$ipmin;
 
5431
                # Is it an authorized ip ?
 
5432
                if (($useripaddress >= $ipmin) && ($useripaddress <= $ipmax)) {
 
5433
                        $allowaccess = 1;
 
5434
                        last;
 
5435
                }
 
5436
        }
 
5437
    if (! $allowaccess) {
 
5438
                error("Access to statistics is not allowed from your IP Address ".$ENV{"REMOTE_ADDR"});
 
5439
        }
 
5440
}
 
5441
if (($UpdateStats || $MigrateStats) && (! $AllowToUpdateStatsFromBrowser) && $ENV{'GATEWAY_INTERFACE'}) {
 
5442
        error("".($UpdateStats?"Update":"Migrate")." of statistics has not been allowed from a browser (AllowToUpdateStatsFromBrowser should be set to 1).");
 
5443
}
 
5444
if (scalar keys %HTMLOutput && $MonthRequired eq 'all') {
 
5445
        if (! $AllowFullYearView) { error("Full year view has not been allowed (AllowFullYearView is set to 0)."); }
 
5446
        if ($AllowFullYearView < 3 && $ENV{'GATEWAY_INTERFACE'}) { error("Full year view has not been allowed from a browser (AllowFullYearView should be set to 3)."); }
 
5447
}
 
5448
 
 
5449
 
 
5450
#------------------------------------------
 
5451
# MIGRATE PROCESS (Must be after reading config cause we need MaxNbOf... and Min...)
 
5452
#------------------------------------------
 
5453
if ($MigrateStats) {
 
5454
        if ($Debug) { debug("MigrateStats is $MigrateStats",2); }
 
5455
        if ($MigrateStats !~ /^(.*)$PROG(\d{0,2})(\d\d)(\d\d\d\d)(.*)\.txt$/) {
 
5456
                error("AWStats history file name must match following syntax: ${PROG}MMYYYY[.config].txt","","",1);
 
5457
        }
 
5458
        $DirData="$1";
 
5459
        $DayRequired="$2";
 
5460
        $MonthRequired="$3";
 
5461
        $YearRequired="$4";
 
5462
        $FileSuffix="$5";
 
5463
        # Correct DirData
 
5464
        if (! $DirData || $DirData =~ /^\./) {
 
5465
             if (! $DirData || $DirData eq '.') { $DirData="$DIR"; }      # If not defined or chosen to '.' value then DirData is current dir
 
5466
             elsif ($DIR && $DIR ne '.') { $DirData="$DIR/$DirData"; }
 
5467
        }
 
5468
        $DirData||='.';         # If current dir not defined then we put it to '.'
 
5469
        $DirData =~ s/[\\\/]+$//;
 
5470
        print "Start migration for file '$MigrateStats'."; print $ENV{'GATEWAY_INTERFACE'}?"<br />\n":"\n";
 
5471
        if ($EnableLockForUpdate) {     &Lock_Update(1); }
 
5472
        my $newhistory=&Read_History_With_TmpUpdate($YearRequired,$MonthRequired,1,0,'all');
 
5473
        if (rename("$newhistory","$MigrateStats")==0) {
 
5474
                unlink "$newhistory";
 
5475
                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.");
 
5476
        }
 
5477
        if ($EnableLockForUpdate) {     &Lock_Update(0); }
 
5478
        print "Migration for file '$MigrateStats' successful."; print $ENV{'GATEWAY_INTERFACE'}?"<br />\n":"\n";
 
5479
        &html_end(1);
 
5480
        exit 0;
 
5481
}
 
5482
 
 
5483
# Output main frame page and exit. This must be after the security check.
 
5484
if ($FrameName eq 'index') {
 
5485
        # Define the NewLinkParams for main chart
 
5486
        my $NewLinkParams=${QueryString};
 
5487
        $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
5488
        $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
5489
        if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
5490
        # Exit if main frame
 
5491
        print "<frameset cols=\"$FRAMEWIDTH,*\" border=\"0\" framespacing=\"2\" frameborder=\"0\">\n";
 
5492
        print "<frame name=\"mainleft\" src=\"".XMLEncode("$AWScript?${NewLinkParams}framename=mainleft")."\" noresize=\"0\" frameborder=\"0\" />\n";
 
5493
        print "<frame name=\"mainright\" src=\"".XMLEncode("$AWScript?${NewLinkParams}framename=mainright")."\" noresize=\"0\" scrolling=\"YES\" frameborder=\"0\" />\n";
 
5494
        print "<noframes><body>";
 
5495
        print "Your browser does not support frames.<br />\n";
 
5496
        print "You must set AWStats UseFramesWhenCGI parameter to 0\n";
 
5497
        print "to see your reports.<br />\n";
 
5498
        print "</body></noframes>\n";
 
5499
        print "</frameset>\n";
 
5500
        &html_end(0);
 
5501
        exit 0;
 
5502
}
 
5503
 
 
5504
%MonthNumLib = ("01","$Message[60]","02","$Message[61]","03","$Message[62]","04","$Message[63]","05","$Message[64]","06","$Message[65]","07","$Message[66]","08","$Message[67]","09","$Message[68]","10","$Message[69]","11","$Message[70]","12","$Message[71]");
 
5505
 
 
5506
# Build ListOfYears list with all existing years
 
5507
if ($Debug) { debug("Scan for last history files into DirData='$DirData'"); }
 
5508
$lastyearbeforeupdate=0;
 
5509
opendir(DIR,"$DirData");
 
5510
foreach (grep /^$PROG(\d\d)(\d\d\d\d)$FileSuffix\.txt(|\.gz)$/, sort readdir DIR) {
 
5511
        /^$PROG(\d\d)(\d\d\d\d)$FileSuffix\.txt(|\.gz)$/;
 
5512
        if (! $ListOfYears{"$2"} || "$1" gt $ListOfYears{"$2"}) {
 
5513
                $ListOfYears{"$2"}="$1";        # ListOfYears contains max month found
 
5514
                if ("$2" gt $lastyearbeforeupdate) { $lastyearbeforeupdate="$2"; }
 
5515
        }
 
5516
}
 
5517
close DIR;
 
5518
 
 
5519
# Get value for LastLine
 
5520
if ($lastyearbeforeupdate) {
 
5521
        # Read 'general' section of last history file for LastLine
 
5522
        &Read_History_With_TmpUpdate($lastyearbeforeupdate,$ListOfYears{$lastyearbeforeupdate},0,0,"general");
 
5523
}
 
5524
if ($Debug) {
 
5525
        debug("Last year=$lastyearbeforeupdate - Last month=$ListOfYears{$lastyearbeforeupdate}");
 
5526
        debug("LastLine=$LastLine");
 
5527
        debug("LastLineNumber=$LastLineNumber");
 
5528
        debug("LastLineOffset=$LastLineOffset");
 
5529
        debug("LastLineChecksum=$LastLineChecksum");
 
5530
}
 
5531
 
 
5532
# Init vars
 
5533
&Init_HashArray();
 
5534
 
 
5535
 
 
5536
#------------------------------------------
 
5537
# UPDATE PROCESS
 
5538
#------------------------------------------
 
5539
my $lastlinenumber=0; my $lastlineoffset=0; my $lastlineoffsetnext=0;
 
5540
 
 
5541
if ($Debug) { debug("UpdateStats is $UpdateStats",2); }
 
5542
if ($UpdateStats && $FrameName ne 'index' && $FrameName ne 'mainleft') {        # Update only on index page or when not framed to avoid update twice
 
5543
 
 
5544
        my %MonthNum = ("Jan","01","jan","01","Feb","02","feb","02","Mar","03","mar","03","Apr","04","apr","04","May","05","may","05","Jun","06","jun","06","Jul","07","jul","07","Aug","08","aug","08","Sep","09","sep","09","Oct","10","oct","10","Nov","11","nov","11","Dec","12","dec","12");       # MonthNum must be in english because used to translate log date in apache log files
 
5545
 
 
5546
        if (! scalar keys %HTMLOutput) {
 
5547
                print "Update for config \"$FileConfig\"\n";
 
5548
                print "With data in log file \"$LogFile\"...\n";
 
5549
        }
 
5550
 
 
5551
        my $lastprocessedyear=$lastyearbeforeupdate;
 
5552
        my $lastprocessedmonth=$ListOfYears{$lastyearbeforeupdate}||0;
 
5553
        my $lastprocessedyearmonth=sprintf("%04i%02i",$lastprocessedyear,$lastprocessedmonth);
 
5554
 
 
5555
        my @list;
 
5556
        # Init RobotsSearchIDOrder required for update process
 
5557
        @list=();
 
5558
        if ($LevelForRobotsDetection >= 1) {
 
5559
                foreach (1..$LevelForRobotsDetection) { push @list,"list$_"; }
 
5560
                push @list,"listgen";           # Always added
 
5561
        }
 
5562
        foreach my $key (@list) {
 
5563
                push @RobotsSearchIDOrder,@{"RobotsSearchIDOrder_$key"};
 
5564
                if ($Debug) { debug("Add ".@{"RobotsSearchIDOrder_$key"}." elements from RobotsSearchIDOrder_$key into RobotsSearchIDOrder",2); }
 
5565
        }
 
5566
        if ($Debug) { debug("RobotsSearchIDOrder has now ".@RobotsSearchIDOrder." elements",1); }
 
5567
        # Init SearchEnginesIDOrder required for update process
 
5568
        @list=();
 
5569
        if ($LevelForSearchEnginesDetection >= 1) {
 
5570
                foreach (1..$LevelForSearchEnginesDetection) { push @list,"list$_"; }
 
5571
                push @list,"listgen";           # Always added
 
5572
        }
 
5573
        foreach my $key (@list) {
 
5574
                push @SearchEnginesSearchIDOrder,@{"SearchEnginesSearchIDOrder_$key"};
 
5575
                if ($Debug) { debug("Add ".@{"SearchEnginesSearchIDOrder_$key"}." elements from SearchEnginesSearchIDOrder_$key into SearchEnginesSearchIDOrder",2); }
 
5576
        }
 
5577
        if ($Debug) { debug("SearchEnginesSearchIDOrder has now ".@SearchEnginesSearchIDOrder." elements",1); }
 
5578
 
 
5579
        # Complete HostAliases array
 
5580
        if (! @HostAliases) {
 
5581
                warning("Warning: HostAliases parameter is not defined, $PROG choose \"$SiteDomain localhost 127.0.0.1\".");
 
5582
                push @HostAliases,qr/^$SiteToAnalyze$/i; push @HostAliases,qr/^localhost$/i; push @HostAliases,qr/^127\.0\.0\.1$/i;
 
5583
        }
 
5584
        unshift @HostAliases,qr/^$SiteToAnalyze$/i;     # Add SiteToAnalyze as first value
 
5585
 
 
5586
        # Optimize arrays
 
5587
        @HostAliases=&OptimizeArray(\@HostAliases,1); if ($Debug) { debug("HostAliases precompiled regex list is now @HostAliases",1); }
 
5588
        @SkipDNSLookupFor=&OptimizeArray(\@SkipDNSLookupFor,1); if ($Debug) { debug("SkipDNSLookupFor precompiled regex list is now @SkipDNSLookupFor",1); }
 
5589
        @SkipHosts=&OptimizeArray(\@SkipHosts,1); if ($Debug) { debug("SkipHosts precompiled regex list is now @SkipHosts",1); }
 
5590
        @SkipUserAgents=&OptimizeArray(\@SkipUserAgents,1); if ($Debug) { debug("SkipUserAgents precompiled regex list is now @SkipUserAgents",1); }
 
5591
        @SkipFiles=&OptimizeArray(\@SkipFiles,$URLNotCaseSensitive); if ($Debug) { debug("SkipFiles precompiled regex list is now @SkipFiles",1); }
 
5592
        @OnlyHosts=&OptimizeArray(\@OnlyHosts,1); if ($Debug) { debug("OnlyHosts precompiled regex list is now @OnlyHosts",1); }
 
5593
        @OnlyUserAgents=&OptimizeArray(\@OnlyUserAgents,1); if ($Debug) { debug("OnlyUserAgents precompiled regex list is now @OnlyUserAgents",1); }
 
5594
        @OnlyFiles=&OptimizeArray(\@OnlyFiles,$URLNotCaseSensitive); if ($Debug) { debug("OnlyFiles precompiled regex list is now @OnlyFiles",1); }
 
5595
        # Precompile the regex search strings with qr
 
5596
        @RobotsSearchIDOrder=map{qr/$_/i} @RobotsSearchIDOrder;
 
5597
        @WormsSearchIDOrder=map{qr/$_/i} @WormsSearchIDOrder;
 
5598
        @BrowsersSearchIDOrder=map{qr/$_/i} @BrowsersSearchIDOrder;
 
5599
        @OSSearchIDOrder=map{qr/$_/i} @OSSearchIDOrder;
 
5600
        @SearchEnginesSearchIDOrder=map{qr/$_/i} @SearchEnginesSearchIDOrder;
 
5601
        my $miscquoted=quotemeta("$MiscTrackerUrl");
 
5602
        my $defquoted=quotemeta("/$DefaultFile[0]");
 
5603
        # Define precompiled regex
 
5604
        my $regmisc=qr/^$miscquoted/;
 
5605
        my $regrobot=qr/^\/robots\.txt$/i;
 
5606
        my $regtruncanchor=qr/#(\w*)$/;
 
5607
        my $regtruncurl=qr/([$URLQuerySeparators])(.*)$/;
 
5608
        my $regext=qr/\.(\w{1,6})$/;
 
5609
        my $regdefault;
 
5610
        if ($URLNotCaseSensitive) { $regdefault=qr/$defquoted$/i; }
 
5611
        else { $regdefault=qr/$defquoted$/; }
 
5612
        my $regipv4=qr/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
 
5613
        my $regipv6=qr/^[0-9A-F]*:/i;
 
5614
        my $regvermsie=qr/msie([+_ ]|)([\d\.]*)/i;
 
5615
        my $regvernetscape=qr/netscape.?\/([\d\.]*)/i;
 
5616
        my $regvermozilla=qr/mozilla(\/|)([\d\.]*)/i;
 
5617
        my $regnotie=qr/webtv|omniweb|opera/i;
 
5618
        my $regnotnetscape=qr/gecko|compatible|opera|galeon|safari/i;
 
5619
        my $regreferer=qr/^(\w+):\/\/([^\/:]+)(:\d+|)/;
 
5620
        my $regreferernoquery=qr/^([^$URLQuerySeparators]+)/;
 
5621
 
 
5622
        # Define value of $PerlParsingFormat and @fieldlib
 
5623
        &DefinePerlParsingFormat();
 
5624
 
 
5625
        # Load DNS Cache Files
 
5626
        #------------------------------------------
 
5627
        if ($DNSLookup) {
 
5628
                &Read_DNS_Cache(\%MyDNSTable,"$DNSStaticCacheFile","",1);                                               # Load with save into a second plugin file if plugin enabled and second file not up to date. No use of FileSuffix
 
5629
                if ($DNSLookup == 1) {          # System DNS lookup required
 
5630
                        #if (! eval("use Socket;")) { error("Failed to load perl module Socket."); }
 
5631
                        #use Socket;
 
5632
                        &Read_DNS_Cache(\%TmpDNSLookup,"$DNSLastUpdateCacheFile","$FileSuffix",0);      # Load with no save into a second plugin file. Use FileSuffix
 
5633
                }
 
5634
        }
 
5635
 
 
5636
        # Processing log
 
5637
        #------------------------------------------
 
5638
 
 
5639
        if ($EnableLockForUpdate) {
 
5640
                # Trap signals to remove lock
 
5641
                $SIG{INT} = \&SigHandler;       # 2
 
5642
                #$SIG{KILL} = \&SigHandler;     # 9
 
5643
                #$SIG{TERM} = \&SigHandler;     # 15
 
5644
                # Set AWStats update lock
 
5645
                &Lock_Update(1);
 
5646
        }
 
5647
 
 
5648
        if ($Debug) { debug("Start Update process (lastprocessedmonth=$lastprocessedmonth, lastprocessedyear=$lastprocessedyear)"); }
 
5649
 
 
5650
        # Open log file
 
5651
        if ($Debug) { debug("Open log file \"$LogFile\""); }
 
5652
        open(LOG,"$LogFile") || error("Couldn't open server log file \"$LogFile\" : $!");
 
5653
        binmode LOG;    # Avoid premature EOF due to log files corrupted with \cZ or bin chars
 
5654
 
 
5655
        # Define local variables for loop scan
 
5656
        my @field=();
 
5657
        my $counterforflushtest=0;
 
5658
        my $qualifdrop='';
 
5659
        my $countedtraffic=0;
 
5660
        # Reset chrono for benchmark (first call to GetDelaySinceStart)
 
5661
        &GetDelaySinceStart(1);
 
5662
        if (! scalar keys %HTMLOutput) { print "Phase 1 : First bypass old records, searching new record...\n"; }
 
5663
 
 
5664
        # Can we try a direct seek access in log ?
 
5665
        my $line;
 
5666
        if ($LastLine && $LastLineNumber && $LastLineOffset && $LastLineChecksum) {
 
5667
                # Try a direct seek access to save time
 
5668
                if ($Debug) { debug("Try a direct access to LastLine=$LastLine, LastLineNumber=$LastLineNumber, LastLineOffset=$LastLineOffset, LastLineChecksum=$LastLineChecksum"); }
 
5669
                seek(LOG,$LastLineOffset,0);
 
5670
                if ($line=<LOG>) {
 
5671
                        chomp $line; $line =~ s/\r$//;
 
5672
                        @field=map(/$PerlParsingFormat/,$line);
 
5673
                        if ($Debug) {
 
5674
                                my $string='';
 
5675
                                foreach (0..@field-1) { $string.="$fieldlib[$_]=$field[$_] "; }
 
5676
                                if ($Debug) { debug(" Read line after direct access: $string",1); }
 
5677
                        }
 
5678
                        my $checksum=&CheckSum($line);
 
5679
                        if ($Debug) { debug(" LastLineChecksum=$LastLineChecksum, Read line checksum=$checksum",1); }
 
5680
                        if ($checksum == $LastLineChecksum ) {
 
5681
                                if (! scalar keys %HTMLOutput) { print "Direct access after last updated record successfull (after line $LastLineNumber)\n"; }
 
5682
                                $lastlinenumber=$LastLineNumber;
 
5683
                                $lastlineoffset=$LastLineOffset;
 
5684
                                $lastlineoffsetnext=$LastLineOffset;
 
5685
                                #seek(LOG,$LastLineOffset,0);   # Direct access succesful, we keep it.
 
5686
                        }
 
5687
                        else {
 
5688
                                if (! scalar keys %HTMLOutput) { print "Direct access to last remembered record has fallen on another record.\nSo searching new records from beginning of log file...\n"; }
 
5689
                                $lastlinenumber=0;
 
5690
                                $lastlineoffset=0;
 
5691
                                $lastlineoffsetnext=0;
 
5692
                                seek(LOG,0,0);
 
5693
                        }
 
5694
                }
 
5695
                else {
 
5696
                        if (! scalar keys %HTMLOutput) { print "Direct access to last remembered record is out of file.\nSo searching it from beginning of log file...\n"; }
 
5697
                        $lastlinenumber=0;
 
5698
                        $lastlineoffset=0;
 
5699
                        $lastlineoffsetnext=0;
 
5700
                        seek(LOG,0,0);
 
5701
                }
 
5702
        }
 
5703
        else {
 
5704
                # No try of direct seek access
 
5705
                if (! scalar keys %HTMLOutput) { print "Searching new records from beginning of log file...\n"; }
 
5706
                $lastlinenumber=0;
 
5707
                $lastlineoffset=0;
 
5708
                $lastlineoffsetnext=0;
 
5709
        }
 
5710
 
 
5711
        while ($line=<LOG>) {
 
5712
                chomp $line; $line =~ s/\r$//;
 
5713
                if ($UpdateFor && $NbOfLinesParsed >= $UpdateFor) { last; }
 
5714
                $NbOfLinesParsed++;
 
5715
 
 
5716
                $lastlineoffset=$lastlineoffsetnext; $lastlineoffsetnext=tell LOG;
 
5717
 
 
5718
                if ($ShowSteps) {
 
5719
                        if ((++$NbOfLinesShowsteps & $NBOFLINESFORBENCHMARK) == 0) {
 
5720
                                my $delay=&GetDelaySinceStart(0);
 
5721
                                print "$NbOfLinesParsed lines processed (".($delay>0?$delay:1000)." ms, ".int(1000*$NbOfLinesShowsteps/($delay>0?$delay:1000))." lines/second)\n";
 
5722
                        }
 
5723
                }
 
5724
 
 
5725
                # Parse line record to get all required fields
 
5726
                if (! (@field=map(/$PerlParsingFormat/,$line))) {
 
5727
                        $NbOfLinesCorrupted++;
 
5728
                        if ($ShowCorrupted) {
 
5729
                                if ($line =~ /^#/ || $line =~ /^!/) { print "Corrupted record line ".($lastlinenumber+$NbOfLinesParsed)." (comment line): $line\n"; }
 
5730
                                elsif ($line =~ /^\s*$/) { print "Corrupted record line ".($lastlinenumber+$NbOfLinesParsed)." (blank line)\n"; }
 
5731
                                else { print "Corrupted record line ".($lastlinenumber+$NbOfLinesParsed)." (record format does not match LogFormat parameter): $line\n"; }
 
5732
                        }
 
5733
                        if ($NbOfLinesParsed >= $NbOfLinesForCorruptedLog && $NbOfLinesParsed == $NbOfLinesCorrupted) { error("Format error",$line,$LogFile); } # Exit with format error
 
5734
                        if ($line =~ /^__end_of_file__/) { last; }      # For test purpose only
 
5735
                        next;
 
5736
                }
 
5737
 
 
5738
                if ($Debug) {
 
5739
                        my $string='';
 
5740
                        foreach (0..@field-1) { $string.="$fieldlib[$_]=$field[$_] "; }
 
5741
                        if ($Debug) { debug(" Correct format line ".($lastlinenumber+$NbOfLinesParsed).": $string",4); }
 
5742
                }
 
5743
 
 
5744
                # Drop wrong virtual host name
 
5745
                #----------------------------------------------------------------------
 
5746
                if ($pos_vh>=0 && $field[$pos_vh] !~ /^$SiteDomain$/i) {
 
5747
                        my $skip=1;
 
5748
                        foreach (@HostAliases) {
 
5749
                                if ($field[$pos_vh] =~ /$_/) { $skip=0; last; }
 
5750
                        }
 
5751
                        if ($skip) {
 
5752
                                $NbOfLinesDropped++;
 
5753
                                if ($ShowDropped) { print "Dropped record (virtual hostname '$field[$pos_vh]' does not match SiteDomain='$SiteDomain' nor HostAliases parameters): $line\n"; }
 
5754
                                next;
 
5755
                        }
 
5756
                }
 
5757
 
 
5758
                # Drop wrong method/protocol
 
5759
                #---------------------------
 
5760
                if ($LogType ne 'M') { $field[$pos_url] =~ s/\s/%20/g; }
 
5761
                if ($LogType eq 'W' && ($field[$pos_method] eq 'GET' || $field[$pos_method] eq 'POST' || $field[$pos_method] eq 'HEAD' || $field[$pos_method] =~ /OK/i || $field[$pos_method] =~ /ERR\!/i)) {
 
5762
                        # HTTP request. Keep only GET, POST, HEAD, *OK* and ERR! for Webstar. Do not keep OPTIONS
 
5763
                }
 
5764
                elsif (($LogType eq 'W' || $LogType eq 'S') && ($field[$pos_method] eq 'mms'|| $field[$pos_method] eq 'rtsp' || $field[$pos_method] eq 'http' || $field[$pos_method] eq 'RTP')) {
 
5765
                        # Streaming request (windows media server or darwin streaming server)
 
5766
                }
 
5767
                elsif ($LogType eq 'M' && $field[$pos_method] eq 'SMTP') {
 
5768
                        # Mail request ('SMTP' for mail log with maillogconvert.pl preprocessor)
 
5769
                }
 
5770
                elsif ($LogType eq 'F' && ($field[$pos_method] eq 'RETR' || $field[$pos_method] eq 'o' || $field[$pos_method] =~ /get/i)) {
 
5771
                        # FTP GET request
 
5772
                }
 
5773
                elsif ($LogType eq 'F' && ($field[$pos_method] eq 'STOR' || $field[$pos_method] eq 'i' || $field[$pos_method] =~ /sent/i)) {
 
5774
                        # FTP SENT request
 
5775
                }
 
5776
                else {
 
5777
                        $NbOfLinesDropped++;
 
5778
                        if ($ShowDropped) { print "Dropped record (method/protocol '$field[$pos_method]' not qualified when LogType=$LogType): $line\n"; }
 
5779
                        next;
 
5780
                }
 
5781
 
 
5782
                # Split DD/Month/YYYY:HH:MM:SS or YYYY-MM-DD HH:MM:SS or MM/DD/YY\tHH:MM:SS
 
5783
                $field[$pos_date] =~ tr/,-\/ \t/:::::/;                 # " \t" is used instead of "\s" not known with tr
 
5784
                my @dateparts=split(/:/,$field[$pos_date]);             # tr and split faster than @dateparts=split(/[\/\-:\s]/,$field[$pos_date])
 
5785
                if ($dateparts[0] =~ /^....$/) { my $tmp=$dateparts[0]; $dateparts[0]=$dateparts[2]; $dateparts[2]=$tmp; }
 
5786
                elsif ($field[$pos_date] =~ /^..:..:..:/) { $dateparts[2]+=2000; my $tmp=$dateparts[0]; $dateparts[0]=$dateparts[1]; $dateparts[1]=$tmp; }
 
5787
                if ($MonthNum{$dateparts[1]}) { $dateparts[1]=$MonthNum{$dateparts[1]}; }       # Change lib month in num month if necessary
 
5788
 
 
5789
                # Now @dateparts is (DD,MM,YYYY,HH,MM,SS) and we're going to create $timerecord=YYYYMMDDHHMMSS
 
5790
                # Plugin call : Convert a @datepart into another @datepart
 
5791
                if ($PluginsLoaded{'ChangeTime'}{'timezone'})  { @dateparts=ChangeTime_timezone(\@dateparts); }
 
5792
                my $yearrecord=int($dateparts[2]);
 
5793
                my $monthrecord=int($dateparts[1]);
 
5794
                my $hourrecord=int($dateparts[3]);
 
5795
                my $yearmonthdayrecord=sprintf("$dateparts[2]%02i%02i",$dateparts[1],$dateparts[0]);
 
5796
                my $timerecord=((int("$yearmonthdayrecord")*100+$dateparts[3])*100+$dateparts[4])*100+$dateparts[5];
 
5797
 
 
5798
                # Check date
 
5799
                #-----------------------
 
5800
                if ($timerecord < 10000000000000 || $timerecord > $tomorrowtime) {
 
5801
                        $NbOfLinesCorrupted++;
 
5802
                        if ($ShowCorrupted) { print "Corrupted record (invalid date, timerecord=$timerecord): $line\n"; }
 
5803
                        next;           # Should not happen, kept in case of parasite/corrupted line
 
5804
                }
 
5805
                if ($NewLinePhase) {
 
5806
# TODO NOTSORTEDRECORDTOLERANCE does not work around midnight
 
5807
                        if ($timerecord < ($LastLine - $NOTSORTEDRECORDTOLERANCE)) {
 
5808
                                # Should not happen, kept in case of parasite/corrupted old line
 
5809
                                $NbOfLinesCorrupted++;
 
5810
                                if ($ShowCorrupted) { print "Corrupted record (date $timerecord lower than $LastLine-$NOTSORTEDRECORDTOLERANCE): $line\n"; } next;
 
5811
                        }
 
5812
                }
 
5813
                else {
 
5814
                        if ($timerecord <= $LastLine) { # Already processed
 
5815
                                $NbOfOldLines++;
 
5816
                                next;
 
5817
                        }
 
5818
                        # We found a new line. This will replace comparison "<=" with "<" between timerecord and LastLine (we should have only new lines now)
 
5819
                        $NewLinePhase=1;        # We will never enter here again
 
5820
                        if ($ShowSteps) {
 
5821
                                if ($NbOfLinesShowsteps > 1 && ($NbOfLinesShowsteps & $NBOFLINESFORBENCHMARK)) {
 
5822
                                        my $delay=&GetDelaySinceStart(0);
 
5823
                                        print "".($NbOfLinesParsed-1)." lines processed (".($delay>0?$delay:1000)." ms, ".int(1000*($NbOfLinesShowsteps-1)/($delay>0?$delay:1000))." lines/second)\n";
 
5824
                                }
 
5825
                                &GetDelaySinceStart(1); $NbOfLinesShowsteps=1;
 
5826
                        }
 
5827
                        if (! scalar keys %HTMLOutput) {
 
5828
                                print "Phase 2 : Now process new records (Flush history on disk after ".($LIMITFLUSH<<2)." hosts)...\n";
 
5829
                                #print "Phase 2 : Now process new records (Flush history on disk after ".($LIMITFLUSH<<2)." hosts or ".($LIMITFLUSH)." URLs)...\n";
 
5830
                        }
 
5831
                }
 
5832
 
 
5833
                # Convert URL for Webstar to common URL
 
5834
                if ($LogFormat eq '3') {
 
5835
                        $field[$pos_url]=~s/:/\//g;
 
5836
                        if ($field[$pos_code] eq '-') { $field[$pos_code]='200'; }
 
5837
                }
 
5838
 
 
5839
                # Here, field array, timerecord and yearmonthdayrecord are initialized for log record
 
5840
                if ($Debug) { debug("  This is a not already processed record ($timerecord)",4); }
 
5841
 
 
5842
                # We found a new line
 
5843
                #----------------------------------------
 
5844
                if ($timerecord > $LastLine) { $LastLine = $timerecord; }       # Test should always be true except with not sorted log files
 
5845
 
 
5846
                # Skip for some client host IP addresses, some URLs, other URLs
 
5847
                if    (@SkipHosts && (&SkipHost($field[$pos_host]) || ($pos_hostr && &SkipHost($field[$pos_hostr]))))   { $qualifdrop="Dropped record (host $field[$pos_host]".($pos_hostr?" and $field[$pos_hostr]":"")." not qualified by SkipHosts)"; }
 
5848
                elsif (@SkipFiles && &SkipFile($field[$pos_url]))    { $qualifdrop="Dropped record (URL $field[$pos_url] not qualified by SkipFiles)"; }
 
5849
                elsif (@SkipUserAgents && $pos_agent >= 0 && &SkipUserAgent($field[$pos_agent]))        { $qualifdrop="Dropped record (user agent '$field[$pos_agent]' not qualified by SkipUserAgents)"; }
 
5850
                elsif (@OnlyHosts && ! &OnlyHost($field[$pos_host]) && (! $pos_hostr || ! &OnlyHost($field[$pos_hostr]))) { $qualifdrop="Dropped record (host $field[$pos_host]".($pos_hostr?" and $field[$pos_hostr]":"")." not qualified by OnlyHosts)"; } 
 
5851
                elsif (@OnlyFiles && ! &OnlyFile($field[$pos_url]))  { $qualifdrop="Dropped record (URL $field[$pos_url] not qualified by OnlyFiles)"; }
 
5852
                elsif (@OnlyUserAgents && ! &OnlyUserAgent($field[$pos_agent]))  { $qualifdrop="Dropped record (user agent '$field[$pos_agent]' not qualified by OnlyUserAgents)"; }
 
5853
                if ($qualifdrop) {
 
5854
                        $NbOfLinesDropped++;
 
5855
                        if ($Debug) { debug("$qualifdrop: $line",4); }
 
5856
                        if ($ShowDropped) { print "$qualifdrop: $line\n"; }
 
5857
                        $qualifdrop='';
 
5858
                        next;
 
5859
                }
 
5860
 
 
5861
                # Record is approved
 
5862
                #-------------------
 
5863
 
 
5864
                # Is it in a new month section ?
 
5865
                #-------------------------------
 
5866
                if ((($monthrecord > $lastprocessedmonth) && ($yearrecord >= $lastprocessedyear)) || ($yearrecord > $lastprocessedyear)) {
 
5867
                        # A new month to process
 
5868
                        if ($lastprocessedmonth) {
 
5869
                                # We save data of processed month
 
5870
                                &Read_History_With_TmpUpdate($lastprocessedyear,$lastprocessedmonth,1,1,"all",($lastlinenumber+$NbOfLinesParsed),$lastlineoffset,&CheckSum($line));
 
5871
                                $counterforflushtest=0; # We reset counterforflushtest
 
5872
                        }
 
5873
                        $lastprocessedyearmonth=sprintf("%04i%02i",$lastprocessedyear=$yearrecord,$lastprocessedmonth=$monthrecord);
 
5874
                }
 
5875
 
 
5876
                $countedtraffic=0;
 
5877
                $NbOfNewLines++;
 
5878
 
 
5879
                # Convert $field[$pos_size]
 
5880
                # if ($field[$pos_size] eq '-') { $field[$pos_size]=0; }
 
5881
 
 
5882
                # Define a clean target URL and referrer URL
 
5883
                # We keep a clean $field[$pos_url] and
 
5884
                # we store original value for urlwithnoquery, tokenquery and standalonequery
 
5885
                #---------------------------------------------------------------------------
 
5886
                if ($URLNotCaseSensitive) { $field[$pos_url]=lc($field[$pos_url]); }
 
5887
                # Possible URL syntax for $field[$pos_url]: /mydir/mypage.ext?param1=x&param2=y#aaa, /mydir/mypage.ext#aaa, /
 
5888
                my $urlwithnoquery; my $tokenquery; my $standalonequery; my $anchor='';
 
5889
                if ($field[$pos_url] =~ s/$regtruncanchor//o) { $anchor=$1; }   # Remove and save anchor
 
5890
                if ($URLWithQuery) {
 
5891
                        $urlwithnoquery=$field[$pos_url];
 
5892
                        my $foundparam=($urlwithnoquery =~ s/$regtruncurl//o);
 
5893
                        $tokenquery=$1||'';
 
5894
                        $standalonequery=$2||'';
 
5895
                        # For IIS setup, if pos_query is enabled we need to combine the URL to query strings
 
5896
                        if (! $foundparam && $pos_query >=0 && $field[$pos_query] && $field[$pos_query] ne '-') {
 
5897
                                $foundparam=1;
 
5898
                                $tokenquery='?';
 
5899
                                $standalonequery=$field[$pos_query];
 
5900
                                # Define query
 
5901
                                $field[$pos_url] .= '?'.$field[$pos_query];
 
5902
                        }
 
5903
                        if ($foundparam) {
 
5904
                                # Keep only params that are defined in URLWithQueryWithOnlyFollowingParameters
 
5905
                                my $newstandalonequery='';
 
5906
                                if (@URLWithQueryWithOnly) {
 
5907
                                        foreach (@URLWithQueryWithOnly) {
 
5908
                                                foreach my $p (split(/&/,$standalonequery)) {
 
5909
                                                        if ($URLNotCaseSensitive) { if ($p =~ /^$_=/i) { $newstandalonequery.="$p&"; last; } }
 
5910
                                                        else { if ($p =~ /^$_=/) { $newstandalonequery.="$p&"; last; } }
 
5911
                                                }
 
5912
                                        }
 
5913
                                        chop $newstandalonequery;
 
5914
                                }
 
5915
                                # Remove params that are marked to be ignored in URLWithQueryWithoutFollowingParameters
 
5916
                                elsif (@URLWithQueryWithout) {
 
5917
                                        foreach my $p (split(/&/,$standalonequery)) {
 
5918
                                                my $found=0;
 
5919
                                                foreach (@URLWithQueryWithout) {
 
5920
                                                        #if ($Debug) { debug("  Check if '$_=' is param '$p' to remove it from query",5); }
 
5921
                                                        if ($URLNotCaseSensitive) { if ($p =~ /^$_=/i) { $found=1; last; } }
 
5922
                                                        else { if ($p =~ /^$_=/) { $found=1; last; } }
 
5923
                                                }
 
5924
                                                if (! $found) { $newstandalonequery.="$p&"; }
 
5925
                                        }
 
5926
                                        chop $newstandalonequery;
 
5927
                                }
 
5928
                                else { $newstandalonequery=$standalonequery; }
 
5929
                                # Define query
 
5930
                                $field[$pos_url]=$urlwithnoquery;
 
5931
                                if ($newstandalonequery) { $field[$pos_url].="$tokenquery$newstandalonequery"; }
 
5932
                        }
 
5933
                }
 
5934
                else {
 
5935
                        # Trunc parameters of URL
 
5936
                        $field[$pos_url] =~ s/$regtruncurl//o;
 
5937
                        $urlwithnoquery=$field[$pos_url];
 
5938
                        $tokenquery=$1||'';
 
5939
                        $standalonequery=$2||'';
 
5940
                }
 
5941
                if ($URLWithAnchor && $anchor) { $field[$pos_url].="#$anchor"; }        # Restore anchor
 
5942
                # Here now urlwithnoquery is /mydir/mypage.ext, /mydir, /, /page#XXX
 
5943
                # Here now tokenquery is '' or '?' or ';'
 
5944
                # Here now standalonequery is '' or 'param1=x'
 
5945
 
 
5946
                # Define page and extension
 
5947
                #--------------------------
 
5948
                my $PageBool=1;
 
5949
                # Extension
 
5950
                my $extension;
 
5951
                if ($urlwithnoquery =~ /$regext/o || ($urlwithnoquery =~ /[\\\/]$/ && $DefaultFile[0] =~ /$regext/o)) {
 
5952
                        $extension=($LevelForFileTypesDetection>=2 || $MimeHashFamily{$1})?lc($1):'Unknown';
 
5953
                        if ($NotPageList{$extension}) { $PageBool=0; }
 
5954
                }
 
5955
                else {
 
5956
                        $extension='Unknown';
 
5957
                }
 
5958
 
 
5959
                # Analyze: misc tracker (must be before return code)
 
5960
                #---------------------------------------------------
 
5961
                if ($urlwithnoquery =~ /$regmisc/o) {
 
5962
                        if ($Debug) { debug("  Found an URL that is a MiscTracker record with standalonequery=$standalonequery",2); }
 
5963
                        my $foundparam=0;
 
5964
                        foreach (split(/&/,$standalonequery)) {
 
5965
                                if ($_ =~ /^screen=(\d+)x(\d+)/i)       { $foundparam++; $_screensize_h{"$1x$2"}++; next; }
 
5966
                                #if ($_ =~ /cdi=(\d+)/i)                        { $foundparam++; $_screendepth_h{"$1"}++; next; }
 
5967
                                if ($_ =~ /^java=(\w+)/i)                       { $foundparam++; if ($1 eq 'true') { $_misc_h{"JavaEnabled"}++; } next; }
 
5968
                                if ($_ =~ /^shk=(\w+)/i)                        { $foundparam++; if ($1 eq 'y')    { $_misc_h{"DirectorSupport"}++; } next; }
 
5969
                                if ($_ =~ /^fla=(\w+)/i)                        { $foundparam++; if ($1 eq 'y')    { $_misc_h{"FlashSupport"}++; } next; }
 
5970
                                if ($_ =~ /^rp=(\w+)/i)                         { $foundparam++; if ($1 eq 'y')    { $_misc_h{"RealPlayerSupport"}++; } next; }
 
5971
                                if ($_ =~ /^mov=(\w+)/i)                        { $foundparam++; if ($1 eq 'y')    { $_misc_h{"QuickTimeSupport"}++; } next; }
 
5972
                                if ($_ =~ /^wma=(\w+)/i)                        { $foundparam++; if ($1 eq 'y')    { $_misc_h{"WindowsMediaPlayerSupport"}++; } next; }
 
5973
                                if ($_ =~ /^pdf=(\w+)/i)                        { $foundparam++; if ($1 eq 'y')    { $_misc_h{"PDFSupport"}++; } next; }
 
5974
                        }
 
5975
                        if ($foundparam) { $_misc_h{"TotalMisc"}++; }
 
5976
                }
 
5977
 
 
5978
                # Analyze: favicon
 
5979
                #-----------------
 
5980
                if ($urlwithnoquery =~ /\/favicon\.ico$/i) {
 
5981
                        if (($field[$pos_code] != 404 || $urlwithnoquery !~ /\/.+\/favicon\.ico$/i) && ($field[$pos_agent] =~ /MSIE/)) {
 
5982
                                # We don't count one hit if (not on root and error) and MSIE
 
5983
                                # If error not on root, another hit will be made on root. If not MSIE, hit are made not only for "Adding".
 
5984
                                $_misc_h{'AddToFavourites'}++;  # Hit on favicon on root or without error, we count it
 
5985
                        }
 
5986
                        $countedtraffic=1;      # favicon is the only case not counted anywhere
 
5987
                }
 
5988
 
 
5989
                # Analyze: Worms
 
5990
                #---------------
 
5991
                if ($LevelForWormsDetection) {
 
5992
                        foreach (@WormsSearchIDOrder) {
 
5993
                                if ($field[$pos_url] =~ /$_/) {
 
5994
                                        # It's a worm
 
5995
                                        my $worm=&UnCompileRegex($_);
 
5996
                                        if ($Debug) { debug(" Record is a hit from a worm identified by '$worm'",2); }
 
5997
                                        $worm=$WormsHashID{$worm}||'unknown';
 
5998
                                        $_worm_h{$worm}++;
 
5999
                                        $_worm_k{$worm}+=int($field[$pos_size]);
 
6000
                                        $_worm_l{$worm}=$timerecord;
 
6001
                                        $countedtraffic=1;
 
6002
                                        if ($PageBool) { $_time_nv_p[$hourrecord]++; }
 
6003
                                        $_time_nv_h[$hourrecord]++;
 
6004
                                        $_time_nv_k[$hourrecord]+=int($field[$pos_size]);
 
6005
                                        last;
 
6006
                                }
 
6007
                        }
 
6008
                }
 
6009
                                
 
6010
                # Analyze: Status code
 
6011
                #---------------------
 
6012
                if (! $countedtraffic) {
 
6013
                if ($LogType eq 'W' || $LogType eq 'S') {               # HTTP record or Stream record
 
6014
                        if ($ValidHTTPCodes{$field[$pos_code]}) {       # Code is valid
 
6015
                                if ($field[$pos_code] == 304) { $field[$pos_size]=0; }
 
6016
                        }
 
6017
                        else {                                                                          # Code is not valid
 
6018
                                if ($field[$pos_code] !~ /^\d\d\d$/) { $field[$pos_code]=999; }
 
6019
                                $_errors_h{$field[$pos_code]}++;
 
6020
                                $_errors_k{$field[$pos_code]}+=int($field[$pos_size]);
 
6021
                                foreach my $code (keys %TrapInfosForHTTPErrorCodes) {
 
6022
                                        if ($field[$pos_code] == $code) {
 
6023
                                                my $newurl=substr($field[$pos_url],0,$MaxLengthOfStoredURL);
 
6024
                                                $newurl =~ s/[$URLQuerySeparators].*$//;
 
6025
                                                $_sider404_h{$newurl}++;
 
6026
                                                my $newreferer=$field[$pos_referer];
 
6027
                                                if (! $URLReferrerWithQuery) { $newreferer =~ s/[$URLQuerySeparators].*$//; }
 
6028
                                                $_referer404_h{$newurl}=$newreferer;
 
6029
                                                last;
 
6030
                                        }
 
6031
                                }
 
6032
                                if ($Debug) { debug(" Record stored in the status code chart (status code=$field[$pos_code])",2); }
 
6033
                                $countedtraffic=1;
 
6034
                                if ($PageBool) { $_time_nv_p[$hourrecord]++; }
 
6035
                                $_time_nv_h[$hourrecord]++;
 
6036
                                $_time_nv_k[$hourrecord]+=int($field[$pos_size]);
 
6037
                        }
 
6038
                }
 
6039
                elsif ($LogType eq 'M') {                                               # Mail record
 
6040
                        if (! $ValidSMTPCodes{$field[$pos_code]}) {     # Code is not valid
 
6041
                                $_errors_h{$field[$pos_code]}++;
 
6042
                                #$_errors_k{$field[$pos_code]}+=int($field[$pos_size]); # Useless since pos_size is often 0 or ? when error
 
6043
                                if ($Debug) { debug(" Record stored in the status code chart (status code=$field[$pos_code])",2); }
 
6044
                                $countedtraffic=1;
 
6045
                                if ($PageBool) { $_time_nv_p[$hourrecord]++; }
 
6046
                                $_time_nv_h[$hourrecord]++;
 
6047
                                $_time_nv_k[$hourrecord]+=int($field[$pos_size]);
 
6048
                        }
 
6049
                }
 
6050
                elsif ($LogType eq 'F') {                                               # FTP record
 
6051
                }
 
6052
                }
 
6053
                
 
6054
                # Analyze: Robot from robot database
 
6055
                #-----------------------------------
 
6056
                if (! $countedtraffic) {
 
6057
                if ($pos_agent >= 0) {
 
6058
                        if ($DecodeUA) { $field[$pos_agent] =~ s/%20/_/g; }     # This is to support servers (like Roxen) that writes user agent with %20 in it
 
6059
                        $UserAgent=$field[$pos_agent];
 
6060
 
 
6061
                        if ($LevelForRobotsDetection) {
 
6062
 
 
6063
                                my $uarobot=$TmpRobot{$UserAgent};
 
6064
                                if (! $uarobot) {
 
6065
                                        #study $UserAgent;              Does not increase speed
 
6066
                                        foreach (@RobotsSearchIDOrder) {
 
6067
                                                if ($UserAgent =~ /$_/) {
 
6068
                                                        my $bot=&UnCompileRegex($_);
 
6069
                                                        $TmpRobot{$UserAgent}=$uarobot="$bot";  # Last time, we won't search if robot or not. We know it is.
 
6070
                                                        if ($Debug) { debug("  UserAgent '$UserAgent' is added to TmpRobot with value '$bot'",2); }
 
6071
                                                        last;
 
6072
                                                }
 
6073
                                        }
 
6074
                                        if (! $uarobot) {                                                               # Last time, we won't search if robot or not. We know it's not.
 
6075
                                                $TmpRobot{$UserAgent}=$uarobot='-';
 
6076
                                        }
 
6077
                                }
 
6078
                                if ($uarobot ne '-') {
 
6079
                                        # If robot, we stop here
 
6080
                                        if ($Debug) { debug("  UserAgent '$UserAgent' contains robot ID '$uarobot'",2); }
 
6081
                                        $_robot_h{$uarobot}++;
 
6082
                                        $_robot_k{$uarobot}+=int($field[$pos_size]);
 
6083
                                        $_robot_l{$uarobot}=$timerecord;
 
6084
                                        if ($urlwithnoquery =~ /$regrobot/o) { $_robot_r{$uarobot}++; }
 
6085
                                        $countedtraffic=1;
 
6086
                                        if ($PageBool) { $_time_nv_p[$hourrecord]++; }
 
6087
                                        $_time_nv_h[$hourrecord]++;
 
6088
                                        $_time_nv_k[$hourrecord]+=int($field[$pos_size]);
 
6089
                                }
 
6090
                        }
 
6091
                }
 
6092
                }
 
6093
 
 
6094
                # Analyze: Robot from "hit on robots.txt" file
 
6095
                # --------------------------------------------
 
6096
                if (! $countedtraffic) {
 
6097
                if ($urlwithnoquery =~ /$regrobot/o) {
 
6098
                        if ($Debug) { debug("  It's an unknown robot",2); }
 
6099
                        $_robot_h{'unknown'}++;
 
6100
                        $_robot_k{'unknown'}+=int($field[$pos_size]);
 
6101
                        $_robot_l{'unknown'}=$timerecord;
 
6102
                        $_robot_r{'unknown'}++;
 
6103
                        $countedtraffic=1;
 
6104
                        if ($PageBool) { $_time_nv_p[$hourrecord]++; }
 
6105
                        $_time_nv_h[$hourrecord]++;
 
6106
                        $_time_nv_k[$hourrecord]+=int($field[$pos_size]);
 
6107
                }
 
6108
                }
 
6109
                
 
6110
                # Analyze: File type - Compression
 
6111
                #---------------------------------
 
6112
                if (! $countedtraffic) {
 
6113
                if ($LevelForFileTypesDetection) {
 
6114
                        $_filetypes_h{$extension}++;
 
6115
                        $_filetypes_k{$extension}+=int($field[$pos_size]);      # TODO can cause a warning
 
6116
                        # Compression
 
6117
                        if ($pos_compratio>=0 && ($field[$pos_compratio] =~ /(\d+)/)) { # Calculate in/out size from percentage (% is size after/before)
 
6118
                                #$_filetypes_gz_in{$extension}+=int($field[$pos_size]*100/((100-$1)||1));
 
6119
                                $_filetypes_gz_in{$extension}+=int($field[$pos_size]*100/($1||1));
 
6120
                                $_filetypes_gz_out{$extension}+=int($field[$pos_size]);
 
6121
                        }
 
6122
                        elsif ($pos_gzipin>=0 && $field[$pos_gzipin]) { # If in and out in log
 
6123
                                my ($notused,$in)=split(/:/,$field[$pos_gzipin]);
 
6124
                                my ($notused1,$out,$notused2)=split(/:/,$field[$pos_gzipout]);
 
6125
                                if ($out) {
 
6126
                                        $_filetypes_gz_in{$extension}+=$in;
 
6127
                                        $_filetypes_gz_out{$extension}+=$out;
 
6128
                                }
 
6129
                        }
 
6130
                }
 
6131
 
 
6132
                # Analyze: Date - Hour - Pages - Hits - Kilo
 
6133
                #-------------------------------------------
 
6134
                if ($PageBool) {
 
6135
                        # Replace default page name with / only ('if' is to increase speed when only 1 value in @DefaultFile)
 
6136
                        if (@DefaultFile > 1) { foreach my $elem (@DefaultFile) { if ($field[$pos_url] =~ s/\/$elem$/\//o) { last; } } }
 
6137
                        else { $field[$pos_url] =~ s/$regdefault/\//o; }
 
6138
                        # FirstTime and LastTime are First and Last human visits (so changed if access to a page)
 
6139
                        $FirstTime{$lastprocessedyearmonth}||=$timerecord;
 
6140
                        $LastTime{$lastprocessedyearmonth}=$timerecord;
 
6141
                        $DayPages{$yearmonthdayrecord}++;
 
6142
#                       $MonthPages{$lastprocessedyearmonth}++;
 
6143
                        $_url_p{$field[$pos_url]}++;                                                                            #Count accesses for page (page)
 
6144
                        $_url_k{$field[$pos_url]}+=int($field[$pos_size]);
 
6145
                        $_time_p[$hourrecord]++;                                                                                        #Count accesses for hour (page)
 
6146
                }
 
6147
                $_time_h[$hourrecord]++;
 
6148
                $_time_k[$hourrecord]+=int($field[$pos_size]);
 
6149
                $DayHits{$yearmonthdayrecord}++;                                                #Count accesses for hour (hit)
 
6150
                $DayBytes{$yearmonthdayrecord}+=int($field[$pos_size]); #Count accesses for hour (kb)
 
6151
#               $MonthHits{$lastprocessedyearmonth}++;
 
6152
#               $MonthBytes{$lastprocessedyearmonth}+=int($field[$pos_size]);
 
6153
 
 
6154
                # Analyze: Login
 
6155
                #---------------
 
6156
                if ($pos_logname>=0 && $field[$pos_logname] && $field[$pos_logname] ne '-') {
 
6157
                        $field[$pos_logname] =~ s/ /_/g; # This is to allow space in logname
 
6158
                        if ($LogFormat eq '6') { $field[$pos_logname] =~ s/^\"//; $field[$pos_logname] =~ s/\"$//;}     # logname field has " with Domino 6+
 
6159
                        if ($AuthenticatedUsersNotCaseSensitive) { $field[$pos_logname]=lc($field[$pos_logname]); }
 
6160
 
 
6161
                        # We found an authenticated user
 
6162
                        if ($PageBool) { $_login_p{$field[$pos_logname]}++; }                           #Count accesses for page (page)
 
6163
                        $_login_h{$field[$pos_logname]}++;                                                                      #Count accesses for page (hit)
 
6164
                        $_login_k{$field[$pos_logname]}+=int($field[$pos_size]);                        #Count accesses for page (kb)
 
6165
                        $_login_l{$field[$pos_logname]}=$timerecord;
 
6166
                }
 
6167
                }
 
6168
                
 
6169
                # Do DNS lookup
 
6170
                #--------------
 
6171
                my $Host=$field[$pos_host];
 
6172
                my $HostResolved='';
 
6173
 
 
6174
                if (! $countedtraffic) {
 
6175
                my $ip=0;
 
6176
                if ($DNSLookup) {                       # DNS lookup is 1 or 2
 
6177
                        if ($Host =~ /$regipv4/o) { $ip=4; }    # IPv4
 
6178
                        elsif ($Host =~ /$regipv6/o) { $ip=6; }                                         # IPv6
 
6179
                        if ($ip) {
 
6180
                                # Check in static DNS cache file
 
6181
                                $HostResolved=$MyDNSTable{$Host};
 
6182
                                if ($HostResolved) {
 
6183
                                        if ($Debug) { debug("  DNS lookup asked for $Host and found in static DNS cache file: $HostResolved",4); }
 
6184
                                }
 
6185
                                elsif ($DNSLookup==1) {
 
6186
                                        # Check in session cache (dynamic DNS cache file + session DNS cache)
 
6187
                                        $HostResolved=$TmpDNSLookup{$Host};
 
6188
                                        if (! $HostResolved) {
 
6189
                                                if (@SkipDNSLookupFor && &SkipDNSLookup($Host)) {
 
6190
                                                        $HostResolved=$TmpDNSLookup{$Host}='*';
 
6191
                                                        if ($Debug) { debug("  No need of reverse DNS lookup for $Host, skipped at user request.",4); }
 
6192
                                                }
 
6193
                                                else {
 
6194
                                                        if ($ip == 4) {
 
6195
                                                                my $lookupresult=gethostbyaddr(pack("C4",split(/\./,$Host)),AF_INET);   # This is very slow, may spend 20 seconds
 
6196
                                                                if (! $lookupresult || $lookupresult =~ /$regipv4/o || ! IsAscii($lookupresult)) {
 
6197
                                                                        $TmpDNSLookup{$Host}=$HostResolved='*';
 
6198
                                                                }
 
6199
                                                                else {
 
6200
                                                                        $TmpDNSLookup{$Host}=$HostResolved=$lookupresult;
 
6201
                                                                }
 
6202
                                                                if ($Debug) { debug("  Reverse DNS lookup for $Host done: $HostResolved",4); }
 
6203
                                                        }
 
6204
                                                        elsif ($ip == 6) {
 
6205
                                                                if ($PluginsLoaded{'GetResolvedIP'}{'ipv6'}) {
 
6206
                                                                        my $lookupresult=GetResolvedIP_ipv6($Host);
 
6207
                                                                        if (! $lookupresult || ! IsAscii($lookupresult)) {
 
6208
                                                                                $TmpDNSLookup{$Host}=$HostResolved='*';
 
6209
                                                                        }
 
6210
                                                                        else {
 
6211
                                                                                $TmpDNSLookup{$Host}=$HostResolved=$lookupresult;
 
6212
                                                                        }
 
6213
                                                                } else {
 
6214
                                                                        $TmpDNSLookup{$Host}=$HostResolved='*';
 
6215
                                                                        warning("Reverse DNS lookup for $Host not available without ipv6 plugin enabled.");
 
6216
                                                                }
 
6217
                                                        }
 
6218
                                                        else { error("Bad value vor ip"); }
 
6219
                                                }
 
6220
                                        }
 
6221
                                }
 
6222
                                else {
 
6223
                                        $HostResolved='*';
 
6224
                                        if ($Debug) { debug("  DNS lookup by static DNS cache file asked for $Host but not found.",4); }
 
6225
                                }
 
6226
                        }
 
6227
                        else {
 
6228
                                if ($Debug) { debug("  DNS lookup asked for $Host but this is not an IP address.",4); }
 
6229
                                $DNSLookupAlreadyDone=$LogFile;
 
6230
                        }
 
6231
                }
 
6232
                else {
 
6233
                        if ($Host =~ /$regipv4/o) { $HostResolved='*'; $ip=4; } # IPv4
 
6234
                        elsif ($Host =~ /$regipv6/o) { $HostResolved='*'; $ip=6; }                                              # IPv6
 
6235
                        if ($Debug) { debug("  No DNS lookup asked.",4); }
 
6236
                }
 
6237
 
 
6238
                # Analyze: Country (Top-level domain)
 
6239
                #------------------------------------
 
6240
                if ($Debug) { debug("  Search country (Host=$Host HostResolved=$HostResolved ip=$ip)",4); }
 
6241
                my $Domain='ip';
 
6242
                # Set $HostResolved to host and resolve domain
 
6243
                if ($HostResolved eq '*') {
 
6244
                        # $Host is an IP address and is not resolved (failed or not asked) or resolution gives an IP address
 
6245
                        $HostResolved = $Host;
 
6246
                        # Resolve Domain
 
6247
                        if ($PluginsLoaded{'GetCountryCodeByAddr'}{'geoipfree'}) { $Domain=GetCountryCodeByAddr_geoipfree($HostResolved); }
 
6248
                        elsif ($PluginsLoaded{'GetCountryCodeByAddr'}{'geoip'}) { $Domain=GetCountryCodeByAddr_geoip($HostResolved); }
 
6249
                }
 
6250
                else {
 
6251
                        # $Host was already a host name ($Host=name => $HostResolved='', $ip=0) or has been resolved ($Host=ip => $HostResolved defined, $ip>0)
 
6252
                        $HostResolved = lc($HostResolved?$HostResolved:$Host);
 
6253
                        # Resolve Domain
 
6254
                        if ($ip) {
 
6255
                                if ($PluginsLoaded{'GetCountryCodeByAddr'}{'geoipfree'}) { $Domain=GetCountryCodeByAddr_geoipfree($Host); }
 
6256
                                elsif ($PluginsLoaded{'GetCountryCodeByAddr'}{'geoip'}) { $Domain=GetCountryCodeByAddr_geoip($Host); }
 
6257
                                elsif ($HostResolved =~ /\.(\w+)$/) { $Domain=$1; }
 
6258
                        }
 
6259
                        else {
 
6260
                                if ($PluginsLoaded{'GetCountryCodeByName'}{'geoipfree'}) { $Domain=GetCountryCodeByName_geoipfree($HostResolved); }
 
6261
                                elsif ($PluginsLoaded{'GetCountryCodeByName'}{'geoip'}) { $Domain=GetCountryCodeByName_geoip($HostResolved); }
 
6262
                                elsif ($HostResolved =~ /\.(\w+)$/) { $Domain=$1; }
 
6263
                        }
 
6264
                }
 
6265
                # Store country
 
6266
                if ($PageBool) { $_domener_p{$Domain}++; }
 
6267
                $_domener_h{$Domain}++;
 
6268
                $_domener_k{$Domain}+=int($field[$pos_size]);
 
6269
 
 
6270
                # Analyze: Host, URL and Session
 
6271
                #-------------------------------
 
6272
                if ($PageBool) {
 
6273
                        my $timehostl=$_host_l{$HostResolved};
 
6274
                        if ($timehostl) {
 
6275
                                # A visit for this host was already detected
 
6276
# TODO everywhere there is $VISITTIMEOUT
 
6277
#                               $timehostl =~ /^\d\d\d\d\d\d(\d\d)/; my $daytimehostl=$1;
 
6278
#                               if ($timerecord > ($timehostl+$VISITTIMEOUT+($dateparts[3]>$daytimehostl?$NEWDAYVISITTIMEOUT:0))) {
 
6279
                                if ($timerecord > ($timehostl+$VISITTIMEOUT)) {
 
6280
                                        # This is a second visit or more
 
6281
                                        if (! $_waithost_s{$HostResolved}) {
 
6282
                                                # This is a second visit or more
 
6283
                                                # We count 'visit','exit','entry','DayVisits'
 
6284
                                                if ($Debug) { debug("  This is a second visit for $HostResolved.",4); }
 
6285
                                                my $timehosts=$_host_s{$HostResolved};
 
6286
                                                my $page=$_host_u{$HostResolved};
 
6287
                                                if ($page) { $_url_x{$page}++; }
 
6288
                                                $_url_e{$field[$pos_url]}++;
 
6289
                                                $DayVisits{$yearmonthdayrecord}++;
 
6290
                                                # We can't count session yet because we don't have the start so
 
6291
                                                # we save save params of first 'wait' session
 
6292
                                                $_waithost_l{$HostResolved}=$timehostl;
 
6293
                                                $_waithost_s{$HostResolved}=$timehosts;
 
6294
                                                $_waithost_u{$HostResolved}=$page;
 
6295
                                        }
 
6296
                                        else {
 
6297
                                                # This is third visit or more
 
6298
                                                # We count 'session','visit','exit','entry','DayVisits'
 
6299
                                                if ($Debug) { debug("  This is a third visit or more for $HostResolved.",4); }
 
6300
                                                my $timehosts=$_host_s{$HostResolved};
 
6301
                                                my $page=$_host_u{$HostResolved};
 
6302
                                                if ($page) { $_url_x{$page}++; }
 
6303
                                                $_url_e{$field[$pos_url]}++;
 
6304
                                                $DayVisits{$yearmonthdayrecord}++;
 
6305
                                                if ($timehosts) { $_session{GetSessionRange($timehosts,$timehostl)}++; }
 
6306
                                        }
 
6307
                                        # Save new session properties
 
6308
                                        $_host_s{$HostResolved}=$timerecord;
 
6309
                                        $_host_l{$HostResolved}=$timerecord;
 
6310
                                        $_host_u{$HostResolved}=$field[$pos_url];
 
6311
                                }
 
6312
                                elsif ($timerecord > $timehostl) {
 
6313
                                        # This is a same visit we can count
 
6314
                                        if ($Debug) { debug("  This is same visit still running for $HostResolved. host_l/host_u changed to $timerecord/$field[$pos_url]",4); }
 
6315
                                        $_host_l{$HostResolved}=$timerecord;
 
6316
                                        $_host_u{$HostResolved}=$field[$pos_url];
 
6317
                                }
 
6318
                                elsif ($timerecord == $timehostl) {
 
6319
                                        # This is a same visit we can count
 
6320
                                        if ($Debug) { debug("  This is same visit still running for $HostResolved. host_l/host_u changed to $timerecord/$field[$pos_url]",4); }
 
6321
                                        $_host_u{$HostResolved}=$field[$pos_url];
 
6322
                                }
 
6323
                                elsif ($timerecord < $_host_s{$HostResolved}) {
 
6324
                                        # Should happens only with not correctly sorted log files
 
6325
                                        if ($Debug) { debug("  This is same visit still running for $HostResolved with start not in order. host_s changed to $timerecord (entry page also changed if first visit)",4); }
 
6326
                                        if (! $_waithost_s{$HostResolved}) {
 
6327
                                                # We can reorder entry page only if it's the first visit found in this update run (The saved entry page was $_waithost_e if $_waithost_s{$HostResolved} is not defined. If second visit or more, entry was directly counted and not saved)
 
6328
                                                $_waithost_e{$HostResolved}=$field[$pos_url];
 
6329
                                        }
 
6330
                                        else {
 
6331
                                                # We can't change entry counted as we dont't know what was the url counted as entry
 
6332
                                        }
 
6333
                                        $_host_s{$HostResolved}=$timerecord;
 
6334
                                }
 
6335
                                else {
 
6336
                                        if ($Debug) { debug("  This is same visit still running for $HostResolved with hit between start and last hits. No change",4); }
 
6337
                                }
 
6338
                        }
 
6339
                        else {
 
6340
                                # This is a new visit (may be). First new visit found for this host. We save in wait array the entry page to count later
 
6341
                                if ($Debug) { debug("  New session (may be) for $HostResolved. Save in wait array to see later",4); }
 
6342
                                $_waithost_e{$HostResolved}=$field[$pos_url];
 
6343
                                # Save new session properties
 
6344
                                $_host_u{$HostResolved}=$field[$pos_url];
 
6345
                                $_host_s{$HostResolved}=$timerecord;
 
6346
                                $_host_l{$HostResolved}=$timerecord;
 
6347
                        }
 
6348
                        $_host_p{$HostResolved}++;
 
6349
                }
 
6350
                $_host_h{$HostResolved}++;
 
6351
                $_host_k{$HostResolved}+=int($field[$pos_size]);
 
6352
 
 
6353
                # Analyze: Browser - OS
 
6354
                #----------------------
 
6355
                if ($pos_agent >= 0 && $UserAgent) {
 
6356
 
 
6357
                        if ($LevelForBrowsersDetection) {
 
6358
 
 
6359
                                # Analyze: Browser
 
6360
                                #-----------------
 
6361
                                my $uabrowser=$TmpBrowser{$UserAgent};
 
6362
                                if (! $uabrowser) {
 
6363
                                        my $found=1;
 
6364
                                        # IE ?
 
6365
                                        if ($UserAgent =~ /$regvermsie/o && $UserAgent !~ /$regnotie/o) {
 
6366
                                                $_browser_h{"msie$2"}++;
 
6367
                                                $TmpBrowser{$UserAgent}="msie$2";
 
6368
                                        }
 
6369
                                        # Netscape 6.x, 7.x ... ?
 
6370
                                        elsif ($UserAgent =~ /$regvernetscape/o) {
 
6371
                                                $_browser_h{"netscape$1"}++;
 
6372
                                                $TmpBrowser{$UserAgent}="netscape$1";
 
6373
                                        }
 
6374
                                        # Netscape 3.x, 4.x ... ?
 
6375
                                        elsif ($UserAgent =~ /$regvermozilla/o && $UserAgent !~ /$regnotnetscape/o) {
 
6376
                                                $_browser_h{"netscape$2"}++;
 
6377
                                                $TmpBrowser{$UserAgent}="netscape$2";
 
6378
                                        }
 
6379
                                        # Other known browsers ?
 
6380
                                        else {
 
6381
                                                $found=0;
 
6382
                                                foreach (@BrowsersSearchIDOrder) {      # Search ID in order of BrowsersSearchIDOrder
 
6383
                                                        if ($UserAgent =~ /$_/) {
 
6384
                                                                my $browser=&UnCompileRegex($_);
 
6385
                                                                # TODO If browser is in a family, use version
 
6386
                                                                $_browser_h{"$browser"}++;
 
6387
                                                                $TmpBrowser{$UserAgent}="$browser";
 
6388
                                                                $found=1;
 
6389
                                                                last;
 
6390
                                                        }
 
6391
                                                }
 
6392
                                        }
 
6393
                                        # Unknown browser ?
 
6394
                                        if (!$found) {
 
6395
                                                $_browser_h{'Unknown'}++;
 
6396
                                                $TmpBrowser{$UserAgent}='Unknown';
 
6397
                                                my $newua=$UserAgent; $newua =~ tr/\+ /__/;
 
6398
                                                $_unknownrefererbrowser_l{$newua}=$timerecord;
 
6399
                                        }
 
6400
                                }
 
6401
                                else {
 
6402
                                        $_browser_h{$uabrowser}++;
 
6403
                                        if ($uabrowser eq 'Unknown') {
 
6404
                                                my $newua=$UserAgent; $newua =~ tr/\+ /__/;
 
6405
                                                $_unknownrefererbrowser_l{$newua}=$timerecord;
 
6406
                                        }
 
6407
                                }
 
6408
 
 
6409
                        }
 
6410
 
 
6411
                        if ($LevelForOSDetection) {
 
6412
 
 
6413
                                # Analyze: OS
 
6414
                                #------------
 
6415
                                my $uaos=$TmpOS{$UserAgent};
 
6416
                                if (! $uaos) {
 
6417
                                        my $found=0;
 
6418
                                        # in OSHashID list ?
 
6419
                                        foreach (@OSSearchIDOrder) {    # Search ID in order of OSSearchIDOrder
 
6420
                                                if ($UserAgent =~ /$_/) {
 
6421
                                                        my $osid=$OSHashID{&UnCompileRegex($_)};
 
6422
                                                        $_os_h{"$osid"}++;
 
6423
                                                        $TmpOS{$UserAgent}="$osid";
 
6424
                                                        $found=1;
 
6425
                                                        last;
 
6426
                                                }
 
6427
                                        }
 
6428
                                        # Unknown OS ?
 
6429
                                        if (!$found) {
 
6430
                                                $_os_h{'Unknown'}++;
 
6431
                                                $TmpOS{$UserAgent}='Unknown';
 
6432
                                                my $newua=$UserAgent; $newua =~ tr/\+ /__/;
 
6433
                                                $_unknownreferer_l{$newua}=$timerecord;
 
6434
                                        }
 
6435
                                }
 
6436
                                else {
 
6437
                                        $_os_h{$uaos}++;
 
6438
                                        if ($uaos eq 'Unknown') {
 
6439
                                                my $newua=$UserAgent; $newua =~ tr/\+ /__/;
 
6440
                                                $_unknownreferer_l{$newua}=$timerecord;
 
6441
                                        }
 
6442
                                }
 
6443
 
 
6444
                        }
 
6445
 
 
6446
                }
 
6447
                else {
 
6448
                        $_browser_h{'Unknown'}++;
 
6449
                        $_os_h{'Unknown'}++;
 
6450
                }
 
6451
 
 
6452
                # Analyze: Referer
 
6453
                #-----------------
 
6454
                my $found=0;
 
6455
                if ($pos_referer >= 0 && $LevelForRefererAnalyze && $field[$pos_referer]) {
 
6456
 
 
6457
                        # Direct ?
 
6458
                        if ($field[$pos_referer] eq '-' || $field[$pos_referer] eq 'bookmarks') {       # "bookmarks" is sent by Netscape, '-' by all others browsers
 
6459
                                # Direct access
 
6460
                                if ($PageBool) { $_from_p[0]++; }
 
6461
                                $_from_h[0]++;
 
6462
                                $found=1;
 
6463
                        }
 
6464
                        else {
 
6465
                                $field[$pos_referer] =~ /$regreferer/o;
 
6466
                                my $refererprot=$1;
 
6467
                                my $refererserver=($2||'').(! $3 || $3 eq ':80'?'':$3); # refererserver is www.xxx.com or www.xxx.com:81 but not www.xxx.com:80
 
6468
                                # HTML link ?
 
6469
                                if ($refererprot =~ /^http/i) {
 
6470
                                        #if ($Debug) { debug("  Analyze referer refererprot=$refererprot refererserver=$refererserver",5); }
 
6471
 
 
6472
                                        # Kind of origin
 
6473
                                        if (!$TmpRefererServer{$refererserver}) {       # is "=" if same site, "search egine key" if search engine, not defined otherwise
 
6474
                                                if ($refererserver =~ /^(www\.|)$SiteToAnalyzeWithoutwww/i) {
 
6475
                                                        # Intern (This hit came from another page of the site)
 
6476
                                                        if ($Debug) { debug("  Server '$refererserver' is added to TmpRefererServer with value '='",2); }
 
6477
                                                        $TmpRefererServer{$refererserver}='=';
 
6478
                                                        $found=1;
 
6479
                                                }
 
6480
                                                else {
 
6481
                                                        foreach (@HostAliases) {
 
6482
                                                                if ($refererserver =~ /$_/) {
 
6483
                                                                        # Intern (This hit came from another page of the site)
 
6484
                                                                        if ($Debug) { debug("  Server '$refererserver' is added to TmpRefererServer with value '='",2); }
 
6485
                                                                        $TmpRefererServer{$refererserver}='=';
 
6486
                                                                        $found=1;
 
6487
                                                                        last;
 
6488
                                                                }
 
6489
                                                        }
 
6490
                                                        if (! $found) {
 
6491
                                                                # Extern (This hit came from an external web site).
 
6492
        
 
6493
                                                                if ($LevelForSearchEnginesDetection) {
 
6494
        
 
6495
                                                                        foreach (@SearchEnginesSearchIDOrder) {         # Search ID in order of SearchEnginesSearchIDOrder
 
6496
                                                                                if ($refererserver =~ /$_/) {
 
6497
                                                                                        my $key=&UnCompileRegex($_);
 
6498
                                                                                        if (! $NotSearchEnginesKeys{$key} || $refererserver !~ /$NotSearchEnginesKeys{$key}/i) {
 
6499
                                                                                                # This hit came from the search engine $key
 
6500
                                                                                                if ($Debug) { debug("  Server '$refererserver' is added to TmpRefererServer with value '$key'",2); }
 
6501
                                                                                                $TmpRefererServer{$refererserver}=$SearchEnginesHashID{$key};
 
6502
                                                                                                $found=1;
 
6503
                                                                                        }
 
6504
                                                                                        last;
 
6505
                                                                                }
 
6506
                                                                        }
 
6507
 
 
6508
                                                                }
 
6509
                                                        }
 
6510
                                                }
 
6511
                                        }
 
6512
 
 
6513
                                        if ($TmpRefererServer{$refererserver}) {
 
6514
                                                if ($TmpRefererServer{$refererserver} eq '=') {
 
6515
                                                        # Intern (This hit came from another page of the site)
 
6516
                                                        if ($PageBool) { $_from_p[4]++; }
 
6517
                                                        $_from_h[4]++;
 
6518
                                                        $found=1;
 
6519
                                                }
 
6520
                                                else {
 
6521
                                                        # This hit came from a search engine
 
6522
                                                        if ($PageBool) { $_from_p[2]++; $_se_referrals_p{$TmpRefererServer{$refererserver}}++; }
 
6523
                                                        $_from_h[2]++;
 
6524
                                                        $_se_referrals_h{$TmpRefererServer{$refererserver}}++;
 
6525
                                                        $found=1;
 
6526
                                                        if ($PageBool && $LevelForKeywordsDetection) {
 
6527
                                                                # we will complete %_keyphrases hash array
 
6528
                                                                my @refurl=split(/\?/,$field[$pos_referer],2);  # TODO Use \? or [$URLQuerySeparators] ?
 
6529
                                                                if ($refurl[1]) {
 
6530
                                                                        # Extract params of referer query string (q=cache:mmm:www/zzz+aaa+bbb q=aaa+bbb/ccc key=ddd%20eee lang_en ie=UTF-8 ...)
 
6531
                                                                        if ($SearchEnginesKnownUrl{$TmpRefererServer{$refererserver}}) {        # Search engine with known URL syntax
 
6532
                                                                                my @paramlist=split(/&/,$KeyWordsNotSensitive?lc($refurl[1]):$refurl[1]);
 
6533
                                                                                foreach my $param (@paramlist) {
 
6534
                                                                                        if ($param =~ s/^$SearchEnginesKnownUrl{$TmpRefererServer{$refererserver}}//) {
 
6535
                                                                                                # We found good parameter
 
6536
                                                                                                # Now param is keyphrase: "cache:mmm:www/zzz+aaa+bbb/ccc+ddd%20eee'fff,ggg"
 
6537
                                                                                                $param =~ s/^(cache|related):[^\+]+//;  # Should ne useless since this is for hit on 'not pages'
 
6538
                                                                                                &ChangeWordSeparatorsIntoSpace($param); # Change [ aaa+bbb/ccc+ddd%20eee'fff,ggg ] into [ aaa bbb/ccc ddd eee fff ggg]
 
6539
                                                                                                $param =~ s/^ +//; $param =~ s/ +$//; $param =~ tr/ /\+/s;
 
6540
                                                                                                if ((length $param) > 0) { $_keyphrases{$param}++; }
 
6541
                                                                                                last;
 
6542
                                                                                        }
 
6543
                                                                                }
 
6544
                                                                        }
 
6545
                                                                        elsif ($LevelForKeywordsDetection >= 2) {                                                       # Search engine with unknown URL syntax
 
6546
                                                                                my @paramlist=split(/&/,$KeyWordsNotSensitive?lc($refurl[1]):$refurl[1]);
 
6547
                                                                                foreach my $param (@paramlist) {
 
6548
                                                                                        my $foundexcludeparam=0;
 
6549
                                                                                        foreach my $paramtoexclude (@WordsToCleanSearchUrl) {
 
6550
                                                                                                if ($param =~ /$paramtoexclude/i) { $foundexcludeparam=1; last; } # Not the param with search criteria
 
6551
                                                                                        }
 
6552
                                                                                        if ($foundexcludeparam) { next; }
 
6553
                                                                                        # We found good parameter
 
6554
                                                                                        $param =~ s/.*=//;
 
6555
                                                                                        # Now param is keyphrase: "aaa+bbb/ccc+ddd%20eee'fff,ggg"
 
6556
                                                                                        $param =~ s/^(cache|related):[^\+]+//;          # Should ne useless since this is for hit on 'not pages'
 
6557
                                                                                        &ChangeWordSeparatorsIntoSpace($param);         # Change [ aaa+bbb/ccc+ddd%20eee'fff,ggg ] into [ aaa bbb/ccc ddd eee fff ggg ]
 
6558
                                                                                        $param =~ s/^ +//; $param =~ s/ +$//; $param =~ tr/ /\+/s;
 
6559
                                                                                        if ((length $param) > 2) { $_keyphrases{$param}++; last; }
 
6560
                                                                                }
 
6561
                                                                        }
 
6562
                                                                }       # End of if refurl[1]
 
6563
                                                        }
 
6564
                                                }
 
6565
                                        }       # End of if ($TmpRefererServer)
 
6566
                                        else {
 
6567
                                                # This hit came from a site other than a search engine
 
6568
                                                if ($PageBool) { $_from_p[3]++; }
 
6569
                                                $_from_h[3]++;
 
6570
                                                # http://www.mysite.com/ must be same referer than http://www.mysite.com but .../mypage/ differs of .../mypage
 
6571
                                                #if ($refurl[0] =~ /^[^\/]+\/$/) { $field[$pos_referer] =~ s/\/$//; }   # Code moved in Save_History
 
6572
                                                # TODO: lowercase the value for referer server to have refering server not case sensitive
 
6573
                                                if ($URLReferrerWithQuery) {
 
6574
                                                        if ($PageBool) { $_pagesrefs_p{$field[$pos_referer]}++; }
 
6575
                                                        $_pagesrefs_h{$field[$pos_referer]}++;
 
6576
                                                }
 
6577
                                                else {
 
6578
                                                        # We discard query for referer
 
6579
                                                        if ($field[$pos_referer]=~/$regreferernoquery/o) {
 
6580
                                                                if ($PageBool) { $_pagesrefs_p{"$1"}++; }
 
6581
                                                                $_pagesrefs_h{"$1"}++;
 
6582
                                                        }
 
6583
                                                        else {
 
6584
                                                                if ($PageBool) { $_pagesrefs_p{$field[$pos_referer]}++; }
 
6585
                                                                $_pagesrefs_h{$field[$pos_referer]}++;
 
6586
                                                        }
 
6587
                                                }
 
6588
                                                $found=1;
 
6589
                                        }
 
6590
                                }
 
6591
 
 
6592
                                # News Link ?
 
6593
                                if (! $found && $refererprot =~ /^news/i) {
 
6594
                                        $found=1;
 
6595
                                        if ($PageBool) { $_from_p[5]++; }
 
6596
                                        $_from_h[5]++;
 
6597
                                }
 
6598
                        }
 
6599
                }
 
6600
 
 
6601
                # Origin not found
 
6602
                if (!$found) {
 
6603
                        if ($ShowUnknownOrigin) { print "Unknown origin: $field[$pos_referer]\n"; }
 
6604
                        if ($PageBool) { $_from_p[1]++; }
 
6605
                        $_from_h[1]++;
 
6606
                }
 
6607
 
 
6608
                # Analyze: EMail
 
6609
                #---------------
 
6610
                if ($pos_emails>=0 && $field[$pos_emails]) {
 
6611
                        if ($field[$pos_emails] eq '<>') { $field[$pos_emails]='Unknown'; }
 
6612
                        elsif ($field[$pos_emails] !~ /\@/) { $field[$pos_emails].="\@$SiteDomain"; }
 
6613
                        $_emails_h{lc($field[$pos_emails])}++;                                                                  #Count accesses for sender email (hit)
 
6614
                        $_emails_k{lc($field[$pos_emails])}+=int($field[$pos_size]);                    #Count accesses for sender email (kb)
 
6615
                        $_emails_l{lc($field[$pos_emails])}=$timerecord;
 
6616
                }
 
6617
                if ($pos_emailr>=0 && $field[$pos_emailr]) {
 
6618
                        if ($field[$pos_emailr] !~ /\@/) { $field[$pos_emailr].="\@$SiteDomain"; }
 
6619
                        $_emailr_h{lc($field[$pos_emailr])}++;                                                                  #Count accesses for receiver email (hit)
 
6620
                        $_emailr_k{lc($field[$pos_emailr])}+=int($field[$pos_size]);                    #Count accesses for receiver email (kb)
 
6621
                        $_emailr_l{lc($field[$pos_emailr])}=$timerecord;
 
6622
                }
 
6623
                }
 
6624
 
 
6625
                # Check cluster
 
6626
                #--------------
 
6627
                if ($pos_cluster>=0) {
 
6628
                        if ($PageBool) { $_cluster_p{$field[$pos_cluster]}++; }                         #Count accesses for page (page)
 
6629
                        $_cluster_h{$field[$pos_cluster]}++;                                                            #Count accesses for page (hit)
 
6630
                        $_cluster_k{$field[$pos_cluster]}+=int($field[$pos_size]);                      #Count accesses for page (kb)
 
6631
                }
 
6632
 
 
6633
                # Analyze: Extra
 
6634
                #---------------
 
6635
                foreach my $extranum (1..@ExtraName-1) {
 
6636
                        if ($Debug) { debug("  Process extra analyze $extranum",4); }
 
6637
 
 
6638
                        # Check conditions
 
6639
                        my $conditionok=0;
 
6640
                        foreach my $condnum (0..@{$ExtraConditionType[$extranum]}-1) {
 
6641
                                my $conditiontype=$ExtraConditionType[$extranum][$condnum];
 
6642
                                my $conditiontypeval=$ExtraConditionTypeVal[$extranum][$condnum];
 
6643
                                if ($conditiontype eq 'URL') {
 
6644
                                        if ($Debug) { debug("  Check condition '$conditiontype' must contain '$conditiontypeval' in $urlwithnoquery.",5); }
 
6645
                                        if ($urlwithnoquery =~ /$conditiontypeval/) { $conditionok=1; last; }
 
6646
                                }
 
6647
                                elsif ($conditiontype eq 'QUERY_STRING') {
 
6648
                                        if ($Debug) { debug("  Check condition '$conditiontype' must contain '$conditiontypeval' in $standalonequery.",5); }
 
6649
                                        if ($standalonequery =~ /$conditiontypeval/) {  $conditionok=1; last; }
 
6650
                                }
 
6651
                                elsif ($conditiontype eq 'REFERER') {
 
6652
                                        if ($Debug) { debug("  Check condition '$conditiontype' must contain '$conditiontypeval' in $field[$pos_referer]",5); }
 
6653
                                        if ($field[$pos_referer] =~ /$conditiontypeval/) { $conditionok=1; last; }
 
6654
                                }
 
6655
                                elsif ($conditiontype eq 'UA') {
 
6656
                                        if ($Debug) { debug("  Check condition '$conditiontype' must contain '$conditiontypeval' in $field[$pos_agent]",5); }
 
6657
                                        if ($field[$pos_agent] =~ /$conditiontypeval/) { $conditionok=1; last; }
 
6658
                                }
 
6659
                                elsif ($conditiontype eq 'HOST') {
 
6660
                                        if ($Debug) { debug("  Check condition '$conditiontype' must contain '$conditiontypeval' in $field[$pos_host]",5); }
 
6661
                                        if ($HostResolved =~ /$conditiontypeval/) { $conditionok=1; last; }
 
6662
                                }
 
6663
                                else { error("Wrong value of parameter ExtraSectionCondition$extranum"); }
 
6664
                        }
 
6665
                        if (! $conditionok && @{$ExtraConditionType[$extranum]}) { next; }      # End for this section
 
6666
                        
 
6667
                        if ($Debug) { debug("  No condition or Condition is OK. Now we extract value for first column of extra chart.",5); }
 
6668
                        
 
6669
                        # Determine actual column value to use.
 
6670
                        my $rowkeyval;
 
6671
                        my $rowkeyok=0;
 
6672
                        foreach my $rowkeynum (0..@{$ExtraFirstColumnValuesType[$extranum]}-1) {
 
6673
                                my $rowkeytype=$ExtraFirstColumnValuesType[$extranum][$rowkeynum];
 
6674
                                my $rowkeytypeval=$ExtraFirstColumnValuesTypeVal[$extranum][$rowkeynum];
 
6675
                                if ($rowkeytype eq 'URL') { 
 
6676
                                        if ($urlwithnoquery =~ /$rowkeytypeval/) { $rowkeyval = "$1"; $rowkeyok = 1; last; }
 
6677
                                } 
 
6678
                                elsif ($rowkeytype eq 'QUERY_STRING') {
 
6679
                                        if ($Debug) { debug("  Extract value from '$standalonequery' with regex '$rowkeytypeval'.",5); }
 
6680
                                        if ($standalonequery =~ /$rowkeytypeval/) { $rowkeyval = "$1"; $rowkeyok = 1; last; }
 
6681
                                }
 
6682
                                elsif ($rowkeytype eq 'REFERER') {
 
6683
                                        if ($field[$pos_referer] =~ /$rowkeytypeval/) { $rowkeyval = "$1"; $rowkeyok = 1; last; }
 
6684
                                }
 
6685
                                elsif ($rowkeytype eq 'UA') {
 
6686
                                        if ($field[$pos_agent] =~ /$rowkeytypeval/) { $rowkeyval = "$1"; $rowkeyok = 1; last; }
 
6687
                                }
 
6688
                                elsif ($rowkeytype eq 'HOST') {
 
6689
                                        if ($HostResolved =~ /$rowkeytypeval/) { $rowkeyval = "$1"; $rowkeyok = 1; last; }
 
6690
                                }
 
6691
                                else { error("Wrong value of parameter ExtraSectionFirstColumnValues$extranum"); }
 
6692
                        }
 
6693
                        if (! $rowkeyok) { next; }      # End for this section
 
6694
                        if ($Debug) { debug("  Key val was found: $rowkeyval",5); }
 
6695
 
 
6696
                        # Here we got all values to increase counters
 
6697
                        if ($PageBool && $ExtraStatTypes[$extranum] =~ /P/i) { ${'_section_' . $extranum . '_p'}{$rowkeyval}++; }
 
6698
                        ${'_section_' . $extranum . '_h'}{$rowkeyval}++;        # Must be set
 
6699
                        if ($ExtraStatTypes[$extranum] =~ /B/i) { ${'_section_' . $extranum . '_k'}{$rowkeyval}+=int($field[$pos_size]); }
 
6700
                        if ($ExtraStatTypes[$extranum] =~ /L/i) {
 
6701
                                if (${'_section_' . $extranum . '_l'}{$rowkeyval}||0 < $timerecord) { ${'_section_' . $extranum . '_l'}{$rowkeyval}=$timerecord; }
 
6702
                        }
 
6703
                        # Check to avoid too large extra sections
 
6704
                        if (scalar keys %{'_section_' . $extranum . '_h'} > $MAXDIFFEXTRA) {
 
6705
                                error("Too many (more than MAXDIFFEXTRA=$MAXDIFFEXTRA) different values for row keys of extra section $extranum. Are you sure you want to track an array with so many values (may be your ExtraSection setup is wrong) ? If yes, increase the MAXDIFFEXTRA constant in awstats.pl");
 
6706
                        }
 
6707
                }
 
6708
 
 
6709
                # Every 20,000 approved lines after a flush, we test to clean too large hash arrays to flush data in tmp file
 
6710
                if (++$counterforflushtest >= 20000) {
 
6711
                #if (++$counterforflushtest >= 1) {
 
6712
                        if ((scalar keys %_host_u) > ($LIMITFLUSH<<2) || (scalar keys %_url_p) > $LIMITFLUSH) {
 
6713
                                # warning("Warning: Try to run AWStats update process more frequently to analyze smaler log files.");
 
6714
                                if ($^X =~ /activestate/i || $^X =~ /activeperl/i) {
 
6715
                                        # We don't flush if perl is activestate to avoid slowing process because of memory hole
 
6716
                                }
 
6717
                                else {
 
6718
                                        # Clean tmp hash arrays
 
6719
                                        #%TmpDNSLookup = ();
 
6720
                                        %TmpOS = %TmpRefererServer = %TmpRobot = %TmpBrowser = ();
 
6721
                                        # We flush if perl is not activestate
 
6722
                                        print "Flush history file on disk";
 
6723
                                        if ((scalar keys %_host_u) > ($LIMITFLUSH<<2)) { print " (unique hosts reach flush limit of ".($LIMITFLUSH<<2).")"; }
 
6724
                                        if ((scalar keys %_url_p) > $LIMITFLUSH) { print " (unique url reach flush limit of ".($LIMITFLUSH).")"; }
 
6725
                                        print "\n";
 
6726
                                        if ($Debug) {
 
6727
                                                debug("End of set of $counterforflushtest records: Some hash arrays are too large. We flush and clean some.",2);
 
6728
                                                print " _host_p:".(scalar keys %_host_p)." _host_h:".(scalar keys %_host_h)." _host_k:".(scalar keys %_host_k)." _host_l:".(scalar keys %_host_l)." _host_s:".(scalar keys %_host_s)." _host_u:".(scalar keys %_host_u)."\n";
 
6729
                                                print " _url_p:".(scalar keys %_url_p)." _url_k:".(scalar keys %_url_k)." _url_e:".(scalar keys %_url_e)." _url_x:".(scalar keys %_url_x)."\n";
 
6730
                                                print " _waithost_e:".(scalar keys %_waithost_e)." _waithost_l:".(scalar keys %_waithost_l)." _waithost_s:".(scalar keys %_waithost_s)." _waithost_u:".(scalar keys %_waithost_u)."\n";
 
6731
                                        }
 
6732
                                        &Read_History_With_TmpUpdate($lastprocessedyear,$lastprocessedmonth,1,1,"all",($lastlinenumber+$NbOfLinesParsed),$lastlineoffset,&CheckSum($_));
 
6733
                                        &GetDelaySinceStart(1); $NbOfLinesShowsteps=1;
 
6734
                                }
 
6735
                        }
 
6736
                        $counterforflushtest=0;
 
6737
                }
 
6738
 
 
6739
        }       # End of loop for processing new record.
 
6740
 
 
6741
        if ($Debug) {
 
6742
                debug(" _host_p:".(scalar keys %_host_p)." _host_h:".(scalar keys %_host_h)." _host_k:".(scalar keys %_host_k)." _host_l:".(scalar keys %_host_l)." _host_s:".(scalar keys %_host_s)." _host_u:".(scalar keys %_host_u)."\n",1);
 
6743
                debug(" _url_p:".(scalar keys %_url_p)." _url_k:".(scalar keys %_url_k)." _url_e:".(scalar keys %_url_e)." _url_x:".(scalar keys %_url_x)."\n",1);
 
6744
                debug(" _waithost_e:".(scalar keys %_waithost_e)." _waithost_l:".(scalar keys %_waithost_l)." _waithost_s:".(scalar keys %_waithost_s)." _waithost_u:".(scalar keys %_waithost_u)."\n",1);
 
6745
                debug("End of processing log file (AWStats memory cache is TmpDNSLookup=".(scalar keys %TmpDNSLookup)." TmpBrowser=".(scalar keys %TmpBrowser)." TmpOS=".(scalar keys %TmpOS)." TmpRefererServer=".(scalar keys %TmpRefererServer)." TmpRobot=".(scalar keys %TmpRobot).")",1);
 
6746
        }
 
6747
 
 
6748
        # Save current processed month $lastprocessedmonth
 
6749
        # If lastprocessedmonth > 0 means there is at least one approved new record in log or at least one existing history file
 
6750
        if ($lastprocessedmonth) {      # TODO: Do not save if we are sure a flush was just already done
 
6751
                # Get last line
 
6752
                seek(LOG,$lastlineoffset,0);
 
6753
                my $line=<LOG>;
 
6754
                chomp $line; $line =~ s/\r$//;
 
6755
                if (! $NbOfLinesParsed) {
 
6756
                        # TODO If there was no lines parsed (log was empty), we only update LastUpdate line with YYYYMMDDHHMMSS 0 0 0 0 0
 
6757
                        &Read_History_With_TmpUpdate($lastprocessedyear,$lastprocessedmonth,1,1,"all",($lastlinenumber+$NbOfLinesParsed),$lastlineoffset,&CheckSum($line));
 
6758
                }
 
6759
                else {
 
6760
                        &Read_History_With_TmpUpdate($lastprocessedyear,$lastprocessedmonth,1,1,"all",($lastlinenumber+$NbOfLinesParsed),$lastlineoffset,&CheckSum($line));
 
6761
                }
 
6762
        }
 
6763
 
 
6764
        if ($Debug) { debug("Close log file \"$LogFile\""); }
 
6765
        close LOG || error("Command for pipe '$LogFile' failed");
 
6766
 
 
6767
        # Process the Rename - Archive - Purge phase
 
6768
        my $renameok=1; my $archiveok=1;
 
6769
 
 
6770
        # Open Log file for writing if PurgeLogFile is on
 
6771
        if ($PurgeLogFile == 1) {
 
6772
                if ($ArchiveLogRecords == 1) {
 
6773
                        $ArchiveFileName="$DirData/${PROG}_archive$FileSuffix.log";
 
6774
                        open(LOG,"+<$LogFile") || error("Enable to archive log records of \"$LogFile\" into \"$ArchiveFileName\" because source can't be opened for read and write: $!<br />\n");
 
6775
                }
 
6776
                else {
 
6777
                        open(LOG,"+<$LogFile");
 
6778
                }
 
6779
                binmode LOG;
 
6780
        }
 
6781
 
 
6782
        # Rename all HISTORYTMP files into HISTORYTXT
 
6783
        &Rename_All_Tmp_History;
 
6784
 
 
6785
        # Purge Log file if option is on and all renaming are ok
 
6786
        if ($PurgeLogFile == 1) {
 
6787
                # Archive LOG file into ARCHIVELOG
 
6788
                if ($ArchiveLogRecords == 1) {
 
6789
                        if ($Debug) { debug("Start of archiving log file"); }
 
6790
                        open(ARCHIVELOG,">>$ArchiveFileName") || error("Couldn't open file \"$ArchiveFileName\" to archive log: $!");
 
6791
                        binmode ARCHIVELOG;
 
6792
                        while (<LOG>) {
 
6793
                                if (! print ARCHIVELOG $_) { $archiveok=0; last; }
 
6794
                        }
 
6795
                        close(ARCHIVELOG) || error("Archiving failed during closing archive: $!");
 
6796
                        if ($SaveDatabaseFilesWithPermissionsForEveryone) {     chmod 0666,"$ArchiveFileName"; }
 
6797
                        if ($Debug) { debug("End of archiving log file"); }
 
6798
                }
 
6799
                # If rename and archive ok
 
6800
                if ($renameok && $archiveok) {
 
6801
                        if ($Debug) { debug("Purge log file"); }
 
6802
                        my $bold=($ENV{'GATEWAY_INTERFACE'}?'<b>':'');
 
6803
                        my $unbold=($ENV{'GATEWAY_INTERFACE'}?'</b>':'');
 
6804
                        my $br=($ENV{'GATEWAY_INTERFACE'}?'<br />':'');
 
6805
                        truncate(LOG,0) || warning("Warning: $bold$PROG$unbold couldn't purge logfile \"$bold$LogFile$unbold\".$br\nChange your logfile permissions to allow write for your web server CGI process or change PurgeLogFile=1 into PurgeLogFile=0 in configure file and think to purge sometines manually your logfile (just after running an update process to not loose any not already processed records your log file contains).");
 
6806
                }
 
6807
                close(LOG);
 
6808
        }
 
6809
 
 
6810
        if ($DNSLookup==1 && $DNSLookupAlreadyDone) {
 
6811
                # DNSLookup warning
 
6812
                my $bold=($ENV{'GATEWAY_INTERFACE'}?'<b>':'');
 
6813
                my $unbold=($ENV{'GATEWAY_INTERFACE'}?'</b>':'');
 
6814
                my $br=($ENV{'GATEWAY_INTERFACE'}?'<br />':'');
 
6815
                warning("Warning: $bold$PROG$unbold has detected that some hosts names were already resolved in your logfile $bold$DNSLookupAlreadyDone$unbold.$br\nIf DNS lookup was already made by the logger (web server), you should change your setup DNSLookup=$DNSLookup into DNSLookup=0 to increase $PROG speed.");
 
6816
        }
 
6817
        if ($DNSLookup==1 && $NbOfNewLines) {
 
6818
                # Save new DNS last update cache file
 
6819
                Save_DNS_Cache_File(\%TmpDNSLookup,"$DirData/$DNSLastUpdateCacheFile","$FileSuffix");   # Save into file using FileSuffix
 
6820
        }
 
6821
 
 
6822
        if ($EnableLockForUpdate) {
 
6823
                # Remove lock
 
6824
                &Lock_Update(0);
 
6825
                # Restore signals handler
 
6826
                $SIG{INT} = 'DEFAULT';  # 2
 
6827
                #$SIG{KILL} = 'DEFAULT';        # 9
 
6828
                #$SIG{TERM} = 'DEFAULT';        # 15
 
6829
        }
 
6830
 
 
6831
}
 
6832
# End of log processing if ($UPdateStats)
 
6833
 
 
6834
 
 
6835
#---------------------------------------------------------------------
 
6836
# SHOW REPORT
 
6837
#---------------------------------------------------------------------
 
6838
 
 
6839
if (scalar keys %HTMLOutput) {
 
6840
 
 
6841
        my $max_p; my $max_h; my $max_k; my $max_v;
 
6842
        my $total_u; my $total_v; my $total_p; my $total_h; my $total_k; my $total_e; my $total_x; my $total_s; my $total_l; my $total_r;
 
6843
        my $average_u; my $average_v; my $average_p; my $average_h; my $average_k; my $average_s;
 
6844
        my $rest_p; my $rest_h; my $rest_k; my $rest_e; my $rest_x; my $rest_s; my $rest_l; my $rest_r;
 
6845
        my $average_nb;
 
6846
 
 
6847
        # Define the NewLinkParams for main chart
 
6848
        my $NewLinkParams=${QueryString};
 
6849
        $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
6850
        $NewLinkParams =~ s/(^|&)output(=\w*|$)//i;
 
6851
        $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
6852
        $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
6853
        my $NewLinkTarget='';
 
6854
        if ($DetailedReportsOnNewWindows) { $NewLinkTarget=" target=\"awstatsbis\""; }
 
6855
        if (($FrameName eq 'mainleft' || $FrameName eq 'mainright') && $DetailedReportsOnNewWindows < 2) {
 
6856
                $NewLinkParams.="&framename=mainright";
 
6857
                $NewLinkTarget=" target=\"mainright\"";
 
6858
        }
 
6859
        $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
6860
        if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
6861
 
 
6862
        if ($FrameName ne 'mainleft') {
 
6863
 
 
6864
                # READING DATA
 
6865
                #-------------
 
6866
                &Init_HashArray();
 
6867
 
 
6868
                # Loop on each month of year
 
6869
                for (my $ix=12; $ix>=1; $ix--) {
 
6870
                        my $monthix=sprintf("%02s",$ix);
 
6871
                        if ($MonthRequired eq 'all' || $monthix eq $MonthRequired) {
 
6872
                                &Read_History_With_TmpUpdate($YearRequired,$monthix,0,0,"all");                         # Read full history file
 
6873
                        }
 
6874
                        elsif (($HTMLOutput{'main'} && $ShowMonthStats) || $HTMLOutput{'alldays'}) {
 
6875
                                &Read_History_With_TmpUpdate($YearRequired,$monthix,0,0,"general time");        # Read general and time sections.
 
6876
                        }
 
6877
                }
 
6878
        }
 
6879
 
 
6880
        # HTMLHeadSection
 
6881
        if ($FrameName ne 'index' && $FrameName ne 'mainleft') {
 
6882
                print "<a name=\"top\">&nbsp;</a>\n\n";
 
6883
                print "$HTMLHeadSection\n";
 
6884
                print "\n";
 
6885
        }
 
6886
 
 
6887
        # Call to plugins' function AddHTMLBodyHeader
 
6888
        foreach my $pluginname (keys %{$PluginsLoaded{'AddHTMLBodyHeader'}})  {
 
6889
                my $function="AddHTMLBodyHeader_$pluginname()";
 
6890
                eval("$function");
 
6891
        }
 
6892
 
 
6893
        # MENU
 
6894
        #---------------------------------------------------------------------
 
6895
        if ($ShowMenu || $FrameName eq 'mainleft') {
 
6896
                if ($Debug) { debug("ShowMenu",2); }
 
6897
                my $frame=($FrameName eq 'mainleft');
 
6898
                print "$Center<a name=\"menu\">&nbsp;</a>\n";
 
6899
 
 
6900
                my $WIDTHMENU1=($FrameName eq 'mainleft'?$FRAMEWIDTH:150);
 
6901
                
 
6902
                if ($FrameName ne 'mainleft') {
 
6903
                        my $NewLinkParams=${QueryString};
 
6904
                        $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
6905
                        $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
6906
                        $NewLinkParams =~ s/(^|&)year=[^&]*//i;
 
6907
                        $NewLinkParams =~ s/(^|&)month=[^&]*//i;
 
6908
                        $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
6909
                        $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
6910
                        my $NewLinkTarget='';
 
6911
                        if ($FrameName eq 'mainright') { $NewLinkTarget=" target=\"_parent\""; }
 
6912
                        print "<form name=\"FormDateFilter\" action=\"".XMLEncode("$AWScript?${NewLinkParams}")."\" style=\"padding: 0px 0px 0px 0px; margin-top: 0\"$NewLinkTarget>\n";
 
6913
                }
 
6914
 
 
6915
                if ($QueryString !~ /buildpdf/i) {
 
6916
                        print "<table class=\"aws_border\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">\n";
 
6917
                        print "<tr><td>\n";
 
6918
                        print "<table class=\"aws_data\" border=\"0\" cellpadding=\"1\" cellspacing=\"0\" width=\"100%\">\n";
 
6919
                }
 
6920
                else {
 
6921
                        print "<table width=\"100%\">\n";       
 
6922
                }
 
6923
 
 
6924
                if ($FrameName ne 'mainright') {
 
6925
                        # Print Statistics Of
 
6926
                        if ($FrameName eq 'mainleft') { print "<tr><td class=\"awsm\"><b>$Message[7]:</b></td></tr><tr><td class=\"aws\"><span style=\"font-size: 12px;\">$SiteDomain</span></td>"; }
 
6927
                        else { print "<tr><td class=\"aws\" valign=\"middle\"><b>$Message[7]:</b>&nbsp;</td><td class=\"aws\"><span style=\"font-size: 14px;\">$SiteDomain</span></td>"; }
 
6928
 
 
6929
                        # Logo and flags
 
6930
                        if ($FrameName ne 'mainleft') {
 
6931
                                if ($LogoLink =~ "http://awstats.sourceforge.net") {
 
6932
                                        print "<td align=\"right\" rowspan=\"3\"><a href=\"".XMLEncode($LogoLink)."\" target=\"awstatshome\"><img src=\"$DirIcons/other/$Logo\" border=\"0\"".AltTitle(ucfirst($PROG)." Web Site")." /></a>";
 
6933
                                }
 
6934
                                else {
 
6935
                                        print "<td align=\"right\" rowspan=\"3\"><a href=\"".XMLEncode($LogoLink)."\" target=\"awstatshome\"><img src=\"$DirIcons/other/$Logo\" border=\"0\" /></a>";
 
6936
                                }
 
6937
                                if (! $StaticLinks) { print "<br />"; Show_Flag_Links($Lang); }
 
6938
                                print "</td>";
 
6939
                        }
 
6940
                        print  "</tr>\n";
 
6941
                }
 
6942
                if ($FrameName ne 'mainleft') {
 
6943
                        # Print Last Update
 
6944
                        print "<tr valign=\"middle\"><td class=\"aws\" valign=\"middle\" width=\"$WIDTHMENU1\"><b>$Message[35]:</b>&nbsp;</td>";
 
6945
                        print "<td class=\"aws\" valign=\"middle\"><span style=\"font-size: 12px;\">";
 
6946
                        if ($LastUpdate) { print Format_Date($LastUpdate,0); }
 
6947
                        else {
 
6948
                                # Here NbOfOldLines = 0 (because LastUpdate is not defined)
 
6949
                                if (! $UpdateStats) { print "<span style=\"color: #880000\">$Message[24]</span>"; }
 
6950
                                else { print "<span style=\"color: #880000\">No qualified records found in log ($NbOfLinesCorrupted corrupted, $NbOfLinesDropped dropped)</span>"; }
 
6951
                                
 
6952
                        }
 
6953
                        print "</span>";
 
6954
                        # Print Update Now link
 
6955
                        if ($AllowToUpdateStatsFromBrowser && ! $StaticLinks) {
 
6956
                                my $NewLinkParams=${QueryString};
 
6957
                                $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
6958
                                $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
6959
                                $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
6960
                                if ($FrameName eq 'mainright') { $NewLinkParams.="&framename=mainright"; }
 
6961
                                $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
6962
                                if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
6963
                                print "&nbsp; &nbsp; &nbsp; &nbsp;";
 
6964
                                print "<a href=\"".XMLEncode("$AWScript?${NewLinkParams}update=1")."\">$Message[74]</a>";
 
6965
                        }
 
6966
                        print "</td>";
 
6967
 
 
6968
                        # Logo and flags
 
6969
                        if ($FrameName eq 'mainright') {
 
6970
                                if ($LogoLink =~ "http://awstats.sourceforge.net") {
 
6971
                                        print "<td align=\"right\" rowspan=\"2\"><a href=\"".XMLEncode($LogoLink)."\" target=\"awstatshome\"><img src=\"$DirIcons/other/$Logo\" border=\"0\"".AltTitle(ucfirst($PROG)." Web Site")." /></a>\n";
 
6972
                                }
 
6973
                                else {
 
6974
                                        print "<td align=\"right\" rowspan=\"2\"><a href=\"".XMLEncode($LogoLink)."\" target=\"awstatshome\"><img src=\"$DirIcons/other/$Logo\" border=\"0\" /></a>\n";
 
6975
                                }
 
6976
                                if (! $StaticLinks) { print "<br />"; Show_Flag_Links($Lang); }
 
6977
                                print "</td>";
 
6978
                        }
 
6979
 
 
6980
                        print "</tr>\n";
 
6981
                        # Print selected period of analysis (month and year required)
 
6982
                        print "<tr><td class=\"aws\" valign=\"middle\"><b>$Message[133]:</b></td>";
 
6983
                        print "<td class=\"aws\" valign=\"middle\">";
 
6984
                        if ($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks) {
 
6985
                                print "<select class=\"aws_formfield\" name=\"month\">\n";
 
6986
                                foreach (1..12) { my $monthix=sprintf("%02s",$_); print "<option".($MonthRequired eq "$monthix"?" selected=\"true\"":"")." value=\"$monthix\">$MonthNumLib{$monthix}</option>\n"; }
 
6987
                                if ($AllowFullYearView >= 2) {
 
6988
                                        print "<option".($MonthRequired eq 'all'?" selected=\"true\"":"")." value='all'>- $Message[6] -</option>\n";
 
6989
                                }
 
6990
                                print "</select>\n";
 
6991
                                print "<select class=\"aws_formfield\" name=\"year\">\n";
 
6992
                                # Add YearRequired in list if not in ListOfYears
 
6993
                                $ListOfYears{$YearRequired}||=$MonthRequired;
 
6994
                                foreach (sort keys %ListOfYears) { print "<option".($YearRequired eq "$_"?" selected=\"true\"":"")." value=\"$_\">$_</option>\n"; }
 
6995
                                print "</select>\n";
 
6996
                                print "<input type=\"hidden\" name=\"output\" value=\"".join(',',keys %HTMLOutput)."\" />\n";
 
6997
                                if ($SiteConfig) { print "<input type=\"hidden\" name=\"config\" value=\"$SiteConfig\" />\n"; }
 
6998
                                if ($DirConfig)  { print "<input type=\"hidden\" name=\"configdir\" value=\"$DirConfig\" />\n"; }
 
6999
                                if ($QueryString =~ /lang=(\w+)/i) { print "<input type=\"hidden\" name=\"lang\" value=\"$1\" />\n"; }
 
7000
                                if ($QueryString =~ /debug=(\d+)/i) { print "<input type=\"hidden\" name=\"debug\" value=\"$1\" />\n"; }
 
7001
                                if ($FrameName eq 'mainright') { print "<input type=\"hidden\" name=\"framename\" value=\"index\" />\n"; }
 
7002
                                print "<input type=\"submit\" value=\" $Message[115] \" class=\"aws_button\" />";
 
7003
                        }
 
7004
                        else {
 
7005
                                print "<span style=\"font-size: 14px;\">";
 
7006
                                if ($MonthRequired eq 'all') { print "$Message[6] $YearRequired"; }
 
7007
                                else { print "$Message[5] $MonthNumLib{$MonthRequired} $YearRequired"; }
 
7008
                                print "</span>";
 
7009
                        }
 
7010
                        print "</td></tr>\n";
 
7011
                }
 
7012
                if ($QueryString !~ /buidpdf/i) {
 
7013
                        print "</table>\n";
 
7014
                        print "</td></tr></table>\n";
 
7015
                }
 
7016
                else {
 
7017
                        print "</table>\n";
 
7018
                }
 
7019
 
 
7020
                if ($FrameName ne 'mainleft') { print "</form>\n"; }
 
7021
                else { print "<br />\n"; }
 
7022
                print "\n";
 
7023
 
 
7024
                # Print menu links
 
7025
                if (($HTMLOutput{'main'} && $FrameName ne 'mainright') || $FrameName eq 'mainleft') {   # If main page asked
 
7026
                        # Define link anchor                    
 
7027
                        my $linkanchor=($FrameName eq 'mainleft'?"$AWScript?${NewLinkParams}":"");
 
7028
                        if ($linkanchor && ($linkanchor !~ /framename=mainright/)) { $linkanchor.="framename=mainright"; }
 
7029
                        $linkanchor =~ s/&$//; $linkanchor=XMLEncode("$linkanchor");
 
7030
                        # Define target
 
7031
                        my $targetpage=($FrameName eq 'mainleft'?" target=\"mainright\"":"");
 
7032
                        # Print Menu
 
7033
                        my $linetitle;
 
7034
                        if (! $PluginsLoaded{'ShowMenu'}{'menuapplet'}) {
 
7035
                                my $menuicon=0;
 
7036
                                # Menu HTML
 
7037
                                print "<table".($frame?" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"":"").">\n";
 
7038
                                if ($FrameName eq 'mainleft' && $ShowMonthStats)                 { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#TOP\"$targetpage>$Message[128]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7039
                                # When
 
7040
                                $linetitle=&AtLeastOneNotNull($ShowMonthStats,$ShowDaysOfMonthStats,$ShowDaysOfWeekStats,$ShowHoursStats);
 
7041
                                if ($linetitle) { print "<tr><td class=\"awsm\" width=\"$WIDTHMENU1\"".($frame?"":" valign=\"top\"").">".($menuicon?"<img src=\"$DirIcons/other/menu4.png\" />&nbsp;":"")."<b>$Message[93]:</b></td>\n"; }
 
7042
                                if ($linetitle) { print ($frame?"</tr>\n":"<td class=\"awsm\">"); }
 
7043
                                if ($ShowMonthStats)             { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#month\"$targetpage>$Message[162]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7044
                                #if ($ShowMonthDayStats)         { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=alldays"):"$PROG$StaticLinks.alldays.$StaticExt")."\"$NewLinkTarget>$Message[130]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7045
                                if ($ShowDaysOfMonthStats)       { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#daysofmonth\"$targetpage>$Message[138]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7046
                                if ($ShowDaysOfWeekStats)        { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#daysofweek\"$targetpage>$Message[91]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7047
                                if ($ShowHoursStats)             { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#hours\"$targetpage>$Message[20]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7048
                                if ($linetitle) { print ($frame?"":"</td></tr>\n"); }
 
7049
                                # Who
 
7050
                                $linetitle=&AtLeastOneNotNull($ShowDomainsStats,$ShowHostsStats,$ShowAuthenticatedUsers,$ShowEMailSenders,$ShowEMailReceivers,$ShowRobotsStats,$ShowWormsStats);
 
7051
                                if ($linetitle) { print "<tr><td class=\"awsm\"".($frame?"":" valign=\"top\"").">".($menuicon?"<img src=\"$DirIcons/other/menu5.png\" />&nbsp;":"")."<b>$Message[92]:</b></td>\n"; }
 
7052
                                if ($linetitle) { print ($frame?"</tr>\n":"<td class=\"awsm\">"); }
 
7053
                                if ($ShowDomainsStats)           { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#countries\"$targetpage>$Message[148]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7054
                                if ($ShowDomainsStats)           { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=alldomains"):"$PROG$StaticLinks.alldomains.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7055
                                if ($ShowHostsStats)             { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#visitors\"$targetpage>".ucfirst($Message[81])."</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7056
                                if ($ShowHostsStats)             { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allhosts"):"$PROG$StaticLinks.allhosts.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7057
                                if ($ShowHostsStats =~ /L/i) { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lasthosts"):"$PROG$StaticLinks.lasthosts.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7058
                                if ($ShowHostsStats)             { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=unknownip"):"$PROG$StaticLinks.unknownip.$StaticExt")."\"$NewLinkTarget>$Message[45]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7059
                                if ($ShowAuthenticatedUsers) { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#logins\"$targetpage>$Message[94]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7060
                                if ($ShowAuthenticatedUsers) { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=alllogins"):"$PROG$StaticLinks.alllogins.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7061
                                if ($ShowAuthenticatedUsers =~ /L/i)    { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastlogins"):"$PROG$StaticLinks.lastlogins.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7062
                                if ($ShowEMailSenders)           { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#emailsenders\"$targetpage>$Message[131]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7063
                                if ($ShowEMailSenders)           { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allemails"):"$PROG$StaticLinks.allemails.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7064
                                if ($ShowEMailSenders =~ /L/i)  { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastemails"):"$PROG$StaticLinks.lastemails.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7065
                                if ($ShowEMailReceivers)         { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#emailreceivers\"$targetpage>$Message[132]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7066
                                if ($ShowEMailReceivers)         { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allemailr"):"$PROG$StaticLinks.allemailr.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7067
                                if ($ShowEMailReceivers =~ /L/i)        { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastemailr"):"$PROG$StaticLinks.lastemailr.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7068
                                if ($ShowRobotsStats)            { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#robots\"$targetpage>$Message[53]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7069
                                if ($ShowRobotsStats)            { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allrobots"):"$PROG$StaticLinks.allrobots.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7070
                                if ($ShowRobotsStats =~ /L/i)   { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastrobots"):"$PROG$StaticLinks.lastrobots.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7071
                                if ($ShowWormsStats)             { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#worms\"$targetpage>$Message[136]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7072
                                #if ($ShowWormsStats)            { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allworms"):"$PROG$StaticLinks.allworms.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7073
                                #if ($ShowWormsStats =~ /L/i)   { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastworms"):"$PROG$StaticLinks.lastworms.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7074
                                if ($linetitle) { print ($frame?"":"</td></tr>\n"); }
 
7075
                                # Navigation
 
7076
                                $linetitle=&AtLeastOneNotNull($ShowSessionsStats,$ShowPagesStats,$ShowFileTypesStats,$ShowFileSizesStats,$ShowOSStats,$ShowBrowsersStats,$ShowScreenSizeStats);
 
7077
                                if ($linetitle) { print "<tr><td class=\"awsm\"".($frame?"":" valign=\"top\"").">".($menuicon?"<img src=\"$DirIcons/other/menu2.png\" />&nbsp;":"")."<b>$Message[72]:</b></td>\n"; }
 
7078
                                if ($linetitle) { print ($frame?"</tr>\n":"<td class=\"awsm\">"); }
 
7079
                                if ($ShowSessionsStats)          { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#sessions\"$targetpage>$Message[117]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7080
                                if ($ShowFileTypesStats)         { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#filetypes\"$targetpage>$Message[73]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7081
                                if ($ShowPagesStats)             { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#urls\"$targetpage>$Message[29]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7082
                                if ($ShowPagesStats)             { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=urldetail"):"$PROG$StaticLinks.urldetail.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7083
                                if ($ShowPagesStats =~ /E/i)    { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=urlentry"):"$PROG$StaticLinks.urlentry.$StaticExt")."\"$NewLinkTarget>$Message[104]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7084
                                if ($ShowPagesStats =~ /X/i)    { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=urlexit"):"$PROG$StaticLinks.urlexit.$StaticExt")."\"$NewLinkTarget>$Message[116]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7085
                                if ($ShowOSStats)                        { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#os\"$targetpage>$Message[59]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7086
                                if ($ShowOSStats)                        { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=osdetail"):"$PROG$StaticLinks.osdetail.$StaticExt")."\"$NewLinkTarget>$Message[58]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7087
                                if ($ShowOSStats)                        { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=unknownos"):"$PROG$StaticLinks.unknownos.$StaticExt")."\"$NewLinkTarget>$Message[0]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7088
                                if ($ShowBrowsersStats)          { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#browsers\"$targetpage>$Message[21]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7089
                                if ($ShowBrowsersStats)          { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=browserdetail"):"$PROG$StaticLinks.browserdetail.$StaticExt")."\"$NewLinkTarget>$Message[58]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7090
                                if ($ShowBrowsersStats)          { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=unknownbrowser"):"$PROG$StaticLinks.unknownbrowser.$StaticExt")."\"$NewLinkTarget>$Message[0]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7091
                                if ($ShowScreenSizeStats)        { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#screensizes\"$targetpage>$Message[135]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7092
                                if ($linetitle) { print ($frame?"":"</td></tr>\n"); }
 
7093
                                # Referers
 
7094
                                $linetitle=&AtLeastOneNotNull($ShowOriginStats,$ShowKeyphrasesStats,$ShowKeywordsStats);
 
7095
                                if ($linetitle) { print "<tr><td class=\"awsm\"".($frame?"":" valign=\"top\"").">".($menuicon?"<img src=\"$DirIcons/other/menu7.png\" />&nbsp;":"")."<b>$Message[23]:</b></td>\n"; }
 
7096
                                if ($linetitle) { print ($frame?"</tr>\n":"<td class=\"awsm\">"); }
 
7097
                                if ($ShowOriginStats)            { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#referer\"$targetpage>$Message[37]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7098
                                if ($ShowOriginStats)            { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=refererse"):"$PROG$StaticLinks.refererse.$StaticExt")."\"$NewLinkTarget>$Message[126]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7099
                                if ($ShowOriginStats)            { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=refererpages"):"$PROG$StaticLinks.refererpages.$StaticExt")."\"$NewLinkTarget>$Message[127]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7100
                                if ($ShowKeyphrasesStats || $ShowKeywordsStats)  { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#keys\"$targetpage>$Message[14]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7101
                                if ($ShowKeyphrasesStats)        { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=keyphrases"):"$PROG$StaticLinks.keyphrases.$StaticExt")."\"$NewLinkTarget>$Message[120]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7102
                                if ($ShowKeywordsStats)          { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=keywords"):"$PROG$StaticLinks.keywords.$StaticExt")."\"$NewLinkTarget>$Message[121]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7103
                                if ($linetitle) { print ($frame?"":"</td></tr>\n"); }
 
7104
                                # Others
 
7105
                                $linetitle=&AtLeastOneNotNull($ShowFileTypesStats=~/C/i,$ShowMiscStats,$ShowHTTPErrorsStats,$ShowSMTPErrorsStats,$ShowClusterStats);
 
7106
                                if ($linetitle) { print "<tr><td class=\"awsm\"".($frame?"":" valign=\"top\"").">".($menuicon?"<img src=\"$DirIcons/other/menu8.png\" />&nbsp;":"")."<b>$Message[2]:</b></td>\n"; }
 
7107
                                if ($linetitle) { print ($frame?"</tr>\n":"<td class=\"awsm\">"); }
 
7108
                                if ($ShowFileTypesStats =~ /C/i)         { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#filetypes\"$targetpage>$Message[98]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7109
                                if ($ShowMiscStats)                      { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#misc\"$targetpage>$Message[139]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7110
                                if ($ShowHTTPErrorsStats)        { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#errors\"$targetpage>$Message[32]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7111
                                foreach (keys %TrapInfosForHTTPErrorCodes) {
 
7112
                                        if ($ShowHTTPErrorsStats)        { print ($frame?"<tr><td class=\"awsm\"> &nbsp; <img height=\"8\" width=\"9\" src=\"$DirIcons/other/page.png\" alt=\"...\" /> ":""); print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=errors$_"):"$PROG$StaticLinks.errors$_.$StaticExt")."\"$NewLinkTarget>$Message[31]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7113
                                }
 
7114
                                if ($ShowSMTPErrorsStats)        { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#errors\"$targetpage>$Message[147]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7115
                                if ($ShowClusterStats)           { print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#clusters\"$targetpage>$Message[155]</a>"; print ($frame?"</td></tr>\n":" &nbsp; "); }
 
7116
                                if ($linetitle) { print ($frame?"":"</td></tr>\n"); }
 
7117
                                # Extra/Marketing
 
7118
                                $linetitle=&AtLeastOneNotNull(@ExtraStatTypes);
 
7119
                                if ($linetitle) { print "<tr><td class=\"awsm\"".($frame?"":" valign=\"top\"")."><b>$Message[134]:</b></td>\n"; }
 
7120
                                if ($linetitle) { print ($frame?"</tr>\n":"<td class=\"awsm\">"); }
 
7121
                                foreach (1..@ExtraName-1) {
 
7122
                                        print ($frame?"<tr><td class=\"awsm\">":""); print "<a href=\"$linkanchor#extra$_\"$targetpage>$ExtraName[$_]</a>\n"; print ($frame?"</td></tr>\n":" &nbsp; ");
 
7123
                                }
 
7124
                                if ($linetitle) { print ($frame?"":"</td></tr>\n"); }
 
7125
                                print "</table>\n";
 
7126
                        }
 
7127
                        else {
 
7128
                                # Menu Applet
 
7129
                                if ($frame) { }
 
7130
                                else {}
 
7131
                        }
 
7132
                        #print ($frame?"":"<br />\n");
 
7133
                        print "<br />\n";
 
7134
                }
 
7135
                # Print Back link
 
7136
                elsif (! $HTMLOutput{'main'}) {
 
7137
                        print "<table>\n";
 
7138
                        $NewLinkParams =~ s/(^|&)hostfilter=[^&]*//i;
 
7139
                        $NewLinkParams =~ s/(^|&)urlfilter=[^&]*//i;
 
7140
                        $NewLinkParams =~ s/(^|&)refererpagesfilter=[^&]*//i;
 
7141
                        $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/&$//;
 
7142
                        if (! $DetailedReportsOnNewWindows || $FrameName eq 'mainright' || $QueryString =~ /buildpdf/i) {
 
7143
                                print "<tr><td class=\"aws\"><a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript".(${NewLinkParams}?"?${NewLinkParams}":"")):"$PROG$StaticLinks.$StaticExt")."\">$Message[76]</a></td></tr>\n";
 
7144
                        }
 
7145
                        else {
 
7146
                                print "<tr><td class=\"aws\"><a href=\"javascript:parent.window.close();\">$Message[118]</a></td></tr>\n";
 
7147
                        }
 
7148
                        print "</table>\n";
 
7149
                        print "\n";
 
7150
                }
 
7151
        }
 
7152
 
 
7153
        # Call to plugins' function AddHTMLMenuFooter
 
7154
        foreach my $pluginname (keys %{$PluginsLoaded{'AddHTMLMenuFooter'}})  {
 
7155
                my $function="AddHTMLMenuFooter_$pluginname()";
 
7156
                eval("$function");
 
7157
        }
 
7158
 
 
7159
        # Exit if left frame
 
7160
        if ($FrameName eq 'mainleft') {
 
7161
                &html_end(0);
 
7162
                exit 0;
 
7163
        }
 
7164
 
 
7165
        # FirstTime LastTime TotalVisits TotalUnique TotalPages TotalHits TotalBytes TotalHostsKnown TotalHostsUnknown
 
7166
        my $FirstTime=0;
 
7167
        my $LastTime=0;
 
7168
        $TotalUnique=$TotalVisits=$TotalPages=$TotalHits=$TotalBytes=0;
 
7169
        $TotalNotViewedPages=$TotalNotViewedHits=$TotalNotViewedBytes=0;
 
7170
        $TotalHostsKnown=$TotalHostsUnknown=0;
 
7171
        my $beginmonth=$MonthRequired;my $endmonth=$MonthRequired;
 
7172
        if ($MonthRequired eq 'all') { $beginmonth=1;$endmonth=12; }
 
7173
        for (my $month=$beginmonth; $month<=$endmonth; $month++) {
 
7174
                my $monthix=sprintf("%02s",$month);
 
7175
                if ($FirstTime{$YearRequired.$monthix} && ($FirstTime == 0 || $FirstTime > $FirstTime{$YearRequired.$monthix})) { $FirstTime = $FirstTime{$YearRequired.$monthix}; }
 
7176
                if ($LastTime < ($LastTime{$YearRequired.$monthix}||0)) { $LastTime = $LastTime{$YearRequired.$monthix}; }
 
7177
                $TotalHostsKnown+=$MonthHostsKnown{$YearRequired.$monthix}||0;          # Wrong in year view
 
7178
                $TotalHostsUnknown+=$MonthHostsUnknown{$YearRequired.$monthix}||0;      # Wrong in year view
 
7179
                $TotalUnique+=$MonthUnique{$YearRequired.$monthix}||0;                          # Wrong in year view
 
7180
                $TotalVisits+=$MonthVisits{$YearRequired.$monthix}||0;
 
7181
                $TotalPages+=$MonthPages{$YearRequired.$monthix}||0;
 
7182
                $TotalHits+=$MonthHits{$YearRequired.$monthix}||0;
 
7183
                $TotalBytes+=$MonthBytes{$YearRequired.$monthix}||0;
 
7184
                $TotalNotViewedPages+=$MonthNotViewedPages{$YearRequired.$monthix}||0;
 
7185
                $TotalNotViewedHits+=$MonthNotViewedHits{$YearRequired.$monthix}||0;
 
7186
                $TotalNotViewedBytes+=$MonthNotViewedBytes{$YearRequired.$monthix}||0;
 
7187
        }
 
7188
        # TotalHitsErrors TotalBytesErrors
 
7189
        my $TotalHitsErrors=0; my $TotalBytesErrors=0;
 
7190
        foreach (keys %_errors_h) { $TotalHitsErrors+=$_errors_h{$_}; $TotalBytesErrors+=$_errors_k{$_}; }
 
7191
        # TotalEntries (if not already specifically counted, we init it from _url_e hash table)
 
7192
        if (!$TotalEntries) { foreach (keys %_url_e) { $TotalEntries+=$_url_e{$_}; } }
 
7193
        # TotalExits (if not already specifically counted, we init it from _url_x hash table)
 
7194
        if (!$TotalExits) { foreach (keys %_url_x) { $TotalExits+=$_url_x{$_}; } }
 
7195
        # TotalBytesPages (if not already specifically counted, we init it from _url_k hash table)
 
7196
        if (!$TotalBytesPages) { foreach (keys %_url_k) { $TotalBytesPages+=$_url_k{$_}; } }
 
7197
        # TotalKeyphrases (if not already specifically counted, we init it from _keyphrases hash table)
 
7198
        if (!$TotalKeyphrases) { foreach (keys %_keyphrases) { $TotalKeyphrases+=$_keyphrases{$_}; } }
 
7199
        # TotalKeywords (if not already specifically counted, we init it from _keywords hash table)
 
7200
        if (!$TotalKeywords) { foreach (keys %_keywords) { $TotalKeywords+=$_keywords{$_}; } }
 
7201
        # TotalSearchEnginesPages (if not already specifically counted, we init it from _se_referrals_p hash table)
 
7202
        if (!$TotalSearchEnginesPages) { foreach (keys %_se_referrals_p) { $TotalSearchEnginesPages+=$_se_referrals_p{$_}; } }
 
7203
        # TotalSearchEnginesHits (if not already specifically counted, we init it from _se_referrals_h hash table)
 
7204
        if (!$TotalSearchEnginesHits) { foreach (keys %_se_referrals_h) { $TotalSearchEnginesHits+=$_se_referrals_h{$_}; } }
 
7205
        # TotalRefererPages (if not already specifically counted, we init it from _pagesrefs_p hash table)
 
7206
        if (!$TotalRefererPages) { foreach (keys %_pagesrefs_p) { $TotalRefererPages+=$_pagesrefs_p{$_}; } }
 
7207
        # TotalRefererHits (if not already specifically counted, we init it from _pagesrefs_h hash table)
 
7208
        if (!$TotalRefererHits) { foreach (keys %_pagesrefs_h) { $TotalRefererHits+=$_pagesrefs_h{$_}; } }
 
7209
        # TotalDifferentPages (if not already specifically counted, we init it from _url_p hash table)
 
7210
        $TotalDifferentPages||=scalar keys %_url_p;
 
7211
        # TotalDifferentKeyphrases (if not already specifically counted, we init it from _keyphrases hash table)
 
7212
        $TotalDifferentKeyphrases||=scalar keys %_keyphrases;
 
7213
        # TotalDifferentKeywords (if not already specifically counted, we init it from _keywords hash table)
 
7214
        $TotalDifferentKeywords||=scalar keys %_keywords;
 
7215
        # TotalDifferentSearchEngines (if not already specifically counted, we init it from _se_referrals_h hash table)
 
7216
        $TotalDifferentSearchEngines||=scalar keys %_se_referrals_h;
 
7217
        # TotalDifferentReferer (if not already specifically counted, we init it from _pagesrefs_h hash table)
 
7218
        $TotalDifferentReferer||=scalar keys %_pagesrefs_h;
 
7219
 
 
7220
        # Define firstdaytocountaverage, lastdaytocountaverage, firstdaytoshowtime, lastdaytoshowtime
 
7221
        my $firstdaytocountaverage=$nowyear.$nowmonth."01";                             # Set day cursor to 1st day of month
 
7222
        my $firstdaytoshowtime=$nowyear.$nowmonth."01";                                 # Set day cursor to 1st day of month
 
7223
        my $lastdaytocountaverage=$nowyear.$nowmonth.$nowday;                   # Set day cursor to today
 
7224
        my $lastdaytoshowtime=$nowyear.$nowmonth."31";                                  # Set day cursor to last day of month
 
7225
        if ($MonthRequired eq 'all') {
 
7226
                $firstdaytocountaverage=$YearRequired."0101";                           # Set day cursor to 1st day of the required year
 
7227
        }
 
7228
        if (($MonthRequired ne $nowmonth && $MonthRequired ne 'all') || $YearRequired ne $nowyear) {
 
7229
                if ($MonthRequired eq 'all') {
 
7230
                        $firstdaytocountaverage=$YearRequired."0101";                   # Set day cursor to 1st day of the required year
 
7231
                        $firstdaytoshowtime=$YearRequired."1201";                               # Set day cursor to 1st day of last month of required year
 
7232
                        $lastdaytocountaverage=$YearRequired."1231";                    # Set day cursor to last day of the required year
 
7233
                        $lastdaytoshowtime=$YearRequired."1231";                                # Set day cursor to last day of last month of required year
 
7234
                }
 
7235
                else {
 
7236
                        $firstdaytocountaverage=$YearRequired.$MonthRequired."01";      # Set day cursor to 1st day of the required month
 
7237
                        $firstdaytoshowtime=$YearRequired.$MonthRequired."01";          # Set day cursor to 1st day of the required month
 
7238
                        $lastdaytocountaverage=$YearRequired.$MonthRequired."31";       # Set day cursor to last day of the required month
 
7239
                        $lastdaytoshowtime=$YearRequired.$MonthRequired."31";           # Set day cursor to last day of the required month
 
7240
                }
 
7241
        }
 
7242
        if ($Debug) {
 
7243
                debug("firstdaytocountaverage=$firstdaytocountaverage, lastdaytocountaverage=$lastdaytocountaverage",1);
 
7244
                debug("firstdaytoshowtime=$firstdaytoshowtime, lastdaytoshowtime=$lastdaytoshowtime",1);
 
7245
        }
 
7246
 
 
7247
        # Output particular part
 
7248
 
 
7249
#       if ($HTMLOutput{'alldays'}) {
 
7250
#               if ($Debug) { debug("ShowMonthDayStats",2); }
 
7251
#               print "$Center<a name=\"monthday\">&nbsp;</a><br />\n";
 
7252
#               &tab_head("$Message[5]",0,0,"alldays");
 
7253
#
 
7254
#               my $NewLinkParams=${QueryString};
 
7255
#               $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
7256
#               $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
7257
#               $NewLinkParams =~ s/(^|&)year=[^&]*//i;
 
7258
#               $NewLinkParams =~ s/(^|&)month=[^&]*//i;
 
7259
#               $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
7260
#               $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
7261
#               if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
7262
#               my $NewLinkTarget="";
 
7263
#               if ($FrameName eq 'mainright') { $NewLinkTarget=" target=\"_parent\""; }
 
7264
#
 
7265
#               # Show monthly stats
 
7266
#               print "<tr valign=\"bottom\"><td align=\"center\">";
 
7267
#               print "<center>";
 
7268
#
 
7269
#               print "<table>";
 
7270
#               print "<tr valign=\"bottom\"><td></td>";
 
7271
#               $max_v=$max_p=$max_h=$max_k=1;
 
7272
#               for (my $ix=1; $ix<=12; $ix++) {
 
7273
#                       my $monthix=sprintf("%02s",$ix);
 
7274
#                       #if ($MonthUnique{$YearRequired.$monthix} > $max_v) { $max_v=$MonthUnique{$YearRequired.$monthix}; }
 
7275
#                       if ($MonthVisits{$YearRequired.$monthix} > $max_v) { $max_v=$MonthVisits{$YearRequired.$monthix}; }
 
7276
#                       #if ($MonthPages{$YearRequired.$monthix} > $max_p)  { $max_p=$MonthPages{$YearRequired.$monthix}; }
 
7277
#                       if ($MonthHits{$YearRequired.$monthix} > $max_h)   { $max_h=$MonthHits{$YearRequired.$monthix}; }
 
7278
#                       if ($MonthBytes{$YearRequired.$monthix} > $max_k)  { $max_k=$MonthBytes{$YearRequired.$monthix}; }
 
7279
#               }
 
7280
#               for (my $ix=1; $ix<=12; $ix++) {
 
7281
#                       my $monthix=sprintf("%02s",$ix);
 
7282
#                       my $bredde_u=0; my $bredde_v=0;my $bredde_p=0;my $bredde_h=0;my $bredde_k=0;
 
7283
#                       if ($max_v > 0) { $bredde_u=int($MonthUnique{$YearRequired.$monthix}/$max_v*$BarHeight)+1; }
 
7284
#                       if ($max_v > 0) { $bredde_v=int($MonthVisits{$YearRequired.$monthix}/$max_v*$BarHeight)+1; }
 
7285
#                       if ($max_h > 0) { $bredde_p=int($MonthPages{$YearRequired.$monthix}/$max_h*$BarHeight)+1; }
 
7286
#                       if ($max_h > 0) { $bredde_h=int($MonthHits{$YearRequired.$monthix}/$max_h*$BarHeight)+1; }
 
7287
#                       if ($max_k > 0) { $bredde_k=int($MonthBytes{$YearRequired.$monthix}/$max_k*$BarHeight)+1; }
 
7288
#                       print "<td>";
 
7289
#                       if ($ShowMonthDayStats =~ /U/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vu'}\" height=\"$bredde_u\" width=\"8\"".AltTitle("$Message[11]: $MonthUnique{$YearRequired.$monthix}")." />"; }
 
7290
#                       if ($ShowMonthDayStats =~ /V/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vv'}\" height=\"$bredde_v\" width=\"8\"".AltTitle("$Message[10]: $MonthVisits{$YearRequired.$monthix}")." />"; }
 
7291
#                       print "&nbsp;";
 
7292
#                       if ($ShowMonthDayStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"8\"".AltTitle("$Message[56]: $MonthPages{$YearRequired.$monthix}")." />"; }
 
7293
#                       if ($ShowMonthDayStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"8\"".AltTitle("$Message[57]: $MonthHits{$YearRequired.$monthix}")." />"; }
 
7294
#                       if ($ShowMonthDayStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"8\"".AltTitle("$Message[75]: ".Format_Bytes($MonthBytes{$YearRequired.$monthix}))." />"; }
 
7295
#                       print "</td>\n";
 
7296
#               }
 
7297
#               print "</tr>\n";
 
7298
#               # Show lib for month
 
7299
#               print "<tr valign=\"middle\" cellspacing=\"0\" cellpadding=\"0\"><td></td>";
 
7300
#               for (my $ix=1; $ix<=12; $ix++) {
 
7301
#                       my $monthix=($ix<10?"0$ix":"$ix");
 
7302
#                       print "<td>";
 
7303
#                       if (($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks) && ! $HTMLOutput{'alldays'}) { print "<a href=\"".XMLEncode($AWScript?${NewLinkParams}year=$YearRequired&month=$monthix)."\"$NewLinkTarget>"; }
 
7304
#                       print "$MonthNumLib{$monthix}";
 
7305
#                       if (($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks) && ! $HTMLOutput{'alldays'}) { print "</a>"; }
 
7306
#                       print "</td>\n";
 
7307
#               }
 
7308
#               print "</tr>\n";
 
7309
#               print "</table>\n<br />\n";
 
7310
#
 
7311
#               # Show data array for month
 
7312
#               print "<table>\n";
 
7313
#               print "<tr><td width=\"15%\" bgcolor=\"#$color_TableBGRowTitle\">$Message[5]</td>";
 
7314
#               if ($ShowMonthDayStats =~ /U/i) { print "<td width=\"17%\" bgcolor=\"#$color_u\" onmouseover=\"ShowTip(2);\" onmouseout=\"HideTip(2);\">$Message[11]</td>"; }
 
7315
#               if ($ShowMonthDayStats =~ /V/i) { print "<td width=\"17%\" bgcolor=\"#$color_v\" onmouseover=\"ShowTip(1);\" onmouseout=\"HideTip(1);\">$Message[10]</td>"; }
 
7316
#               if ($ShowMonthDayStats =~ /P/i) { print "<td width=\"17%\" bgcolor=\"#$color_p\" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\">$Message[56]</td>"; }
 
7317
#               if ($ShowMonthDayStats =~ /H/i) { print "<td width=\"17%\" bgcolor=\"#$color_h\" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\">$Message[57]</td>"; }
 
7318
#               if ($ShowMonthDayStats =~ /B/i) { print "<td width=\"17%\" bgcolor=\"#$color_k\" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\">$Message[75]</td>"; }
 
7319
#               print "</tr>\n";
 
7320
#               for (my $ix=1; $ix<=12; $ix++) {
 
7321
#                       my $monthix=($ix<10?"0$ix":"$ix");
 
7322
#                       print "<tr>";
 
7323
#                       print "<td>",$MonthNumLib{$monthix},"</td>";
 
7324
#                       if ($ShowMonthDayStats =~ /U/i) { print "<td>",$MonthUnique{$YearRequired.$monthix}?$MonthUnique{$YearRequired.$monthix}:"0","</td>"; }
 
7325
#                       if ($ShowMonthDayStats =~ /V/i) { print "<td>",$MonthVisits{$YearRequired.$monthix}?$MonthVisits{$YearRequired.$monthix}:"0","</td>"; }
 
7326
#                       if ($ShowMonthDayStats =~ /P/i) { print "<td>",$MonthPages{$YearRequired.$monthix}?$MonthPages{$YearRequired.$monthix}:"0","</td>"; }
 
7327
#                       if ($ShowMonthDayStats =~ /H/i) { print "<td>",$MonthHits{$YearRequired.$monthix}?$MonthHits{$YearRequired.$monthix}:"0","</td>"; }
 
7328
#                       if ($ShowMonthDayStats =~ /B/i) { print "<td>",Format_Bytes(int($MonthBytes{$YearRequired.$monthix})),"</td>"; }
 
7329
#                       print "</tr>\n";
 
7330
#               }
 
7331
#               print "</table>\n<br />";
 
7332
#
 
7333
#               print "</center>\n";
 
7334
#               print "</td></tr>\n";
 
7335
#               &tab_end;
 
7336
#
 
7337
#               print "<br />\n";
 
7338
#
 
7339
#               &tab_head("$Message[4]",0,0,"");
 
7340
#               print "<tr valign=\"bottom\"><td align=\"center\">";
 
7341
#               print "<center>";
 
7342
#
 
7343
#               print "<table>";
 
7344
#               print "<tr valign=\"bottom\"><td></td>";
 
7345
#               # Get max_v, max_h and max_k values
 
7346
#               $max_v=$max_h=$max_k=0;         # Start from 0 because can be lower than 1
 
7347
#               foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
7348
#                       $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
7349
#                       my $year=$1; my $month=$2; my $day=$3;
 
7350
#                       if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
7351
#                       if (($DayVisits{$year.$month.$day}||0) > $max_v)  { $max_v=$DayVisits{$year.$month.$day}; }
 
7352
#                       #if (($DayPages{$year.$month.$day}||0) > $max_p)  { $max_p=$DayPages{$year.$month.$day}; }
 
7353
#                       if (($DayHits{$year.$month.$day}||0) > $max_h)   { $max_h=$DayHits{$year.$month.$day}; }
 
7354
#                       if (($DayBytes{$year.$month.$day}||0) > $max_k)  { $max_k=$DayBytes{$year.$month.$day}; }
 
7355
#               }
 
7356
#               # Calculate average values
 
7357
#               my $average_nb=0; my $average_v=0; my $average_p=0; my $average_h=0; my $average_k=0;
 
7358
#               foreach my $daycursor ($firstdaytocountaverage..$lastdaytocountaverage) {
 
7359
#                       $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
7360
#                       my $year=$1; my $month=$2; my $day=$3;
 
7361
#                       if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
7362
#                       $average_nb++;                                                                                  # Increase number of day used to count
 
7363
#                       $average_v+=($DayVisits{$daycursor}||0);
 
7364
#                       $average_p+=($DayPages{$daycursor}||0);
 
7365
#                       $average_h+=($DayHits{$daycursor}||0);
 
7366
#                       $average_k+=($DayBytes{$daycursor}||0);
 
7367
#               }
 
7368
#               if ($average_nb) {
 
7369
#                       $average_v=$average_v/$average_nb;
 
7370
#                       $average_p=$average_p/$average_nb;
 
7371
#                       $average_h=$average_h/$average_nb;
 
7372
#                       $average_k=$average_k/$average_nb;
 
7373
#                       if ($average_v > $max_v) { $max_v=$average_v; }
 
7374
#                       #if ($average_p > $max_p) { $max_p=$average_p; }
 
7375
#                       if ($average_h > $max_h) { $max_h=$average_h; }
 
7376
#                       if ($average_k > $max_k) { $max_k=$average_k; }
 
7377
#               }
 
7378
#               else {
 
7379
#                       $average_v="?";
 
7380
#                       $average_p="?";
 
7381
#                       $average_h="?";
 
7382
#                       $average_k="?";
 
7383
#               }
 
7384
#               foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
7385
#                       $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
7386
#                       my $year=$1; my $month=$2; my $day=$3;
 
7387
#                       if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
7388
#                       my $bredde_v=0; my $bredde_p=0; my $bredde_h=0; my $bredde_k=0;
 
7389
#                       if ($max_v > 0) { $bredde_v=int(($DayVisits{$year.$month.$day}||0)/$max_v*$BarHeight)+1; }
 
7390
#                       if ($max_h > 0) { $bredde_p=int(($DayPages{$year.$month.$day}||0)/$max_h*$BarHeight)+1; }
 
7391
#                       if ($max_h > 0) { $bredde_h=int(($DayHits{$year.$month.$day}||0)/$max_h*$BarHeight)+1; }
 
7392
#                       if ($max_k > 0) { $bredde_k=int(($DayBytes{$year.$month.$day}||0)/$max_k*$BarHeight)+1; }
 
7393
#                       print "<td>";
 
7394
#                       if ($ShowMonthDayStats =~ /V/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vv'}\" height=\"$bredde_v\" width=\"4\"".AltTitle("$Message[10]: ".int($DayVisits{$year.$month.$day}||0))." />"; }
 
7395
#                       if ($ShowMonthDayStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"4\"".AltTitle("$Message[56]: ".int($DayPages{$year.$month.$day}||0))." />"; }
 
7396
#                       if ($ShowMonthDayStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"4\"".AltTitle("$Message[57]: ".int($DayHits{$year.$month.$day}||0))." />"; }
 
7397
#                       if ($ShowMonthDayStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"4\"".AltTitle("$Message[75]: ".Format_Bytes($DayBytes{$year.$month.$day}))." />"; }
 
7398
#                       print "</td>\n";
 
7399
#               }
 
7400
#               print "<td>&nbsp;</td>";
 
7401
#               print "<td>";   # Show average value cell
 
7402
#               my $bredde_v=0; my $bredde_p=0; my $bredde_h=0; my $bredde_k=0;
 
7403
#               if ($max_v > 0) { $bredde_v=int($average_v/$max_v*$BarHeight)+1; }
 
7404
#               if ($max_h > 0) { $bredde_p=int($average_p/$max_h*$BarHeight)+1; }
 
7405
#               if ($max_h > 0) { $bredde_h=int($average_h/$max_h*$BarHeight)+1; }
 
7406
#               if ($max_k > 0) { $bredde_k=int($average_k/$max_k*$BarHeight)+1; }
 
7407
#               $average_v=sprintf("%.2f",$average_v);
 
7408
#               $average_p=sprintf("%.2f",$average_p);
 
7409
#               $average_h=sprintf("%.2f",$average_h);
 
7410
#               $average_k=sprintf("%.2f",$average_k);
 
7411
#               if ($ShowMonthDayStats =~ /V/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vv'}\" height=\"$bredde_v\" width=\"4\"".AltTitle("$Message[10]: $average_v")." />"; }
 
7412
#               if ($ShowMonthDayStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"4\"".AltTitle("$Message[56]: $average_p")." />"; }
 
7413
#               if ($ShowMonthDayStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"4\"".AltTitle("$Message[57]: $average_h")." />"; }
 
7414
#               if ($ShowMonthDayStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"4\"".AltTitle("$Message[75]: ".Format_Bytes($average_k))." />"; }
 
7415
#               print "</td>";
 
7416
#               print "<td></td>\n";
 
7417
#               print "</tr>\n";
 
7418
#               # Show lib for days
 
7419
#               print "<tr><td></td>";
 
7420
#               foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
7421
#                       $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
7422
#                       my $year=$1; my $month=$2; my $day=$3;
 
7423
#                       if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
7424
#                       my $dayofweekcursor=DayOfWeek($day,$month,$year);
 
7425
#                       print "<td valign=\"middle\"".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">";
 
7426
#                       print ($day==$nowday && $month==$nowmonth && $year==$nowyear?'<b>':'');
 
7427
#                       print "$day<br /><span style=\"font-size: ".($FrameName ne 'mainright'?"10":"9")."px;\">".$MonthNumLib{$month}."</span>";
 
7428
#                       print ($day==$nowday && $month==$nowmonth && $year==$nowyear?'</b>':'');
 
7429
#                       print "</td>\n";
 
7430
#               }
 
7431
#               print "<td>&nbsp;</td>";
 
7432
#               print "<td valign=\"middle\"".($TOOLTIPON?" onmouseover=\"ShowTip(18);\" onmouseout=\"HideTip(18);\"":"").">$Message[96]</td>\n";
 
7433
#               print "<td></td>\n";
 
7434
#               print "</tr>\n";
 
7435
#               print "</table>\n<br />\n";
 
7436
#
 
7437
#               # Show data array for days
 
7438
#               print "<table>\n";
 
7439
#               print "<tr><td width=\"20%\" bgcolor=\"#$color_TableBGRowTitle\">$Message[4]</td>";
 
7440
#               if ($ShowMonthDayStats =~ /V/i) { print "<td width=\"20%\" bgcolor=\"#$color_v\"".($TOOLTIPON?" onmouseover=\"ShowTip(1);\" onmouseout=\"HideTip(1);\"":"").">$Message[10]</td>"; }
 
7441
#               if ($ShowMonthDayStats =~ /P/i) { print "<td width=\"20%\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; }
 
7442
#               if ($ShowMonthDayStats =~ /H/i) { print "<td width=\"20%\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; }
 
7443
#               if ($ShowMonthDayStats =~ /B/i) { print "<td width=\"20%\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td>"; }
 
7444
#               print "</tr>\n";
 
7445
#               foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
7446
#                       $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
7447
#                       my $year=$1; my $month=$2; my $day=$3;
 
7448
#                       if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
7449
#                       my $dayofweekcursor=DayOfWeek($day,$month,$year);
 
7450
#                       print "<tr>";
 
7451
#                       print "<td".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">",Format_Date("$year$month$day"."000000",2),"</td>";
 
7452
#                       if ($ShowMonthDayStats =~ /V/i) { print "<td".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">",$DayVisits{$year.$month.$day}?$DayVisits{$year.$month.$day}:"0","</td>"; }
 
7453
#                       if ($ShowMonthDayStats =~ /P/i) { print "<td".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">",$DayPages{$year.$month.$day}?$DayPages{$year.$month.$day}:"0","</td>"; }
 
7454
#                       if ($ShowMonthDayStats =~ /H/i) { print "<td".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">",$DayHits{$year.$month.$day}?$DayHits{$year.$month.$day}:"0","</td>"; }
 
7455
#                       if ($ShowMonthDayStats =~ /B/i) { print "<td".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">",Format_Bytes(int($DayBytes{$year.$month.$day})),"</td>"; }
 
7456
#                       print "</tr>\n";
 
7457
#               }
 
7458
#               print "</table>\n<br />";
 
7459
#
 
7460
#               print "</center>\n";
 
7461
#               print "</td></tr>\n";
 
7462
#               &tab_end;
 
7463
#               &html_end;
 
7464
#               exit(0);
 
7465
#       }
 
7466
        if ($HTMLOutput{'alldomains'}) {
 
7467
                print "$Center<a name=\"domains\">&nbsp;</a><br />\n";
 
7468
                # Show domains list
 
7469
                my $title=''; my $cpt=0;
 
7470
                if ($HTMLOutput{'alldomains'})  { $title.="$Message[25]"; $cpt=(scalar keys %_domener_h); }
 
7471
                &tab_head("$title",19,0,'domains');
 
7472
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th width=\"$WIDTHCOLICON\">&nbsp;</th><th colspan=\"2\">$Message[17]</th>";
 
7473
                if ($ShowDomainsStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
7474
                if ($ShowDomainsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
7475
                if ($ShowDomainsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
7476
                print "<th>&nbsp;</th>";
 
7477
                print "</tr>\n";
 
7478
                $total_p=$total_h=$total_k=0;
 
7479
                $max_h=1; foreach (values %_domener_h) { if ($_ > $max_h) { $max_h = $_; } }
 
7480
                $max_k=1; foreach (values %_domener_k) { if ($_ > $max_k) { $max_k = $_; } }
 
7481
                my $count=0;
 
7482
                &BuildKeyList($MaxRowsInHTMLOutput,1,\%_domener_h,\%_domener_p);
 
7483
                foreach my $key (@keylist) {
 
7484
                        my $bredde_p=0;my $bredde_h=0;my $bredde_k=0;
 
7485
                        if ($max_h > 0) { $bredde_p=int($BarWidth*$_domener_p{$key}/$max_h)+1; }        # use max_h to enable to compare pages with hits
 
7486
                        if ($_domener_p{$key} && $bredde_p==1) { $bredde_p=2; }
 
7487
                        if ($max_h > 0) { $bredde_h=int($BarWidth*$_domener_h{$key}/$max_h)+1; }
 
7488
                        if ($_domener_h{$key} && $bredde_h==1) { $bredde_h=2; }
 
7489
                        if ($max_k > 0) { $bredde_k=int($BarWidth*($_domener_k{$key}||0)/$max_k)+1; }
 
7490
                        if ($_domener_k{$key} && $bredde_k==1) { $bredde_k=2; }
 
7491
                        my $newkey=lc($key);
 
7492
                        if ($newkey eq 'ip' || ! $DomainsHashIDLib{$newkey}) {
 
7493
                                print "<tr><td width=\"$WIDTHCOLICON\"><img src=\"$DirIcons\/flags\/ip.png\" height=\"14\"".AltTitle("$Message[0]")." /></td><td class=\"aws\">$Message[0]</td><td>$newkey</td>";
 
7494
                        }
 
7495
                        else {
 
7496
                                print "<tr><td width=\"$WIDTHCOLICON\"><img src=\"$DirIcons\/flags\/$newkey.png\" height=\"14\"".AltTitle("$newkey")." /></td><td class=\"aws\">$DomainsHashIDLib{$newkey}</td><td>$newkey</td>";
 
7497
                        }
 
7498
                        if ($ShowDomainsStats =~ /P/i) { print "<td>$_domener_p{$key}</td>"; }
 
7499
                        if ($ShowDomainsStats =~ /H/i) { print "<td>$_domener_h{$key}</td>"; }
 
7500
                        if ($ShowDomainsStats =~ /B/i) { print "<td>".Format_Bytes($_domener_k{$key})."</td>"; }
 
7501
                        print "<td style=\"text-align:left; font-size:4px;\">";
 
7502
                        if ($ShowDomainsStats =~ /P/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hp'}\" width=\"$bredde_p\" height=\"5\"".AltTitle("$Message[56]: ".int($_domener_p{$key}))." /><br />\n"; }
 
7503
                        if ($ShowDomainsStats =~ /H/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hh'}\" width=\"$bredde_h\" height=\"5\"".AltTitle("$Message[57]: ".int($_domener_h{$key}))." /><br />\n"; }
 
7504
                        if ($ShowDomainsStats =~ /B/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hk'}\" width=\"$bredde_k\" height=\"5\"".AltTitle("$Message[75]: ".Format_Bytes($_domener_k{$key}))." />"; }
 
7505
                        print "</td>";
 
7506
                        print "</tr>\n";
 
7507
                        $total_p += $_domener_p{$key};
 
7508
                        $total_h += $_domener_h{$key};
 
7509
                        $total_k += $_domener_k{$key}||0;
 
7510
                        $count++;
 
7511
                }
 
7512
                $rest_p=$TotalPages-$total_p;
 
7513
                $rest_h=$TotalHits-$total_h;
 
7514
                $rest_k=$TotalBytes-$total_k;
 
7515
                if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other domains (known or not)
 
7516
                        print "<tr><td width=\"$WIDTHCOLICON\">&nbsp;</td><td colspan=\"2\" class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
7517
                        if ($ShowDomainsStats =~ /P/i) { print "<td>$rest_p</td>"; }
 
7518
                        if ($ShowDomainsStats =~ /H/i) { print "<td>$rest_h</td>"; }
 
7519
                        if ($ShowDomainsStats =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
7520
                        print "<td class=\"aws\">&nbsp;</td>";
 
7521
                        print "</tr>\n";
 
7522
                }
 
7523
                &tab_end;
 
7524
                &html_end(1);
 
7525
        }
 
7526
        if ($HTMLOutput{'allhosts'} || $HTMLOutput{'lasthosts'}) {
 
7527
                print "$Center<a name=\"hosts\">&nbsp;</a><br />\n";
 
7528
                # Show filter form
 
7529
                &ShowFormFilter("hostfilter",$FilterIn{'host'},$FilterEx{'host'});
 
7530
                # Show hosts list
 
7531
                my $title=''; my $cpt=0;
 
7532
                if ($HTMLOutput{'allhosts'})  { $title.="$Message[81]"; $cpt=(scalar keys %_host_h); }
 
7533
                if ($HTMLOutput{'lasthosts'}) { $title.="$Message[9]"; $cpt=(scalar keys %_host_h); }
 
7534
                &tab_head("$title",19,0,'hosts');
 
7535
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>";
 
7536
                if ($FilterIn{'host'} || $FilterEx{'host'}) {   # With filter
 
7537
                        if ($FilterIn{'host'}) { print "$Message[79] '<b>$FilterIn{'host'}</b>'"; }
 
7538
                        if ($FilterIn{'host'} && $FilterEx{'host'}) { print " - "; }
 
7539
                        if ($FilterEx{'host'}) { print " Exlude $Message[79] '<b>$FilterEx{'host'}</b>'"; }
 
7540
                        if ($FilterIn{'host'} || $FilterEx{'host'}) { print ": "; }
 
7541
                        print "$cpt $Message[81]";
 
7542
                        if ($MonthRequired ne 'all') {
 
7543
                                if ($HTMLOutput{'allhosts'} || $HTMLOutput{'lasthosts'}) { print "<br />$Message[102]: $TotalHostsKnown $Message[82], $TotalHostsUnknown $Message[1] - $TotalUnique $Message[11]"; }
 
7544
                        }
 
7545
                }
 
7546
                else {  # Without filter
 
7547
                        if ($MonthRequired ne 'all') { print "$Message[102] : $TotalHostsKnown $Message[82], $TotalHostsUnknown $Message[1] - $TotalUnique $Message[11]"; }
 
7548
                        else { print "$Message[102] : ".(scalar keys %_host_h); }
 
7549
                }
 
7550
                print "</th>";
 
7551
                &ShowHostInfo('__title__');
 
7552
                if ($ShowHostsStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
7553
                if ($ShowHostsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
7554
                if ($ShowHostsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
7555
                if ($ShowHostsStats =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
7556
                print "</tr>\n";
 
7557
                $total_p=$total_h=$total_k=0;
 
7558
                my $count=0;
 
7559
                if ($HTMLOutput{'allhosts'})  { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Host'},\%_host_h,\%_host_p); }
 
7560
                if ($HTMLOutput{'lasthosts'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Host'},\%_host_h,\%_host_l); }
 
7561
                foreach my $key (@keylist) {
 
7562
                        my $host=CleanFromCSSA($key);
 
7563
                        print "<tr><td class=\"aws\">".($_robot_l{$key}?'<b>':'')."$host".($_robot_l{$key}?'</b>':'')."</td>";
 
7564
                        &ShowHostInfo($key);
 
7565
                        if ($ShowHostsStats =~ /P/i) { print "<td>".($_host_p{$key}?$_host_p{$key}:"&nbsp;")."</td>"; }
 
7566
                        if ($ShowHostsStats =~ /H/i) { print "<td>$_host_h{$key}</td>"; }
 
7567
                        if ($ShowHostsStats =~ /B/i) { print "<td>".Format_Bytes($_host_k{$key})."</td>"; }
 
7568
                        if ($ShowHostsStats =~ /L/i) { print "<td>".($_host_l{$key}?Format_Date($_host_l{$key},1):'-')."</td>"; }
 
7569
                        print "</tr>\n";
 
7570
                        $total_p += $_host_p{$key};
 
7571
                        $total_h += $_host_h{$key};
 
7572
                        $total_k += $_host_k{$key}||0;
 
7573
                        $count++;
 
7574
                }
 
7575
                if ($Debug) { debug("Total real / shown : $TotalPages / $total_p - $TotalHits / $total_h - $TotalBytes / $total_h",2); }
 
7576
                $rest_p=$TotalPages-$total_p;
 
7577
                $rest_h=$TotalHits-$total_h;
 
7578
                $rest_k=$TotalBytes-$total_k;
 
7579
                if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other visitors (known or not)
 
7580
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
7581
                        &ShowHostInfo('');
 
7582
                        if ($ShowHostsStats =~ /P/i) { print "<td>".($rest_p?$rest_p:"&nbsp;")."</td>"; }
 
7583
                        if ($ShowHostsStats =~ /H/i) { print "<td>$rest_h</td>"; }
 
7584
                        if ($ShowHostsStats =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
7585
                        if ($ShowHostsStats =~ /L/i) { print "<td>&nbsp;</td>"; }
 
7586
                        print "</tr>\n";
 
7587
                }
 
7588
                &tab_end;
 
7589
                &html_end(1);
 
7590
        }
 
7591
        if ($HTMLOutput{'unknownip'}) {
 
7592
                print "$Center<a name=\"unknownip\">&nbsp;</a><br />\n";
 
7593
                &tab_head("$Message[45]",19,0,'unknownwip');
 
7594
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>".(scalar keys %_host_h)." $Message[1]</th>";
 
7595
                &ShowHostInfo('__title__');
 
7596
                if ($ShowHostsStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
7597
                if ($ShowHostsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
7598
                if ($ShowHostsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
7599
                if ($ShowHostsStats =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
7600
                print "</tr>\n";
 
7601
                $total_p=$total_h=$total_k=0;
 
7602
                my $count=0;
 
7603
                &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Host'},\%_host_h,\%_host_p);
 
7604
                foreach my $key (@keylist) {
 
7605
                        my $host=CleanFromCSSA($key);
 
7606
                        print "<tr><td class=\"aws\">$host</td>";
 
7607
                        &ShowHostInfo($key);
 
7608
                        if ($ShowHostsStats =~ /P/i) { print "<td>".($_host_p{$key}?$_host_p{$key}:"&nbsp;")."</td>"; }
 
7609
                        if ($ShowHostsStats =~ /H/i) { print "<td>$_host_h{$key}</td>"; }
 
7610
                        if ($ShowHostsStats =~ /B/i) { print "<td>".Format_Bytes($_host_k{$key})."</td>"; }
 
7611
                        if ($ShowHostsStats =~ /L/i) { print "<td>".($_host_l{$key}?Format_Date($_host_l{$key},1):'-')."</td>"; }
 
7612
                        print "</tr>\n";
 
7613
                        $total_p += $_host_p{$key};
 
7614
                        $total_h += $_host_h{$key};
 
7615
                        $total_k += $_host_k{$key}||0;
 
7616
                        $count++;
 
7617
                }
 
7618
                if ($Debug) { debug("Total real / shown : $TotalPages / $total_p - $TotalHits / $total_h - $TotalBytes / $total_h",2); }
 
7619
                $rest_p=$TotalPages-$total_p;
 
7620
                $rest_h=$TotalHits-$total_h;
 
7621
                $rest_k=$TotalBytes-$total_k;
 
7622
                if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other visitors (known or not)
 
7623
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[82]</span></td>";
 
7624
                        &ShowHostInfo('');
 
7625
                        if ($ShowHostsStats =~ /P/i) { print "<td>".($rest_p?$rest_p:"&nbsp;")."</td>"; }
 
7626
                        if ($ShowHostsStats =~ /H/i) { print "<td>$rest_h</td>"; }
 
7627
                        if ($ShowHostsStats =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
7628
                        if ($ShowHostsStats =~ /L/i) { print "<td>&nbsp;</td>"; }
 
7629
                        print "</tr>\n";
 
7630
                }
 
7631
                &tab_end;
 
7632
                &html_end(1);
 
7633
        }
 
7634
        if ($HTMLOutput{'allemails'} || $HTMLOutput{'lastemails'}) {
 
7635
                &ShowEmailSendersChart($NewLinkParams,$NewLinkTarget);
 
7636
                &html_end(1);
 
7637
        }
 
7638
        if ($HTMLOutput{'allemailr'} || $HTMLOutput{'lastemailr'}) {
 
7639
                &ShowEmailReceiversChart($NewLinkParams,$NewLinkTarget);
 
7640
                &html_end(1);
 
7641
        }
 
7642
        if ($HTMLOutput{'alllogins'} || $HTMLOutput{'lastlogins'}) {
 
7643
                print "$Center<a name=\"logins\">&nbsp;</a><br />\n";
 
7644
                my $title='';
 
7645
                if ($HTMLOutput{'alllogins'}) { $title.="$Message[94]"; }
 
7646
                if ($HTMLOutput{'lastlogins'}) { $title.="$Message[9]"; }
 
7647
                &tab_head("$title",19,0,'logins');
 
7648
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$Message[94] : ".(scalar keys %_login_h)."</th>";
 
7649
                &ShowUserInfo('__title__');
 
7650
                if ($ShowAuthenticatedUsers =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
7651
                if ($ShowAuthenticatedUsers =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
7652
                if ($ShowAuthenticatedUsers =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
7653
                if ($ShowAuthenticatedUsers =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
7654
                print "</tr>\n";
 
7655
                $total_p=$total_h=$total_k=0;
 
7656
                my $count=0;
 
7657
                if ($HTMLOutput{'alllogins'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Host'},\%_login_h,\%_login_p); }
 
7658
                if ($HTMLOutput{'lastlogins'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Host'},\%_login_h,\%_login_l); }
 
7659
                foreach my $key (@keylist) {
 
7660
                        print "<tr><td class=\"aws\">$key</td>";
 
7661
                        &ShowUserInfo($key);
 
7662
                        if ($ShowAuthenticatedUsers =~ /P/i) { print "<td>".($_login_p{$key}?$_login_p{$key}:"&nbsp;")."</td>"; }
 
7663
                        if ($ShowAuthenticatedUsers =~ /H/i) { print "<td>$_login_h{$key}</td>"; }
 
7664
                        if ($ShowAuthenticatedUsers =~ /B/i) { print "<td>".Format_Bytes($_login_k{$key})."</td>"; }
 
7665
                        if ($ShowAuthenticatedUsers =~ /L/i) { print "<td>".($_login_l{$key}?Format_Date($_login_l{$key},1):'-')."</td>"; }
 
7666
                        print "</tr>\n";
 
7667
                        $total_p += $_login_p{$key}||0;
 
7668
                        $total_h += $_login_h{$key};
 
7669
                        $total_k += $_login_k{$key}||0;
 
7670
                        $count++;
 
7671
                }
 
7672
                if ($Debug) { debug("Total real / shown : $TotalPages / $total_p - $TotalHits / $total_h - $TotalBytes / $total_h",2); }
 
7673
                $rest_p=$TotalPages-$total_p;
 
7674
                $rest_h=$TotalHits-$total_h;
 
7675
                $rest_k=$TotalBytes-$total_k;
 
7676
                if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other logins and/or anonymous
 
7677
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[125]</span></td>";
 
7678
                        &ShowUserInfo('');
 
7679
                        if ($ShowAuthenticatedUsers =~ /P/i) { print "<td>".($rest_p?$rest_p:"&nbsp;")."</td>"; }
 
7680
                        if ($ShowAuthenticatedUsers =~ /H/i) { print "<td>$rest_h</td>"; }
 
7681
                        if ($ShowAuthenticatedUsers =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
7682
                        if ($ShowAuthenticatedUsers =~ /L/i) { print "<td>&nbsp;</td>"; }
 
7683
                        print "</tr>\n";
 
7684
                }
 
7685
                &tab_end;
 
7686
                &html_end(1);
 
7687
        }
 
7688
        if ($HTMLOutput{'allrobots'} || $HTMLOutput{'lastrobots'}) {
 
7689
                print "$Center<a name=\"robots\">&nbsp;</a><br />\n";
 
7690
                my $title='';
 
7691
                if ($HTMLOutput{'allrobots'})  { $title.="$Message[53]"; }
 
7692
                if ($HTMLOutput{'lastrobots'}) { $title.="$Message[9]"; }
 
7693
                &tab_head("$title",19,0,'robots');
 
7694
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>".(scalar keys %_robot_h)." $Message[51]</th>";
 
7695
                if ($ShowRobotsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
7696
                if ($ShowRobotsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
7697
                if ($ShowRobotsStats =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
7698
                print "</tr>\n";
 
7699
                $total_p=$total_h=$total_k=$total_r=0;
 
7700
                my $count=0;
 
7701
                if ($HTMLOutput{'allrobots'})  { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Robot'},\%_robot_h,\%_robot_h); }
 
7702
                if ($HTMLOutput{'lastrobots'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Robot'},\%_robot_h,\%_robot_l); }
 
7703
                foreach my $key (@keylist) {
 
7704
                        print "<tr><td class=\"aws\">".($RobotsHashIDLib{$key}?$RobotsHashIDLib{$key}:$key)."</td>";
 
7705
                        if ($ShowRobotsStats =~ /H/i) { print "<td>".($_robot_h{$key}-$_robot_r{$key}).($_robot_r{$key}?"+$_robot_r{$key}":"")."</td>"; }
 
7706
                        if ($ShowRobotsStats =~ /B/i) { print "<td>".Format_Bytes($_robot_k{$key})."</td>"; }
 
7707
                        if ($ShowRobotsStats =~ /L/i) { print "<td>".($_robot_l{$key}?Format_Date($_robot_l{$key},1):'-')."</td>"; }
 
7708
                        print "</tr>\n";
 
7709
                        #$total_p += $_robot_p{$key}||0;
 
7710
                        $total_h += $_robot_h{$key};
 
7711
                        $total_k += $_robot_k{$key}||0;
 
7712
                        $total_r += $_robot_r{$key}||0;
 
7713
                        $count++;
 
7714
                }
 
7715
                # For bots we need to count Totals
 
7716
                my $TotalPagesRobots = 0; #foreach (values %_robot_p) { $TotalPagesRobots+=$_; }
 
7717
                my $TotalHitsRobots = 0; foreach (values %_robot_h) { $TotalHitsRobots+=$_; }
 
7718
                my $TotalBytesRobots = 0; foreach (values %_robot_k) { $TotalBytesRobots+=$_; }
 
7719
                my $TotalRRobots = 0; foreach (values %_robot_r) { $TotalRRobots+=$_; }
 
7720
                $rest_p=0;      #$rest_p=$TotalPagesRobots-$total_p;
 
7721
                $rest_h=$TotalHitsRobots-$total_h;
 
7722
                $rest_k=$TotalBytesRobots-$total_k;
 
7723
                $rest_r=$TotalRRobots-$total_r;
 
7724
                if ($Debug) { debug("Total real / shown : $TotalPagesRobots / $total_p - $TotalHitsRobots / $total_h - $TotalBytesRobots / $total_k",2); }
 
7725
                if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0 || $rest_r > 0) { # All other robots
 
7726
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
7727
                        if ($ShowRobotsStats =~ /H/i) { print "<td>$rest_h</td>"; }
 
7728
                        if ($ShowRobotsStats =~ /B/i) { print "<td>".(Format_Bytes($rest_k))."</td>"; }
 
7729
                        if ($ShowRobotsStats =~ /L/i) { print "<td>&nbsp;</td>"; }
 
7730
                        print "</tr>\n";
 
7731
                }
 
7732
                &tab_end("* $Message[157]");
 
7733
                &html_end(1);
 
7734
        }
 
7735
        if ($HTMLOutput{'urldetail'} || $HTMLOutput{'urlentry'} || $HTMLOutput{'urlexit'}) {
 
7736
                # Call to plugins' function ShowPagesFilter
 
7737
                foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesFilter'}})  {
 
7738
                        my $function="ShowPagesFilter_$pluginname()";
 
7739
                        eval("$function");
 
7740
                }
 
7741
                print "$Center<a name=\"urls\">&nbsp;</a><br />\n";
 
7742
                # Show filter form
 
7743
                &ShowFormFilter("urlfilter",$FilterIn{'url'},$FilterEx{'url'});
 
7744
                # Show URL list
 
7745
                my $title=''; my $cpt=0;
 
7746
                if ($HTMLOutput{'urldetail'}) { $title=$Message[19]; $cpt=(scalar keys %_url_p); }
 
7747
                if ($HTMLOutput{'urlentry'})  { $title=$Message[104]; $cpt=(scalar keys %_url_e); }
 
7748
                if ($HTMLOutput{'urlexit'})   { $title=$Message[116]; $cpt=(scalar keys %_url_x); }
 
7749
                &tab_head("$title",19,0,'urls');
 
7750
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>";
 
7751
                if ($FilterIn{'url'} || $FilterEx{'url'}) {
 
7752
                        if ($FilterIn{'url'}) { print "$Message[79] <b>$FilterIn{'url'}</b>"; }
 
7753
                        if ($FilterIn{'url'} && $FilterEx{'url'}) { print " - "; }
 
7754
                        if ($FilterEx{'url'}) { print "Exclude $Message[79] <b>$FilterEx{'url'}</b>"; }
 
7755
                        if ($FilterIn{'url'} || $FilterEx{'url'}) { print ": "; }
 
7756
                        print "$cpt $Message[28]";
 
7757
                        if ($MonthRequired ne 'all') {
 
7758
                                if ($HTMLOutput{'urldetail'}) { print "<br />$Message[102]: $TotalDifferentPages $Message[28]"; }
 
7759
                        }
 
7760
                }
 
7761
                else { print "$Message[102]: $cpt $Message[28]"; }
 
7762
                print "</th>";
 
7763
                if ($ShowPagesStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[29]</th>"; }
 
7764
                if ($ShowPagesStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[106]</th>"; }
 
7765
                if ($ShowPagesStats =~ /E/i) { print "<th bgcolor=\"#$color_e\" width=\"80\">$Message[104]</th>"; }
 
7766
                if ($ShowPagesStats =~ /X/i) { print "<th bgcolor=\"#$color_x\" width=\"80\">$Message[116]</th>"; }
 
7767
                # Call to plugins' function ShowPagesAddField
 
7768
                foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesAddField'}})  {
 
7769
                        my $function="ShowPagesAddField_$pluginname('title')";
 
7770
                        eval("$function");
 
7771
                }
 
7772
                print "<th>&nbsp;</th></tr>\n";
 
7773
                $total_p=$total_k=$total_e=$total_x=0;
 
7774
                my $count=0;
 
7775
                if ($HTMLOutput{'urlentry'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'File'},\%_url_e,\%_url_e); }
 
7776
                elsif ($HTMLOutput{'urlexit'}) { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'File'},\%_url_x,\%_url_x); }
 
7777
                else { &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'File'},\%_url_p,\%_url_p); }
 
7778
                $max_p=1; $max_k=1;
 
7779
                foreach my $key (@keylist) {
 
7780
                        if ($_url_p{$key} > $max_p) { $max_p = $_url_p{$key}; }
 
7781
                        if ($_url_k{$key}/($_url_p{$key}||1) > $max_k) { $max_k = $_url_k{$key}/($_url_p{$key}||1); }
 
7782
                }
 
7783
                foreach my $key (@keylist) {
 
7784
                        print "<tr><td class=\"aws\">";
 
7785
                        &ShowURLInfo($key);
 
7786
                        print "</td>";
 
7787
                        my $bredde_p=0; my $bredde_e=0; my $bredde_x=0; my $bredde_k=0;
 
7788
                        if ($max_p > 0) { $bredde_p=int($BarWidth*($_url_p{$key}||0)/$max_p)+1; }
 
7789
                        if (($bredde_p==1) && $_url_p{$key}) { $bredde_p=2; }
 
7790
                        if ($max_p > 0) { $bredde_e=int($BarWidth*($_url_e{$key}||0)/$max_p)+1; }
 
7791
                        if (($bredde_e==1) && $_url_e{$key}) { $bredde_e=2; }
 
7792
                        if ($max_p > 0) { $bredde_x=int($BarWidth*($_url_x{$key}||0)/$max_p)+1; }
 
7793
                        if (($bredde_x==1) && $_url_x{$key}) { $bredde_x=2; }
 
7794
                        if ($max_k > 0) { $bredde_k=int($BarWidth*(($_url_k{$key}||0)/($_url_p{$key}||1))/$max_k)+1; }
 
7795
                        if (($bredde_k==1) && $_url_k{$key}) { $bredde_k=2; }
 
7796
                        if ($ShowPagesStats =~ /P/i) { print "<td>$_url_p{$key}</td>"; }
 
7797
                        if ($ShowPagesStats =~ /B/i) { print "<td>".($_url_k{$key}?Format_Bytes($_url_k{$key}/($_url_p{$key}||1)):"&nbsp;")."</td>"; }
 
7798
                        if ($ShowPagesStats =~ /E/i) { print "<td>".($_url_e{$key}?$_url_e{$key}:"&nbsp;")."</td>"; }
 
7799
                        if ($ShowPagesStats =~ /X/i) { print "<td>".($_url_x{$key}?$_url_x{$key}:"&nbsp;")."</td>"; }
 
7800
                        # Call to plugins' function ShowPagesAddField
 
7801
                        foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesAddField'}})  {
 
7802
                                my $function="ShowPagesAddField_$pluginname('$key')"; 
 
7803
                                eval("$function");
 
7804
                        }
 
7805
                        print "<td style=\"text-align:left; font-size:4px;\">";
 
7806
                        # alt and title are not provided to reduce page size
 
7807
                        if ($ShowPagesStats =~ /P/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hp'}\" width=\"$bredde_p\" height=\"4\" /><br />"; }
 
7808
                        if ($ShowPagesStats =~ /B/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hk'}\" width=\"$bredde_k\" height=\"4\" /><br />"; }
 
7809
                        if ($ShowPagesStats =~ /E/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'he'}\" width=\"$bredde_e\" height=\"4\" /><br />"; }
 
7810
                        if ($ShowPagesStats =~ /X/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hx'}\" width=\"$bredde_x\" height=\"4\" />"; }
 
7811
                        print "</td></tr>\n";
 
7812
                        $total_p += $_url_p{$key};
 
7813
                        $total_e += $_url_e{$key};
 
7814
                        $total_x += $_url_x{$key};
 
7815
                        $total_k += $_url_k{$key};
 
7816
                        $count++;
 
7817
                }
 
7818
                if ($Debug) { debug("Total real / shown : $TotalPages / $total_p - $TotalEntries / $total_e - $TotalExits / $total_x - $TotalBytesPages / $total_k",2); }
 
7819
                $rest_p=$TotalPages-$total_p;
 
7820
                $rest_k=$TotalBytesPages-$total_k;
 
7821
                $rest_e=$TotalEntries-$total_e;
 
7822
                $rest_x=$TotalExits-$total_x;
 
7823
                if ($rest_p > 0 || $rest_e > 0 || $rest_k > 0) {
 
7824
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
7825
                        if ($ShowPagesStats =~ /P/i) { print "<td>".($rest_p?$rest_p:"&nbsp;")."</td>"; }
 
7826
                        if ($ShowPagesStats =~ /B/i) { print "<td>".($rest_k?Format_Bytes($rest_k/($rest_p||1)):"&nbsp;")."</td>"; }
 
7827
                        if ($ShowPagesStats =~ /E/i) { print "<td>".($rest_e?$rest_e:"&nbsp;")."</td>"; }
 
7828
                        if ($ShowPagesStats =~ /X/i) { print "<td>".($rest_x?$rest_x:"&nbsp;")."</td>"; }
 
7829
                        # Call to plugins' function ShowPagesAddField
 
7830
                        foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesAddField'}})  {
 
7831
                                my $function="ShowPagesAddField_$pluginname('')";
 
7832
                                eval("$function");
 
7833
                        }
 
7834
                        print "<td>&nbsp;</td></tr>\n";
 
7835
                }
 
7836
                &tab_end;
 
7837
                &html_end(1);
 
7838
        }
 
7839
        if ($HTMLOutput{'unknownos'}) {
 
7840
                print "$Center<a name=\"unknownos\">&nbsp;</a><br />\n";
 
7841
                my $title="$Message[46]";
 
7842
                &tab_head("$title",19,0,'unknownos');
 
7843
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>User agent (".(scalar keys %_unknownreferer_l).")</th><th>$Message[9]</th></tr>\n";
 
7844
                $total_l=0;
 
7845
                my $count=0;
 
7846
                &BuildKeyList($MaxRowsInHTMLOutput,1,\%_unknownreferer_l,\%_unknownreferer_l);
 
7847
                foreach my $key (@keylist) {
 
7848
                        my $useragent=CleanFromCSSA($key);
 
7849
                        print "<tr><td class=\"aws\">$useragent</td>";
 
7850
                        print "<td>".Format_Date($_unknownreferer_l{$key},1)."</td>";
 
7851
                        print "</tr>\n";
 
7852
                        $total_l+=1;
 
7853
                        $count++;
 
7854
                }
 
7855
                $rest_l=(scalar keys %_unknownreferer_l)-$total_l;
 
7856
                if ($rest_l > 0) {
 
7857
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
7858
                        print "<td>-</td>";
 
7859
                        print "</tr>\n";
 
7860
                }
 
7861
                &tab_end;
 
7862
                &html_end(1);
 
7863
        }
 
7864
        if ($HTMLOutput{'unknownbrowser'}) {
 
7865
                print "$Center<a name=\"unknownbrowser\">&nbsp;</a><br />\n";
 
7866
                my $title="$Message[50]";
 
7867
                &tab_head("$title",19,0,'unknownbrowser');
 
7868
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>User agent (".(scalar keys %_unknownrefererbrowser_l).")</th><th>$Message[9]</th></tr>\n";
 
7869
                $total_l=0;
 
7870
                my $count=0;
 
7871
                &BuildKeyList($MaxRowsInHTMLOutput,1,\%_unknownrefererbrowser_l,\%_unknownrefererbrowser_l);
 
7872
                foreach my $key (@keylist) {
 
7873
                        my $useragent=CleanFromCSSA($key);
 
7874
                        print "<tr><td class=\"aws\">$useragent</td><td>".Format_Date($_unknownrefererbrowser_l{$key},1)."</td></tr>\n";
 
7875
                        $total_l+=1;
 
7876
                        $count++;
 
7877
                }
 
7878
                $rest_l=(scalar keys %_unknownrefererbrowser_l)-$total_l;
 
7879
                if ($rest_l > 0) {
 
7880
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
7881
                        print "<td>-</td>";
 
7882
                        print "</tr>\n";
 
7883
                }
 
7884
                &tab_end;
 
7885
                &html_end(1);
 
7886
        }
 
7887
        if ($HTMLOutput{'osdetail'}) {
 
7888
                # Show os versions
 
7889
                print "$Center<a name=\"osversions\">&nbsp;</a><br />";
 
7890
                my $title="$Message[59]";
 
7891
                &tab_head("$title",19,0,'osversions');
 
7892
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"2\">$Message[58]</th>";
 
7893
                print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>";
 
7894
                print "<th>&nbsp;</th>";
 
7895
                print "</tr>\n";
 
7896
                $total_h=0;
 
7897
                my $count=0;
 
7898
                &BuildKeyList(MinimumButNoZero(scalar keys %_os_h,500),1,\%_os_h,\%_os_h);
 
7899
                my %keysinkeylist=();
 
7900
                $max_h=1;
 
7901
                # Count total by family
 
7902
                my %totalfamily_h=();
 
7903
                my $TotalFamily=0;
 
7904
                OSLOOP: foreach my $key (@keylist) {
 
7905
                        $total_h+=$_os_h{$key};
 
7906
                        if ($_os_h{$key} > $max_h) { $max_h = $_os_h{$key}; }
 
7907
                        foreach my $family (@OSFamily) { if ($key =~ /^$family/i) { $totalfamily_h{$family}+=$_os_h{$key}; $TotalFamily+=$_os_h{$key}; next OSLOOP; } }
 
7908
                }
 
7909
                # Write records grouped in a browser family
 
7910
                foreach my $family (@OSFamily) {
 
7911
                        my $p='&nbsp;';
 
7912
                        if ($total_h) { $p=int($totalfamily_h{$family}/$total_h*1000)/10; $p="$p %"; }
 
7913
                        my $familyheadershown=0;
 
7914
                        foreach my $key (reverse sort keys %_os_h) {
 
7915
                                if ($key =~ /^$family(.*)/i) {
 
7916
                                        if (! $familyheadershown) {
 
7917
                                                print "<tr bgcolor=\"#F6F6F6\"><td class=\"aws\" colspan=\"2\"><b>".uc($family)."</b></td>";
 
7918
                                                print "<td><b>".int($totalfamily_h{$family})."</b></td><td><b>$p</b></td><td>&nbsp;</td>";
 
7919
                                                print "</tr>\n";
 
7920
                                                $familyheadershown=1;
 
7921
                                        }
 
7922
                                        $keysinkeylist{$key}=1;
 
7923
                                        my $ver=$1;
 
7924
                                        my $p='&nbsp;';
 
7925
                                        if ($total_h) { $p=int($_os_h{$key}/$total_h*1000)/10; $p="$p %"; }
 
7926
                                        print "<tr>";
 
7927
                                        print "<td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/os\/$key.png\"".AltTitle("")." /></td>";
 
7928
                                        print "<td class=\"aws\">$OSHashLib{$key}</td>";
 
7929
                                        my $bredde_h=0;
 
7930
                                        if ($max_h > 0) { $bredde_h=int($BarWidth*($_os_h{$key}||0)/$max_h)+1; }
 
7931
                                        if (($bredde_h==1) && $_os_h{$key}) { $bredde_h=2; }
 
7932
                                        print "<td>$_os_h{$key}</td><td>$p</td>";
 
7933
                                        print "<td class=\"aws\">";
 
7934
                                        # alt and title are not provided to reduce page size
 
7935
                                        if ($ShowOSStats) { print "<img src=\"$DirIcons\/other\/$BarPng{'hh'}\" width=\"$bredde_h\" height=\"5\" /><br />"; }
 
7936
                                        print "</td>";
 
7937
                                        print "</tr>\n";
 
7938
                                        $count++;
 
7939
                                }
 
7940
                        }
 
7941
                }
 
7942
                # Write other records
 
7943
                my $familyheadershown=0;
 
7944
                foreach my $key (@keylist) {
 
7945
                        if ($keysinkeylist{$key}) { next; }
 
7946
                        if (! $familyheadershown) {
 
7947
                                my $p='&nbsp;';
 
7948
                                if ($total_h) { $p=int(($total_h-$TotalFamily)/$total_h*1000)/10; $p="$p %"; }
 
7949
                                print "<tr bgcolor=\"#F6F6F6\"><td class=\"aws\" colspan=\"2\"><b>".uc($Message[2])."</b></td>";
 
7950
                                print "<td><b>".($total_h-$TotalFamily)."</b></td><td><b>$p</b></td><td>&nbsp;</td>";
 
7951
                                print "</tr>\n";
 
7952
                                $familyheadershown=1;
 
7953
                        }
 
7954
                        my $p='&nbsp;';
 
7955
                        if ($total_h) { $p=int($_os_h{$key}/$total_h*1000)/10; $p="$p %"; }
 
7956
                        print "<tr>";
 
7957
                        if ($key eq 'Unknown') {
 
7958
                                print "<td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/browser\/unknown.png\"".AltTitle("")." /></td><td class=\"aws\"><span style=\"color: #$color_other\">$Message[0]</span></td>";
 
7959
                        }
 
7960
                        else {
 
7961
                                my $keywithoutcumul=$key; $keywithoutcumul =~ s/cumul$//i;
 
7962
                                my $libos=$OSHashLib{$keywithoutcumul}||$keywithoutcumul;
 
7963
                                my $nameicon=$keywithoutcumul; $nameicon =~ s/[^\w]//g;
 
7964
                                print "<td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/os\/$nameicon.png\"".AltTitle("")." /></td><td class=\"aws\">$libos</td>";
 
7965
                        }
 
7966
                        my $bredde_h=0;
 
7967
                        if ($max_h > 0) { $bredde_h=int($BarWidth*($_os_h{$key}||0)/$max_h)+1; }
 
7968
                        if (($bredde_h==1) && $_os_h{$key}) { $bredde_h=2; }
 
7969
                        print "<td>$_os_h{$key}</td><td>$p</td>";
 
7970
                        print "<td class=\"aws\">";
 
7971
                        # alt and title are not provided to reduce page size
 
7972
                        if ($ShowOSStats) { print "<img src=\"$DirIcons\/other\/$BarPng{'hh'}\" width=\"$bredde_h\" height=\"5\" /><br />"; }
 
7973
                        print "</td>";
 
7974
                        print "</tr>\n";
 
7975
                }
 
7976
                &tab_end;
 
7977
                &html_end(1);
 
7978
        }
 
7979
        if ($HTMLOutput{'browserdetail'}) {
 
7980
                # Show browsers versions
 
7981
                print "$Center<a name=\"browsersversions\">&nbsp;</a><br />";
 
7982
                my $title="$Message[21]";
 
7983
                &tab_head("$title",19,0,'browsersversions');
 
7984
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"2\">$Message[58]</th>";
 
7985
                print "<th width=\"80\">$Message[111]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>";
 
7986
                print "<th>&nbsp;</th>";
 
7987
                print "</tr>\n";
 
7988
                $total_h=0;
 
7989
                my $count=0;
 
7990
                &BuildKeyList(MinimumButNoZero(scalar keys %_browser_h,500),1,\%_browser_h,\%_browser_h);
 
7991
                my %keysinkeylist=();
 
7992
                $max_h=1;
 
7993
                # Count total by family
 
7994
                my %totalfamily_h=();
 
7995
                my $TotalFamily=0;
 
7996
                BROWSERLOOP: foreach my $key (@keylist) {
 
7997
                        $total_h+=$_browser_h{$key};
 
7998
                        if ($_browser_h{$key} > $max_h) { $max_h = $_browser_h{$key}; }
 
7999
                        foreach my $family (keys %BrowsersFamily) { if ($key =~ /^$family/i) { $totalfamily_h{$family}+=$_browser_h{$key}; $TotalFamily+=$_browser_h{$key}; next BROWSERLOOP; } }
 
8000
                }
 
8001
                # Write records grouped in a browser family
 
8002
                foreach my $family (sort { $BrowsersFamily{$a} <=> $BrowsersFamily{$b} } keys %BrowsersFamily) {
 
8003
                        my $p='&nbsp;';
 
8004
                        if ($total_h) { $p=int($totalfamily_h{$family}/$total_h*1000)/10; $p="$p %"; }
 
8005
                        my $familyheadershown=0;
 
8006
                        foreach my $key (reverse sort keys %_browser_h) {
 
8007
                                if ($key =~ /^$family(.*)/i) {
 
8008
                                        if (! $familyheadershown) {
 
8009
                                                print "<tr bgcolor=\"#F6F6F6\"><td class=\"aws\" colspan=\"2\"><b>".uc($family)."</b></td>";
 
8010
                                                print "<td>&nbsp;</td><td><b>".int($totalfamily_h{$family})."</b></td><td><b>$p</b></td><td>&nbsp;</td>";
 
8011
                                                print "</tr>\n";
 
8012
                                                $familyheadershown=1;
 
8013
                                        }
 
8014
                                        $keysinkeylist{$key}=1;
 
8015
                                        my $ver=$1;
 
8016
                                        my $p='&nbsp;';
 
8017
                                        if ($total_h) { $p=int($_browser_h{$key}/$total_h*1000)/10; $p="$p %"; }
 
8018
                                        print "<tr>";
 
8019
                                        print "<td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/browser\/$family.png\"".AltTitle("")." /></td>";
 
8020
                                        print "<td class=\"aws\">".ucfirst($family)." ".($ver?"$ver":"?")."</td>";
 
8021
                                        print "<td>".($BrowsersHereAreGrabbers{$family}?"<b>$Message[112]</b>":"$Message[113]")."</td>";
 
8022
                                        my $bredde_h=0;
 
8023
                                        if ($max_h > 0) { $bredde_h=int($BarWidth*($_browser_h{$key}||0)/$max_h)+1; }
 
8024
                                        if (($bredde_h==1) && $_browser_h{$key}) { $bredde_h=2; }
 
8025
                                        print "<td>$_browser_h{$key}</td><td>$p</td>";
 
8026
                                        print "<td class=\"aws\">";
 
8027
                                        # alt and title are not provided to reduce page size
 
8028
                                        if ($ShowBrowsersStats) { print "<img src=\"$DirIcons\/other\/$BarPng{'hh'}\" width=\"$bredde_h\" height=\"5\" /><br />"; }
 
8029
                                        print "</td>";
 
8030
                                        print "</tr>\n";
 
8031
                                        $count++;
 
8032
                                }
 
8033
                        }
 
8034
                }
 
8035
                # Write other records
 
8036
                my $familyheadershown=0;
 
8037
                foreach my $key (@keylist) {
 
8038
                        if ($keysinkeylist{$key}) { next; }
 
8039
                        if (! $familyheadershown) {
 
8040
                                my $p='&nbsp;';
 
8041
                                if ($total_h) { $p=int(($total_h-$TotalFamily)/$total_h*1000)/10; $p="$p %"; }
 
8042
                                print "<tr bgcolor=\"#F6F6F6\"><td class=\"aws\" colspan=\"2\"><b>".uc($Message[2])."</b></td>";
 
8043
                                print "<td>&nbsp;</td><td><b>".($total_h-$TotalFamily)."</b></td><td><b>$p</b></td><td>&nbsp;</td>";
 
8044
                                print "</tr>\n";
 
8045
                                $familyheadershown=1;
 
8046
                        }
 
8047
                        my $p='&nbsp;';
 
8048
                        if ($total_h) { $p=int($_browser_h{$key}/$total_h*1000)/10; $p="$p %"; }
 
8049
                        print "<tr>";
 
8050
                        if ($key eq 'Unknown') {
 
8051
                                print "<td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/browser\/unknown.png\"".AltTitle("")." /></td><td class=\"aws\"><span style=\"color: #$color_other\">$Message[0]</span></td><td width=\"80\">?</td>";
 
8052
                        }
 
8053
                        else {
 
8054
                                my $keywithoutcumul=$key; $keywithoutcumul =~ s/cumul$//i;
 
8055
                                my $libbrowser=$BrowsersHashIDLib{$keywithoutcumul}||$keywithoutcumul;
 
8056
                                my $nameicon=$BrowsersHashIcon{$keywithoutcumul}||"notavailable";
 
8057
                                print "<td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/browser\/$nameicon.png\"".AltTitle("")." /></td><td class=\"aws\">$libbrowser</td><td>".($BrowsersHereAreGrabbers{$key}?"<b>$Message[112]</b>":"$Message[113]")."</td>";
 
8058
                        }
 
8059
                        my $bredde_h=0;
 
8060
                        if ($max_h > 0) { $bredde_h=int($BarWidth*($_browser_h{$key}||0)/$max_h)+1; }
 
8061
                        if (($bredde_h==1) && $_browser_h{$key}) { $bredde_h=2; }
 
8062
                        print "<td>$_browser_h{$key}</td><td>$p</td>";
 
8063
                        print "<td class=\"aws\">";
 
8064
                        # alt and title are not provided to reduce page size
 
8065
                        if ($ShowBrowsersStats) { print "<img src=\"$DirIcons\/other\/$BarPng{'hh'}\" width=\"$bredde_h\" height=\"5\" /><br />"; }
 
8066
                        print "</td>";
 
8067
                        print "</tr>\n";
 
8068
                }
 
8069
                &tab_end;
 
8070
                &html_end(1);
 
8071
        }
 
8072
        if ($HTMLOutput{'refererse'}) {
 
8073
                print "$Center<a name=\"refererse\">&nbsp;</a><br />\n";
 
8074
                my $title="$Message[40]";
 
8075
                &tab_head("$title",19,0,'refererse');
 
8076
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$TotalDifferentSearchEngines $Message[122]</th>";
 
8077
                print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th><th bgcolor=\"#$color_p\" width=\"80\">$Message[15]</th>";
 
8078
                print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>";
 
8079
                print "</tr>\n";
 
8080
                $total_s=0;
 
8081
                my $count=0;
 
8082
                &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Refer'},\%_se_referrals_h,\%_se_referrals_p);
 
8083
                foreach my $key (@keylist) {
 
8084
                        my $newreferer=CleanFromCSSA($SearchEnginesHashLib{$key}||$key);
 
8085
                        my $p_p; my $p_h;
 
8086
                        if ($TotalSearchEnginesPages) { $p_p=int($_se_referrals_p{$key}/$TotalSearchEnginesPages*1000)/10; }
 
8087
                        if ($TotalSearchEnginesHits) { $p_h=int($_se_referrals_h{$key}/$TotalSearchEnginesHits*1000)/10; }
 
8088
                        print "<tr><td class=\"aws\">$newreferer</td>";
 
8089
                        print "<td>".($_se_referrals_p{$key}?$_se_referrals_p{$key}:'&nbsp;')."</td>";
 
8090
                        print "<td>".($_se_referrals_p{$key}?"$p_p %":'&nbsp;')."</td>";
 
8091
                        print "<td>$_se_referrals_h{$key}</td>";
 
8092
                        print "<td>$p_h %</td>";
 
8093
                        print "</tr>\n";
 
8094
                        $total_p += $_se_referrals_p{$key};
 
8095
                        $total_h += $_se_referrals_h{$key};
 
8096
                        $count++;
 
8097
                }
 
8098
                if ($Debug) { debug("Total real / shown : $TotalSearchEnginesPages / $total_p - $TotalSearchEnginesHits / $total_h",2); }
 
8099
                $rest_p=$TotalSearchEnginesPages-$total_p;
 
8100
                $rest_h=$TotalSearchEnginesHits-$total_h;
 
8101
                if ($rest_p > 0 || $rest_h > 0) {
 
8102
                        my $p_p;my $p_h;
 
8103
                        if ($TotalSearchEnginesPages) { $p_p=int($rest_p/$TotalSearchEnginesPages*1000)/10; }
 
8104
                        if ($TotalSearchEnginesHits) { $p_h=int($rest_h/$TotalSearchEnginesHits*1000)/10; }
 
8105
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
8106
                        print "<td>".($rest_p?$rest_p:'&nbsp;')."</td>";
 
8107
                        print "<td>".($rest_p?"$p_p %":'&nbsp;')."</td>";
 
8108
                        print "<td>$rest_h</td>";
 
8109
                        print "<td>$p_h %</td>";
 
8110
                        print "</tr>\n";
 
8111
                }
 
8112
                &tab_end;
 
8113
                &html_end(1);
 
8114
        }
 
8115
        if ($HTMLOutput{'refererpages'}) {
 
8116
                print "$Center<a name=\"refererpages\">&nbsp;</a><br />\n";
 
8117
                # Show filter form
 
8118
                &ShowFormFilter("refererpagesfilter",$FilterIn{'refererpages'},$FilterEx{'refererpages'});
 
8119
                my $title="$Message[41]"; my $cpt=0;
 
8120
                $cpt=(scalar keys %_pagesrefs_h);
 
8121
                &tab_head("$title",19,0,'refererpages');
 
8122
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>";
 
8123
                if ($FilterIn{'refererpages'} || $FilterEx{'refererpages'}) {
 
8124
                        if ($FilterIn{'refererpages'}) { print "$Message[79] <b>$FilterIn{'refererpages'}</b>"; }
 
8125
                        if ($FilterIn{'refererpages'} && $FilterEx{'refererpages'}) { print " - "; }
 
8126
                        if ($FilterEx{'refererpages'}) { print "Exclude $Message[79] <b>$FilterEx{'refererpages'}</b>"; }
 
8127
                        if ($FilterIn{'refererpages'} || $FilterEx{'refererpages'}) { print ": "; }
 
8128
                        print "$cpt $Message[28]";
 
8129
                        #if ($MonthRequired ne 'all') {
 
8130
                        #       if ($HTMLOutput{'refererpages'}) { print "<br />$Message[102]: $TotalDifferentPages $Message[28]"; }
 
8131
                        #}
 
8132
                }
 
8133
                else { print "$Message[102]: $cpt $Message[28]"; }
 
8134
                print "</th>";
 
8135
                print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th><th bgcolor=\"#$color_p\" width=\"80\">$Message[15]</th>";
 
8136
                print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>";
 
8137
                print "</tr>\n";
 
8138
                $total_s=0;
 
8139
                my $count=0;
 
8140
                &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Refer'},\%_pagesrefs_h,\%_pagesrefs_p);
 
8141
                foreach my $key (@keylist) {
 
8142
                        my $nompage=CleanFromCSSA($key);
 
8143
                        if (length($nompage)>$MaxLengthOfShownURL) { $nompage=substr($nompage,0,$MaxLengthOfShownURL)."..."; }
 
8144
                        my $p_p; my $p_h;
 
8145
                        if ($TotalRefererPages) { $p_p=int($_pagesrefs_p{$key}/$TotalRefererPages*1000)/10; }
 
8146
                        if ($TotalRefererHits) { $p_h=int($_pagesrefs_h{$key}/$TotalRefererHits*1000)/10; }
 
8147
                        print "<tr><td class=\"aws\">";
 
8148
                        &ShowURLInfo($key);
 
8149
                        print "</td>";
 
8150
                        print "<td>".($_pagesrefs_p{$key}?$_pagesrefs_p{$key}:'&nbsp;')."</td><td>".($_pagesrefs_p{$key}?"$p_p %":'&nbsp;')."</td>";
 
8151
                        print "<td>".($_pagesrefs_h{$key}?$_pagesrefs_h{$key}:'&nbsp;')."</td><td>".($_pagesrefs_h{$key}?"$p_h %":'&nbsp;')."</td>";
 
8152
                        print "</tr>\n";
 
8153
                        $total_p += $_pagesrefs_p{$key};
 
8154
                        $total_h += $_pagesrefs_h{$key};
 
8155
                        $count++;
 
8156
                }
 
8157
                if ($Debug) { debug("Total real / shown : $TotalRefererPages / $total_p - $TotalRefererHits / $total_h",2); }
 
8158
                $rest_p=$TotalRefererPages-$total_p;
 
8159
                $rest_h=$TotalRefererHits-$total_h;
 
8160
                if ($rest_p > 0 || $rest_h > 0) {
 
8161
                        my $p_p; my $p_h;
 
8162
                        if ($TotalRefererPages) { $p_p=int($rest_p/$TotalRefererPages*1000)/10; }
 
8163
                        if ($TotalRefererHits) { $p_h=int($rest_h/$TotalRefererHits*1000)/10; }
 
8164
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
8165
                        print "<td>".($rest_p?$rest_p:'&nbsp;')."</td>";
 
8166
                        print "<td>".($rest_p?"$p_p %":'&nbsp;')."</td>";
 
8167
                        print "<td>$rest_h</td>";
 
8168
                        print "<td>$p_h %</td>";
 
8169
                        print "</tr>\n";
 
8170
                }
 
8171
                &tab_end;
 
8172
                &html_end(1);
 
8173
        }
 
8174
        if ($HTMLOutput{'keyphrases'}) {
 
8175
                print "$Center<a name=\"keyphrases\">&nbsp;</a><br />\n";
 
8176
                &tab_head($Message[43],19,0,'keyphrases');
 
8177
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(15);\" onmouseout=\"HideTip(15);\"":"")."><th>$TotalDifferentKeyphrases $Message[103]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[14]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[15]</th></tr>\n";
 
8178
                $total_s=0;
 
8179
                my $count=0;
 
8180
                &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Keyphrase'},\%_keyphrases,\%_keyphrases);
 
8181
                foreach my $key (@keylist) {
 
8182
                        my $mot;
 
8183
                        # Convert coded keywords (utf8,...) to be correctly reported in HTML page.
 
8184
                        if ($PluginsLoaded{'DecodeKey'}{'decodeutfkeys'})  { $mot=CleanFromCSSA(DecodeKey_decodeutfkeys($key,$PageCode||'iso-8859-1')); }
 
8185
                        else { $mot = CleanFromCSSA(DecodeEncodedString($key)); }
 
8186
                        my $p;
 
8187
                        if ($TotalKeyphrases) { $p=int($_keyphrases{$key}/$TotalKeyphrases*1000)/10; }
 
8188
                        print "<tr><td class=\"aws\">".XMLEncode($mot)."</td><td>$_keyphrases{$key}</td><td>$p %</td></tr>\n";
 
8189
                        $total_s += $_keyphrases{$key};
 
8190
                        $count++;
 
8191
                }
 
8192
                if ($Debug) { debug("Total real / shown : $TotalKeyphrases / $total_s",2); }
 
8193
                $rest_s=$TotalKeyphrases-$total_s;
 
8194
                if ($rest_s > 0) {
 
8195
                        my $p;
 
8196
                        if ($TotalKeyphrases) { $p=int($rest_s/$TotalKeyphrases*1000)/10; }
 
8197
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[124]</span></td><td>$rest_s</td>";
 
8198
                        print "<td>$p %</td></tr>\n";
 
8199
                }
 
8200
                &tab_end;
 
8201
                &html_end(1);
 
8202
        }
 
8203
        if ($HTMLOutput{'keywords'}) {
 
8204
                print "$Center<a name=\"keywords\">&nbsp;</a><br />\n";
 
8205
                &tab_head($Message[44],19,0,'keywords');
 
8206
                print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(15);\" onmouseout=\"HideTip(15);\"":"")."><th>$TotalDifferentKeywords $Message[13]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[14]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[15]</th></tr>\n";
 
8207
                $total_s=0;
 
8208
                my $count=0;
 
8209
                &BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Keyword'},\%_keywords,\%_keywords);
 
8210
                foreach my $key (@keylist) {
 
8211
                        my $mot;
 
8212
                        # Convert coded keywords (utf8,...) to be correctly reported in HTML page.
 
8213
                        if ($PluginsLoaded{'DecodeKey'}{'decodeutfkeys'})  { $mot=CleanFromCSSA(DecodeKey_decodeutfkeys($key,$PageCode||'iso-8859-1')); }
 
8214
                        else { $mot = CleanFromCSSA(DecodeEncodedString($key)); }
 
8215
                        my $p;
 
8216
                        if ($TotalKeywords) { $p=int($_keywords{$key}/$TotalKeywords*1000)/10; }
 
8217
                        print "<tr><td class=\"aws\">".XMLEncode($mot)."</td><td>$_keywords{$key}</td><td>$p %</td></tr>\n";
 
8218
                        $total_s += $_keywords{$key};
 
8219
                        $count++;
 
8220
                }
 
8221
                if ($Debug) { debug("Total real / shown : $TotalKeywords / $total_s",2); }
 
8222
                $rest_s=$TotalKeywords-$total_s;
 
8223
                if ($rest_s > 0) {
 
8224
                        my $p;
 
8225
                        if ($TotalKeywords) { $p=int($rest_s/$TotalKeywords*1000)/10; }
 
8226
                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[30]</span></td><td>$rest_s</td>";
 
8227
                        print "<td>$p %</td></tr>\n";
 
8228
                }
 
8229
                &tab_end;
 
8230
                &html_end(1);
 
8231
        }
 
8232
        foreach my $code (keys %TrapInfosForHTTPErrorCodes) {
 
8233
                if ($HTMLOutput{"errors$code"}) {
 
8234
                        print "$Center<a name=\"errors$code\">&nbsp;</a><br />\n";
 
8235
                        &tab_head($Message[47],19,0,"errors$code");
 
8236
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>URL (".(scalar keys %_sider404_h).")</th><th bgcolor=\"#$color_h\">$Message[49]</th><th>$Message[23]</th></tr>\n";
 
8237
                        $total_h=0;
 
8238
                        my $count=0;
 
8239
                        &BuildKeyList($MaxRowsInHTMLOutput,1,\%_sider404_h,\%_sider404_h);
 
8240
                        foreach my $key (@keylist) {
 
8241
                                my $nompage=CleanFromCSSA($key);
 
8242
                                #if (length($nompage)>$MaxLengthOfShownURL) { $nompage=substr($nompage,0,$MaxLengthOfShownURL)."..."; }
 
8243
                                my $referer=CleanFromCSSA($_referer404_h{$key});
 
8244
                                print "<tr><td class=\"aws\">$nompage</td>";
 
8245
                                print "<td>$_sider404_h{$key}</td>";
 
8246
                                print "<td class=\"aws\">".($referer?"$referer":"&nbsp;")."</td>";
 
8247
                                print "</tr>\n";
 
8248
                                $total_s += $_sider404_h{$key};
 
8249
                                $count++;
 
8250
                        }
 
8251
                        # TODO Build TotalErrorHits
 
8252
#                       if ($Debug) { debug("Total real / shown : $TotalErrorHits / $total_h",2); }
 
8253
#                       $rest_h=$TotalErrorHits-$total_h;
 
8254
#                       if ($rest_h > 0) {
 
8255
#                               my $p;
 
8256
#                               if ($TotalErrorHits) { $p=int($rest_h/$TotalErrorHits*1000)/10; }
 
8257
#                               print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[30]</span></td>";
 
8258
#                               print "<td>$rest_h</td>";
 
8259
#                               print "<td>...</td>";
 
8260
#                               print "</tr>\n";
 
8261
#                       }
 
8262
                        &tab_end;
 
8263
                        &html_end(1);
 
8264
                }
 
8265
        }
 
8266
        if ($HTMLOutput{'info'}) {
 
8267
                # Not yet available
 
8268
                print "$Center<a name=\"info\">&nbsp;</a><br />";
 
8269
                &html_end(1);
 
8270
        }
 
8271
        if ($HTMLOutput{'main'}) {
 
8272
 
 
8273
                # SUMMARY
 
8274
                #---------------------------------------------------------------------
 
8275
                if ($ShowMonthStats) {
 
8276
                        if ($Debug) { debug("ShowMonthStats",2); }
 
8277
                        my $title="$Message[128]";
 
8278
                        &tab_head("$title",0,0,'month');
 
8279
 
 
8280
                        my $NewLinkParams=${QueryString};
 
8281
                        $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
8282
                        $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
8283
                        $NewLinkParams =~ s/(^|&)year=[^&]*//i;
 
8284
                        $NewLinkParams =~ s/(^|&)month=[^&]*//i;
 
8285
                        $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
8286
                        $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
8287
                        if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
8288
                        my $NewLinkTarget='';
 
8289
                        if ($FrameName eq 'mainright') { $NewLinkTarget=" target=\"_parent\""; }
 
8290
        
 
8291
                        # Ratio
 
8292
                        my $RatioVisits=0; my $RatioPages=0; my $RatioHits=0; my $RatioBytes=0;
 
8293
                        if ($TotalUnique > 0) { $RatioVisits=int($TotalVisits/$TotalUnique*100)/100; }
 
8294
                        if ($TotalVisits > 0) { $RatioPages=int($TotalPages/$TotalVisits*100)/100; }
 
8295
                        if ($TotalVisits > 0) { $RatioHits=int($TotalHits/$TotalVisits*100)/100; }
 
8296
                        if ($TotalVisits > 0) { $RatioBytes=int(($TotalBytes/1024)*100/($LogType eq 'M'?$TotalHits:$TotalVisits))/100; }
 
8297
        
 
8298
                        my $colspan=5;
 
8299
                        my $w='20';
 
8300
                        if ($LogType eq 'W' || $LogType eq 'S') { $w='17'; $colspan=6; }
 
8301
                        
 
8302
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\">";
 
8303
                        if ($LogType eq 'W' || $LogType eq 'S') { print "<td>&nbsp;</td>"; }
 
8304
                        print "<td><b>$Message[8]</b></td>\n";
 
8305
                        print "<td colspan=\"3\">$Message[128]</td>";
 
8306
                        print "<td><b>$Message[9]</b></td></tr>\n";
 
8307
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\">";
 
8308
                        if ($LogType eq 'W' || $LogType eq 'S') { print "<td>&nbsp;</td>"; }
 
8309
                        if ($FirstTime) { print "<td>".Format_Date($FirstTime,0)."</td>"; }
 
8310
                        else { print "<td>NA</td>"; }
 
8311
                        print "<td colspan=\"3\"><b>";
 
8312
                        print ($MonthRequired eq 'all'?"$Message[6] $YearRequired":"$Message[5] ".$MonthNumLib{$MonthRequired}." $YearRequired");
 
8313
                        print "</b></td>";
 
8314
                        if ($LastTime) { print "<td>".Format_Date($LastTime,0)."</td></tr>\n"; }
 
8315
                        else { print "<td>NA</td></tr>\n"; }
 
8316
                        # Show main indicators
 
8317
                        print "<tr>";
 
8318
                        if ($LogType eq 'W' || $LogType eq 'S') { print "<td bgcolor=\"#$color_TableBGRowTitle\">&nbsp;</td>"; }
 
8319
                        if ($ShowMonthStats =~ /U/i) { print "<td width=\"$w%\" bgcolor=\"#$color_u\"".($TOOLTIPON?" onmouseover=\"ShowTip(2);\" onmouseout=\"HideTip(2);\"":"").">$Message[11]</td>"; } else { print "<td width=\"20%\">&nbsp;</td>"; }
 
8320
                        if ($ShowMonthStats =~ /V/i) { print "<td width=\"$w%\" bgcolor=\"#$color_v\"".($TOOLTIPON?" onmouseover=\"ShowTip(1);\" onmouseout=\"HideTip(1);\"":"").">$Message[10]</td>"; } else { print "<td width=\"20%\">&nbsp;</td>"; }
 
8321
                        if ($ShowMonthStats =~ /P/i) { print "<td width=\"$w%\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; } else { print "<td width=\"20%\">&nbsp;</td>"; }
 
8322
                        if ($ShowMonthStats =~ /H/i) { print "<td width=\"$w%\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; } else { print "<td width=\"20%\">&nbsp;</td>"; }
 
8323
                        if ($ShowMonthStats =~ /B/i) { print "<td width=\"$w%\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td>"; } else { print "<td width=\"20%\">&nbsp;</td>"; }
 
8324
                        print "</tr>\n";
 
8325
                        print "<tr>";
 
8326
                        if ($LogType eq 'W' || $LogType eq 'S') { $w='17'; print "<td class=\"aws\">$Message[160]&nbsp;*</td>"; }
 
8327
                        if ($ShowMonthStats =~ /U/i) { print "<td>".($MonthRequired eq 'all'?"<b><= $TotalUnique</b><br />$Message[129]":"<b>$TotalUnique</b><br />&nbsp;")."</td>"; } else { print "<td>&nbsp;</td>"; }
 
8328
                        if ($ShowMonthStats =~ /V/i) { print "<td><b>$TotalVisits</b><br />($RatioVisits&nbsp;$Message[52])</td>"; } else { print "<td>&nbsp;</td>"; }
 
8329
                        if ($ShowMonthStats =~ /P/i) { print "<td><b>$TotalPages</b><br />($RatioPages&nbsp;".lc($Message[56]."/".$Message[12]).")</td>"; } else { print "<td>&nbsp;</td>"; }
 
8330
                        if ($ShowMonthStats =~ /H/i) { print "<td><b>$TotalHits</b>".($LogType eq 'M'?"":"<br />($RatioHits&nbsp;".lc($Message[57]."/".$Message[12]).")</td>"); } else { print "<td>&nbsp;</td>"; }
 
8331
                        if ($ShowMonthStats =~ /B/i) { print "<td><b>".Format_Bytes(int($TotalBytes))."</b><br />($RatioBytes&nbsp;$Message[108]/".lc($Message[($LogType eq 'M'?149:12)]).")</td>"; } else { print "<td>&nbsp;</td>"; }
 
8332
                        print "</tr>\n";
 
8333
                        print "<tr>";
 
8334
                        if ($LogType eq 'W' || $LogType eq 'S') {
 
8335
                                print "<td class=\"aws\">$Message[161]&nbsp;*</td>";
 
8336
                                print "<td colspan=2>&nbsp;<br>&nbsp;</td>\n";
 
8337
                                if ($ShowMonthStats =~ /P/i) { print "<td><b>$TotalNotViewedPages</b></td>"; } else { print "<td>&nbsp;</td>"; }
 
8338
                                if ($ShowMonthStats =~ /H/i) { print "<td><b>$TotalNotViewedHits</b></td>"; } else { print "<td>&nbsp;</td>"; }
 
8339
                                if ($ShowMonthStats =~ /B/i) { print "<td><b>".Format_Bytes(int($TotalNotViewedBytes))."</b></td>"; } else { print "<td>&nbsp;</td>"; }
 
8340
                        }
 
8341
                        print "</tr>\n";
 
8342
                        &tab_end($LogType eq 'W' || $LogType eq 'S'?"* $Message[159]":"");
 
8343
 
 
8344
                        # BY MONTH
 
8345
                        #---------------------------------------------------------------------
 
8346
                        if ($ShowMonthStats) {
 
8347
 
 
8348
                        if ($Debug) { debug("ShowMonthStats",2); }
 
8349
                        print "$Center<a name=\"month\">&nbsp;</a><br />\n";
 
8350
                        my $title="$Message[162]";
 
8351
                        &tab_head("$title",0,0,'month');
 
8352
                        print "<tr><td align=\"center\">\n";
 
8353
                        print "<center>\n";
 
8354
 
 
8355
                        $average_nb=$average_u=$average_v=$average_p=$average_h=$average_k=0;
 
8356
                        $total_u=$total_v=$total_p=$total_h=$total_k=0;
 
8357
 
 
8358
                        $max_v=$max_p=$max_h=$max_k=1;
 
8359
                        # Define total and max
 
8360
                        for (my $ix=1; $ix<=12; $ix++) {
 
8361
                                my $monthix=sprintf("%02s",$ix);
 
8362
                                $total_u+=$MonthUnique{$YearRequired.$monthix}||0;
 
8363
                                $total_v+=$MonthVisits{$YearRequired.$monthix}||0;
 
8364
                                $total_p+=$MonthPages{$YearRequired.$monthix}||0;
 
8365
                                $total_h+=$MonthHits{$YearRequired.$monthix}||0;
 
8366
                                $total_k+=$MonthBytes{$YearRequired.$monthix}||0;
 
8367
                                #if (($MonthUnique{$YearRequired.$monthix}||0) > $max_v) { $max_v=$MonthUnique{$YearRequired.$monthix}; }
 
8368
                                if (($MonthVisits{$YearRequired.$monthix}||0) > $max_v) { $max_v=$MonthVisits{$YearRequired.$monthix}; }
 
8369
                                #if (($MonthPages{$YearRequired.$monthix}||0) > $max_p)  { $max_p=$MonthPages{$YearRequired.$monthix}; }
 
8370
                                if (($MonthHits{$YearRequired.$monthix}||0) > $max_h)   { $max_h=$MonthHits{$YearRequired.$monthix}; }
 
8371
                                if (($MonthBytes{$YearRequired.$monthix}||0) > $max_k)  { $max_k=$MonthBytes{$YearRequired.$monthix}; }
 
8372
                        }
 
8373
                        # Define average
 
8374
                        # TODO
 
8375
 
 
8376
                        # Show bars for month
 
8377
                        if ($PluginsLoaded{'ShowGraph'}{'graphapplet'}) {
 
8378
                                my @blocklabel=();
 
8379
                                for (my $ix=1; $ix<=12; $ix++) {
 
8380
                                        my $monthix=sprintf("%02s",$ix);
 
8381
                                        push @blocklabel,"$MonthNumLib{$monthix}ļæ½$YearRequired";
 
8382
                                }
 
8383
                                my @vallabel=("$Message[11]","$Message[10]","$Message[56]","$Message[57]","$Message[75]");
 
8384
                                my @valcolor=("$color_u","$color_v","$color_p","$color_h","$color_k");
 
8385
                                my @valmax=($max_v,$max_v,$max_h,$max_h,$max_k);
 
8386
                                my @valtotal=($total_u,$total_v,$total_p,$total_h,$total_k);
 
8387
                                my @valaverage=();
 
8388
                                #my @valaverage=($average_v,$average_p,$average_h,$average_k);
 
8389
                                my @valdata=();
 
8390
                                my $xx=0;
 
8391
                                for (my $ix=1; $ix<=12; $ix++) {
 
8392
                                        my $monthix=sprintf("%02s",$ix);
 
8393
                                        $valdata[$xx++]=$MonthUnique{$YearRequired.$monthix}||0;
 
8394
                                        $valdata[$xx++]=$MonthVisits{$YearRequired.$monthix}||0;
 
8395
                                        $valdata[$xx++]=$MonthPages{$YearRequired.$monthix}||0;
 
8396
                                        $valdata[$xx++]=$MonthHits{$YearRequired.$monthix}||0;
 
8397
                                        $valdata[$xx++]=$MonthBytes{$YearRequired.$monthix}||0;
 
8398
                                }
 
8399
                                ShowGraph_graphapplet("$title","month",$ShowMonthStats,\@blocklabel,\@vallabel,\@valcolor,\@valmax,\@valtotal,\@valaverage,\@valdata);
 
8400
                        }
 
8401
                        else {                  
 
8402
                                print "<table>\n";
 
8403
                                print "<tr valign=\"bottom\">";
 
8404
                                print "<td>&nbsp;</td>\n";
 
8405
                                for (my $ix=1; $ix<=12; $ix++) {
 
8406
                                        my $monthix=sprintf("%02s",$ix);
 
8407
                                        my $bredde_u=0; my $bredde_v=0;my $bredde_p=0;my $bredde_h=0;my $bredde_k=0;
 
8408
                                        if ($max_v > 0) { $bredde_u=int(($MonthUnique{$YearRequired.$monthix}||0)/$max_v*$BarHeight)+1; }
 
8409
                                        if ($max_v > 0) { $bredde_v=int(($MonthVisits{$YearRequired.$monthix}||0)/$max_v*$BarHeight)+1; }
 
8410
                                        if ($max_h > 0) { $bredde_p=int(($MonthPages{$YearRequired.$monthix}||0)/$max_h*$BarHeight)+1; }
 
8411
                                        if ($max_h > 0) { $bredde_h=int(($MonthHits{$YearRequired.$monthix}||0)/$max_h*$BarHeight)+1; }
 
8412
                                        if ($max_k > 0) { $bredde_k=int(($MonthBytes{$YearRequired.$monthix}||0)/$max_k*$BarHeight)+1; }
 
8413
                                        print "<td>";
 
8414
                                        if ($ShowMonthStats =~ /U/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vu'}\" height=\"$bredde_u\" width=\"6\"".AltTitle("$Message[11]: ".($MonthUnique{$YearRequired.$monthix}||0))." />"; }
 
8415
                                        if ($ShowMonthStats =~ /V/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vv'}\" height=\"$bredde_v\" width=\"6\"".AltTitle("$Message[10]: ".($MonthVisits{$YearRequired.$monthix}||0))." />"; }
 
8416
                                        if ($QueryString !~ /buildpdf/i) { print "&nbsp;"; }
 
8417
                                        if ($ShowMonthStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"6\"".AltTitle("$Message[56]: ".($MonthPages{$YearRequired.$monthix}||0))." />"; }
 
8418
                                        if ($ShowMonthStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"6\"".AltTitle("$Message[57]: ".($MonthHits{$YearRequired.$monthix}||0))." />"; }
 
8419
                                        if ($ShowMonthStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"6\"".AltTitle("$Message[75]: ".Format_Bytes($MonthBytes{$YearRequired.$monthix}))." />"; }
 
8420
                                        print "</td>\n";
 
8421
                                }
 
8422
                                print "<td>&nbsp;</td>";
 
8423
                                print "</tr>\n";
 
8424
                                # Show lib for month
 
8425
                                print "<tr valign=\"middle\">";
 
8426
#                               if ($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks) {
 
8427
#                                       print "<td><a href=\"".XMLEncode("$AWScript?${NewLinkParams}month=12&year=".($YearRequired-1))."\">&lt;&lt;</a></td>";
 
8428
#                               }
 
8429
#                               else {
 
8430
                                        print "<td>&nbsp;</td>";
 
8431
#                               }
 
8432
                                for (my $ix=1; $ix<=12; $ix++) {
 
8433
                                        my $monthix=sprintf("%02s",$ix);
 
8434
#                                       if ($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks) {
 
8435
#                                               print "<td><a href=\"".XMLEncode("$AWScript?${NewLinkParams}month=$monthix&year=$YearRequired")."\">$MonthNumLib{$monthix}<br />$YearRequired</a></td>";
 
8436
#                                       }
 
8437
#                                       else {
 
8438
                                                print "<td>$MonthNumLib{$monthix}<br />$YearRequired</td>";
 
8439
#                                       }
 
8440
                                }
 
8441
#                               if ($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks) {
 
8442
#                                       print "<td><a href=\"".XMLEncode("$AWScript?${NewLinkParams}month=1&year=".($YearRequired+1))."\">&gt;&gt;</a></td>";
 
8443
#                               }
 
8444
#                               else {
 
8445
                                        print "<td>&nbsp;</td>";
 
8446
#                               }
 
8447
                                print "</tr>\n";
 
8448
                                print "</table>\n";
 
8449
                        }
 
8450
                        print "<br />\n";
 
8451
 
 
8452
                        # Show data array for month
 
8453
                        if ($AddDataArrayMonthStats) {
 
8454
                                print "<table>\n";
 
8455
                                print "<tr><td width=\"80\" bgcolor=\"#$color_TableBGRowTitle\">$Message[5]</td>";
 
8456
                                if ($ShowMonthStats =~ /U/i) { print "<td width=\"80\" bgcolor=\"#$color_u\"".($TOOLTIPON?" onmouseover=\"ShowTip(2);\" onmouseout=\"HideTip(2);\"":"").">$Message[11]</td>"; }
 
8457
                                if ($ShowMonthStats =~ /V/i) { print "<td width=\"80\" bgcolor=\"#$color_v\"".($TOOLTIPON?" onmouseover=\"ShowTip(1);\" onmouseout=\"HideTip(1);\"":"").">$Message[10]</td>"; }
 
8458
                                if ($ShowMonthStats =~ /P/i) { print "<td width=\"80\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; }
 
8459
                                if ($ShowMonthStats =~ /H/i) { print "<td width=\"80\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; }
 
8460
                                if ($ShowMonthStats =~ /B/i) { print "<td width=\"80\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td>"; }
 
8461
                                print "</tr>\n";
 
8462
                                for (my $ix=1; $ix<=12; $ix++) {
 
8463
                                        my $monthix=sprintf("%02s",$ix);
 
8464
                                        print "<tr>";
 
8465
                                        print "<td>$MonthNumLib{$monthix} $YearRequired</td>";
 
8466
                                        if ($ShowMonthStats =~ /U/i) { print "<td>",$MonthUnique{$YearRequired.$monthix}?$MonthUnique{$YearRequired.$monthix}:"0","</td>"; }
 
8467
                                        if ($ShowMonthStats =~ /V/i) { print "<td>",$MonthVisits{$YearRequired.$monthix}?$MonthVisits{$YearRequired.$monthix}:"0","</td>"; }
 
8468
                                        if ($ShowMonthStats =~ /P/i) { print "<td>",$MonthPages{$YearRequired.$monthix}?$MonthPages{$YearRequired.$monthix}:"0","</td>"; }
 
8469
                                        if ($ShowMonthStats =~ /H/i) { print "<td>",$MonthHits{$YearRequired.$monthix}?$MonthHits{$YearRequired.$monthix}:"0","</td>"; }
 
8470
                                        if ($ShowMonthStats =~ /B/i) { print "<td>",Format_Bytes(int($MonthBytes{$YearRequired.$monthix}||0)),"</td>"; }
 
8471
                                        print "</tr>\n";
 
8472
                                }
 
8473
                                # Average row
 
8474
                                # TODO
 
8475
                                # Total row
 
8476
                                print "<tr><td bgcolor=\"#$color_TableBGRowTitle\">$Message[102]</td>";
 
8477
                                if ($ShowMonthStats =~ /U/i) { print "<td bgcolor=\"#$color_TableBGRowTitle\">$total_u</td>"; }
 
8478
                                if ($ShowMonthStats =~ /V/i) { print "<td bgcolor=\"#$color_TableBGRowTitle\">$total_v</td>"; }
 
8479
                                if ($ShowMonthStats =~ /P/i) { print "<td bgcolor=\"#$color_TableBGRowTitle\">$total_p</td>"; }
 
8480
                                if ($ShowMonthStats =~ /H/i) { print "<td bgcolor=\"#$color_TableBGRowTitle\">$total_h</td>"; }
 
8481
                                if ($ShowMonthStats =~ /B/i) { print "<td bgcolor=\"#$color_TableBGRowTitle\">".Format_Bytes($total_k)."</td>"; }
 
8482
                                print "</tr>\n";                
 
8483
                                print "</table>\n<br />\n";
 
8484
                        }
 
8485
                                
 
8486
                        print "</center>\n";
 
8487
                        print "</td></tr>\n";
 
8488
                        &tab_end;
 
8489
                }
 
8490
                }
 
8491
 
 
8492
                print "\n<a name=\"when\">&nbsp;</a>\n\n";
 
8493
 
 
8494
                # BY DAY OF MONTH
 
8495
                #---------------------------------------------------------------------
 
8496
                if ($ShowDaysOfMonthStats) {
 
8497
                        if ($Debug) { debug("ShowDaysOfMonthStats",2); }
 
8498
                        print "$Center<a name=\"daysofmonth\">&nbsp;</a><br />\n";
 
8499
                        my $title="$Message[138]";
 
8500
                        &tab_head("$title",0,0,'daysofmonth');
 
8501
                        print "<tr>";
 
8502
                        print "<td align=\"center\">\n";
 
8503
                        print "<center>\n";
 
8504
                        
 
8505
                        my $NewLinkParams=${QueryString};
 
8506
                        $NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
 
8507
                        $NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
 
8508
                        $NewLinkParams =~ s/(^|&)year=[^&]*//i;
 
8509
                        $NewLinkParams =~ s/(^|&)month=[^&]*//i;
 
8510
                        $NewLinkParams =~ s/(^|&)framename=[^&]*//i;
 
8511
                        $NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
 
8512
                        if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
 
8513
                        my $NewLinkTarget='';
 
8514
                        if ($FrameName eq 'mainright') { $NewLinkTarget=" target=\"_parent\""; }
 
8515
                                
 
8516
                        $average_nb=$average_u=$average_v=$average_p=$average_h=$average_k=0;
 
8517
                        $total_u=$total_v=$total_p=$total_h=$total_k=0;
 
8518
                        # Define total and max
 
8519
                        $max_v=$max_h=$max_k=0;         # Start from 0 because can be lower than 1
 
8520
                        foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
8521
                                $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8522
                                my $year=$1; my $month=$2; my $day=$3;
 
8523
                                if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8524
                                $total_v+=$DayVisits{$year.$month.$day}||0;
 
8525
                                $total_p+=$DayPages{$year.$month.$day}||0;
 
8526
                                $total_h+=$DayHits{$year.$month.$day}||0;
 
8527
                                $total_k+=$DayBytes{$year.$month.$day}||0;
 
8528
                                if (($DayVisits{$year.$month.$day}||0) > $max_v)  { $max_v=$DayVisits{$year.$month.$day}; }
 
8529
                                #if (($DayPages{$year.$month.$day}||0) > $max_p)  { $max_p=$DayPages{$year.$month.$day}; }
 
8530
                                if (($DayHits{$year.$month.$day}||0) > $max_h)   { $max_h=$DayHits{$year.$month.$day}; }
 
8531
                                if (($DayBytes{$year.$month.$day}||0) > $max_k)  { $max_k=$DayBytes{$year.$month.$day}; }
 
8532
                        }
 
8533
                        # Define average
 
8534
                        foreach my $daycursor ($firstdaytocountaverage..$lastdaytocountaverage) {
 
8535
                                $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8536
                                my $year=$1; my $month=$2; my $day=$3;
 
8537
                                if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8538
                                $average_nb++;                                                                                  # Increase number of day used to count
 
8539
                                $average_v+=($DayVisits{$daycursor}||0);
 
8540
                                $average_p+=($DayPages{$daycursor}||0);
 
8541
                                $average_h+=($DayHits{$daycursor}||0);
 
8542
                                $average_k+=($DayBytes{$daycursor}||0);
 
8543
                        }
 
8544
                        if ($average_nb) {
 
8545
                                $average_v=$average_v/$average_nb;
 
8546
                                $average_p=$average_p/$average_nb;
 
8547
                                $average_h=$average_h/$average_nb;
 
8548
                                $average_k=$average_k/$average_nb;
 
8549
                                if ($average_v > $max_v) { $max_v=$average_v; }
 
8550
                                #if ($average_p > $max_p) { $max_p=$average_p; }
 
8551
                                if ($average_h > $max_h) { $max_h=$average_h; }
 
8552
                                if ($average_k > $max_k) { $max_k=$average_k; }
 
8553
                        }
 
8554
                        else {
 
8555
                                $average_v="?";
 
8556
                                $average_p="?";
 
8557
                                $average_h="?";
 
8558
                                $average_k="?";
 
8559
                        }
 
8560
 
 
8561
                        # Show bars for day
 
8562
                        if ($PluginsLoaded{'ShowGraph'}{'graphapplet'}) {
 
8563
                                my @blocklabel=();
 
8564
                                foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
8565
                                        $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8566
                                        my $year=$1; my $month=$2; my $day=$3;
 
8567
                                        if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8568
                                        my $bold=($day==$nowday && $month==$nowmonth && $year==$nowyear?':':'');
 
8569
                                        my $weekend=(DayOfWeek($day,$month,$year)=~/[06]/?'!':'');
 
8570
                                        push @blocklabel,"$dayļæ½$MonthNumLib{$month}$weekend$bold";
 
8571
                                }
 
8572
                                my @vallabel=("$Message[10]","$Message[56]","$Message[57]","$Message[75]");
 
8573
                                my @valcolor=("$color_v","$color_p","$color_h","$color_k");
 
8574
                                my @valmax=($max_v,$max_h,$max_h,$max_k);
 
8575
                                my @valtotal=($total_v,$total_p,$total_h,$total_k);
 
8576
                                $average_v=sprintf("%.2f",$average_v);
 
8577
                                $average_p=sprintf("%.2f",$average_p);
 
8578
                                $average_h=sprintf("%.2f",$average_h);
 
8579
                                $average_k=(int($average_k)?Format_Bytes(sprintf("%.2f",$average_k)):"0.00");
 
8580
                                my @valaverage=($average_v,$average_p,$average_h,$average_k);
 
8581
                                my @valdata=();
 
8582
                                my $xx=0;
 
8583
                                foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
8584
                                        $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8585
                                        my $year=$1; my $month=$2; my $day=$3;
 
8586
                                        if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8587
                                        $valdata[$xx++]=$DayVisits{$year.$month.$day}||0;
 
8588
                                        $valdata[$xx++]=$DayPages{$year.$month.$day}||0;
 
8589
                                        $valdata[$xx++]=$DayHits{$year.$month.$day}||0;
 
8590
                                        $valdata[$xx++]=$DayBytes{$year.$month.$day}||0;
 
8591
                                }
 
8592
                                ShowGraph_graphapplet("$title","daysofmonth",$ShowDaysOfMonthStats,\@blocklabel,\@vallabel,\@valcolor,\@valmax,\@valtotal,\@valaverage,\@valdata);
 
8593
                        }
 
8594
                        else {                  
 
8595
                                print "<table>\n";
 
8596
                                print "<tr valign=\"bottom\">\n";
 
8597
                                foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
8598
                                        $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8599
                                        my $year=$1; my $month=$2; my $day=$3;
 
8600
                                        if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8601
                                        my $bredde_v=0; my $bredde_p=0; my $bredde_h=0; my $bredde_k=0;
 
8602
                                        if ($max_v > 0) { $bredde_v=int(($DayVisits{$year.$month.$day}||0)/$max_v*$BarHeight)+1; }
 
8603
                                        if ($max_h > 0) { $bredde_p=int(($DayPages{$year.$month.$day}||0)/$max_h*$BarHeight)+1; }
 
8604
                                        if ($max_h > 0) { $bredde_h=int(($DayHits{$year.$month.$day}||0)/$max_h*$BarHeight)+1; }
 
8605
                                        if ($max_k > 0) { $bredde_k=int(($DayBytes{$year.$month.$day}||0)/$max_k*$BarHeight)+1; }
 
8606
                                        print "<td>";
 
8607
                                        if ($ShowDaysOfMonthStats =~ /V/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vv'}\" height=\"$bredde_v\" width=\"4\"".AltTitle("$Message[10]: ".int($DayVisits{$year.$month.$day}||0))." />"; }
 
8608
                                        if ($ShowDaysOfMonthStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"4\"".AltTitle("$Message[56]: ".int($DayPages{$year.$month.$day}||0))." />"; }
 
8609
                                        if ($ShowDaysOfMonthStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"4\"".AltTitle("$Message[57]: ".int($DayHits{$year.$month.$day}||0))." />"; }
 
8610
                                        if ($ShowDaysOfMonthStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"4\"".AltTitle("$Message[75]: ".Format_Bytes($DayBytes{$year.$month.$day}))." />"; }
 
8611
                                        print "</td>\n";
 
8612
                                }
 
8613
                                print "<td>&nbsp;</td>";
 
8614
                                # Show average value cell
 
8615
                                print "<td>";
 
8616
                                my $bredde_v=0; my $bredde_p=0; my $bredde_h=0; my $bredde_k=0;
 
8617
                                if ($max_v > 0) { $bredde_v=int($average_v/$max_v*$BarHeight)+1; }
 
8618
                                if ($max_h > 0) { $bredde_p=int($average_p/$max_h*$BarHeight)+1; }
 
8619
                                if ($max_h > 0) { $bredde_h=int($average_h/$max_h*$BarHeight)+1; }
 
8620
                                if ($max_k > 0) { $bredde_k=int($average_k/$max_k*$BarHeight)+1; }
 
8621
                                $average_v=sprintf("%.2f",$average_v);
 
8622
                                $average_p=sprintf("%.2f",$average_p);
 
8623
                                $average_h=sprintf("%.2f",$average_h);
 
8624
                                $average_k=(int($average_k)?Format_Bytes(sprintf("%.2f",$average_k)):"0.00");
 
8625
                                if ($ShowDaysOfMonthStats =~ /V/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vv'}\" height=\"$bredde_v\" width=\"4\"".AltTitle("$Message[10]: $average_v")." />"; }
 
8626
                                if ($ShowDaysOfMonthStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"4\"".AltTitle("$Message[56]: $average_p")." />"; }
 
8627
                                if ($ShowDaysOfMonthStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"4\"".AltTitle("$Message[57]: $average_h")." />"; }
 
8628
                                if ($ShowDaysOfMonthStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"4\"".AltTitle("$Message[75]: $average_k")." />"; }
 
8629
                                print "</td>\n";
 
8630
                                print "</tr>\n";
 
8631
                                # Show lib for day
 
8632
                                print "<tr valign=\"middle\">";
 
8633
                                foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
8634
                                        $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8635
                                        my $year=$1; my $month=$2; my $day=$3;
 
8636
                                        if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8637
                                        my $dayofweekcursor=DayOfWeek($day,$month,$year);
 
8638
                                        print "<td".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">";
 
8639
                                        print ($day==$nowday && $month==$nowmonth && $year==$nowyear?'<b>':'');
 
8640
                                        print "$day<br /><span style=\"font-size: ".($FrameName ne 'mainright' && $QueryString !~ /buildpdf/i?"9":"8")."px;\">".$MonthNumLib{$month}."</span>";
 
8641
                                        print ($day==$nowday && $month==$nowmonth && $year==$nowyear?'</b>':'');
 
8642
                                        print "</td>\n";
 
8643
                                }
 
8644
                                print "<td>&nbsp;</td>";
 
8645
                                print "<td valign=\"middle\"".($TOOLTIPON?" onmouseover=\"ShowTip(18);\" onmouseout=\"HideTip(18);\"":"").">$Message[96]</td>\n";
 
8646
                                print "</tr>\n";
 
8647
                                print "</table>\n";
 
8648
                        }
 
8649
                        print "<br />\n";
 
8650
        
 
8651
                        # Show data array for days
 
8652
                        if ($AddDataArrayShowDaysOfMonthStats) {
 
8653
                                print "<table>\n";
 
8654
                                print "<tr><td width=\"80\" bgcolor=\"#$color_TableBGRowTitle\">$Message[4]</td>";
 
8655
                                if ($ShowDaysOfMonthStats =~ /V/i) { print "<td width=\"80\" bgcolor=\"#$color_v\"".($TOOLTIPON?" onmouseover=\"ShowTip(1);\" onmouseout=\"HideTip(1);\"":"").">$Message[10]</td>"; }
 
8656
                                if ($ShowDaysOfMonthStats =~ /P/i) { print "<td width=\"80\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; }
 
8657
                                if ($ShowDaysOfMonthStats =~ /H/i) { print "<td width=\"80\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; }
 
8658
                                if ($ShowDaysOfMonthStats =~ /B/i) { print "<td width=\"80\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td></tr>"; }
 
8659
                                foreach my $daycursor ($firstdaytoshowtime..$lastdaytoshowtime) {
 
8660
                                        $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8661
                                        my $year=$1; my $month=$2; my $day=$3;
 
8662
                                        if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8663
                                        my $dayofweekcursor=DayOfWeek($day,$month,$year);
 
8664
                                        print "<tr".($dayofweekcursor=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">";
 
8665
                                        print "<td>",Format_Date("$year$month$day"."000000",2),"</td>";
 
8666
                                        if ($ShowDaysOfMonthStats =~ /V/i) { print "<td>",$DayVisits{$year.$month.$day}?$DayVisits{$year.$month.$day}:"0","</td>"; }
 
8667
                                        if ($ShowDaysOfMonthStats =~ /P/i) { print "<td>",$DayPages{$year.$month.$day}?$DayPages{$year.$month.$day}:"0","</td>"; }
 
8668
                                        if ($ShowDaysOfMonthStats =~ /H/i) { print "<td>",$DayHits{$year.$month.$day}?$DayHits{$year.$month.$day}:"0","</td>"; }
 
8669
                                        if ($ShowDaysOfMonthStats =~ /B/i) { print "<td>",Format_Bytes(int($DayBytes{$year.$month.$day}||0)),"</td>"; }
 
8670
                                        print "</tr>\n";
 
8671
                                }
 
8672
                                # Average row
 
8673
                                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><td>$Message[96]</td>";
 
8674
                                if ($ShowDaysOfMonthStats =~ /V/i) { print "<td>$average_v</td>"; }
 
8675
                                if ($ShowDaysOfMonthStats =~ /P/i) { print "<td>$average_p</td>"; }
 
8676
                                if ($ShowDaysOfMonthStats =~ /H/i) { print "<td>$average_h</td>"; }
 
8677
                                if ($ShowDaysOfMonthStats =~ /B/i) { print "<td>$average_k</td>"; }
 
8678
                                print "</tr>\n";                
 
8679
                                # Total row
 
8680
                                print "<tr bgcolor=\"#$color_TableBGRowTitle\"><td>$Message[102]</td>";
 
8681
                                if ($ShowDaysOfMonthStats =~ /V/i) { print "<td>$total_v</td>"; }
 
8682
                                if ($ShowDaysOfMonthStats =~ /P/i) { print "<td>$total_p</td>"; }
 
8683
                                if ($ShowDaysOfMonthStats =~ /H/i) { print "<td>$total_h</td>"; }
 
8684
                                if ($ShowDaysOfMonthStats =~ /B/i) { print "<td>".Format_Bytes($total_k)."</td>"; }
 
8685
                                print "</tr>\n";                
 
8686
                                print "</table>\n<br />";
 
8687
                        }
 
8688
                                
 
8689
                        print "</center>\n";
 
8690
                        print "</td></tr>\n";
 
8691
                        &tab_end;
 
8692
                }
 
8693
 
 
8694
                # BY DAY OF WEEK
 
8695
                #-------------------------
 
8696
                if ($ShowDaysOfWeekStats) {
 
8697
                        if ($Debug) { debug("ShowDaysOfWeekStats",2); }
 
8698
                        print "$Center<a name=\"daysofweek\">&nbsp;</a><br />\n";
 
8699
                        my $title="$Message[91]";
 
8700
                        &tab_head("$title",18,0,'daysofweek');
 
8701
                        print "<tr>";
 
8702
                        print "<td align=\"center\">";
 
8703
                        print "<center>\n";
 
8704
 
 
8705
                        $max_h=$max_k=0;        # Start from 0 because can be lower than 1
 
8706
                        # Get average value for day of week
 
8707
                        my @avg_dayofweek_nb = my @avg_dayofweek_p = my @avg_dayofweek_h = my @avg_dayofweek_k = ();
 
8708
                        foreach my $daycursor ($firstdaytocountaverage..$lastdaytocountaverage) {
 
8709
                                $daycursor =~ /^(\d\d\d\d)(\d\d)(\d\d)/;
 
8710
                                my $year=$1; my $month=$2; my $day=$3;
 
8711
                                if (! DateIsValid($day,$month,$year)) { next; }                 # If not an existing day, go to next
 
8712
                                my $dayofweekcursor=DayOfWeek($day,$month,$year);
 
8713
                                $avg_dayofweek_nb[$dayofweekcursor]++;                                  # Increase number of day used to count for this day of week
 
8714
                                $avg_dayofweek_p[$dayofweekcursor]+=($DayPages{$daycursor}||0);
 
8715
                                $avg_dayofweek_h[$dayofweekcursor]+=($DayHits{$daycursor}||0);
 
8716
                                $avg_dayofweek_k[$dayofweekcursor]+=($DayBytes{$daycursor}||0);
 
8717
                        }
 
8718
                        for (@DOWIndex) {
 
8719
                                if ($avg_dayofweek_nb[$_]) {
 
8720
                                        $avg_dayofweek_p[$_]=$avg_dayofweek_p[$_]/$avg_dayofweek_nb[$_];
 
8721
                                        $avg_dayofweek_h[$_]=$avg_dayofweek_h[$_]/$avg_dayofweek_nb[$_];
 
8722
                                        $avg_dayofweek_k[$_]=$avg_dayofweek_k[$_]/$avg_dayofweek_nb[$_];
 
8723
                                        #if ($avg_dayofweek_p[$_] > $max_p) { $max_p = $avg_dayofweek_p[$_]; }
 
8724
                                        if ($avg_dayofweek_h[$_] > $max_h) { $max_h = $avg_dayofweek_h[$_]; }
 
8725
                                        if ($avg_dayofweek_k[$_] > $max_k) { $max_k = $avg_dayofweek_k[$_]; }
 
8726
                                }
 
8727
                                else {
 
8728
                                        $avg_dayofweek_p[$_]="?";
 
8729
                                        $avg_dayofweek_h[$_]="?";
 
8730
                                        $avg_dayofweek_k[$_]="?";
 
8731
                                }
 
8732
                        }
 
8733
 
 
8734
                        # Show bars for days of week
 
8735
                        if ($PluginsLoaded{'ShowGraph'}{'graphapplet'}) {
 
8736
                                my @blocklabel=();
 
8737
                                for (@DOWIndex) { push @blocklabel,($Message[$_+84].($_=~/[06]/?"!":"")); }
 
8738
                                my @vallabel=("$Message[56]","$Message[57]","$Message[75]");
 
8739
                                my @valcolor=("$color_p","$color_h","$color_k");
 
8740
                                my @valmax=(int($max_h),int($max_h),int($max_k));
 
8741
                                my @valtotal=($total_p,$total_h,$total_k);
 
8742
                                $average_p=sprintf("%.2f",$average_p);
 
8743
                                $average_h=sprintf("%.2f",$average_h);
 
8744
                                $average_k=(int($average_k)?Format_Bytes(sprintf("%.2f",$average_k)):"0.00");
 
8745
                                my @valaverage=($average_p,$average_h,$average_k);
 
8746
                                my @valdata=();
 
8747
                                my $xx=0;
 
8748
                                for (@DOWIndex) {
 
8749
                                        $valdata[$xx++]=$avg_dayofweek_p[$_]||0;
 
8750
                                        $valdata[$xx++]=$avg_dayofweek_h[$_]||0;
 
8751
                                        $valdata[$xx++]=$avg_dayofweek_k[$_]||0;
 
8752
                                        # Round to be ready to show array
 
8753
                                        $avg_dayofweek_p[$_]=sprintf("%.2f",$avg_dayofweek_p[$_]);
 
8754
                                        $avg_dayofweek_h[$_]=sprintf("%.2f",$avg_dayofweek_h[$_]);
 
8755
                                        $avg_dayofweek_k[$_]=sprintf("%.2f",$avg_dayofweek_k[$_]);
 
8756
                                        # Remove decimal part that are .0
 
8757
                                        if ($avg_dayofweek_p[$_] == int($avg_dayofweek_p[$_])) { $avg_dayofweek_p[$_]=int($avg_dayofweek_p[$_]); }
 
8758
                                        if ($avg_dayofweek_h[$_] == int($avg_dayofweek_h[$_])) { $avg_dayofweek_h[$_]=int($avg_dayofweek_h[$_]); }
 
8759
                                }
 
8760
                                ShowGraph_graphapplet("$title","daysofweek",$ShowDaysOfWeekStats,\@blocklabel,\@vallabel,\@valcolor,\@valmax,\@valtotal,\@valaverage,\@valdata);
 
8761
                        }
 
8762
                        else {                  
 
8763
                                print "<table>\n";
 
8764
                                print "<tr valign=\"bottom\">\n";
 
8765
                                for (@DOWIndex) {
 
8766
                                        my $bredde_p=0; my $bredde_h=0; my $bredde_k=0;
 
8767
                                        if ($max_h > 0) { $bredde_p=int($avg_dayofweek_p[$_]/$max_h*$BarHeight)+1; }
 
8768
                                        if ($max_h > 0) { $bredde_h=int($avg_dayofweek_h[$_]/$max_h*$BarHeight)+1; }
 
8769
                                        if ($max_k > 0) { $bredde_k=int($avg_dayofweek_k[$_]/$max_k*$BarHeight)+1; }
 
8770
                                        $avg_dayofweek_p[$_]=sprintf("%.2f",$avg_dayofweek_p[$_]);
 
8771
                                        $avg_dayofweek_h[$_]=sprintf("%.2f",$avg_dayofweek_h[$_]);
 
8772
                                        $avg_dayofweek_k[$_]=sprintf("%.2f",$avg_dayofweek_k[$_]);
 
8773
                                        # Remove decimal part that are .0
 
8774
                                        if ($avg_dayofweek_p[$_] == int($avg_dayofweek_p[$_])) { $avg_dayofweek_p[$_]=int($avg_dayofweek_p[$_]); }
 
8775
                                        if ($avg_dayofweek_h[$_] == int($avg_dayofweek_h[$_])) { $avg_dayofweek_h[$_]=int($avg_dayofweek_h[$_]); }
 
8776
                                        print "<td valign=\"bottom\">";
 
8777
                                        if ($ShowDaysOfWeekStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"6\"".AltTitle("$Message[56]: $avg_dayofweek_p[$_]")." />"; }
 
8778
                                        if ($ShowDaysOfWeekStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"6\"".AltTitle("$Message[57]: $avg_dayofweek_h[$_]")." />"; }
 
8779
                                        if ($ShowDaysOfWeekStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"6\"".AltTitle("$Message[75]: ".Format_Bytes($avg_dayofweek_k[$_]))." />"; }
 
8780
                                        print "</td>\n";
 
8781
                                }
 
8782
                                print "</tr>\n";
 
8783
                                print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip(17);\" onmouseout=\"HideTip(17);\"":"").">\n";
 
8784
                                for (@DOWIndex) {
 
8785
                                        print "<td".($_=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">".$Message[$_+84]."</td>";
 
8786
                                }
 
8787
                                print "</tr>\n</table>\n";
 
8788
                        }
 
8789
                        print "<br />\n";
 
8790
                        
 
8791
                        # Show data array for days of week
 
8792
                        if ($AddDataArrayShowDaysOfWeekStats) {
 
8793
                                print "<table>\n";
 
8794
                                print "<tr><td width=\"80\" bgcolor=\"#$color_TableBGRowTitle\">$Message[4]</td>";
 
8795
                                if ($ShowDaysOfWeekStats =~ /P/i) { print "<td width=\"80\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; }
 
8796
                                if ($ShowDaysOfWeekStats =~ /H/i) { print "<td width=\"80\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; }
 
8797
                                if ($ShowDaysOfWeekStats =~ /B/i) { print "<td width=\"80\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td></tr>"; }
 
8798
                                for (@DOWIndex) {
 
8799
                                        print "<tr".($_=~/[06]/?" bgcolor=\"#$color_weekend\"":"").">";
 
8800
                                        print "<td>".$Message[$_+84]."</td>";
 
8801
                                        if ($ShowDaysOfWeekStats =~ /P/i) { print "<td>",$avg_dayofweek_p[$_],"</td>"; }
 
8802
                                        if ($ShowDaysOfWeekStats =~ /H/i) { print "<td>",$avg_dayofweek_h[$_],"</td>"; }
 
8803
                                        if ($ShowDaysOfWeekStats =~ /B/i) { print "<td>",Format_Bytes($avg_dayofweek_k[$_]),"</td>"; }
 
8804
                                        print "</tr>\n";
 
8805
                                }
 
8806
                                print "</table>\n<br />\n";
 
8807
                        }
 
8808
                                                
 
8809
                        print "</center></td>";
 
8810
                        print "</tr>\n";
 
8811
                        &tab_end;
 
8812
                }
 
8813
        
 
8814
                # BY HOUR
 
8815
                #----------------------------
 
8816
                if ($ShowHoursStats) {
 
8817
                        if ($Debug) { debug("ShowHoursStats",2); }
 
8818
                        print "$Center<a name=\"hours\">&nbsp;</a><br />\n";
 
8819
                        my $title="$Message[20]";
 
8820
                        if ($PluginsLoaded{'GetTimeZoneTitle'}{'timezone'}) { $title.=" (GMT ".(GetTimeZoneTitle_timezone()>=0?"+":"").int(GetTimeZoneTitle_timezone()).")"; }
 
8821
                        &tab_head("$title",19,0,'hours');
 
8822
                        print "<tr><td align=\"center\">\n";
 
8823
                        print "<center>\n";
 
8824
                        
 
8825
                        $max_h=$max_k=1;
 
8826
                        for (my $ix=0; $ix<=23; $ix++) {
 
8827
                          #if ($_time_p[$ix]>$max_p) { $max_p=$_time_p[$ix]; }
 
8828
                          if ($_time_h[$ix]>$max_h) { $max_h=$_time_h[$ix]; }
 
8829
                          if ($_time_k[$ix]>$max_k) { $max_k=$_time_k[$ix]; }
 
8830
                        }
 
8831
 
 
8832
                        # Show bars for hour
 
8833
                        if ($PluginsLoaded{'ShowGraph'}{'graphapplet'}) {
 
8834
                                my @blocklabel=(0..23);
 
8835
                                my @vallabel=("$Message[56]","$Message[57]","$Message[75]");
 
8836
                                my @valcolor=("$color_p","$color_h","$color_k");
 
8837
                                my @valmax=(int($max_h),int($max_h),int($max_k));
 
8838
                                my @valtotal=($total_p,$total_h,$total_k);
 
8839
                                my @valaverage=($average_p,$average_h,$average_k);
 
8840
                                my @valdata=();
 
8841
                                my $xx=0;
 
8842
                                for (0..23) {
 
8843
                                        $valdata[$xx++]=$_time_p[$_]||0;
 
8844
                                        $valdata[$xx++]=$_time_h[$_]||0;
 
8845
                                        $valdata[$xx++]=$_time_k[$_]||0;
 
8846
                                }
 
8847
                                ShowGraph_graphapplet("$title","hours",$ShowHoursStats,\@blocklabel,\@vallabel,\@valcolor,\@valmax,\@valtotal,\@valaverage,\@valdata);
 
8848
                        }
 
8849
                        else {                  
 
8850
                                print "<table>\n";
 
8851
                                print "<tr valign=\"bottom\">\n";
 
8852
                                for (my $ix=0; $ix<=23; $ix++) {
 
8853
                                        my $bredde_p=0;my $bredde_h=0;my $bredde_k=0;
 
8854
                                        if ($max_h > 0) { $bredde_p=int($BarHeight*$_time_p[$ix]/$max_h)+1; }
 
8855
                                        if ($max_h > 0) { $bredde_h=int($BarHeight*$_time_h[$ix]/$max_h)+1; }
 
8856
                                        if ($max_k > 0) { $bredde_k=int($BarHeight*$_time_k[$ix]/$max_k)+1; }
 
8857
                                        print "<td>";
 
8858
                                        if ($ShowHoursStats =~ /P/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vp'}\" height=\"$bredde_p\" width=\"6\"".AltTitle("$Message[56]: ".int($_time_p[$ix]))." />"; }
 
8859
                                        if ($ShowHoursStats =~ /H/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vh'}\" height=\"$bredde_h\" width=\"6\"".AltTitle("$Message[57]: ".int($_time_h[$ix]))." />"; }
 
8860
                                        if ($ShowHoursStats =~ /B/i) { print "<img align=\"bottom\" src=\"$DirIcons\/other\/$BarPng{'vk'}\" height=\"$bredde_k\" width=\"6\"".AltTitle("$Message[75]: ".Format_Bytes($_time_k[$ix]))." />"; }
 
8861
                                        print "</td>\n";
 
8862
                                }
 
8863
                                print "</tr>\n";
 
8864
                                # Show hour lib
 
8865
                                print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip(17);\" onmouseout=\"HideTip(17);\"":"").">";
 
8866
                                for (my $ix=0; $ix<=23; $ix++) {
 
8867
                                  print "<th width=\"19\">$ix</th>\n";  # width=19 instead of 18 to avoid a MacOS browser bug.
 
8868
                                }
 
8869
                                print "</tr>\n";
 
8870
                                # Show clock icon
 
8871
                                print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip(17);\" onmouseout=\"HideTip(17);\"":"").">\n";
 
8872
                                for (my $ix=0; $ix<=23; $ix++) {
 
8873
                                        my $hrs=($ix>=12?$ix-12:$ix);
 
8874
                                        my $hre=($ix>=12?$ix-11:$ix+1);
 
8875
                                        my $apm=($ix>=12?"pm":"am");
 
8876
                                        print "<td><img src=\"$DirIcons\/clock\/hr$hre.png\" width=\"10\" alt=\"$hrs:00 - $hre:00 $apm\" /></td>\n";
 
8877
                                }
 
8878
                                print "</tr>\n";
 
8879
                                print "</table>\n";
 
8880
                        }
 
8881
                        print "<br />\n";
 
8882
                        
 
8883
                        # Show data array for hours
 
8884
                        if ($AddDataArrayShowHoursStats) {
 
8885
                                print "<table width=\"650\"><tr>\n";
 
8886
                                print "<td align=\"center\"><center>\n";
 
8887
 
 
8888
                                print "<table>\n";
 
8889
                                print "<tr><td width=\"80\" bgcolor=\"#$color_TableBGRowTitle\">$Message[20]</td>";
 
8890
                                if ($ShowHoursStats =~ /P/i) { print "<td width=\"80\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; }
 
8891
                                if ($ShowHoursStats =~ /H/i) { print "<td width=\"80\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; }
 
8892
                                if ($ShowHoursStats =~ /B/i) { print "<td width=\"80\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td>"; }
 
8893
                                print "</tr>";
 
8894
                                for (my $ix=0; $ix<=11; $ix++) {
 
8895
                                        my $monthix=($ix<10?"0$ix":"$ix");
 
8896
                                        print "<tr>";
 
8897
                                        print "<td>$monthix</td>";
 
8898
                                        if ($ShowHoursStats =~ /P/i) { print "<td>",$_time_p[$monthix]?$_time_p[$monthix]:"0","</td>"; }
 
8899
                                        if ($ShowHoursStats =~ /H/i) { print "<td>",$_time_h[$monthix]?$_time_h[$monthix]:"0","</td>"; }
 
8900
                                        if ($ShowHoursStats =~ /B/i) { print "<td>",Format_Bytes(int($_time_k[$monthix])),"</td>"; }
 
8901
                                        print "</tr>\n";
 
8902
                                }
 
8903
                                print "</table>\n";
 
8904
 
 
8905
                                print "</center></td>";
 
8906
                                print "<td width=\"10\">&nbsp;</td>";
 
8907
                                print "<td align=\"center\"><center>\n";
 
8908
 
 
8909
                                print "<table>\n";
 
8910
                                print "<tr><td width=\"80\" bgcolor=\"#$color_TableBGRowTitle\">$Message[20]</td>";
 
8911
                                if ($ShowHoursStats =~ /P/i) { print "<td width=\"80\" bgcolor=\"#$color_p\"".($TOOLTIPON?" onmouseover=\"ShowTip(3);\" onmouseout=\"HideTip(3);\"":"").">$Message[56]</td>"; }
 
8912
                                if ($ShowHoursStats =~ /H/i) { print "<td width=\"80\" bgcolor=\"#$color_h\"".($TOOLTIPON?" onmouseover=\"ShowTip(4);\" onmouseout=\"HideTip(4);\"":"").">$Message[57]</td>"; }
 
8913
                                if ($ShowHoursStats =~ /B/i) { print "<td width=\"80\" bgcolor=\"#$color_k\"".($TOOLTIPON?" onmouseover=\"ShowTip(5);\" onmouseout=\"HideTip(5);\"":"").">$Message[75]</td>"; }
 
8914
                                print "</tr>\n";
 
8915
                                for (my $ix=12; $ix<=23; $ix++) {
 
8916
                                        my $monthix=($ix<10?"0$ix":"$ix");
 
8917
                                        print "<tr>";
 
8918
                                        print "<td>$monthix</td>";
 
8919
                                        if ($ShowHoursStats =~ /P/i) { print "<td>",$_time_p[$monthix]?$_time_p[$monthix]:"0","</td>"; }
 
8920
                                        if ($ShowHoursStats =~ /H/i) { print "<td>",$_time_h[$monthix]?$_time_h[$monthix]:"0","</td>"; }
 
8921
                                        if ($ShowHoursStats =~ /B/i) { print "<td>",Format_Bytes(int($_time_k[$monthix])),"</td>"; }
 
8922
                                        print "</tr>\n";
 
8923
                                }
 
8924
                                print "</table>\n";
 
8925
 
 
8926
                                print "</center></td></tr></table>\n";
 
8927
                                print "<br />\n";
 
8928
                        }
 
8929
                                        
 
8930
                        print "</center></td></tr>\n";
 
8931
                        &tab_end;
 
8932
                }
 
8933
        
 
8934
                print "\n<a name=\"who\">&nbsp;</a>\n\n";
 
8935
        
 
8936
                # BY COUNTRY/DOMAIN
 
8937
                #---------------------------
 
8938
                if ($ShowDomainsStats) {
 
8939
                        if ($Debug) { debug("ShowDomainsStats",2); }
 
8940
                        print "$Center<a name=\"countries\">&nbsp;</a><br />\n";
 
8941
                        my $title="$Message[25] ($Message[77] $MaxNbOf{'Domain'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=alldomains"):"$PROG$StaticLinks.alldomains.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>";
 
8942
                        &tab_head("$title",19,0,'countries');
 
8943
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th width=\"$WIDTHCOLICON\">&nbsp;</th><th colspan=\"2\">$Message[17]</th>";
 
8944
                        if ($ShowDomainsStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
8945
                        if ($ShowDomainsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
8946
                        if ($ShowDomainsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
8947
                        print "<th>&nbsp;</th>";
 
8948
                        print "</tr>\n";
 
8949
                        $total_p=$total_h=$total_k=0;
 
8950
                        $max_h=1; foreach (values %_domener_h) { if ($_ > $max_h) { $max_h = $_; } }
 
8951
                        $max_k=1; foreach (values %_domener_k) { if ($_ > $max_k) { $max_k = $_; } }
 
8952
                        my $count=0;
 
8953
                        &BuildKeyList($MaxNbOf{'Domain'},$MinHit{'Domain'},\%_domener_h,\%_domener_p);
 
8954
                        foreach my $key (@keylist) {
 
8955
                                my $bredde_p=0;my $bredde_h=0;my $bredde_k=0;
 
8956
                                if ($max_h > 0) { $bredde_p=int($BarWidth*$_domener_p{$key}/$max_h)+1; }        # use max_h to enable to compare pages with hits
 
8957
                                if ($_domener_p{$key} && $bredde_p==1) { $bredde_p=2; }
 
8958
                                if ($max_h > 0) { $bredde_h=int($BarWidth*$_domener_h{$key}/$max_h)+1; }
 
8959
                                if ($_domener_h{$key} && $bredde_h==1) { $bredde_h=2; }
 
8960
                                if ($max_k > 0) { $bredde_k=int($BarWidth*($_domener_k{$key}||0)/$max_k)+1; }
 
8961
                                if ($_domener_k{$key} && $bredde_k==1) { $bredde_k=2; }
 
8962
                                my $newkey=lc($key);
 
8963
                                if ($newkey eq 'ip' || ! $DomainsHashIDLib{$newkey}) {
 
8964
                                        print "<tr><td width=\"$WIDTHCOLICON\"><img src=\"$DirIcons\/flags\/ip.png\" height=\"14\"".AltTitle("$Message[0]")." /></td><td class=\"aws\">$Message[0]</td><td>$newkey</td>";
 
8965
                                }
 
8966
                                else {
 
8967
                                        print "<tr><td width=\"$WIDTHCOLICON\"><img src=\"$DirIcons\/flags\/$newkey.png\" height=\"14\"".AltTitle("$newkey")." /></td><td class=\"aws\">$DomainsHashIDLib{$newkey}</td><td>$newkey</td>";
 
8968
                                }
 
8969
                                if ($ShowDomainsStats =~ /P/i) { print "<td>".($_domener_p{$key}?$_domener_p{$key}:'&nbsp;')."</td>"; }
 
8970
                                if ($ShowDomainsStats =~ /H/i) { print "<td>$_domener_h{$key}</td>"; }
 
8971
                                if ($ShowDomainsStats =~ /B/i) { print "<td>".Format_Bytes($_domener_k{$key})."</td>"; }
 
8972
                                print "<td style=\"text-align:left; font-size:4px;\">";
 
8973
                                if ($ShowDomainsStats =~ /P/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hp'}\" width=\"$bredde_p\" height=\"5\"".AltTitle("")." /><br />\n"; }
 
8974
                                if ($ShowDomainsStats =~ /H/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hh'}\" width=\"$bredde_h\" height=\"5\"".AltTitle("")." /><br />\n"; }
 
8975
                                if ($ShowDomainsStats =~ /B/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hk'}\" width=\"$bredde_k\" height=\"5\"".AltTitle("")." />"; }
 
8976
                                print "</td>";
 
8977
                                print "</tr>\n";
 
8978
                                $total_p += $_domener_p{$key};
 
8979
                                $total_h += $_domener_h{$key};
 
8980
                                $total_k += $_domener_k{$key}||0;
 
8981
                                $count++;
 
8982
                        }
 
8983
                        $rest_p=$TotalPages-$total_p;
 
8984
                        $rest_h=$TotalHits-$total_h;
 
8985
                        $rest_k=$TotalBytes-$total_k;
 
8986
                        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other domains (known or not)
 
8987
                                print "<tr><td width=\"$WIDTHCOLICON\">&nbsp;</td><td colspan=\"2\" class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
8988
                                if ($ShowDomainsStats =~ /P/i) { print "<td>$rest_p</td>"; }
 
8989
                                if ($ShowDomainsStats =~ /H/i) { print "<td>$rest_h</td>"; }
 
8990
                                if ($ShowDomainsStats =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
8991
                                print "<td class=\"aws\">&nbsp;</td>";
 
8992
                                print "</tr>\n";
 
8993
                        }
 
8994
                        &tab_end;
 
8995
                }
 
8996
        
 
8997
                # BY HOST/VISITOR
 
8998
                #--------------------------
 
8999
                if ($ShowHostsStats) {
 
9000
                        if ($Debug) { debug("ShowHostsStats",2); }
 
9001
                        print "$Center<a name=\"visitors\">&nbsp;</a><br />\n";
 
9002
                        my $title="$Message[81] ($Message[77] $MaxNbOf{'HostsShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allhosts"):"$PROG$StaticLinks.allhosts.$StaticExt")."\"$NewLinkTarget>$Message[80]</a> &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lasthosts"):"$PROG$StaticLinks.lasthosts.$StaticExt")."\"$NewLinkTarget>$Message[9]</a> &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=unknownip"):"$PROG$StaticLinks.unknownip.$StaticExt")."\"$NewLinkTarget>$Message[45]</a>";
 
9003
                        &tab_head("$title",19,0,'visitors');
 
9004
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\">";
 
9005
                        print "<th>";
 
9006
                        if ($MonthRequired ne 'all') { print "$Message[81] : $TotalHostsKnown $Message[82], $TotalHostsUnknown $Message[1] - $TotalUnique $Message[11]</th>"; }
 
9007
                        else { print "$Message[81] : ".(scalar keys %_host_h)."</th>"; }
 
9008
                        &ShowHostInfo('__title__');
 
9009
                        if ($ShowHostsStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
9010
                        if ($ShowHostsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
9011
                        if ($ShowHostsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
9012
                        if ($ShowHostsStats =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
9013
                        print "</tr>\n";
 
9014
                        $total_p=$total_h=$total_k=0;
 
9015
                        my $count=0;
 
9016
                        &BuildKeyList($MaxNbOf{'HostsShown'},$MinHit{'Host'},\%_host_h,\%_host_p);
 
9017
                        foreach my $key (@keylist) {
 
9018
                                print "<tr>";
 
9019
                                print "<td class=\"aws\">$key</td>";
 
9020
                                &ShowHostInfo($key);
 
9021
                                if ($ShowHostsStats =~ /P/i) { print "<td>".($_host_p{$key}||"&nbsp;")."</td>"; }
 
9022
                                if ($ShowHostsStats =~ /H/i) { print "<td>$_host_h{$key}</td>"; }
 
9023
                                if ($ShowHostsStats =~ /B/i) { print "<td>".Format_Bytes($_host_k{$key})."</td>"; }
 
9024
                                if ($ShowHostsStats =~ /L/i) { print "<td>".($_host_l{$key}?Format_Date($_host_l{$key},1):'-')."</td>"; }
 
9025
                                print "</tr>\n";
 
9026
                                $total_p += $_host_p{$key};
 
9027
                                $total_h += $_host_h{$key};
 
9028
                                $total_k += $_host_k{$key}||0;
 
9029
                                $count++;
 
9030
                        }
 
9031
                        $rest_p=$TotalPages-$total_p;
 
9032
                        $rest_h=$TotalHits-$total_h;
 
9033
                        $rest_k=$TotalBytes-$total_k;
 
9034
                        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other visitors (known or not)
 
9035
                                print "<tr>";
 
9036
                                print "<td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
9037
                                &ShowHostInfo('');
 
9038
                                if ($ShowHostsStats =~ /P/i) { print "<td>$rest_p</td>"; }
 
9039
                                if ($ShowHostsStats =~ /H/i) { print "<td>$rest_h</td>"; }
 
9040
                                if ($ShowHostsStats =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
9041
                                if ($ShowHostsStats =~ /L/i) { print "<td>&nbsp;</td>"; }
 
9042
                                print "</tr>\n";
 
9043
                        }
 
9044
                        &tab_end;
 
9045
                }
 
9046
        
 
9047
                # BY SENDER EMAIL
 
9048
                #----------------------------
 
9049
                if ($ShowEMailSenders) {
 
9050
                        &ShowEmailSendersChart($NewLinkParams,$NewLinkTarget);
 
9051
                }
 
9052
 
 
9053
                # BY RECEIVER EMAIL
 
9054
                #----------------------------
 
9055
                if ($ShowEMailReceivers) {
 
9056
                        &ShowEmailReceiversChart($NewLinkParams,$NewLinkTarget);
 
9057
                }
 
9058
        
 
9059
                # BY LOGIN
 
9060
                #----------------------------
 
9061
                if ($ShowAuthenticatedUsers) {
 
9062
                        if ($Debug) { debug("ShowAuthenticatedUsers",2); }
 
9063
                        print "$Center<a name=\"logins\">&nbsp;</a><br />\n";
 
9064
                        my $title="$Message[94] ($Message[77] $MaxNbOf{'LoginShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=alllogins"):"$PROG$StaticLinks.alllogins.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>";
 
9065
                        if ($ShowAuthenticatedUsers =~ /L/i) { $title.=" &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastlogins"):"$PROG$StaticLinks.lastlogins.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>"; }
 
9066
                        &tab_head("$title",19,0,'logins');
 
9067
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$Message[94] : ".(scalar keys %_login_h)."</th>";
 
9068
                        &ShowUserInfo('__title__');
 
9069
                        if ($ShowAuthenticatedUsers =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
9070
                        if ($ShowAuthenticatedUsers =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
9071
                        if ($ShowAuthenticatedUsers =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
9072
                        if ($ShowAuthenticatedUsers =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
9073
                        print "</tr>\n";
 
9074
                        $total_p=$total_h=$total_k=0;
 
9075
                        $max_h=1; foreach (values %_login_h) { if ($_ > $max_h) { $max_h = $_; } }
 
9076
                        $max_k=1; foreach (values %_login_k) { if ($_ > $max_k) { $max_k = $_; } }
 
9077
                        my $count=0;
 
9078
                        &BuildKeyList($MaxNbOf{'LoginShown'},$MinHit{'Login'},\%_login_h,\%_login_p);
 
9079
                        foreach my $key (@keylist) {
 
9080
                                my $bredde_p=0;my $bredde_h=0;my $bredde_k=0;
 
9081
                                if ($max_h > 0) { $bredde_p=int($BarWidth*$_login_p{$key}/$max_h)+1; }  # use max_h to enable to compare pages with hits
 
9082
                                if ($max_h > 0) { $bredde_h=int($BarWidth*$_login_h{$key}/$max_h)+1; }
 
9083
                                if ($max_k > 0) { $bredde_k=int($BarWidth*$_login_k{$key}/$max_k)+1; }
 
9084
                                print "<tr><td class=\"aws\">$key</td>";
 
9085
                                &ShowUserInfo($key);
 
9086
                                if ($ShowAuthenticatedUsers =~ /P/i) { print "<td>".($_login_p{$key}?$_login_p{$key}:"&nbsp;")."</td>"; }
 
9087
                                if ($ShowAuthenticatedUsers =~ /H/i) { print "<td>$_login_h{$key}</td>"; }
 
9088
                                if ($ShowAuthenticatedUsers =~ /B/i) { print "<td>".Format_Bytes($_login_k{$key})."</td>"; }
 
9089
                                if ($ShowAuthenticatedUsers =~ /L/i) { print "<td>".($_login_l{$key}?Format_Date($_login_l{$key},1):'-')."</td>"; }
 
9090
                                print "</tr>\n";
 
9091
                                $total_p += $_login_p{$key};
 
9092
                                $total_h += $_login_h{$key};
 
9093
                                $total_k += $_login_k{$key};
 
9094
                                $count++;
 
9095
                        }
 
9096
                        $rest_p=$TotalPages-$total_p;
 
9097
                        $rest_h=$TotalHits-$total_h;
 
9098
                        $rest_k=$TotalBytes-$total_k;
 
9099
                        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other logins
 
9100
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">".($PageDir eq 'rtl'?"<span dir=\"ltr\">":"")."$Message[125]".($PageDir eq 'rtl'?"</span>":"")."</span></td>";
 
9101
                                &ShowUserInfo('');
 
9102
                                if ($ShowAuthenticatedUsers =~ /P/i) { print "<td>".($rest_p?$rest_p:"&nbsp;")."</td>"; }
 
9103
                                if ($ShowAuthenticatedUsers =~ /H/i) { print "<td>$rest_h</td>"; }
 
9104
                                if ($ShowAuthenticatedUsers =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
 
9105
                                if ($ShowAuthenticatedUsers =~ /L/i) { print "<td>&nbsp;</td>"; }
 
9106
                                print "</tr>\n";
 
9107
                        }
 
9108
                        &tab_end;
 
9109
                }
 
9110
        
 
9111
                # BY ROBOTS
 
9112
                #----------------------------
 
9113
                if ($ShowRobotsStats) {
 
9114
                        if ($Debug) { debug("ShowRobotStats",2); }
 
9115
                        print "$Center<a name=\"robots\">&nbsp;</a><br />\n";
 
9116
                        &tab_head("$Message[53] ($Message[77] $MaxNbOf{'RobotShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=allrobots"):"$PROG$StaticLinks.allrobots.$StaticExt")."\"$NewLinkTarget>$Message[80]</a> &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=lastrobots"):"$PROG$StaticLinks.lastrobots.$StaticExt")."\"$NewLinkTarget>$Message[9]</a>",19,0,'robots');
 
9117
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(16);\" onmouseout=\"HideTip(16);\"":"")."><th>".(scalar keys %_robot_h)." $Message[51]*</th>";
 
9118
                        if ($ShowRobotsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
9119
                        if ($ShowRobotsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
9120
                        if ($ShowRobotsStats =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
9121
                        print "</tr>\n";
 
9122
                        $total_p=$total_h=$total_k=$total_r=0;
 
9123
                        my $count=0;
 
9124
                        &BuildKeyList($MaxNbOf{'RobotShown'},$MinHit{'Robot'},\%_robot_h,\%_robot_h);
 
9125
                        foreach my $key (@keylist) {
 
9126
                                print "<tr><td class=\"aws\">".($PageDir eq 'rtl'?"<span dir=\"ltr\">":"").($RobotsHashIDLib{$key}?$RobotsHashIDLib{$key}:$key).($PageDir eq 'rtl'?"</span>":"")."</td>";
 
9127
                                if ($ShowRobotsStats =~ /H/i) { print "<td>".($_robot_h{$key}-$_robot_r{$key}).($_robot_r{$key}?"+$_robot_r{$key}":"")."</td>"; }
 
9128
                                if ($ShowRobotsStats =~ /B/i) { print "<td>".Format_Bytes($_robot_k{$key})."</td>"; }
 
9129
                                if ($ShowRobotsStats =~ /L/i) { print "<td>".($_robot_l{$key}?Format_Date($_robot_l{$key},1):'-')."</td>"; }
 
9130
                                print "</tr>\n";
 
9131
                                #$total_p += $_robot_p{$key};
 
9132
                                $total_h += $_robot_h{$key};
 
9133
                                $total_k += $_robot_k{$key}||0;
 
9134
                                $total_r += $_robot_r{$key}||0;
 
9135
                                $count++;
 
9136
                                }
 
9137
                        # For bots we need to count Totals
 
9138
                        my $TotalPagesRobots = 0; #foreach (values %_robot_p) { $TotalPagesRobots+=$_; }
 
9139
                        my $TotalHitsRobots = 0; foreach (values %_robot_h) { $TotalHitsRobots+=$_; }
 
9140
                        my $TotalBytesRobots = 0; foreach (values %_robot_k) { $TotalBytesRobots+=$_; }
 
9141
                        my $TotalRRobots = 0; foreach (values %_robot_r) { $TotalRRobots+=$_; }
 
9142
                        $rest_p=0;      #$rest_p=$TotalPagesRobots-$total_p;
 
9143
                        $rest_h=$TotalHitsRobots-$total_h;
 
9144
                        $rest_k=$TotalBytesRobots-$total_k;
 
9145
                        $rest_r=$TotalRRobots-$total_r;
 
9146
                        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0 || $rest_r > 0) { # All other robots
 
9147
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
9148
                                if ($ShowRobotsStats =~ /H/i) { print "<td>".($rest_h-$rest_r).($rest_r?"+$rest_r":"")."</td>"; }
 
9149
                                if ($ShowRobotsStats =~ /B/i) { print "<td>".(Format_Bytes($rest_k))."</td>"; }
 
9150
                                if ($ShowRobotsStats =~ /L/i) { print "<td>&nbsp;</td>"; }
 
9151
                                print "</tr>\n";
 
9152
                        }
 
9153
                        &tab_end("* $Message[156]".($TotalRRobots?" $Message[157]":""));
 
9154
                }
 
9155
 
 
9156
                # BY WORMS
 
9157
                #----------------------------
 
9158
                if ($ShowWormsStats) {
 
9159
                        if ($Debug) { debug("ShowWormsStats",2); }
 
9160
                        print "$Center<a name=\"worms\">&nbsp;</a><br />\n";
 
9161
                        &tab_head("$Message[163] ($Message[77] $MaxNbOf{'WormsShown'})",19,0,'worms');
 
9162
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(16);\" onmouseout=\"HideTip(16);\"":"")."><th>".(scalar keys %_worm_h)." $Message[164]*</th>";
 
9163
                        if ($ShowWormsStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
9164
                        if ($ShowWormsStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
9165
                        if ($ShowWormsStats =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
9166
                        print "</tr>\n";
 
9167
                        $total_p=$total_h=$total_k=0;
 
9168
                        my $count=0;
 
9169
                        &BuildKeyList($MaxNbOf{'WormsShown'},$MinHit{'Worm'},\%_worm_h,\%_worm_h);
 
9170
                        foreach my $key (@keylist) {
 
9171
                                print "<tr><td class=\"aws\">".($PageDir eq 'rtl'?"<span dir=\"ltr\">":"").($WormsHashLib{$key}?$WormsHashLib{$key}:$key).($PageDir eq 'rtl'?"</span>":"")."</td>";
 
9172
                                if ($ShowWormsStats =~ /H/i) { print "<td>".$_worm_h{$key}."</td>"; }
 
9173
                                if ($ShowWormsStats =~ /B/i) { print "<td>".Format_Bytes($_worm_k{$key})."</td>"; }
 
9174
                                if ($ShowWormsStats =~ /L/i) { print "<td>".($_worm_l{$key}?Format_Date($_worm_l{$key},1):'-')."</td>"; }
 
9175
                                print "</tr>\n";
 
9176
                                #$total_p += $_worm_p{$key};
 
9177
                                $total_h += $_worm_h{$key};
 
9178
                                $total_k += $_worm_k{$key}||0;
 
9179
                                $count++;
 
9180
                                }
 
9181
                        # For worms we need to count Totals
 
9182
                        my $TotalPagesWorms = 0; #foreach (values %_worm_p) { $TotalPagesWorms+=$_; }
 
9183
                        my $TotalHitsWorms = 0; foreach (values %_worm_h) { $TotalHitsWorms+=$_; }
 
9184
                        my $TotalBytesWorms = 0; foreach (values %_worm_k) { $TotalBytesWorms+=$_; }
 
9185
                        $rest_p=0;      #$rest_p=$TotalPagesRobots-$total_p;
 
9186
                        $rest_h=$TotalHitsWorms-$total_h;
 
9187
                        $rest_k=$TotalBytesWorms-$total_k;
 
9188
                        if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) {        # All other worms
 
9189
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
9190
                                if ($ShowWormsStats =~ /H/i) { print "<td>".($rest_h)."</td>"; }
 
9191
                                if ($ShowWormsStats =~ /B/i) { print "<td>".(Format_Bytes($rest_k))."</td>"; }
 
9192
                                if ($ShowWormsStats =~ /L/i) { print "<td>&nbsp;</td>"; }
 
9193
                                print "</tr>\n";
 
9194
                        }
 
9195
                        &tab_end("* $Message[158]");
 
9196
                }
 
9197
        
 
9198
                print "\n<a name=\"how\">&nbsp;</a>\n\n";
 
9199
        
 
9200
                # BY SESSION
 
9201
                #----------------------------
 
9202
                if ($ShowSessionsStats) {
 
9203
                        if ($Debug) { debug("ShowSessionsStats",2); }
 
9204
                        print "$Center<a name=\"sessions\">&nbsp;</a><br />\n";
 
9205
                        my $title="$Message[117]";
 
9206
                        &tab_head($title,19,0,'sessions');
 
9207
                        my $Totals=0; foreach (@SessionsRange) { $average_s+=($_session{$_}||0)*$SessionsAverage{$_}; $Totals+=$_session{$_}||0; }
 
9208
                        if ($Totals) { $average_s=int($average_s/$Totals); }
 
9209
                        else { $average_s='?'; }
 
9210
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(1);\" onmouseout=\"HideTip(1);\"":"")."><th>$Message[10]: $TotalVisits - $Message[96]: $average_s s</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[10]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[15]</th></tr>\n";
 
9211
                        $average_s=0;
 
9212
                        $total_s=0;
 
9213
                        my $count=0;
 
9214
                        foreach my $key (@SessionsRange) {
 
9215
                                my $p=0;
 
9216
                                if ($TotalVisits) { $p=int($_session{$key}/$TotalVisits*1000)/10; }
 
9217
                                $total_s+=$_session{$key}||0;
 
9218
                                print "<tr><td class=\"aws\">$key</td>";
 
9219
                                print "<td>".($_session{$key}?$_session{$key}:"&nbsp;")."</td>";
 
9220
                                print "<td>".($_session{$key}?"$p %":"&nbsp;")."</td>";
 
9221
                                print "</tr>\n";
 
9222
                                $count++;
 
9223
                        }
 
9224
                        $rest_s=$TotalVisits-$total_s;
 
9225
                        if ($rest_s > 0) {      # All others sessions
 
9226
                                my $p=0;
 
9227
                                if ($TotalVisits) { $p=int($rest_s/$TotalVisits*1000)/10; }
 
9228
                                print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip(20);\" onmouseout=\"HideTip(20);\"":"")."><td class=\"aws\"><span style=\"color: #$color_other\">$Message[0]</span></td>";
 
9229
                                print "<td>$rest_s</td>";
 
9230
                                print "<td>".($rest_s?"$p %":"&nbsp;")."</td>";
 
9231
                                print "</tr>\n";
 
9232
                        }
 
9233
                        &tab_end;
 
9234
                }
 
9235
        
 
9236
                # BY FILE TYPE
 
9237
                #-------------------------
 
9238
                if ($ShowFileTypesStats) {
 
9239
                        if ($Debug) { debug("ShowFileTypesStatsCompressionStats",2); }
 
9240
                        print "$Center<a name=\"filetypes\">&nbsp;</a><br />\n";
 
9241
                        my $Totalh=0; foreach (keys %_filetypes_h) { $Totalh+=$_filetypes_h{$_}; }
 
9242
                        my $Totalk=0; foreach (keys %_filetypes_k) { $Totalk+=$_filetypes_k{$_}; }
 
9243
                        my $title="$Message[73]";
 
9244
                        if ($ShowFileTypesStats =~ /C/i) { $title.=" - $Message[98]"; }
 
9245
                        &tab_head("$title",19,0,'filetypes');
 
9246
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"3\">$Message[73]</th>";
 
9247
                        if ($ShowFileTypesStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>"; }
 
9248
                        if ($ShowFileTypesStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th><th bgcolor=\"#$color_k\" width=\"80\">$Message[15]</th>"; }
 
9249
                        if ($ShowFileTypesStats =~ /C/i) { print "<th bgcolor=\"#$color_k\" width=\"120\">$Message[100]</th><th bgcolor=\"#$color_k\" width=\"120\">$Message[101]</th><th bgcolor=\"#$color_k\" width=\"120\">$Message[99]</th>"; }
 
9250
                        print "</tr>\n";
 
9251
                        my $total_con=0; my $total_cre=0;
 
9252
                        my $count=0;
 
9253
                        &BuildKeyList($MaxRowsInHTMLOutput,1,\%_filetypes_h,\%_filetypes_h);
 
9254
                        foreach my $key (@keylist) {
 
9255
                                my $p_h='&nbsp;'; my $p_k='&nbsp;';
 
9256
                                if ($Totalh) { $p_h=int($_filetypes_h{$key}/$Totalh*1000)/10; $p_h="$p_h %"; }
 
9257
                                if ($Totalk) { $p_k=int($_filetypes_k{$key}/$Totalk*1000)/10; $p_k="$p_k %"; }
 
9258
                                if ($key eq 'Unknown') {
 
9259
                                        print "<tr><td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/mime\/unknown.png\"".AltTitle("")." /></td><td class=\"aws\" colspan=\"2\"><span style=\"color: #$color_other\">$Message[0]</span></td>";
 
9260
                                }
 
9261
                                else {
 
9262
                                        my $nameicon=$MimeHashIcon{$key}||"notavailable";
 
9263
                                        my $nametype=$MimeHashLib{$MimeHashFamily{$key}||""}||"&nbsp;";
 
9264
                                        print "<tr><td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/mime\/$nameicon.png\"".AltTitle("")." /></td><td class=\"aws\">$key</td>";
 
9265
                                        print "<td class=\"aws\">$nametype</td>";
 
9266
                                }
 
9267
                                if ($ShowFileTypesStats =~ /H/i) { print "<td>$_filetypes_h{$key}</td><td>$p_h</td>"; }
 
9268
                                if ($ShowFileTypesStats =~ /B/i) { print "<td>".Format_Bytes($_filetypes_k{$key})."</td><td>$p_k</td>"; }
 
9269
                                if ($ShowFileTypesStats =~ /C/i) {
 
9270
                                        if ($_filetypes_gz_in{$key}) {
 
9271
                                                my $percent=int(100*(1-$_filetypes_gz_out{$key}/$_filetypes_gz_in{$key}));
 
9272
                                                printf("<td>%s</td><td>%s</td><td>%s (%s%)</td>",Format_Bytes($_filetypes_gz_in{$key}),Format_Bytes($_filetypes_gz_out{$key}),Format_Bytes($_filetypes_gz_in{$key}-$_filetypes_gz_out{$key}),$percent);
 
9273
                                                $total_con+=$_filetypes_gz_in{$key};
 
9274
                                                $total_cre+=$_filetypes_gz_out{$key};
 
9275
                                        }
 
9276
                                        else {
 
9277
                                                print "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>";
 
9278
                                        }
 
9279
                                }
 
9280
                                print "</tr>\n";
 
9281
                                $count++;
 
9282
                        }
 
9283
                        # Add total (only usefull if compression is enabled)
 
9284
                        if ($ShowFileTypesStats =~ /C/i) {      
 
9285
                                my $colspan=3;
 
9286
                                if ($ShowFileTypesStats =~ /H/i) { $colspan+=2; }
 
9287
                                if ($ShowFileTypesStats =~ /B/i) { $colspan+=2; }
 
9288
                                print "<tr>";
 
9289
                                print "<td class=\"aws\" colspan=\"$colspan\"><b>$Message[98]</b></td>";
 
9290
                                if ($ShowFileTypesStats =~ /C/i) {
 
9291
                                        if ($total_con) {
 
9292
                                                my $percent=int(100*(1-$total_cre/$total_con));
 
9293
                                                printf("<td>%s</td><td>%s</td><td>%s (%s%)</td>",Format_Bytes($total_con),Format_Bytes($total_cre),Format_Bytes($total_con-$total_cre),$percent);
 
9294
                                        }
 
9295
                                        else {
 
9296
                                                print "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>";
 
9297
                                        }
 
9298
                                }
 
9299
                                print "</tr>\n";
 
9300
                        }
 
9301
                        &tab_end;
 
9302
                }
 
9303
        
 
9304
                # BY FILE SIZE
 
9305
                #-------------------------
 
9306
                if ($ShowFileSizesStats) {
 
9307
        
 
9308
                }
 
9309
        
 
9310
                # BY FILE/URL
 
9311
                #-------------------------
 
9312
                if ($ShowPagesStats) {
 
9313
                        if ($Debug) { debug("ShowPagesStats (MaxNbOf{'PageShown'}=$MaxNbOf{'PageShown'} TotalDifferentPages=$TotalDifferentPages)",2); }
 
9314
                        print "$Center<a name=\"urls\">&nbsp;</a><a name=\"entry\">&nbsp;</a><a name=\"exit\">&nbsp;</a><br />\n";
 
9315
                        my $title="$Message[19] ($Message[77] $MaxNbOf{'PageShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=urldetail"):"$PROG$StaticLinks.urldetail.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>";
 
9316
                        if ($ShowPagesStats =~ /E/i) { $title.=" &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=urlentry"):"$PROG$StaticLinks.urlentry.$StaticExt")."\"$NewLinkTarget>$Message[104]</a>"; }
 
9317
                        if ($ShowPagesStats =~ /X/i) { $title.=" &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=urlexit"):"$PROG$StaticLinks.urlexit.$StaticExt")."\"$NewLinkTarget>$Message[116]</a>"; }
 
9318
                        &tab_head("$title",19,0,'urls');
 
9319
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$TotalDifferentPages $Message[28]</th>";
 
9320
                        if ($ShowPagesStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[29]</th>"; }
 
9321
                        if ($ShowPagesStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[106]</th>"; }
 
9322
                        if ($ShowPagesStats =~ /E/i) { print "<th bgcolor=\"#$color_e\" width=\"80\">$Message[104]</th>"; }
 
9323
                        if ($ShowPagesStats =~ /X/i) { print "<th bgcolor=\"#$color_x\" width=\"80\">$Message[116]</th>"; }
 
9324
                        # Call to plugins' function ShowPagesAddField
 
9325
                        foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesAddField'}})  {
 
9326
                                my $function="ShowPagesAddField_$pluginname('title')";
 
9327
                                eval("$function");
 
9328
                        }
 
9329
                        print "<th>&nbsp;</th></tr>\n";
 
9330
                        $total_p=$total_e=$total_x=$total_k=0;
 
9331
                        $max_p=1; $max_k=1;
 
9332
                        my $count=0;
 
9333
                        &BuildKeyList($MaxNbOf{'PageShown'},$MinHit{'File'},\%_url_p,\%_url_p);
 
9334
                        foreach my $key (@keylist) {
 
9335
                                if ($_url_p{$key} > $max_p) { $max_p = $_url_p{$key}; }
 
9336
                                if ($_url_k{$key}/($_url_p{$key}||1) > $max_k) { $max_k = $_url_k{$key}/($_url_p{$key}||1); }
 
9337
                        }
 
9338
                        foreach my $key (@keylist) {
 
9339
                                print "<tr><td class=\"aws\">";
 
9340
                                &ShowURLInfo($key);
 
9341
                                print "</td>";
 
9342
                                my $bredde_p=0; my $bredde_e=0; my $bredde_x=0; my $bredde_k=0;
 
9343
                                if ($max_p > 0) { $bredde_p=int($BarWidth*($_url_p{$key}||0)/$max_p)+1; }
 
9344
                                if (($bredde_p==1) && $_url_p{$key}) { $bredde_p=2; }
 
9345
                                if ($max_p > 0) { $bredde_e=int($BarWidth*($_url_e{$key}||0)/$max_p)+1; }
 
9346
                                if (($bredde_e==1) && $_url_e{$key}) { $bredde_e=2; }
 
9347
                                if ($max_p > 0) { $bredde_x=int($BarWidth*($_url_x{$key}||0)/$max_p)+1; }
 
9348
                                if (($bredde_x==1) && $_url_x{$key}) { $bredde_x=2; }
 
9349
                                if ($max_k > 0) { $bredde_k=int($BarWidth*(($_url_k{$key}||0)/($_url_p{$key}||1))/$max_k)+1; }
 
9350
                                if (($bredde_k==1) && $_url_k{$key}) { $bredde_k=2; }
 
9351
                                if ($ShowPagesStats =~ /P/i) { print "<td>$_url_p{$key}</td>"; }
 
9352
                                if ($ShowPagesStats =~ /B/i) { print "<td>".($_url_k{$key}?Format_Bytes($_url_k{$key}/($_url_p{$key}||1)):"&nbsp;")."</td>"; }
 
9353
                                if ($ShowPagesStats =~ /E/i) { print "<td>".($_url_e{$key}?$_url_e{$key}:"&nbsp;")."</td>"; }
 
9354
                                if ($ShowPagesStats =~ /X/i) { print "<td>".($_url_x{$key}?$_url_x{$key}:"&nbsp;")."</td>"; }
 
9355
                                # Call to plugins' function ShowPagesAddField
 
9356
                                foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesAddField'}})  {
 
9357
                                        my $function="ShowPagesAddField_$pluginname('$key')";
 
9358
                                        eval("$function");
 
9359
                                }
 
9360
                                print "<td style=\"text-align:left; font-size:4px;\">";
 
9361
                                if ($ShowPagesStats =~ /P/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hp'}\" width=\"$bredde_p\" height=\"4\"".AltTitle("")." /><br />"; }
 
9362
                                if ($ShowPagesStats =~ /B/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hk'}\" width=\"$bredde_k\" height=\"4\"".AltTitle("")." /><br />"; }
 
9363
                                if ($ShowPagesStats =~ /E/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'he'}\" width=\"$bredde_e\" height=\"4\"".AltTitle("")." /><br />"; }
 
9364
                                if ($ShowPagesStats =~ /X/i) { print "<img src=\"$DirIcons\/other\/$BarPng{'hx'}\" width=\"$bredde_x\" height=\"4\"".AltTitle("")." />"; }
 
9365
                                print "</td></tr>\n";
 
9366
                                $total_p += $_url_p{$key};
 
9367
                                $total_e += $_url_e{$key};
 
9368
                                $total_x += $_url_x{$key};
 
9369
                                $total_k += $_url_k{$key};
 
9370
                                $count++;
 
9371
                        }
 
9372
                        $rest_p=$TotalPages-$total_p;
 
9373
                        $rest_e=$TotalEntries-$total_e;
 
9374
                        $rest_x=$TotalExits-$total_x;
 
9375
                        $rest_k=$TotalBytesPages-$total_k;
 
9376
                        if ($rest_p > 0 || $rest_k > 0 || $rest_e > 0 || $rest_x > 0) { # All other urls
 
9377
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
9378
                                if ($ShowPagesStats =~ /P/i) { print "<td>$rest_p</td>"; }
 
9379
                                if ($ShowPagesStats =~ /B/i) { print "<td>".($rest_k?Format_Bytes($rest_k/($rest_p||1)):"&nbsp;")."</td>"; }
 
9380
                                if ($ShowPagesStats =~ /E/i) { print "<td>".($rest_e?$rest_e:"&nbsp;")."</td>"; }
 
9381
                                if ($ShowPagesStats =~ /X/i) { print "<td>".($rest_x?$rest_x:"&nbsp;")."</td>"; }
 
9382
                                # Call to plugins' function ShowPagesAddField
 
9383
                                foreach my $pluginname (keys %{$PluginsLoaded{'ShowPagesAddField'}})  {
 
9384
                                        my $function="ShowPagesAddField_$pluginname('')";
 
9385
                                        eval("$function");
 
9386
                                }
 
9387
                                print "<td>&nbsp;</td></tr>\n";
 
9388
                        }
 
9389
                        &tab_end;
 
9390
                }
 
9391
        
 
9392
                # BY OS
 
9393
                #----------------------------
 
9394
                if ($ShowOSStats) {
 
9395
                        if ($Debug) { debug("ShowOSStats",2); }
 
9396
                        print "$Center<a name=\"os\">&nbsp;</a><br />\n";
 
9397
                        my $Totalh=0; my %new_os_h=();
 
9398
                        OSLOOP: foreach my $key (keys %_os_h) {
 
9399
                                $Totalh+=$_os_h{$key};
 
9400
                                foreach my $family (@OSFamily) { if ($key =~ /^$family/i) { $new_os_h{"${family}cumul"}+=$_os_h{$key}; next OSLOOP; } }
 
9401
                                $new_os_h{$key}+=$_os_h{$key};
 
9402
                        }
 
9403
                        my $title="$Message[59] ($Message[77] $MaxNbOf{'OsShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=osdetail"):"$PROG$StaticLinks.osdetail.$StaticExt")."\"$NewLinkTarget>$Message[80]/$Message[58]</a> &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=unknownos"):"$PROG$StaticLinks.unknownos.$StaticExt")."\"$NewLinkTarget>$Message[0]</a>";
 
9404
                        &tab_head("$title",19,0,'os');
 
9405
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th width=\"$WIDTHCOLICON\">&nbsp;</th><th>$Message[59]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th></tr>\n";
 
9406
                        $total_h=0;
 
9407
                        my $count=0;
 
9408
                        &BuildKeyList($MaxNbOf{'OsShown'},$MinHit{'Os'},\%new_os_h,\%new_os_h);
 
9409
                        foreach my $key (@keylist) {
 
9410
                                my $p='&nbsp;';
 
9411
                                if ($Totalh) { $p=int($new_os_h{$key}/$Totalh*1000)/10; $p="$p %"; }
 
9412
                                if ($key eq 'Unknown') {
 
9413
                                        print "<tr><td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/os\/unknown.png\"".AltTitle("")." /></td><td class=\"aws\"><span style=\"color: #$color_other\">$Message[0]</span></td><td>$_os_h{$key}</td><td>$p</td></tr>\n";
 
9414
                                }
 
9415
                                else {
 
9416
                                        my $keywithoutcumul=$key; $keywithoutcumul =~ s/cumul$//i;
 
9417
                                        my $libos=$OSHashLib{$keywithoutcumul}||$keywithoutcumul;
 
9418
                                        my $nameicon=$keywithoutcumul; $nameicon =~ s/[^\w]//g;
 
9419
                                        # TODO Use OSFamilyLib
 
9420
                                        if ($libos eq 'win') { $libos="<b>Windows</b>"; }
 
9421
                                        if ($libos eq 'mac') { $libos="<b>Macintosh</b>"; }
 
9422
                                        print "<tr><td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/os\/$nameicon.png\"".AltTitle("")." /></td><td class=\"aws\">$libos</td><td>$new_os_h{$key}</td><td>$p</td></tr>\n";
 
9423
                                }
 
9424
                                $total_h += $new_os_h{$key};
 
9425
                                $count++;
 
9426
                        }
 
9427
                        if ($Debug) { debug("Total real / shown : $Totalh / $total_h",2); }
 
9428
                        $rest_h=$Totalh-$total_h;
 
9429
                        if ($rest_h > 0) {
 
9430
                                my $p;
 
9431
                                if ($Totalh) { $p=int($rest_h/$Totalh*1000)/10; }
 
9432
                                print "<tr>";
 
9433
                                print "<td>&nbsp;</td>";
 
9434
                                print "<td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td><td>$rest_h</td>";
 
9435
                                print "<td>$p %</td></tr>\n";
 
9436
                        }
 
9437
                        &tab_end;
 
9438
                }
 
9439
                
 
9440
                # BY BROWSER
 
9441
                #----------------------------
 
9442
                if ($ShowBrowsersStats) {
 
9443
                        if ($Debug) { debug("ShowBrowsersStats",2); }
 
9444
                        print "$Center<a name=\"browsers\">&nbsp;</a><br />\n";
 
9445
                        my $Totalh=0; my %new_browser_h=();
 
9446
                        BROWSERLOOP: foreach my $key (keys %_browser_h) {
 
9447
                                $Totalh+=$_browser_h{$key};
 
9448
                                foreach my $family (keys %BrowsersFamily) { if ($key =~ /^$family/i) { $new_browser_h{"${family}cumul"}+=$_browser_h{$key}; next BROWSERLOOP; } }
 
9449
                                $new_browser_h{$key}+=$_browser_h{$key};
 
9450
                        }
 
9451
                        my $title="$Message[21] ($Message[77] $MaxNbOf{'BrowsersShown'}) &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=browserdetail"):"$PROG$StaticLinks.browserdetail.$StaticExt")."\"$NewLinkTarget>$Message[80]/$Message[58]</a> &nbsp; - &nbsp; <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=unknownbrowser"):"$PROG$StaticLinks.unknownbrowser.$StaticExt")."\"$NewLinkTarget>$Message[0]</a>";
 
9452
                        &tab_head("$title",19,0,'browsers');
 
9453
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th width=\"$WIDTHCOLICON\">&nbsp;</th><th>$Message[21]</th><th width=\"80\">$Message[111]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th></tr>\n";
 
9454
                        $total_h=0;
 
9455
                        my $count=0;
 
9456
                        &BuildKeyList($MaxNbOf{'BrowsersShown'},$MinHit{'Browser'},\%new_browser_h,\%new_browser_h);
 
9457
                        foreach my $key (@keylist) {
 
9458
                                my $p='&nbsp;';
 
9459
                                if ($Totalh) { $p=int($new_browser_h{$key}/$Totalh*1000)/10; $p="$p %"; }
 
9460
                                if ($key eq 'Unknown') {
 
9461
                                        print "<tr><td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/browser\/unknown.png\"".AltTitle("")." /></td><td class=\"aws\"><span style=\"color: #$color_other\">$Message[0]</span></td><td width=\"80\">?</td><td>$_browser_h{$key}</td><td>$p</td></tr>\n";
 
9462
                                }
 
9463
                                else {
 
9464
                                        my $keywithoutcumul=$key; $keywithoutcumul =~ s/cumul$//i;
 
9465
                                        my $libbrowser=$BrowsersHashIDLib{$keywithoutcumul}||$keywithoutcumul;
 
9466
                                        my $nameicon=$BrowsersHashIcon{$keywithoutcumul}||"notavailable";
 
9467
                                        if ($BrowsersFamily{$keywithoutcumul}) { $libbrowser="<b>$libbrowser</b>"; }
 
9468
                                        print "<tr><td".($count?"":" width=\"$WIDTHCOLICON\"")."><img src=\"$DirIcons\/browser\/$nameicon.png\"".AltTitle("")." /></td><td class=\"aws\">".($PageDir eq 'rtl'?"<span dir=\"ltr\">":"")."$libbrowser".($PageDir eq 'rtl'?"</span>":"")."</td><td>".($BrowsersHereAreGrabbers{$key}?"<b>$Message[112]</b>":"$Message[113]")."</td><td>$new_browser_h{$key}</td><td>$p</td></tr>\n";
 
9469
                                }
 
9470
                                $total_h += $new_browser_h{$key};
 
9471
                                $count++;
 
9472
                        }
 
9473
                        if ($Debug) { debug("Total real / shown : $Totalh / $total_h",2); }
 
9474
                        $rest_h=$Totalh-$total_h;
 
9475
                        if ($rest_h > 0) {
 
9476
                                my $p;
 
9477
                                if ($Totalh) { $p=int($rest_h/$Totalh*1000)/10; }
 
9478
                                print "<tr>";
 
9479
                                print "<td>&nbsp;</td>";
 
9480
                                print "<td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td><td>&nbsp;</td><td>$rest_h</td>";
 
9481
                                print "<td>$p %</td></tr>\n";
 
9482
                        }
 
9483
                        &tab_end;
 
9484
                }
 
9485
        
 
9486
                # BY SCREEN SIZE
 
9487
                #----------------------------
 
9488
                if ($ShowScreenSizeStats) {
 
9489
                        if ($Debug) { debug("ShowScreenSizeStats",2); }
 
9490
                        print "$Center<a name=\"screensizes\">&nbsp;</a><br />\n";
 
9491
                        my $Totalh=0; foreach (keys %_screensize_h) { $Totalh+=$_screensize_h{$_}; }
 
9492
                        my $title="$Message[135] ($Message[77] $MaxNbOf{'ScreenSizesShown'})";
 
9493
                        &tab_head("$title",0,0,'screensizes');
 
9494
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$Message[135]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th></tr>\n";
 
9495
                        my $total_h=0;
 
9496
                        my $count=0;
 
9497
                        &BuildKeyList($MaxNbOf{'ScreenSizesShown'},$MinHit{'ScreenSize'},\%_screensize_h,\%_screensize_h);
 
9498
                        foreach my $key (@keylist) {
 
9499
                                my $p='&nbsp;';
 
9500
                                if ($Totalh) { $p=int($_screensize_h{$key}/$Totalh*1000)/10; $p="$p %"; }
 
9501
                                $total_h+=$_screensize_h{$key}||0;
 
9502
                                print "<tr>";
 
9503
                                if ($key eq 'Unknown') {
 
9504
                                        print "<td class=\"aws\"><span style=\"color: #$color_other\">$Message[0]</span></td>";
 
9505
                                        print "<td>$p</td>";
 
9506
                                        }
 
9507
                                else {
 
9508
                                        my $screensize=$key;
 
9509
                                        print "<td class=\"aws\">$screensize</td>";
 
9510
                                        print "<td>$p</td>";
 
9511
                                }
 
9512
                                print "</tr>\n";
 
9513
                                $count++;
 
9514
                        }
 
9515
                        $rest_h=$Totalh-$total_h;
 
9516
                        if ($rest_h > 0) {      # All others sessions
 
9517
                                my $p=0;
 
9518
                                if ($Totalh) { $p=int($rest_h/$Totalh*1000)/10; }
 
9519
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[2]</span></td>";
 
9520
                                print "<td>".($rest_h?"$p %":"&nbsp;")."</td>";
 
9521
                                print "</tr>\n";
 
9522
                        }
 
9523
                        &tab_end;
 
9524
                }
 
9525
 
 
9526
                print "\n<a name=\"refering\">&nbsp;</a>\n\n";
 
9527
        
 
9528
                # BY REFERENCE
 
9529
                #---------------------------
 
9530
                if ($ShowOriginStats) {
 
9531
                        if ($Debug) { debug("ShowOriginStats",2); }
 
9532
                        print "$Center<a name=\"referer\">&nbsp;</a><br />\n";
 
9533
                        my $Totalp=0; foreach (0..5) { $Totalp+=$_from_p[$_]; }
 
9534
                        my $Totalh=0; foreach (0..5) { $Totalh+=$_from_h[$_]; }
 
9535
                        &tab_head($Message[36],19,0,'referer');
 
9536
                        my @p_p=(0,0,0,0,0,0);
 
9537
                        if ($Totalp > 0) {
 
9538
                                $p_p[0]=int($_from_p[0]/$Totalp*1000)/10;
 
9539
                                $p_p[1]=int($_from_p[1]/$Totalp*1000)/10;
 
9540
                                $p_p[2]=int($_from_p[2]/$Totalp*1000)/10;
 
9541
                                $p_p[3]=int($_from_p[3]/$Totalp*1000)/10;
 
9542
                                $p_p[4]=int($_from_p[4]/$Totalp*1000)/10;
 
9543
                                $p_p[5]=int($_from_p[5]/$Totalp*1000)/10;
 
9544
                        }
 
9545
                        my @p_h=(0,0,0,0,0,0);
 
9546
                        if ($Totalh > 0) {
 
9547
                                $p_h[0]=int($_from_h[0]/$Totalh*1000)/10;
 
9548
                                $p_h[1]=int($_from_h[1]/$Totalh*1000)/10;
 
9549
                                $p_h[2]=int($_from_h[2]/$Totalh*1000)/10;
 
9550
                                $p_h[3]=int($_from_h[3]/$Totalh*1000)/10;
 
9551
                                $p_h[4]=int($_from_h[4]/$Totalh*1000)/10;
 
9552
                                $p_h[5]=int($_from_h[5]/$Totalh*1000)/10;
 
9553
                        }
 
9554
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$Message[37]</th>";
 
9555
                        if ($ShowOriginStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th><th bgcolor=\"#$color_p\" width=\"80\">$Message[15]</th>"; }
 
9556
                        if ($ShowOriginStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>"; }
 
9557
                        print "</tr>\n";
 
9558
                        #------- Referrals by direct address/bookmarks
 
9559
                        print "<tr><td class=\"aws\"><b>$Message[38]</b></td>";
 
9560
                        if ($ShowOriginStats =~ /P/i) { print "<td>".($_from_p[0]?$_from_p[0]:"&nbsp;")."</td><td>".($_from_p[0]?"$p_p[0] %":"&nbsp;")."</td>"; }
 
9561
                        if ($ShowOriginStats =~ /H/i) { print "<td>".($_from_h[0]?$_from_h[0]:"&nbsp;")."</td><td>".($_from_h[0]?"$p_h[0] %":"&nbsp;")."</td>"; }
 
9562
                        print "</tr>\n";
 
9563
                        #------- Referrals by news group
 
9564
                        print "<tr><td class=\"aws\"><b>$Message[107]</b></td>";
 
9565
                        if ($ShowOriginStats =~ /P/i) { print "<td>".($_from_p[5]?$_from_p[5]:"&nbsp;")."</td><td>".($_from_p[5]?"$p_p[5] %":"&nbsp;")."</td>"; }
 
9566
                        if ($ShowOriginStats =~ /H/i) { print "<td>".($_from_h[5]?$_from_h[5]:"&nbsp;")."</td><td>".($_from_h[5]?"$p_h[5] %":"&nbsp;")."</td>"; }
 
9567
                        print "</tr>\n";
 
9568
                        #------- Referrals by search engines
 
9569
                        print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip(13);\" onmouseout=\"HideTip(13);\"":"")."><td class=\"aws\"><b>$Message[40]</b> - <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=refererse"):"$PROG$StaticLinks.refererse.$StaticExt")."\"$NewLinkTarget>$Message[80]</a><br />\n";
 
9570
                        if (scalar keys %_se_referrals_h) {
 
9571
                                print "<table>\n";
 
9572
                                $total_p=0; $total_h=0;
 
9573
                                my $count=0;
 
9574
                                &BuildKeyList($MaxNbOf{'RefererShown'},$MinHit{'Refer'},\%_se_referrals_h,\%_se_referrals_p);
 
9575
                                foreach my $key (@keylist) {
 
9576
                                        my $newreferer=CleanFromCSSA($SearchEnginesHashLib{$key}||$key);
 
9577
                                        print "<tr><td class=\"aws\">- $newreferer</td>";
 
9578
                                        print "<td>".($_se_referrals_p{$key}?$_se_referrals_p{$key}:'0')."</td>";
 
9579
                                        print "<td>$_se_referrals_h{$key}</td>";
 
9580
                                        print "</tr>\n";
 
9581
                                        $total_p += $_se_referrals_p{$key};
 
9582
                                        $total_h += $_se_referrals_h{$key};
 
9583
                                        $count++;
 
9584
                                }
 
9585
                                if ($Debug) { debug("Total real / shown : $TotalSearchEnginesPages / $total_p -  $TotalSearchEnginesHits / $total_h",2); }
 
9586
                                $rest_p=$TotalSearchEnginesPages-$total_p;
 
9587
                                $rest_h=$TotalSearchEnginesHits-$total_h;
 
9588
                                if ($rest_p > 0 || $rest_h > 0) {
 
9589
                                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">- $Message[2]</span></td>";
 
9590
                                        print "<td>$rest_p</td>";
 
9591
                                        print "<td>$rest_h</td>";
 
9592
                                        print "</tr>\n";
 
9593
                                }
 
9594
                                print "</table>";
 
9595
                        }
 
9596
                        print "</td>\n";
 
9597
                        if ($ShowOriginStats =~ /P/i) { print "<td valign=\"top\">".($_from_p[2]?$_from_p[2]:"&nbsp;")."</td><td valign=\"top\">".($_from_p[2]?"$p_p[2] %":"&nbsp;")."</td>"; }
 
9598
                        if ($ShowOriginStats =~ /H/i) { print "<td valign=\"top\">".($_from_h[2]?$_from_h[2]:"&nbsp;")."</td><td valign=\"top\">".($_from_h[2]?"$p_h[2] %":"&nbsp;")."</td>"; }
 
9599
                        print "</tr>\n";
 
9600
                        #------- Referrals by external HTML link
 
9601
                        print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip(14);\" onmouseout=\"HideTip(14);\"":"")."><td class=\"aws\"><b>$Message[41]</b> - <a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=refererpages"):"$PROG$StaticLinks.refererpages.$StaticExt")."\"$NewLinkTarget>$Message[80]</a><br />\n";
 
9602
                        if (scalar keys %_pagesrefs_h) {
 
9603
                                print "<table>\n";
 
9604
                                $total_p=0; $total_h=0;
 
9605
                                my $count=0;
 
9606
                                &BuildKeyList($MaxNbOf{'RefererShown'},$MinHit{'Refer'},\%_pagesrefs_h,\%_pagesrefs_p);
 
9607
                                foreach my $key (@keylist) {
 
9608
                                        print "<tr><td class=\"aws\">- ";
 
9609
                                        &ShowURLInfo($key);
 
9610
                                        print "</td>";
 
9611
                                        print "<td>".($_pagesrefs_p{$key}?$_pagesrefs_p{$key}:'0')."</td>";
 
9612
                                        print "<td>$_pagesrefs_h{$key}</td>";
 
9613
                                        print "</tr>\n";
 
9614
                                        $total_p += $_pagesrefs_p{$key};
 
9615
                                        $total_h += $_pagesrefs_h{$key};
 
9616
                                        $count++;
 
9617
                                }
 
9618
                                if ($Debug) { debug("Total real / shown : $TotalRefererPages / $total_p - $TotalRefererHits / $total_h",2); }
 
9619
                                $rest_p=$TotalRefererPages-$total_p;
 
9620
                                $rest_h=$TotalRefererHits-$total_h;
 
9621
                                if ($rest_p > 0 || $rest_h > 0) {
 
9622
                                        print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">- $Message[2]</span></td>";
 
9623
                                        print "<td>$rest_p</td>";
 
9624
                                        print "<td>$rest_h</td>";
 
9625
                                        print "</tr>\n";
 
9626
                                }
 
9627
                                print "</table>";
 
9628
                        }
 
9629
                        print "</td>\n";
 
9630
                        if ($ShowOriginStats =~ /P/i) { print "<td valign=\"top\">".($_from_p[3]?$_from_p[3]:"&nbsp;")."</td><td valign=\"top\">".($_from_p[3]?"$p_p[3] %":"&nbsp;")."</td>"; }
 
9631
                        if ($ShowOriginStats =~ /H/i) { print "<td valign=\"top\">".($_from_h[3]?$_from_h[3]:"&nbsp;")."</td><td valign=\"top\">".($_from_h[3]?"$p_h[3] %":"&nbsp;")."</td>"; }
 
9632
                        print "</tr>\n";
 
9633
                        #------- Referrals by internal HTML link
 
9634
                        print "<tr><td class=\"aws\"><b>$Message[42]</b></td>";
 
9635
                        if ($ShowOriginStats =~ /P/i) { print "<td>".($_from_p[4]?$_from_p[4]:"&nbsp;")."</td><td>".($_from_p[4]?"$p_p[4] %":"&nbsp;")."</td>"; }
 
9636
                        if ($ShowOriginStats =~ /H/i) { print "<td>".($_from_h[4]?$_from_h[4]:"&nbsp;")."</td><td>".($_from_h[4]?"$p_h[4] %":"&nbsp;")."</td>"; }
 
9637
                        print "</tr>\n";
 
9638
                        #------- Unknown origin
 
9639
                        print "<tr><td class=\"aws\"><b>$Message[39]</b></td>";
 
9640
                        if ($ShowOriginStats =~ /P/i) { print "<td>".($_from_p[1]?$_from_p[1]:"&nbsp;")."</td><td>".($_from_p[1]?"$p_p[1] %":"&nbsp;")."</td>"; }
 
9641
                        if ($ShowOriginStats =~ /H/i) { print "<td>".($_from_h[1]?$_from_h[1]:"&nbsp;")."</td><td>".($_from_h[1]?"$p_h[1] %":"&nbsp;")."</td>"; }
 
9642
                        print "</tr>\n";
 
9643
                        &tab_end;
 
9644
                }
 
9645
        
 
9646
                print "\n<a name=\"keys\">&nbsp;</a>\n\n";
 
9647
        
 
9648
                # BY SEARCH KEYWORDS AND/OR KEYPHRASES
 
9649
                #-------------------------------------
 
9650
                if ($ShowKeyphrasesStats) { print "$Center<a name=\"keyphrases\">&nbsp;</a>"; }
 
9651
                if ($ShowKeywordsStats)   {     print "$Center<a name=\"keywords\">&nbsp;</a>"; }
 
9652
                if ($ShowKeyphrasesStats || $ShowKeywordsStats) { print "<br />\n"; }
 
9653
                if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"><tr>"; }
 
9654
                if ($ShowKeyphrasesStats) {
 
9655
                        # By Keyphrases
 
9656
                        if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "<td width=\"50%\" valign=\"top\">\n";  }
 
9657
                        if ($Debug) { debug("ShowKeyphrasesStats",2); }
 
9658
                        &tab_head("$Message[120] ($Message[77] $MaxNbOf{'KeyphrasesShown'})<br /><a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=keyphrases"):"$PROG$StaticLinks.keyphrases.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>",19,($ShowKeyphrasesStats && $ShowKeywordsStats)?95:70,'keyphrases');
 
9659
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(15);\" onmouseout=\"HideTip(15);\"":"")."><th>$TotalDifferentKeyphrases $Message[103]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[14]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[15]</th></tr>\n";
 
9660
                        $total_s=0;
 
9661
                        my $count=0;
 
9662
                        &BuildKeyList($MaxNbOf{'KeyphrasesShown'},$MinHit{'Keyphrase'},\%_keyphrases,\%_keyphrases);
 
9663
                        foreach my $key (@keylist) {
 
9664
                                my $mot;
 
9665
                                # Convert coded keywords (utf8,...) to be correctly reported in HTML page.
 
9666
                                if ($PluginsLoaded{'DecodeKey'}{'decodeutfkeys'})  { $mot=CleanFromCSSA(DecodeKey_decodeutfkeys($key,$PageCode||'iso-8859-1')); }
 
9667
                                else { $mot = CleanFromCSSA(DecodeEncodedString($key)); }
 
9668
                                my $p;
 
9669
                                if ($TotalKeyphrases) { $p=int($_keyphrases{$key}/$TotalKeyphrases*1000)/10; }
 
9670
                                print "<tr><td class=\"aws\">".XMLEncode($mot)."</td><td>$_keyphrases{$key}</td><td>$p %</td></tr>\n";
 
9671
                                $total_s += $_keyphrases{$key};
 
9672
                                $count++;
 
9673
                        }
 
9674
                        if ($Debug) { debug("Total real / shown : $TotalKeyphrases / $total_s",2); }
 
9675
                        $rest_s=$TotalKeyphrases-$total_s;
 
9676
                        if ($rest_s > 0) {
 
9677
                                my $p;
 
9678
                                if ($TotalKeyphrases) { $p=int($rest_s/$TotalKeyphrases*1000)/10; }
 
9679
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[124]</span></td><td>$rest_s</td>";
 
9680
                                print "<td>$p&nbsp;%</td></tr>\n";
 
9681
                        }
 
9682
                        &tab_end;
 
9683
                        if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "</td>\n";      }
 
9684
                }
 
9685
                if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "<td> &nbsp; </td>"; }
 
9686
                if ($ShowKeywordsStats) {
 
9687
                        # By Keywords
 
9688
                        if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "<td width=\"50%\" valign=\"top\">\n";  }
 
9689
                        if ($Debug) { debug("ShowKeywordsStats",2); }
 
9690
                        &tab_head("$Message[121] ($Message[77] $MaxNbOf{'KeywordsShown'})<br /><a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=keywords"):"$PROG$StaticLinks.keywords.$StaticExt")."\"$NewLinkTarget>$Message[80]</a>",19,($ShowKeyphrasesStats && $ShowKeywordsStats)?95:70,'keywords');
 
9691
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"".($TOOLTIPON?" onmouseover=\"ShowTip(15);\" onmouseout=\"HideTip(15);\"":"")."><th>$TotalDifferentKeywords $Message[13]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[14]</th><th bgcolor=\"#$color_s\" width=\"80\">$Message[15]</th></tr>\n";
 
9692
                        $total_s=0;
 
9693
                        my $count=0;
 
9694
                        &BuildKeyList($MaxNbOf{'KeywordsShown'},$MinHit{'Keyword'},\%_keywords,\%_keywords);
 
9695
                        foreach my $key (@keylist) {
 
9696
                                my $mot;
 
9697
                                # Convert coded keywords (utf8,...) to be correctly reported in HTML page.
 
9698
                                if ($PluginsLoaded{'DecodeKey'}{'decodeutfkeys'})  { $mot=CleanFromCSSA(DecodeKey_decodeutfkeys($key,$PageCode||'iso-8859-1')); }
 
9699
                                else { $mot = CleanFromCSSA(DecodeEncodedString($key)); }
 
9700
                                my $p;
 
9701
                                if ($TotalKeywords) { $p=int($_keywords{$key}/$TotalKeywords*1000)/10; }
 
9702
                                print "<tr><td class=\"aws\">".XMLEncode($mot)."</td><td>$_keywords{$key}</td><td>$p %</td></tr>\n";
 
9703
                                $total_s += $_keywords{$key};
 
9704
                                $count++;
 
9705
                        }
 
9706
                        if ($Debug) { debug("Total real / shown : $TotalKeywords / $total_s",2); }
 
9707
                        $rest_s=$TotalKeywords-$total_s;
 
9708
                        if ($rest_s > 0) {
 
9709
                                my $p;
 
9710
                                if ($TotalKeywords) { $p=int($rest_s/$TotalKeywords*1000)/10; }
 
9711
                                print "<tr><td class=\"aws\"><span style=\"color: #$color_other\">$Message[30]</span></td><td>$rest_s</td>";
 
9712
                                print "<td>$p %</td></tr>\n";
 
9713
                        }
 
9714
                        &tab_end;
 
9715
                        if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "</td>\n";      }
 
9716
                }
 
9717
                if ($ShowKeyphrasesStats && $ShowKeywordsStats) { print "</tr></table>\n"; }
 
9718
        
 
9719
                print "\n<a name=\"other\">&nbsp;</a>\n\n";
 
9720
        
 
9721
                # BY MISC
 
9722
                #----------------------------
 
9723
                if ($ShowMiscStats) {
 
9724
                        if ($Debug) { debug("ShowMiscStats",2); }
 
9725
                        print "$Center<a name=\"misc\">&nbsp;</a><br />\n";
 
9726
                        my $Totalh=0; my %new_browser_h=();
 
9727
                        if ($_misc_h{'AddToFavourites'}) {
 
9728
                                foreach my $key (keys %_browser_h) {
 
9729
                                        $Totalh+=$_browser_h{$key};
 
9730
                                        if ($key =~ /^msie/i) { $new_browser_h{"msiecumul"}+=$_browser_h{$key}; }
 
9731
                                }
 
9732
                                if ($new_browser_h{'msiecumul'}) { $_misc_h{'AddToFavourites'}=int(0.5+$_misc_h{'AddToFavourites'}*$Totalh/$new_browser_h{'msiecumul'}); }
 
9733
                        }
 
9734
                        my $title="$Message[139]";
 
9735
                        &tab_head("$title",19,0,'misc');
 
9736
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th>$Message[139]</th>";
 
9737
                        print "<th width=\"100\">&nbsp;</th>";
 
9738
                        print "<th width=\"100\">&nbsp;</th>";
 
9739
                        print "</tr>\n";
 
9740
                        my %label=('AddToFavourites'=>$Message[137],'JavaEnabled'=>$Message[140],'DirectorSupport'=>$Message[141],
 
9741
                        'FlashSupport'=>$Message[142],'RealPlayerSupport'=>$Message[143],'QuickTimeSupport'=>$Message[144],
 
9742
                        'WindowsMediaPlayerSupport'=>$Message[145],'PDFSupport'=>$Message[146]);
 
9743
                        foreach my $key (@MiscListOrder) {
 
9744
                                my $mischar=substr($key,0,1);
 
9745
                                if ($ShowMiscStats !~ /$mischar/i) { next; }
 
9746
                                my $total=0;
 
9747
                                my $p;
 
9748
                                if ($MiscListCalc{$key} eq 'v') { $total=$TotalVisits; }
 
9749
                                if ($MiscListCalc{$key} eq 'u') { $total=$TotalUnique; }
 
9750
                                if ($MiscListCalc{$key} eq 'hm') { $total=$_misc_h{'TotalMisc'}||0; }
 
9751
                                if ($total) { $p=int($_misc_h{$key}/$total*1000)/10; }
 
9752
                                print "<tr>";
 
9753
                                print "<td class=\"aws\">".($PageDir eq 'rtl'?"<span dir=\"ltr\">":"").$label{$key}.($PageDir eq 'rtl'?"</span>":"")."</td>";
 
9754
                                if ($MiscListCalc{$key} eq 'v') { print "<td>".($_misc_h{$key}||0)." / $total $Message[12]</td>"; }
 
9755
                                if ($MiscListCalc{$key} eq 'u') { print "<td>".($_misc_h{$key}||0)." / $total $Message[18]</td>"; }
 
9756
                                if ($MiscListCalc{$key} eq 'hm') { print "<td>-</td>"; }
 
9757
                                print "<td>".($total?"$p %":"&nbsp;")."</td>";
 
9758
                                print "</tr>\n";
 
9759
                        }
 
9760
                        &tab_end;
 
9761
                }
 
9762
        
 
9763
                # BY HTTP STATUS
 
9764
                #----------------------------
 
9765
                if ($ShowHTTPErrorsStats) {
 
9766
                        if ($Debug) { debug("ShowHTTPErrorsStats",2); }
 
9767
                        print "$Center<a name=\"errors\">&nbsp;</a><br />\n";
 
9768
                        my $title="$Message[32]";
 
9769
                        &tab_head("$title",19,0,'errors');
 
9770
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"2\">$Message[32]*</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th><th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th></tr>\n";
 
9771
                        $total_h=0;
 
9772
                        my $count=0;
 
9773
                        &BuildKeyList($MaxRowsInHTMLOutput,1,\%_errors_h,\%_errors_h);
 
9774
                        foreach my $key (@keylist) {
 
9775
                                my $p=int($_errors_h{$key}/$TotalHitsErrors*1000)/10;
 
9776
                                print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip($key);\" onmouseout=\"HideTip($key);\"":"").">";
 
9777
                                if ($TrapInfosForHTTPErrorCodes{$key}) { print "<td><a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=errors$key"):"$PROG$StaticLinks.errors$key.$StaticExt")."\"$NewLinkTarget>$key</a></td>"; }
 
9778
                                else { print "<td valign=\"top\">$key</td>"; }
 
9779
                                print "<td class=\"aws\">".($httpcodelib{$key}?$httpcodelib{$key}:'Unknown error')."</td><td>$_errors_h{$key}</td><td>$p %</td><td>".Format_Bytes($_errors_k{$key})."</td>";
 
9780
                                print "</tr>\n";
 
9781
                                $total_h+=$_errors_h{$key};
 
9782
                                $count++;
 
9783
                        }
 
9784
                        &tab_end("* $Message[154]");
 
9785
                }
 
9786
 
 
9787
                # BY SMTP STATUS
 
9788
                #----------------------------
 
9789
                if ($ShowSMTPErrorsStats) {
 
9790
                        if ($Debug) { debug("ShowSMTPErrorsStats",2); }
 
9791
                        print "$Center<a name=\"errors\">&nbsp;</a><br />\n";
 
9792
                        my $title="$Message[147]";
 
9793
                        &tab_head("$title",19,0,'errors');
 
9794
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"2\">$Message[147]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th><th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th></tr>\n";
 
9795
                        $total_h=0;
 
9796
                        my $count=0;
 
9797
                        &BuildKeyList($MaxRowsInHTMLOutput,1,\%_errors_h,\%_errors_h);
 
9798
                        foreach my $key (@keylist) {
 
9799
                                my $p=int($_errors_h{$key}/$TotalHitsErrors*1000)/10;
 
9800
                                print "<tr".($TOOLTIPON?" onmouseover=\"ShowTip($key);\" onmouseout=\"HideTip($key);\"":"").">";
 
9801
                                print "<td valign=\"top\">$key</td>";
 
9802
                                print "<td class=\"aws\">".($smtpcodelib{$key}?$smtpcodelib{$key}:'Unknown error')."</td><td>$_errors_h{$key}</td><td>$p %</td><td>".Format_Bytes($_errors_k{$key})."</td>";
 
9803
                                print "</tr>\n";
 
9804
                                $total_h+=$_errors_h{$key};
 
9805
                                $count++;
 
9806
                        }
 
9807
                        &tab_end;
 
9808
                }
 
9809
        
 
9810
                # BY CLUSTER
 
9811
                #----------------------------
 
9812
                if ($ShowClusterStats) {
 
9813
                        if ($Debug) { debug("ShowClusterStats",2); }
 
9814
                        print "$Center<a name=\"clusters\">&nbsp;</a><br />\n";
 
9815
                        my $title="$Message[155]";
 
9816
                        &tab_head("$title",19,0,'clusters');
 
9817
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"2\">$Message[155]</th>";
 
9818
                        if ($ShowClusterStats =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th><th bgcolor=\"#$color_p\" width=\"80\">$Message[15]</th>"; }
 
9819
                        if ($ShowClusterStats =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th><th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>"; }
 
9820
                        if ($ShowClusterStats =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th><th bgcolor=\"#$color_k\" width=\"80\">$Message[15]</th>"; }
 
9821
                        print "</tr>\n";
 
9822
                        $total_p=$total_h=$total_k=0;
 
9823
                        # Cluster feature might have been enable in middle of month so we recalculate
 
9824
                        # total for cluster section only, to calculate ratio, instead of using global total
 
9825
                        foreach my $key (keys %_cluster_h) {
 
9826
                                $total_p+=int($_cluster_p{$key}||0);
 
9827
                                $total_h+=int($_cluster_h{$key}||0);
 
9828
                                $total_k+=int($_cluster_k{$key}||0);
 
9829
                        }
 
9830
                        my $count=0;
 
9831
                        foreach my $key (keys %_cluster_h) {
 
9832
                                my $p_p=int($_cluster_p{$key}/$total_p*1000)/10;
 
9833
                                my $p_h=int($_cluster_h{$key}/$total_h*1000)/10;
 
9834
                                my $p_k=int($_cluster_k{$key}/$total_k*1000)/10;
 
9835
                                print "<tr>";
 
9836
                                print "<td class=\"aws\" colspan=\"2\">Computer $key</td>";
 
9837
                                if ($ShowClusterStats =~ /P/i) { print "<td>".($_cluster_p{$key}?$_cluster_p{$key}:"&nbsp;")."</td><td>$p_p %</td>"; }
 
9838
                                if ($ShowClusterStats =~ /H/i) { print "<td>$_cluster_h{$key}</td><td>$p_h %</td>"; }
 
9839
                                if ($ShowClusterStats =~ /B/i) { print "<td>".Format_Bytes($_cluster_k{$key})."</td><td>$p_k %</td>"; }
 
9840
                                print "</tr>\n";
 
9841
                                $count++;
 
9842
                        }
 
9843
                        &tab_end;
 
9844
                }
 
9845
 
 
9846
                # BY EXTRA SECTIONS
 
9847
                #----------------------------
 
9848
                foreach my $extranum (1..@ExtraName-1) {
 
9849
                        if ($Debug) { debug("ExtraName$extranum",2); }
 
9850
                        print "$Center<a name=\"extra$extranum\">&nbsp;</a><br />";
 
9851
                        my $title=$ExtraName[$extranum];
 
9852
                        &tab_head("$title",19,0,"extra$extranum");
 
9853
                        print "<tr bgcolor=\"#$color_TableBGRowTitle\">";
 
9854
                        print "<th>".$ExtraFirstColumnTitle[$extranum]."</th>";
 
9855
                        if ($ExtraStatTypes[$extranum] =~ m/P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
 
9856
                        if ($ExtraStatTypes[$extranum] =~ m/H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
 
9857
                        if ($ExtraStatTypes[$extranum] =~ m/B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
 
9858
                        if ($ExtraStatTypes[$extranum] =~ m/L/i) { print "<th width=\"120\">$Message[9]</th>"; }
 
9859
                        print "</tr>\n";
 
9860
                        $total_p=$total_h=$total_k=0;
 
9861
                        #$max_h=1; foreach (values %_login_h) { if ($_ > $max_h) { $max_h = $_; } }
 
9862
                        #$max_k=1; foreach (values %_login_k) { if ($_ > $max_k) { $max_k = $_; } }
 
9863
                        my $count=0;
 
9864
                        if ($ExtraStatTypes[$extranum] =~ m/P/i) { 
 
9865
                                &BuildKeyList($MaxNbOfExtra[$extranum],$MinHitExtra[$extranum],\%{'_section_' . $extranum . '_h'},\%{'_section_' . $extranum . '_p'});
 
9866
                        }
 
9867
                        else {
 
9868
                                &BuildKeyList($MaxNbOfExtra[$extranum],$MinHitExtra[$extranum],\%{'_section_' . $extranum . '_h'},\%{'_section_' . $extranum . '_h'});
 
9869
                        }
 
9870
                        foreach my $key (@keylist) {
 
9871
                                my $firstcol = CleanFromCSSA(DecodeEncodedString($key));
 
9872
                                $total_p+=${'_section_' . $extranum . '_p'}{$key};
 
9873
                                $total_h+=${'_section_' . $extranum . '_h'}{$key};
 
9874
                                $total_k+=${'_section_' . $extranum . '_k'}{$key};
 
9875
                                print "<tr>";
 
9876
                                printf("<td class=\"aws\">$ExtraFirstColumnFormat[$extranum]</td>", $firstcol, $firstcol, $firstcol, $firstcol, $firstcol);
 
9877
                                if ($ExtraStatTypes[$extranum] =~ m/P/i) { print "<td>" . ${'_section_' . $extranum . '_p'}{$key} . "</td>"; }
 
9878
                                if ($ExtraStatTypes[$extranum] =~ m/H/i) { print "<td>" . ${'_section_' . $extranum . '_h'}{$key} . "</td>"; }
 
9879
                                if ($ExtraStatTypes[$extranum] =~ m/B/i) { print "<td>" . Format_Bytes(${'_section_' . $extranum . '_k'}{$key}) . "</td>"; }
 
9880
                                if ($ExtraStatTypes[$extranum] =~ m/L/i) { print "<td>" . (${'_section_' . $extranum . '_l'}{$key}?Format_Date(${'_section_' . $extranum . '_l'}{$key},1):'-') . "</td>"; }
 
9881
                                print "</tr>\n";
 
9882
                                $count++;
 
9883
                        }
 
9884
                        if ($ExtraAddAverageRow[$extranum]) {
 
9885
                                print "<tr>";
 
9886
                                print "<td class=\"aws\"><b>$Message[96]</b></td>";
 
9887
                                if ($ExtraStatTypes[$extranum] =~ m/P/i) { print "<td>" . ($count?($total_p/$count):"&nbsp;") . "</td>"; }
 
9888
                                if ($ExtraStatTypes[$extranum] =~ m/H/i) { print "<td>" . ($count?($total_h/$count):"&nbsp;") . "</td>"; }
 
9889
                                if ($ExtraStatTypes[$extranum] =~ m/B/i) { print "<td>" . ($count?Format_Bytes($total_k/$count):"&nbsp;") . "</td>"; }
 
9890
                                if ($ExtraStatTypes[$extranum] =~ m/L/i) { print "<td>&nbsp;</td>"; }
 
9891
                                print "</tr>\n";
 
9892
                        }
 
9893
                        if ($ExtraAddSumRow[$extranum]) {
 
9894
                                print "<tr>";
 
9895
                                print "<td class=\"aws\"><b>$Message[102]</b></td>";
 
9896
                                if ($ExtraStatTypes[$extranum] =~ m/P/i) { print "<td>" . ($total_p) . "</td>"; }
 
9897
                                if ($ExtraStatTypes[$extranum] =~ m/H/i) { print "<td>" . ($total_h) . "</td>"; }
 
9898
                                if ($ExtraStatTypes[$extranum] =~ m/B/i) { print "<td>" . Format_Bytes($total_k) . "</td>"; }
 
9899
                                if ($ExtraStatTypes[$extranum] =~ m/L/i) { print "<td>&nbsp;</td>"; }
 
9900
                                print "</tr>\n";
 
9901
                        }
 
9902
                        &tab_end;
 
9903
                }
 
9904
        
 
9905
                &html_end(1);
 
9906
        }
 
9907
}
 
9908
else {
 
9909
        print "Jumped lines in file: $lastlinenumber\n";
 
9910
        if ($lastlinenumber) { print " Found $lastlinenumber old records.\n"; }
 
9911
        print "Parsed lines in file: $NbOfLinesParsed\n";
 
9912
        print " Found $NbOfLinesDropped dropped records,\n";
 
9913
        print " Found $NbOfLinesCorrupted corrupted records,\n";
 
9914
        print " Found $NbOfOldLines old records,\n";
 
9915
        print " Found $NbOfNewLines new qualified records.\n";
 
9916
}
 
9917
 
 
9918
#sleep 10;
 
9919
 
 
9920
0;      # Do not remove this line
 
9921
 
 
9922
 
 
9923
#-------------------------------------------------------
 
9924
# ALGORITHM SUMMARY
 
9925
#
 
9926
# Read_Config();
 
9927
# Check_Config() and Init variables
 
9928
# if 'frame not index'
 
9929
#       &Read_Language_Data($Lang);
 
9930
#       if 'frame not mainleft'
 
9931
#               &Read_Ref_Data();
 
9932
#               &Read_Plugins();
 
9933
# html_head
 
9934
#
 
9935
# If 'migrate'
 
9936
#   We create/update tmp file with
 
9937
#     &Read_History_With_TmpUpdate(year,month,UPDATE,NOPURGE,"all");
 
9938
#   Rename the tmp file
 
9939
#   html_end
 
9940
#   Exit
 
9941
# End of 'migrate'
 
9942
#
 
9943
# Get last history file name
 
9944
# Get value for $LastLine $LastLineNumber $LastLineOffset $LastLineChecksum with
 
9945
#       &Read_History_With_TmpUpdate(lastyear,lastmonth,NOUPDATE,NOPURGE,"general");
 
9946
#
 
9947
# &Init_HashArray()
 
9948
#
 
9949
# If 'update'
 
9950
#   Loop on each new line in log file
 
9951
#     lastlineoffset=lastlineoffsetnext; lastlineoffsetnext=file pointer position
 
9952
#     If line corrupted, skip --> next on loop
 
9953
#         Drop wrong virtual host --> next on loop
 
9954
#     Drop wrong method/protocol --> next on loop
 
9955
#     Check date --> next on loop
 
9956
#     If line older than $LastLine, skip --> next on loop
 
9957
#     So it's new line
 
9958
#     $LastLine = time or record
 
9959
#     Skip if url is /robots.txt --> next on loop
 
9960
#     Skip line for @SkipHosts --> next on loop
 
9961
#     Skip line for @SkipFiles --> next on loop
 
9962
#     Skip line for @SkipUserAgent --> next on loop
 
9963
#     Skip line for not @OnlyHosts --> next on loop
 
9964
#     Skip line for not @OnlyFiles --> next on loop
 
9965
#     Skip line for not @OnlyUserAgent --> next on loop
 
9966
#     So it's new line approved
 
9967
#     If other month/year, create/update tmp file and purge data arrays with
 
9968
#       &Read_History_With_TmpUpdate(lastprocessedyear,lastprocessedmonth,UPDATE,PURGE,"all",lastlinenumber,lastlineoffset,CheckSum($_));
 
9969
#     Define a clean Url and Query (set urlwithnoquery, tokenquery and standalonequery and $field[$pos_url])
 
9970
#     Define PageBool and extension
 
9971
#     Analyze: Misc tracker --> complete %misc
 
9972
#     Analyze: Add to favorites --> complete %_misc, next on loop
 
9973
#     Analyze: Worms --> complete %_worms, countedtraffic=1
 
9974
#     If (!countedtraffic) Analyze: Status code --> complete %_error_, %_sider404, %_referrer404 --> countedtraffic=1
 
9975
#     If (!countedtraffic) Analyze: Robots known --> complete %_robot, countedtraffic=1
 
9976
#     If (!countedtraffic) Analyze: Robots unkown on robots.txt --> complete %_robot, countedtraffic=1
 
9977
#     If (!countedtraffic) Analyze: File types - Compression
 
9978
#     If (!countedtraffic) Analyze: Date - Hour - Pages - Hits - Kilo
 
9979
#     If (!countedtraffic) Analyze: Login
 
9980
#     If (!countedtraffic) Analyze: Lookup
 
9981
#     If (!countedtraffic) Analyze: Country
 
9982
#     If (!countedtraffic) Analyze: Host - Url - Session
 
9983
#     If (!countedtraffic) Analyze: Browser - OS
 
9984
#     If (!countedtraffic) Analyze: Referer
 
9985
#     If (!countedtraffic) Analyze: EMail
 
9986
#     Analyze: Cluster
 
9987
#     Analyze: Extra (must be after 'Clean Url and Query')
 
9988
#     If too many records, we flush data arrays with
 
9989
#       &Read_History_With_TmpUpdate($lastprocessedyear,$lastprocessedmonth,UPDATE,PURGE,"all",lastlinenumber,lastlineoffset,CheckSum($_));
 
9990
#   End of loop
 
9991
#   Create/update tmp file
 
9992
#         Seek to lastlineoffset to read and get last line into $_ 
 
9993
#         &Read_History_With_TmpUpdate($lastprocessedyear,$lastprocessedmonth,UPDATE,PURGE,"all",lastlinenumber,lastlineoffset,CheckSum($_))
 
9994
#   Rename all tmp files
 
9995
# End of 'update'
 
9996
#
 
9997
# &Init_HashArray()
 
9998
#
 
9999
# If 'output'
 
10000
#   Loop for each month of required year
 
10001
#     &Read_History_With_TmpUpdate($YearRequired,monthloop,NOUPDATE,NOPURGE,"all" or "general time" if not required month)
 
10002
#   End of loop
 
10003
#   Show data arrays in HTML page
 
10004
#   html_end
 
10005
# End of 'output'
 
10006
#-------------------------------------------------------
 
10007
 
 
10008
#-------------------------------------------------------
 
10009
# DNS CACHE FILE FORMATS SUPPORTED BY AWSTATS
 
10010
# Format /etc/hosts     x.y.z.w hostname
 
10011
# Format analog         UT/60 x.y.z.w hostname
 
10012
#-------------------------------------------------------
 
10013
 
 
10014
#-------------------------------------------------------
 
10015
# IP Format (d=decimal on 16 bits, x=hexadecimal on 16 bits)
 
10016
#
 
10017
# 13.1.68.3                                             IPv4 (d.d.d.d)
 
10018
# 0:0:0:0:0:0:13.1.68.3                 IPv6 (x:x:x:x:x:x:d.d.d.d)
 
10019
# ::13.1.68.3
 
10020
# 0:0:0:0:0:FFFF:13.1.68.3              IPv6 (x:x:x:x:x:x:d.d.d.d)
 
10021
# ::FFFF:13.1.68.3                              IPv6
 
10022
#
 
10023
# 1070:0:0:0:0:800:200C:417B    IPv6
 
10024
# 1070:0:0:0:0:800:200C:417B    IPv6
 
10025
# 1070::800:200C:417B                   IPv6
 
10026
#-------------------------------------------------------