' Gambas module file

Export 

Property Read Fields As String[]
Property Read Cookies As Collection
Property Read Method As String
Property Path As String
Property Query As String
Property Read Files As Collection
Property Delimiter As String
Property Read InternetExplorer As Integer

'' Return the referer of the request.
Property Read Referer As String

'' Return the user agent of the request.
Property Read UserAgent As String

'' Return the preferred language of the request.
''
'' The 'AcceptLanguage' header of the request is analyzed, and a language description suitable
'' to the [System.Language](/comp/gb/system/language) property is returned.
Property Read Language As String

'' Return or set the temporary directory used to store the files uploaded by the request.
''
'' By default, uploaded files are stored in the '/tmp' directory. Changing it is useful if '/tmp' is not big enough.
Property TempDir As String

'' Return or set the maximum size of an uploaded file.
''
'' By default, files bigger than 128 MB are now allowed.
''
'' [[ warning
'' Do check your HTTP server that usually has its own limit too.
'' ]]
Property MaxFileSize As Long

'' Return the content type of the request.
Property Read ContentType As String

'' Return the content lenth of the request.
Property Read ContentLength As Integer

'' Return or set the scheme of the request.
''
'' It is normally 'http' or 'https'.
''
'' [[ warning
'' The value of this property is guessed by analyzing a few well-known request headers sent by the HTTP server to the CGI script.
'' If it fails for you, please fill an issue on the Gambas bugtracker.
'' ]]
Property Scheme As String

Property Read Get As _Request_Get
Property Read Post As _Request_Post
Property Debug As Boolean

Private $cCookies As Collection
Private $cVal As Collection
Private $cKey As Collection
Private $aField As String[]
Private $sDelimiter As String = "&"
Private $iIE As Integer
Private $bDecoded As Boolean
Private $bPost As Boolean
Private $bDebug As Boolean
Private $sTempDir As String
Private $iMaxFileSize As Long = 128 * 1048576
Private $sLanguage As String
Private $sScheme As String
Private $bSchemeInit As Boolean

Private Sub Decode()

  If $bDecoded Then Return
  $bPost = CGI["REQUEST_METHOD"] = "POST"
  $bDecoded = True
  
End

Public Sub _init()
  
  Dim sAgent As String = CGI["HTTP_USER_AGENT"]
  Dim aScan As String[] = Scan(sAgent, "*; MSIE *;*")
  Try $iIE = Val(aScan[1])
  
End

'' Reset the request decoding

Public Sub Reset()
  
  $bDecoded = False
  _Request_Get._Reset
  _Request_Post._Reset
  
End


Public Sub _get(Key As String) As String

  Dim sVal As String
  
  If $cKey And If $cKey.Exist(Key) Then Return $cVal[Key]
  
  Decode
  
  If $bPost Then
    sVal = _Request_Post[Key]
    If sVal Then Return sVal
  Endif
  
  Return _Request_Get[Key]
  
End

Public Sub _put(Value As String, Key As String)
  
  If Not $cVal Then
    $cVal = New Collection
    $cKey = New Collection
  Endif
  
  $cVal[Key] = Value
  $cKey[Key] = True
  
End

Private Function Fields_Read() As String[]

  Dim sField As String

  Decode

  If Not $aField Then
    If Not $bPost Then
      $aField = _Request_Get.Fields
    Else
      $aField = _Request_Get.Fields.Copy()
      For Each sField In _Request_Post.Fields
        If Not $aField.Exist(sField) Then $aField.Add(sField)
      Next
    Endif
  Endif
  
  Return $aField

End

Private Function Cookies_Read() As Collection

  Dim sCookie As String
  Dim aCookie As String[]

  If Not $cCookies Then
    
    $cCookies = New Collection
    
    For Each sCookie In Split(CGI["HTTP_COOKIE"], ";")
      sCookie = Trim(sCookie)
      aCookie = Split(sCookie, "=")
      Try $cCookies[aCookie[0]] = aCookie[1]
    Next
 
  Endif

  Return $cCookies

End


