Jump to content

Imgur UDF using Curl


Rex
 Share

Recommended Posts

Some time ago I needed a way to uploade images to imgur, from one of my programs, and took a look at there API.

Don't know if anyone can/would use it, but here is my code :)

 

#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
; #INDEX# =======================================================================================================================
; Title .........: IMGUR Curl udf
; AutoIt Version : 1.0
; Description ...: Uploads files to imgur using curl, and returns imgur url, deletion key, imgsize ect. in an array
; Author(s) .....: Rex
; ===============================================================================================================================
#include-once
#include <curl.au3> ; By Ward
#include <JSON.au3> ; by Ward

; #FUNCTION# ====================================================================================================================
; Name...........:  _Imgur
; Description ...:  Allows the user to uploade images to Imgur, or delete an already uploaded image using the images DeleteHash
; Syntax.........:  _Imgur($AuthKey, True/False, $vData)
; Parameters ....: $AuthKey     - API key from Imgur
;                  $bImg_Up     - If true an image uploade is expected, if False a DeleteHas is expected
;                  $vData       - The image to uploade, or the DeleteHash that was returned from Imgur at Image uploade
; Return values .: Success      - An Array containing: ID, Datetime, type, animated, width, height, size, deletehash and url
;                  Failur       - Sets @Error to 1 if no AuthKey is provided
;                  Failur       - Sets @Error to 2 if $bImg_Up = True but no Image data is provided
;                  Failur       - Sets @Error to 3 if $bImg_Up = True but $vData isn't Binary
;                  Failur       - Sets @Error to 4 if $bImg_Up = False but no DeleteHash is provided
;                  Failur       - Sets @Error to 5 if the API returns 400 -> Bad Request
;                  Failur       - Sets @Error to 6 if the API returns 403 -> Permission Denied
;                  Failur       - Sets @Error to 7 if the API returns 413 -> Data to large
;                  Failur       - Sets @Error to 8 if the API returns 415 -> Unsupported data
;                  Failur       - Sets @Error to 9 if Curl returns no Curl
;                  Failur       - Sets @Error to 10 and returns Curl error msg if Curl fails
;                  Failur       - Sets @Error to 11 If StringRegExp failed on the header (no array)
; Author ........: Rex
; Modified.......:
; Remarks .......: Needs Curl, Json And BinaryCall by Ward - Base64Encode By Ward and _EPOCH_Decrypt by Trancexx
;                  Is includede in the UDF is self 
; Related .......:
; Link ..........:
; Example .......: $dFile = FileOpenDialog('Open', @ScriptDir, 'Image Files (*.jpg;*.jpeg;*.png;*.bmp;*.gif)', 1) ; Browse image
;                  $hData = FileOpen($dFile, 16) ; Open as binary
;                  $dData = FileRead($hData) ; Read the data
;                  FileClose($hData) ; Close the FileHandle
;                  $aData = _Imgur('APIKEY', True, $dData) ; Uploade the Image
;
;                  $aDelete = _Imgur('APIKEY', False, 'DELETEHASH')
;
; ===============================================================================================================================


