2apache_log_hap(Content,Time) -->
    3    {Content = log(IP,Ident,UserID,ReadableTime,Request,Status,Size,Referer,Browser)},
    4    ip(IP)," ",
    5    ident(Ident)," ",
    6    user_id(UserID)," ",
    7    apache_time(ReadableTime,Time)," ",
    8    request(Request)," ",
    9    integer_na(Status)," ",
   10    integer_na(Size)," ",
   11    referer(Referer)," ",
   12    browser(Browser),"\n".
   13
   14ip(IP) -->
   15    integer(I3), ".",
   16    integer(I2), ".",
   17    integer(I1), ".",
   18    integer(I0),
   19    {IP is I0+I1*256+I2*256*256+I3*256*256*256}.
   20
   21ident(_) -->
   22    "-", {!}.
   23ident(H) -->
   24    alphanumeric_string(String),
   25    {(String = [F|R], F>=65, F=< 90 % If it is capitalised convert to lower case
   26        ->  F1 is F+32,
   27            String1 = [F1|R]
   28        ;   String1 = String),
   29    atom_codes(H,String1)}.
   30    %{write("FOUND IDENTITY: NEEDED IMPROVEMENT OF APACHE_LOG_PARSER"),nl}.
   31
   32user_id(_) -->
   33    "-", {!}.
   34user_id(H) -->
   35    alphanumeric_string(String),
   36    {(String = [F|R], F>=65, F=< 90 % If it is capitalised convert to lower case
   37        ->  F1 is F+32,
   38            String1 = [F1|R]
   39        ;   String1 = String),
   40    atom_codes(H,String1)}.
   41    %{write("FOUND IDENTITY: NEEDED IMPROVEMENT OF APACHE_LOG_PARSER"),nl}.
   42
   43apache_time(ReadableTime,Time) -->
   44    {ReadableTime = time(Day/Month/Year,Hour/Min/Sec,TimeZone)},
   45    "[", integer(Day), "/", month(Month,MonthNum), "/", integer(Year), ":", integer(Hour),
   46    ":", integer(Min), ":", integer(Sec), " ", signed_int(TZ), "]",
   47    {T1 is (Year-2000)+12*MonthNum,
   48    T2 is T1*30+Day,
   49    T3 is T2*24+Hour,
   50    T4 is T3*60+Min,
   51    Time is T4*60+Sec,
   52    TimeZone is TZ//100}.
   53
   54month(jan,1) --> "Jan".
   55month(feb,2) --> "Feb".
   56month(mar,3) --> "Mar".
   57month(apr,4) --> "Apr".
   58month(may,5) --> "May".
   59month(jun,6) --> "Jun".
   60month(jul,7) --> "Jul".
   61month(aug,8) --> "Aug".
   62month(sep,9) --> "Sep".
   63month(oct,10) --> "Oct".
   64month(nov,11) --> "Nov".
   65month(dec,12) --> "Dec".
   66
   67request(get(Path)) -->
   68    [34], % character '"'
   69    "GET ", path(Path), " HTTP/", version, [34]. 
   70request(post(Path)) -->
   71    [34], % character '"'
   72    "POST ", path(Path), " HTTP/", version, [34].
   73
   74path(_) --> "-".
   75path([]) --> [].
   76path(L) -->
   77    path_separator,
   78    path(L).
   79path([H|T]) -->
   80    alphanumeric_string(String),
   81    {(String = [F|R], F>=65, F=< 90 % If it is capitalised convert to lower case
   82        ->  F1 is F+32,
   83            String1 = [F1|R]
   84        ;   String1 = String),
   85    atom_codes(H,String1)},
   86    path(T).
   87
   88path_separator --> "/".
   89path_separator --> "?".
   90path_separator --> ".".
   91path_separator --> ":".
   92path_separator --> "=".
   93path_separator --> "&".
   94path_separator --> "+".
   95
   96version --> integer(_).
   97version --> integer(_), ".", integer(_).
   98
   99% Integer or not available
  100integer_na(Int) --> integer(Int).
  101integer_na(_) --> "-".
  102
  103referer(Ref) --> [34], % character '"'
  104    path(Ref), [34].
  105
  106browser(Browser) -->
  107    [34], any_string(CodeList), [34],
  108    {append([39|CodeList],[39],ListWithQuotations),
  109     atom_codes(Browser,ListWithQuotations)}.
  110    
  111
  112any_string([]) --> [].
  113any_string([H|T]) --> any_char_excluded_nl(H), any_string(T).
  114
  115
  116any_char_excluded_nl(Code) -->
  117	[Code],
  118	{
  119		char_code('\n', A),
  120		Code =\= A
  121	}