Private Function Method_Read() As String

  Return CGI["REQUEST_METHOD"]  

End

Private Function Path_Read() As String

  Return CGI["PATH_INFO"]  

End

Private Function Query_Read() As String

  Return CGI["QUERY_STRING"]  

End

Private Function Files_Read() As Collection

  Return _Request_Post.Files

End

Public Sub Exist(Field As String) As Boolean
  
  Fields_Read()
  Return $aField.Exist(Field)
  
End


Private Function Delimiter_Read() As String

  Return $sDelimiter  

End

Private Sub Delimiter_Write(Value As String)

  $sDelimiter = Value

End

Private Function InternetExplorer_Read() As Integer

  Return $iIE  

End

Private Function Get_Read() As _Request_Get

  Return _Request_Get

End

Private Function Post_Read() As _Request_Post

  Return _Request_Post

End

Private Function Debug_Read() As Boolean

  Return $bDebug

End

Private Sub Debug_Write(Value As Boolean)

  $bDebug = Value

End

Private Sub Reload()
  
  _Request_Get._Reset
  
End


Private Sub Path_Write(Value As String)

  CGI["PATH_INFO"] = Value
  Reload

End

Private Sub Query_Write(Value As String)

  CGI["QUERY_STRING"] = Value
  Reload

End

Private Function Referer_Read() As String

  Return CGI["HTTP_REFERER"]

End

Private Function UserAgent_Read() As String

  Return CGI["HTTP_USER_AGENT"]

End

Private Function Language_Read() As String

  Dim aLang As String[]
  Dim sLang As String
  Dim iPos As Integer
  Dim I As Integer
  Dim aQuality As Integer[]
  Dim fQuality As Float
  Dim sQuality As String

  'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
  
  If $sLanguage Then Return $sLanguage
  
  aLang = Split(CGI["HTTP_ACCEPT_LANGUAGE"], ",", "", True)
  If aLang.Count = 0 Then
    $sLanguage = System.Language
    Return $sLanguage
  Endif
  
  aQuality = New Integer[aLang.Count]
  
  For I = 0 To aLang.Max
    
    fQuality = 1
    
    iPos = InStr(sLang, ";")
    If iPos Then 
      sQuality = Trim(Mid$(sLang, iPos + 1))
      If sQuality Begins "q=" Then Try fQuality = CFloat(Mid$(sQuality, 3))
      sLang = Left(sLang, iPos - 1)
    Endif
    
    aQuality[I] = CInt(fQuality * 1000) + aLang.Max - I
      
  Next
  
  aLang.SortUsing(aQuality)
  $sLanguage = Main.ToLanguage(aLang.Last)
  Return $sLanguage

End

Private Function TempDir_Read() As String

  Return $sTempDir

End

Private Sub TempDir_Write(Value As String)

  $sTempDir = Value

End

Private Function MaxFileSize_Read() As Long

  Return $iMaxFileSize

End

Private Sub MaxFileSize_Write(Value As Long)

  $iMaxFileSize = Value

End

Private Function ContentType_Read() As String

  Return CGI["CONTENT_TYPE"]

End

Private Function ContentLength_Read() As Integer

  Try Return CInt(CGI["CONTENT_LENGTH"])
  Return -1

End

Private Function Scheme_Read() As String

  If Not $bSchemeInit Then

    If CGI["HTTP_X_CGI"] = "https" Or If CGI["REQUEST_SCHEME"] = "https" Or If CGI["X_CGI"] = "https" Or If CGI["X_FORWARDED_PROTO"] = "https" Then 
      $sScheme = "https"
    Else If CGI["HTTP_CF_VISITOR"] Then
      If InStr(CGI["HTTP_CF_VISITOR"], "\"scheme\":\"https\"") Then
        $sScheme = "https"
      Endif
    Endif

    $bSchemeInit = True
    
  Endif
  
  If $sScheme Then Return $sScheme
  Return "http"

End

Private Sub Scheme_Write(Value As String)

  $sScheme = Value
  $bSchemeInit = Value

End