Func _Imgur($sAuthKey, $bImg_Up = True, $vData = '')
    ; Performe some error checking
    Select
        Case $sAuthKey = '' ; If no authkey is provided
            Return SetError(1, 0, -1) ; We set error to 1
        Case $vData = '' And $bImg_Up = True ; If no image data is sendt
            Return SetError(2, 0, -1) ; We sent error to 2
        Case $vData <> '' And $bImg_Up = True And IsBinary($vData) = 0 ; If $vData isn't binary
            Return SetError(3, 0, -1) ; We sent error to 3
        Case $vData = '' And $bImg_Up = False ; If no deleta hash was send
            Return SetError(4, 0, -1) ; We sent error to 4
    EndSelect

    Local $aResult[9] ; Return array
    Local $ProgressCallback = DllCallbackGetPtr(DllCallbackRegister("ShowProgress", "int:cdecl", "ptr;uint64;uint64;uint64;uint64"))
    Local $Curl = Curl_Easy_Init()
    If Not $Curl Then Return SetError(9, 0, -1)
    Local $sHtml = $Curl
    Local $sHeader = $Curl + 1 ; any number as identify
    Local $sList = Curl_Slist_Append(0, "User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:34.0) Gecko/20100101 Firefox/34.0")
    $sList = Curl_Slist_Append($sList, 'Referer: http://imgur.com/')
    $sList = Curl_Slist_Append($sList, 'Type: Base64')
    $sList = Curl_Slist_Append($sList, "Authorization: client-ID " & $sAuthKey)
    Curl_Easy_Setopt($Curl, $CURLOPT_HTTPHEADER, $sList)

    ; If $bImg_Up is true we uploads the image
    If $bImg_Up = True Then
        $dImage = _Base64Encode($vData) ; Convert the image to Base64
        Curl_Easy_Setopt($Curl, $CURLOPT_URL, "https://api.imgur.com/3/upload/") ; If we wants to uploade an image
        Curl_Easy_Setopt($Curl, $CURLOPT_POST, 1)
        Curl_Easy_Setopt($Curl, $CURLOPT_COPYPOSTFIELDS, $dImage)
    Else ; If no img we expect a delete
        Curl_Easy_Setopt($Curl, $CURLOPT_URL, "https://api.imgur.com/3/image/" & $vData) ; If we wants to delete an image
        Curl_Easy_Setopt($Curl, $CURLOPT_CUSTOMREQUEST, 'DELETE') ; When we deletes an image
    EndIf
    ; Get header
    Curl_Easy_Setopt($Curl, $CURLOPT_HEADERFUNCTION, Curl_DataWriteCallback())
    Curl_Easy_Setopt($Curl, $CURLOPT_HEADERDATA, $sHeader)
    Curl_Easy_Setopt($Curl, $CURLOPT_FOLLOWLOCATION, 1)

    ; Checks use this to see the respons from server, and get img url/delete hash ect.
    Curl_Easy_Setopt($Curl, $CURLOPT_WRITEFUNCTION, Curl_DataWriteCallback())
    Curl_Easy_Setopt($Curl, $CURLOPT_WRITEDATA, $sHtml)
    Curl_Easy_Setopt($Curl, $CURLOPT_TIMEOUT, 30)
    Curl_Easy_Setopt($Curl, $CURLOPT_SSL_VERIFYPEER, 0)
    Curl_Easy_Setopt($Curl, $CURLOPT_NOPROGRESS, 0)
    Curl_Easy_Setopt($Curl, $CURLOPT_XFERINFOFUNCTION, $ProgressCallback)

    Local $Code = Curl_Easy_Perform($Curl)
    If $Code <> $CURLE_OK Then
        Return SetError(10, 0, Curl_Easy_StrError($Code))
    EndIf
    ;ConsoleWrite(@CRLF & 'HEADER: ' & BinaryToString(Curl_Data_Get($sHeader)) & @CRLF)
    ;ConsoleWrite(@CRLF & 'HTML RAW: ' & BinaryToString(Curl_Data_Get($sHtml)) & @CRLF)
    ; Check what the header returns
    $aHeader = StringRegExp(BinaryToString(Curl_Data_Get($sHeader)), 'HTTP/1.1 (400|403|413|415|200)', 1)
    If IsArray($aHeader) Then
        Select
            Case $aHeader[0] = 400 ; If 403 then Permission Denied
                Return SetError(5, 0, -1)
            Case $aHeader[0] = 403 ; If 403 then Permission Denied
                Return SetError(6, 0, -1)
            Case $aHeader[0] = 413 ; If 413 then the data is to large
                Return SetError(7, 0, -1)
            Case $aHeader[0] = 415 ; If 415 then the data is unsupported
                Return SetError(8, 0, -1)
            Case $aHeader[0] = 200 ; If 200 uploade/delete was a sucess
                ; Decode the json returned from imgur
                Local $sJson = Json_Decode(BinaryToString(Curl_Data_Get($sHtml)))
                ; If deleting an image we only needs to return Sucess - IMGUR returns Sucess
                If $bImg_Up = False Then
                    ReDim $aResult[1] ; Slim down the array
                    $aResult[0] = 'Success'
                    Return $aResult
                EndIf
                ; If an image was uploaded then we need to return some data to the user
                $aResult[0] = Json_Get($sJson, '["data"]["id"]') ; Imgur image id
                ; Date time the image was uploaded, it's returned in unix timestamp, so we converts it to regular time stamp
                $aResult[1] = _EPOCH_Decrypt(Json_Get($sJson, '["data"]["datetime"]'))
                ; Type of uploaded image
                $aResult[2] = Json_Get($sJson, '["data"]["type"]')
                ; Was the image animated
                $aResult[3] = Json_Get($sJson, '["data"]["animated"]')
                ; Width of the image
                $aResult[4] = Json_Get($sJson, '["data"]["width"]')
                ; Height of the image
                $aResult[5] = Json_Get($sJson, '["data"]["height"]')
                ; Size of the image
                $aResult[6] = Json_Get($sJson, '["data"]["size"]')
                ; Delete hash of the image
                $aResult[7] = Json_Get($sJson, '["data"]["deletehash"]')
                ; Image link
                $aResult[8] = Json_Get($sJson, '["data"]["link"]')
                Curl_Easy_Cleanup($Curl)
                Curl_Data_Cleanup($Curl)
                Curl_Slist_Free_All($sList)
                Return $aResult
        EndSelect
    Else ; If the Regexp failed
        Return SetError(11, 1, -1)
    EndIf

EndFunc   ;==>_Imgur

