Announcement

Collapse
No announcement yet.

using PBCC for CGI - file upload adds 46kb to file

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • using PBCC for CGI - file upload adds 46kb to file

    I use PBCC for a website back-end.

    When I upload a file to the webserver, my code adds 46 bytes somewhere and for the life of me I don't see it.

    Here is the primary code to accept the file and write it to disk.

    Code:
      sParams=webdatastdin()     
    
      ' find user token         
      userID=findToken("name="+$Dq+"muName"+$Dq,"------",sParams,0)      
      userPW=findToken("name="+$Dq+"muPW"+$Dq,"------",sParams,0)            
      muCID=findToken("name="+$Dq+"muCID"+$Dq,"------",sParams,0)        
      dzGroupID=findToken("name="+$Dq+"dzGroupID"+$Dq,"------",sParams,0)        
      fName=findToken("filename=","Content-Type",sParams,0)     
      Replace $Dq With "" In fName            
      contentType=findToken("Content-Type: ", $CrLf,sParams,1)     
    
       tmpBuf = Remain$(sParams,"filename=")    
       tmpbuf = Trim$(Remain$(tmpbuf,"Content-Type: "+contentType))          
       mydata=Right$(tmpbuf,Len(tmpbuf)-4)           
    
      ' write to file
      fName=$dataPath+"\data\webUploads\"+dzGroupID+"\"+fName
      fNumber=FreeFile
      Open fName For Binary As #fNumber
      Put #fNumber,1,mydata    
      SetEof #fNumber  
      Close #fNumber
    I only found out about the problem because XLSX files give an error when opening the uploaded file (it recovers and the file opens).
    Other file formats get the extra 46 bytes but don't complain.

    Original file size: 34190
    uploaded size: 34236

    So I'm adding 46 bytes somewhere.

    other functions:

    Code:
    ' parse out token from cgi string   
    ' value of tokenToFind=name=dztoken
    ' delim is character after value to stop 
    ' extraChar is to add an additional character to search string 
    ' sParams is total content of file
    Function findToken(tokenToFind As String,delim As String,sParams As String,extraChar As Long) As String     
       Local searchStr As String  
       Local sp1,sp2 As Long
       Local token As String
    
       searchStr=tokenToFind
       sp1=InStr(sParams,searchStr)
       sp2=InStr(sp1,sParams,delim)+extraChar
       token=Trim$(Mid$(sParams,sp1+Len(searchStr),sp2-sp1-1-Len(searchStr)))   
       Replace $CrLf With "" In token  
       Replace Chr$(10) With "" In token
       Replace Chr$(13) With "" In token
    
       Function=token
    
    End Function
    Code:
    Function webdatastdin() As String
    
    '   dim iff as long
       Dim hinput As Long
       Dim itoread As Long
       Dim iread As Long
       Dim iresult As Long
       Dim sbuffer As String
       Dim soutbuffer As String
    
       itoread = Val(Environ$("content_length"))
       hinput = getstdhandle(%std_input_handle)
       If hinput Then
          Do
             If itoread > 32000 Then
                sbuffer = Space$(32000)
             ElseIf itoread = 0 Then
                Exit Do
             Else
                sbuffer = Space$(itoread)
             End If
    
             iresult = readfile(hinput, ByVal StrPtr(sbuffer), _
                                Len(sbuffer), iread, ByVal %Null)
    
             '- if there was an error, return nothing
             If iresult = 0 Then
                Exit Do
    
             '- we're done if iread is 0
             ElseIf iread < 1 Then
                Exit Do
    
             '- otherwise, accumulate the buffer
             Else
                soutbuffer = soutbuffer + Left$(sbuffer, iread)
                If Len(soutbuffer) >= itoread Then Exit Do
    
             End If
          Loop
       End If
    
       Function = soutbuffer
    
    End Function
    the file itself looks like
    Code:
    ------WebKitFormBoundaryRsxBljue6C6RyPRT
    Content-Disposition: form-data; name="muName"
    
    shawn
    ------WebKitFormBoundaryRsxBljue6C6RyPRT
    Content-Disposition: form-data; name="muPW"
    
    shawn
    ------WebKitFormBoundaryRsxBljue6C6RyPRT
    Content-Disposition: form-data; name="muCID"
    
    test
    ------WebKitFormBoundaryRsxBljue6C6RyPRT
    Content-Disposition: form-data; name="dzGroupID"
    
    91
    ------WebKitFormBoundaryRsxBljue6C6RyPRT
    Content-Disposition: form-data; name="file"; filename="Guide to CSS Support in Email.xlsx"
    Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    
    PK     ! r???o     [Content_Types].xml ?(?                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ??Mn?0???z???*1tQU?m?-R??xB,?????wb?PJ?`???{?'?&?Z'k?????0?La?2??}???g?`F
    m ?l?&????|? ?6??*??9?3???Ji}-M??;Q,???`??k???F??G?P????>?I<hd?t?x?L8?U!????'.i??Qf??J9| ?;??? ?O*?W????C????o?_?X???tP?TH[[email protected]???X?Zgq?j????[email protected]?x|^?ez
    
    .... more lines of binary then ends with:
    
    ------WebKitFormBoundary6YF0JGPLmAqDN9Z9--
    I'm not really sure how to debug this.


  • #2
    What is the value of the Content-length in the html header ?

    A way to debug is to output the iread variable. I notice that you never reduce the initial itoread variable. You start out by allocating a 32000 bytes buffer but the second iteration should allocated only itoread - 32000 and then compare that with 32000 (if itoread > 32000)

    add itoread = itoread - iread at the end before loop.
    So here we are, this is the end.
    But all that dies, is born again.
    - From The Ashes (In This Moment)

    Comment


    • #3
      Content-length shows as 34841

      adding itoread = itoread - iread stripped out too much and the file was too corrupt to open

      I assume you meant like this?
      Code:
         hinput = getstdhandle(%std_input_handle)
         If hinput Then
            Do
               If itoread > 32000 Then
                  sbuffer = Space$(32000)
               ElseIf itoread = 0 Then                 
                  Exit Do
               Else                                    
                  sbuffer = Space$(itoread)
               End If
      
               iresult = readfile(hinput, ByVal StrPtr(sbuffer), _
                                  Len(sbuffer), iread, ByVal %Null)
      
               '- if there was an error, return nothing
               If iresult = 0 Then
                  Exit Do
      
               '- we're done if iread is 0
               ElseIf iread < 1 Then
                  Exit Do
      
               '- otherwise, accumulate the buffer
               Else
                  soutbuffer = soutbuffer + Left$(sbuffer, iread)
                  If Len(soutbuffer) >= itoread Then Exit Do
      
               End If    
               itoread = itoread - iread
            Loop
         End If
      ...investigating further.
      thanks

      Comment


      • #4
        Then I think you must look into setting a series of boundary character s not available in the file contents.

        search for hex$(Gettickcount()) if I recall correctly
        So here we are, this is the end.
        But all that dies, is born again.
        - From The Ashes (In This Moment)

        Comment


        • #5
          the values of iread per iteration are
          16384
          16384
          2073
          which add up to the length of Content-length : 34841

          why is it bigger than the file size of 34190? Does IIS add overhead somewhere?

          Comment


          • #6
            What is this part ?
            PK ! r???o [Content_Types].xml ?(?

            Especially the [Content_Types] This looks like a PHP problem to me ?

            Edit: forget about it. i just opened an xlsx file myself. It is in there. Sorry.
            So here we are, this is the end.
            But all that dies, is born again.
            - From The Ashes (In This Moment)

            Comment


            • #7
              The extra 46 bytes are probably the last line
              ------WebKitFormBoundary6YF0JGPLmAqDN9Z9-- which is 43 chars.

              So a couple of CR and LF add to 46.

              BTW, the '------WebKitFormBoundary6YF0JGPLmAqDN9Z9--' is the boundary value I wrote about above

              The problem lies in the 'mydata' variable

              Something wrong with the parsing of the filedata.
              So here we are, this is the end.
              But all that dies, is born again.
              - From The Ashes (In This Moment)

              Comment


              • #8
                Good catch!
                I've edited the code like this:

                Code:
                   tmpBuf = Remain$(sParams,"filename=")    
                   tmpbuf = Trim$(Remain$(tmpbuf,"Content-Type: "+contentType))          
                   mydata=Remain$(tmpbuf,$CrLf+$CrLf)                                              ' remove preceding (2) $crlf
                
                   If InStr(myData,"------WebKitFormBoundary")>0 Then
                        myData=Extract$(myData,"------WebKitFormBoundary")               'remove trailing boundary if it exists
                   End If    
                
                   mydata=Extract$(mydata,$CrLf)                                                         ' remove trailing $crlf
                Thanks so much! I'm in business!

                Comment


                • #9
                  I had to tweak this a little. Here is what looks like it's working for everything now:

                  Code:
                     tmpBuf = Remain$(sParams,"filename=")    
                     tmpbuf = Trim$(Remain$(tmpbuf,"Content-Type: "+contentType))          
                     mydata=Remain$(tmpbuf,$CrLf+$CrLf)                      ' remove preceding (2) $crlf  
                  
                     If InStr(myData,"------WebKitFormBoundary")>0 Then
                          myData=Extract$(myData,"------WebKitFormBoundary") ' remove trailing boundry if it exists       
                     End If     
                  
                     If Right$(mydata,2)=$CrLf Then
                          mydata=Left$(mydata,Len(mydata)-2)       ' remove trailing $crlf
                     End If

                  Comment


                  • #10
                    What is this part ?
                    PK ! r???o [Content_Types].xml ?(?
                    I think that's part of the body of the XLSX file.

                    Comment


                    • #11
                      So it turns out the FireFox and Chrome use a different boundary value at the end of the data.This works with both in my testing.

                      Code:
                         tmpBuf = Remain$(sParams,"filename=")    
                         tmpbuf = Trim$(Remain$(tmpbuf,"Content-Type: "+contentType))          
                         mydata=Remain$(tmpbuf,$CrLf+$CrLf)                      ' remove preceding (2) $crlf  
                      
                          If InStr( Right$(myData,46),"------" ) > 0 Then
                              ' upload in firefox or chrome
                              myData=Extract$(myData,"------") ' remove trailing boundry if it exists       
                          End If    
                      
                      
                         If Right$(mydata,2)=$CrLf Then
                              mydata=Left$(mydata,Len(mydata)-2)       ' remove trailing $crlf
                         End If

                      Comment


                      • #12
                        Make sure your testing includes a file that includes the boundary delimiter. Especially if you're parsing on ------ which is hardly unheard of as text file content

                        Comment


                        • #13
                          Make sure your testing includes a file that includes the boundary delimiter
                          it does now!

                          Comment

                          Working...
                          X