Func ShowProgress($Ptr, $dltotal, $dlnow, $ultotal, $ulnow)
    ProgressSet(Int($ulnow / $ultotal * 100), '% Sendt = ' & Int($ulnow / $ultotal * 100))
    Return 0
EndFunc   ;==>ShowProgress


; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: _EPOCH_Decrypt
; Description ...: Converts Epoch Time to human time
; Syntax ........: _EPOCH_Decrypt(TIMESTAMP)
; Return values .: Convertede timestamp
; Author ........: Trancexx
; Modified ......:
; Remarks .......:
; ===============================================================================================================================

Func _EPOCH_Decrypt($iEpochTime) ; By trancexx forum thread: https://www.autoitscript.com/forum/topic/83667-epoch-time/
    Local $iDayToAdd = Int($iEpochTime / 86400)
    Local $iTimeVal = Mod($iEpochTime, 86400)
    If $iTimeVal < 0 Then
        $iDayToAdd -= 1
        $iTimeVal += 86400
    EndIf
    Local $i_wFactor = Int((573371.75 + $iDayToAdd) / 36524.25)
    Local $i_xFactor = Int($i_wFactor / 4)
    Local $i_bFactor = 2442113 + $iDayToAdd + $i_wFactor - $i_xFactor
    Local $i_cFactor = Int(($i_bFactor - 122.1) / 365.25)
    Local $i_dFactor = Int(365.25 * $i_cFactor)
    Local $i_eFactor = Int(($i_bFactor - $i_dFactor) / 30.6001)
    Local $aDatePart[3]
    $aDatePart[2] = $i_bFactor - $i_dFactor - Int(30.6001 * $i_eFactor)
    $aDatePart[1] = $i_eFactor - 1 - 12 * ($i_eFactor - 2 > 11)
    $aDatePart[0] = $i_cFactor - 4716 + ($aDatePart[1] < 3)
    Local $aTimePart[3]
    $aTimePart[0] = Int($iTimeVal / 3600)
    $iTimeVal = Mod($iTimeVal, 3600)
    $aTimePart[1] = Int($iTimeVal / 60)
    $aTimePart[2] = Mod($iTimeVal, 60)
    Return StringFormat("%.2d/%.2d/%.2d %.2d:%.2d:%.2d", $aDatePart[0], $aDatePart[1], $aDatePart[2], $aTimePart[0], $aTimePart[1], $aTimePart[2])
EndFunc   ;==>_EPOCH_Decrypt


; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: _Base64Encode
; Description ...: Encodes data into Base64
; Syntax ........: _Base64Encode(Data, Linebreak)
; Return values .: Base64 Encodede string
; Author ........: Ward
; Modified ......:
; Remarks .......:
; ===============================================================================================================================

Func _Base64Encode($Data, $LineBreak = 76) ; By Ward
    Local $Opcode = '0x5589E5FF7514535657E8410000004142434445464748494A4B4C4D4E4F505152535455565758595A6162636465666768696A6B6C6D6E6F707172737'
    $Opcode &= '475767778797A303132333435363738392B2F005A8B5D088B7D108B4D0CE98F0000000FB633C1EE0201D68A06880731C083F901760C0FB6430125F0000000C1'
    $Opcode &= 'E8040FB63383E603C1E60409C601D68A0688470183F90176210FB6430225C0000000C1E8060FB6730183E60FC1E60209C601D68A06884702EB04C647023D83F'
    $Opcode &= '90276100FB6730283E63F01D68A06884703EB04C647033D8D5B038D7F0483E903836DFC04750C8B45148945FC66B80D0A66AB85C90F8F69FFFFFFC607005F5E'
    $Opcode &= '5BC9C21000'

    Local $CodeBuffer = DllStructCreate("byte[" & BinaryLen($Opcode) & "]")
    DllStructSetData($CodeBuffer, 1, $Opcode)

    $Data = Binary($Data)
    Local $Input = DllStructCreate("byte[" & BinaryLen($Data) & "]")
    DllStructSetData($Input, 1, $Data)

    $LineBreak = Floor($LineBreak / 4) * 4
    Local $OputputSize = Ceiling(BinaryLen($Data) * 4 / 3)
    $OputputSize = $OputputSize + Ceiling($OputputSize / $LineBreak) * 2 + 4

    Local $Ouput = DllStructCreate("char[" & $OputputSize & "]")
    DllCall("user32.dll", "none", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), _
            "ptr", DllStructGetPtr($Input), _
            "int", BinaryLen($Data), _
            "ptr", DllStructGetPtr($Ouput), _
            "uint", $LineBreak)
    Return DllStructGetData($Ouput, 1)
EndFunc   ;==>_Base64Encode

I have added Wards curl, json and BinaryCall to the att. zip file.

 

Cheers

/Rex

Includes.zip

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...